fix: build

This commit is contained in:
2023-03-14 18:04:29 +01:00
parent 3792a14e90
commit fd740b3091
185 changed files with 21932 additions and 71486 deletions

View File

@@ -0,0 +1,2 @@
#!/usr/bin/env node
require('./lib/cli.js')

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +1,9 @@
{
"name": "@openstapps/configuration",
"version": "0.34.0",
"description": "A collection of configuration base files for StApps projects.",
"scripts": {
"build": "npm run lint && npm run compile",
"compile": "rimraf lib && tsc --outDir lib && prepend lib/cli.js '#!/usr/bin/env node\n'",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md",
"documentation": "typedoc --out docs --readme README.md --includeVersion --listInvalidSymbolLinks --entryPointStrategy expand src",
"prepublishOnly": "npm ci && npm run build",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "echo \"Error: no test specified\" && exit 1",
"lint": "eslint -c .eslintrc.json --ignore-path .eslintignore --ext .ts src/"
},
"repository": {
"type": "git",
"url": "git@gitlab.com:openstapps/configuration.git"
},
"version": "2.1.0",
"license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/configuration.git",
"author": "Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
"contributors": [
"Anselm Rochus Stordeur",
@@ -24,36 +11,47 @@
"Rainer Killinger <mail-openstapps@killinger.co>",
"Thea Schöbl"
],
"license": "GPL-3.0-only",
"prettier": "@openstapps/prettier-config",
"bin": {
"openstapps-configuration": "app.js"
},
"scripts": {
"build": "npm run lint && npm run compile",
"compile": "rimraf lib && tsc --outDir lib",
"documentation": "typedoc --out docs --readme README.md --includeVersion --listInvalidSymbolLinks --entryPointStrategy expand src",
"format:fix": "prettier --write .",
"lint": "eslint -c .eslintrc.json --ignore-path .eslintignore --ext .ts src/",
"prepublishOnly": "npm ci && npm run build",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "echo \"Error: no test specified\" && exit 1",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md"
},
"dependencies": {
"@types/node": "14.18.36",
"@types/semver": "7.3.13",
"@types/yaml": "1.9.7",
"chalk": "4.1.2",
"commander": "9.5.0",
"commander": "10.0.0",
"semver": "7.3.8",
"yaml": "1.10.2"
},
"devDependencies": {
"@openstapps/eslint-config": "1.1.0",
"@typescript-eslint/eslint-plugin": "5.33.1",
"@typescript-eslint/parser": "5.33.1",
"@openstapps/eslint-config": "workspace:*",
"@openstapps/prettier-config": "workspace:*",
"@types/node": "18.15.3",
"@types/semver": "7.3.13",
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"conventional-changelog-cli": "2.2.2",
"eslint": "8.31.0",
"eslint": "8.33.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-jsdoc": "39.6.4",
"eslint-plugin-jsdoc": "39.7.4",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "43.0.2",
"prepend-file-cli": "1.0.6",
"prettier": "2.8.2",
"rimraf": "3.0.2",
"eslint-plugin-unicorn": "45.0.2",
"prettier": "2.8.3",
"rimraf": "4.4.0",
"typedoc": "0.22.18",
"typescript": "4.4.4"
},
"peerDependencies": {
"typescript": "4.4.4"
},
"bin": {
"openstapps-configuration": "lib/cli.js"
}
}

View File

@@ -819,11 +819,6 @@ export function getRules(configuration: Configuration): Rules {
scripts.build = 'npm run lint && npm run compile';
scripts.compile = 'rimraf lib && tsc';
devDependencies.push('rimraf');
if (configuration.hasCli) {
devDependencies.push('prepend-file-cli');
scripts.compile += " && prepend lib/cli.js '#!/usr/bin/env node\n'";
}
}
if (configuration.standardDocumentation) {

View File

@@ -6,6 +6,7 @@
"esModuleInterop": true,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true,
"inlineSourceMap": true,
"module": "CommonJS",
"moduleResolution": "node",
@@ -16,6 +17,7 @@
"noUnusedLocals": true,
"noUnusedParameters": true,
"outDir": "../../../lib/",
"lib": ["ES2021", "DOM"],
"strict": true,
"target": "es6"
},

View File

@@ -13,12 +13,11 @@ module.exports = {
},
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
'plugin:prettier/recommended',
'plugin:jsdoc/recommended',
'plugin:unicorn/recommended',
'prettier'
],
plugins: ['eslint-plugin-unicorn', 'eslint-plugin-jsdoc', 'prettier'],
plugins: ['eslint-plugin-unicorn', 'eslint-plugin-jsdoc'],
settings: {
jsdoc: {
mode: 'typescript',
@@ -43,6 +42,9 @@ module.exports = {
],
'unicorn/no-nested-ternary': 'off',
'unicorn/better-regex': 'off',
'unicorn/no-typeof-undefined': 'off',
'unicorn/no-non-null-assertion': 'off',
'unicorn/prefer-array-some': 'off',
'jsdoc/no-types': 'error',
'jsdoc/require-param': 'off',
@@ -82,22 +84,6 @@ module.exports = {
'@typescript-eslint/lines-between-class-members': ['error', 'always'],
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-non-null-assertion': 'off',
'prettier/prettier': [
'error',
{
tabWidth: 2,
printWidth: 110,
useTabs: false,
semi: true,
singleQuote: true,
quoteProps: 'consistent',
trailingComma: 'all',
bracketSpacing: false,
arrowParens: 'avoid',
endOfLine: 'lf',
},
],
},
},
],

File diff suppressed because it is too large Load Diff

View File

@@ -1,47 +1,42 @@
{
"name": "@openstapps/eslint-config",
"version": "1.1.0",
"main": "index.js",
"description": "A collection of configuration base files for StApps projects.",
"scripts": {
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'docs: update changelog'",
"test": "eslint -c index.js test/test-file.ts",
"prepublishOnly": "npm ci && npm test",
"postversion": "npm run changelog",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\""
},
"repository": {
"type": "git",
"url": "git@gitlab.com:openstapps/eslint-config.git"
},
"version": "2.1.0",
"license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/eslint-config.git",
"author": "Thea Schöbl",
"contributors": [
"Rainer Killinger <mail-openstapps@killinger.co>"
],
"license": "GPL-3.0-only",
"dependencies": {},
"main": "index.js",
"scripts": {
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'docs: update changelog'",
"postversion": "npm run changelog",
"prepublishOnly": "npm ci && npm test",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "eslint -c index.js test/test-file.ts"
},
"devDependencies": {
"@openstapps/configuration": "0.31.0",
"@typescript-eslint/eslint-plugin": ">=5.29.0",
"@typescript-eslint/parser": ">=5.29.0",
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"conventional-changelog-cli": "2.2.2",
"eslint": ">=8.18.0",
"eslint-config-prettier": ">=8.5.0",
"eslint-plugin-jsdoc": ">=39.3.3",
"eslint-plugin-prettier": ">=4.0.0",
"eslint-plugin-unicorn": ">=42.0.0",
"prettier": ">=2.7.1",
"eslint": "8.33.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-jsdoc": "39.7.4",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "45.0.2",
"prettier": "2.8.3",
"typescript": "4.4.4"
},
"peerDependencies": {
"@typescript-eslint/eslint-plugin": ">=5.29.0",
"@typescript-eslint/parser": ">=5.29.0",
"eslint": ">=8.18.0",
"eslint-config-prettier": ">=8.5.0",
"eslint-plugin-jsdoc": ">=39.3.3",
"eslint-plugin-prettier": ">=4.0.0",
"eslint-plugin-unicorn": ">=41.0.1",
"prettier": ">=2.7.1"
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"eslint": "8.33.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-jsdoc": "39.7.4",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "45.0.2",
"prettier": "2.8.3"
}
}

View File

@@ -1,12 +0,0 @@
/**
* Simple TS source file to get linted
* Can be used to verify new/changed rule behavior
*/
function addNumbers(a: number, b: number) {
return a + b;
}
const sum: number = addNumbers(10, 15);
// eslint-disable-next-line no-console
console.log('Sum of the two numbers is: ' + sum);

View File

@@ -1,3 +0,0 @@
{
"extends": "./node_modules/@openstapps/configuration/tsconfig.json"
}

View File

@@ -1,23 +1,20 @@
{
"name": "@openstapps/prettier-config",
"version": "1.0.0",
"description": "StApps Prettier Config",
"main": "index.json",
"author": "Thea Schöbl <dev@theaninova.de>",
"version": "2.1.0",
"license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/prettier-config.git",
"author": "Thea Schöbl <dev@theaninova.de>",
"contributors": [
"Rainer Killinger <mail-openstapps@killinger.co>"
],
"repository": {
"type": "git",
"url": "git@gitlab.com:openstapps/prettier-config.git"
},
"main": "index.json",
"scripts": {
"changelog": "npx conventional-changelog-cli -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md && git commit -m 'docs: update changelog'",
"test": "npx prettier --config index.json --check \"test/*.js\"",
"prepublishOnly": "npm test",
"postversion": "npm run changelog",
"prepublishOnly": "npm test",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\""
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "npx prettier --config index.json --check \"test/*.js\""
}
}

View File

@@ -116,7 +116,7 @@ remind:
stage: maintenance
only:
variables:
- $MAINTENANCE_MODE == "remind"
- $MAINTENANCE_MODE == "remind"
tags:
- secrecy
@@ -173,7 +173,7 @@ renovate:
DOCKER_TLS_VERIFY: 1
DOCKER_TLS_CERTDIR: /certs
DOCKER_CERT_PATH: /certs/client
RENOVATE_EXTENDS: "gitlab>openstapps/projectmanagement"
RENOVATE_EXTENDS: 'gitlab>openstapps/projectmanagement'
RENOVATE_BASE_DIR: $CI_PROJECT_DIR/renovate
RENOVATE_ENDPOINT: $CI_API_V4_URL
RENOVATE_PLATFORM: gitlab
@@ -195,7 +195,7 @@ renovate:
when: always
expire_in: 1d
paths:
- "$RENOVATE_LOG_FILE"
- '$RENOVATE_LOG_FILE'
before_script: []
script:
- renovate $RENOVATE_EXTRA_FLAGS

View File

@@ -2,35 +2,29 @@
(Summarize the bug encountered concisely)
## Steps to reproduce
(How one can reproduce the issue - this is very important)
## Example Project
(If possible, please create an example project here on GitLab.com that exhibits the problematic behaviour, and link to it here in the bug report)
(If you are using an older version of GitLab, this will also determine whether the bug has been fixed in a more recent version)
## What is the current bug behavior?
(What actually happens)
## What is the expected correct behavior?
(What you should see instead)
## Relevant logs and/or screenshots
(Paste any relevant logs - please use code blocks (```) to format console output,
logs, and code as it's very hard to read otherwise.)
## Possible fixes
(If you can, link to the line of code that might be responsible for the problem)

View File

@@ -2,15 +2,12 @@
(Describe the feature that you're requesting concisely)
## Explanation
(Explain why the feature is necessary)
## Dependencies, issues to be resolved beforehand
(List issues or dependencies that need to be resolved before this feature can be implemented)
/label ~meeting

View File

@@ -1,314 +1,206 @@
# [0.25.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.24.0...v0.25.0) (2023-01-17)
### Bug Fixes
* broken cypress build ([a37d3a9](https://gitlab.com/openstapps/projectmanagement/commit/a37d3a9ec4c8303bef7f7f29fdb8f7401ef7b02a))
* renovate job timeout ([116c880](https://gitlab.com/openstapps/projectmanagement/commit/116c8809e4f7d524361275e910fdc582a9baf78a))
- broken cypress build ([a37d3a9](https://gitlab.com/openstapps/projectmanagement/commit/a37d3a9ec4c8303bef7f7f29fdb8f7401ef7b02a))
- renovate job timeout ([116c880](https://gitlab.com/openstapps/projectmanagement/commit/116c8809e4f7d524361275e910fdc582a9baf78a))
# [0.24.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.23.1...v0.24.0) (2022-10-10)
## [0.23.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.23.0...v0.23.1) (2022-07-05)
### Bug Fixes
* documentation not generating ([ac226d1](https://gitlab.com/openstapps/projectmanagement/commit/ac226d178a41e24a57f5e24409255aee2cfabf8d))
- documentation not generating ([ac226d1](https://gitlab.com/openstapps/projectmanagement/commit/ac226d178a41e24a57f5e24409255aee2cfabf8d))
# [0.23.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.22.0...v0.23.0) (2022-07-05)
# [0.22.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.21.0...v0.22.0) (2021-12-14)
# [0.21.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.20.1...v0.21.0) (2021-12-14)
### Bug Fixes
* exclude npm audit from maintenance runs ([42e6812](https://gitlab.com/openstapps/projectmanagement/commit/42e68120b7215b6fe0f929955d99907103b7bfed))
* link to old gitlab server ([aa9991a](https://gitlab.com/openstapps/projectmanagement/commit/aa9991ad708dd80b873b738a304c94f6f21dd4ba)), closes [#27](https://gitlab.com/openstapps/projectmanagement/issues/27)
- exclude npm audit from maintenance runs ([42e6812](https://gitlab.com/openstapps/projectmanagement/commit/42e68120b7215b6fe0f929955d99907103b7bfed))
- link to old gitlab server ([aa9991a](https://gitlab.com/openstapps/projectmanagement/commit/aa9991ad708dd80b873b738a304c94f6f21dd4ba)), closes [#27](https://gitlab.com/openstapps/projectmanagement/issues/27)
### Features
* make slack notification optional ([84921ad](https://gitlab.com/openstapps/projectmanagement/commit/84921ad5ce90c24ce53197235e8f8a8aff0f4aba))
- make slack notification optional ([84921ad](https://gitlab.com/openstapps/projectmanagement/commit/84921ad5ce90c24ce53197235e8f8a8aff0f4aba))
## [0.20.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.20.0...v0.20.1) (2020-07-27)
### Bug Fixes
* ignore archived projects in milestone tidy ([cd768a9](https://gitlab.com/openstapps/projectmanagement/commit/cd768a9dcdb8edc62f8277a45b054e261311e404))
* remove invalid project name element ([e4c065d](https://gitlab.com/openstapps/projectmanagement/commit/e4c065d5058512ecab1b7fb173e34d950abb123f))
- ignore archived projects in milestone tidy ([cd768a9](https://gitlab.com/openstapps/projectmanagement/commit/cd768a9dcdb8edc62f8277a45b054e261311e404))
- remove invalid project name element ([e4c065d](https://gitlab.com/openstapps/projectmanagement/commit/e4c065d5058512ecab1b7fb173e34d950abb123f))
### Features
* add merge request assignment ([65d05bf](https://gitlab.com/openstapps/projectmanagement/commit/65d05bfe692c7589ae4138439724ba7c0c73bec5))
- add merge request assignment ([65d05bf](https://gitlab.com/openstapps/projectmanagement/commit/65d05bfe692c7589ae4138439724ba7c0c73bec5))
# [0.20.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.19.0...v0.20.0) (2020-05-06)
### Features
* change builder base image to docker/compose ([5ea40b2](https://gitlab.com/openstapps/projectmanagement/commit/5ea40b2ece8cb2ae764096121492dd9703963f1d))
- change builder base image to docker/compose ([5ea40b2](https://gitlab.com/openstapps/projectmanagement/commit/5ea40b2ece8cb2ae764096121492dd9703963f1d))
# [0.19.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.18.0...v0.19.0) (2020-01-08)
# [0.18.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.17.1...v0.18.0) (2019-11-25)
## [0.17.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.17.0...v0.17.1) (2019-11-19)
### Features
* add documentation for automatic publishing ([ab45e35](https://gitlab.com/openstapps/projectmanagement/commit/ab45e35117ef0cca3f42c557e100d4e57a2571df)), closes [#23](https://gitlab.com/openstapps/projectmanagement/issues/23)
- add documentation for automatic publishing ([ab45e35](https://gitlab.com/openstapps/projectmanagement/commit/ab45e35117ef0cca3f42c557e100d4e57a2571df)), closes [#23](https://gitlab.com/openstapps/projectmanagement/issues/23)
# [0.17.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.16.1...v0.17.0) (2019-11-13)
### Features
* update to new meeting date ([98c73b5](https://gitlab.com/openstapps/projectmanagement/commit/98c73b575846fb342c4ffb6a2cf09152a3205f95))
- update to new meeting date ([98c73b5](https://gitlab.com/openstapps/projectmanagement/commit/98c73b575846fb342c4ffb6a2cf09152a3205f95))
## [0.16.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.16.0...v0.16.1) (2019-08-20)
### Bug Fixes
* add colors to cli log output ([7d271a7](https://gitlab.com/openstapps/projectmanagement/commit/7d271a73648d2367e57a3b6c6bb5725d106dced6))
- add colors to cli log output ([7d271a7](https://gitlab.com/openstapps/projectmanagement/commit/7d271a73648d2367e57a3b6c6bb5725d106dced6))
# [0.16.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.15.0...v0.16.0) (2019-08-20)
### Features
* only unlabel closed issues before last meeting ([d7b68ae](https://gitlab.com/openstapps/projectmanagement/commit/d7b68ae45c8321f0a1d9cba998b604507445f9fb))
- only unlabel closed issues before last meeting ([d7b68ae](https://gitlab.com/openstapps/projectmanagement/commit/d7b68ae45c8321f0a1d9cba998b604507445f9fb))
# [0.15.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.14.1...v0.15.0) (2019-07-23)
### Features
* add function and task to get version of used dependency ([067a201](https://gitlab.com/openstapps/projectmanagement/commit/067a2011c03b1e3e9d164844d594e4f332982f12)), closes [#20](https://gitlab.com/openstapps/projectmanagement/issues/20)
- add function and task to get version of used dependency ([067a201](https://gitlab.com/openstapps/projectmanagement/commit/067a2011c03b1e3e9d164844d594e4f332982f12)), closes [#20](https://gitlab.com/openstapps/projectmanagement/issues/20)
## [0.14.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.14.0...v0.14.1) (2019-06-05)
# [0.14.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.13.0...v0.14.0) (2019-06-04)
### Bug Fixes
* fix regression with protected tags ([65a7233](https://gitlab.com/openstapps/projectmanagement/commit/65a723390572f48601e52dac975c9e2b4a0f06c4))
- fix regression with protected tags ([65a7233](https://gitlab.com/openstapps/projectmanagement/commit/65a723390572f48601e52dac975c9e2b4a0f06c4))
### Features
* add max depth for reminders ([3641ec4](https://gitlab.com/openstapps/projectmanagement/commit/3641ec4d00890f81b24301b61d689cd113e33997))
- add max depth for reminders ([3641ec4](https://gitlab.com/openstapps/projectmanagement/commit/3641ec4d00890f81b24301b61d689cd113e33997))
# [0.13.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.12.1...v0.13.0) (2019-06-03)
### Features
* add curl to Node.js image ([2ec80fb](https://gitlab.com/openstapps/projectmanagement/commit/2ec80fbb2f1256530e61a389a8444163c7aef8bd)), closes [#18](https://gitlab.com/openstapps/projectmanagement/issues/18)
- add curl to Node.js image ([2ec80fb](https://gitlab.com/openstapps/projectmanagement/commit/2ec80fbb2f1256530e61a389a8444163c7aef8bd)), closes [#18](https://gitlab.com/openstapps/projectmanagement/issues/18)
## [0.12.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.12.0...v0.12.1) (2019-05-27)
# [0.12.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.11.0...v0.12.0) (2019-05-27)
### Bug Fixes
* use user 'node' in Node.js image ([0c8aa72](https://gitlab.com/openstapps/projectmanagement/commit/0c8aa7257add9fd5997105f18b69211152fd8971)), closes [#17](https://gitlab.com/openstapps/projectmanagement/issues/17)
- use user 'node' in Node.js image ([0c8aa72](https://gitlab.com/openstapps/projectmanagement/commit/0c8aa7257add9fd5997105f18b69211152fd8971)), closes [#17](https://gitlab.com/openstapps/projectmanagement/issues/17)
### Features
* add git to node image ([c0058f9](https://gitlab.com/openstapps/projectmanagement/commit/c0058f9c2918bae3e5fce58f11802174ea08084c)), closes [#16](https://gitlab.com/openstapps/projectmanagement/issues/16)
* notify merge request assignee instead of author ([d60625c](https://gitlab.com/openstapps/projectmanagement/commit/d60625c461c6fe54b7c60091050a31f7f77a958e))
- add git to node image ([c0058f9](https://gitlab.com/openstapps/projectmanagement/commit/c0058f9c2918bae3e5fce58f11802174ea08084c)), closes [#16](https://gitlab.com/openstapps/projectmanagement/issues/16)
- notify merge request assignee instead of author ([d60625c](https://gitlab.com/openstapps/projectmanagement/commit/d60625c461c6fe54b7c60091050a31f7f77a958e))
# [0.11.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.10.0...v0.11.0) (2019-04-30)
### Features
* tidy sub groups ([de05b52](https://gitlab.com/openstapps/projectmanagement/commit/de05b52f24985a882dbacdf82cc1a7c3c4efbe88))
- tidy sub groups ([de05b52](https://gitlab.com/openstapps/projectmanagement/commit/de05b52f24985a882dbacdf82cc1a7c3c4efbe88))
# [0.10.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.9.0...v0.10.0) (2019-04-17)
### Features
* add timestamp to reports ([ad99e45](https://gitlab.com/openstapps/projectmanagement/commit/ad99e45ee3de59de4b5fcca312cb077d90d73335))
- add timestamp to reports ([ad99e45](https://gitlab.com/openstapps/projectmanagement/commit/ad99e45ee3de59de4b5fcca312cb077d90d73335))
# [0.9.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.8.1...v0.9.0) (2019-04-09)
### Features
* add check for protected tags to tidy task ([feb0c3b](https://gitlab.com/openstapps/projectmanagement/commit/feb0c3ba019b1fdfdc5912db86b20d9cc2dd650f)), closes [#14](https://gitlab.com/openstapps/projectmanagement/issues/14)
- add check for protected tags to tidy task ([feb0c3b](https://gitlab.com/openstapps/projectmanagement/commit/feb0c3ba019b1fdfdc5912db86b20d9cc2dd650f)), closes [#14](https://gitlab.com/openstapps/projectmanagement/issues/14)
## [0.8.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.8.0...v0.8.1) (2019-03-20)
# [0.8.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.7.0...v0.8.0) (2019-03-20)
### Features
* use mustache instead of tangular ([95f7521](https://gitlab.com/openstapps/projectmanagement/commit/95f7521dbddc13a6acb5835ae05dd5535cce067f))
- use mustache instead of tangular ([95f7521](https://gitlab.com/openstapps/projectmanagement/commit/95f7521dbddc13a6acb5835ae05dd5535cce067f))
# [0.7.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.6.0...v0.7.0) (2019-03-20)
# [0.6.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.5.0...v0.6.0) (2019-02-25)
### Features
* adjust reminder for unfixed merge requests ([e02939c](https://gitlab.com/openstapps/projectmanagement/commit/e02939c470ff9a63fb33c9754e06ea4dfbbd9b15))
- adjust reminder for unfixed merge requests ([e02939c](https://gitlab.com/openstapps/projectmanagement/commit/e02939c470ff9a63fb33c9754e06ea4dfbbd9b15))
# [0.5.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.4.1...v0.5.0) (2019-02-05)
### Features
* add new task to remind about open merge requests ([201ec09](https://gitlab.com/openstapps/projectmanagement/commit/201ec093b7ab676d5d7a84972c5d9e64664af7e0))
- add new task to remind about open merge requests ([201ec09](https://gitlab.com/openstapps/projectmanagement/commit/201ec093b7ab676d5d7a84972c5d9e64664af7e0))
## [0.4.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.4.0...v0.4.1) (2019-01-30)
# [0.4.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.3.0...v0.4.0) (2019-01-30)
### Features
* add slack reminder for open merge requests ([47e9775](https://gitlab.com/openstapps/projectmanagement/commit/47e977583bc036d48194d1e6bc9e6214dbbe6062))
- add slack reminder for open merge requests ([47e9775](https://gitlab.com/openstapps/projectmanagement/commit/47e977583bc036d48194d1e6bc9e6214dbbe6062))
# [0.3.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.2.2...v0.3.0) (2019-01-28)
### Features
* include sub groups in report generation ([040c666](https://gitlab.com/openstapps/projectmanagement/commit/040c666e747df35b773be1a0e30b7ba99f3b6598))
- include sub groups in report generation ([040c666](https://gitlab.com/openstapps/projectmanagement/commit/040c666e747df35b773be1a0e30b7ba99f3b6598))
## [0.2.2](https://gitlab.com/openstapps/projectmanagement/compare/v0.2.1...v0.2.2) (2019-01-23)
### Bug Fixes
* correctly determine project for issue ([8f06fc3](https://gitlab.com/openstapps/projectmanagement/commit/8f06fc35347f06e8409e4190079323af91fc0a37))
- correctly determine project for issue ([8f06fc3](https://gitlab.com/openstapps/projectmanagement/commit/8f06fc35347f06e8409e4190079323af91fc0a37))
## [0.2.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.2.0...v0.2.1) (2019-01-17)
### Bug Fixes
* correctly add shebang line to cli ([f2933ef](https://gitlab.com/openstapps/projectmanagement/commit/f2933ef9e23e6fa92086800d791c9e4c6685fd4b))
- correctly add shebang line to cli ([f2933ef](https://gitlab.com/openstapps/projectmanagement/commit/f2933ef9e23e6fa92086800d791c9e4c6685fd4b))
# [0.2.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.1.1...v0.2.0) (2019-01-17)
### Bug Fixes
* correct link for projects ([a95ec14](https://gitlab.com/openstapps/projectmanagement/commit/a95ec14be8e169ee1e9f84e3ef98a9712babd302))
* do not add issues to report from backlog ([e902d70](https://gitlab.com/openstapps/projectmanagement/commit/e902d705bf66e07f70a9c34f9f13160c5db5982f))
* unlabel issues with label meeting only ([41a349e](https://gitlab.com/openstapps/projectmanagement/commit/41a349ead50db256916f5506829e587d1ecb4a43))
- correct link for projects ([a95ec14](https://gitlab.com/openstapps/projectmanagement/commit/a95ec14be8e169ee1e9f84e3ef98a9712babd302))
- do not add issues to report from backlog ([e902d70](https://gitlab.com/openstapps/projectmanagement/commit/e902d705bf66e07f70a9c34f9f13160c5db5982f))
- unlabel issues with label meeting only ([41a349e](https://gitlab.com/openstapps/projectmanagement/commit/41a349ead50db256916f5506829e587d1ecb4a43))
## [0.1.1](https://gitlab.com/openstapps/projectmanagement/compare/v0.1.0...v0.1.1) (2019-01-07)
### Bug Fixes
* remove failing deletion of labels ([ac8f2e1](https://gitlab.com/openstapps/projectmanagement/commit/ac8f2e10f965ef0e4950d8f294b6c34a26f4bad0))
- remove failing deletion of labels ([ac8f2e1](https://gitlab.com/openstapps/projectmanagement/commit/ac8f2e10f965ef0e4950d8f294b6c34a26f4bad0))
# [0.1.0](https://gitlab.com/openstapps/projectmanagement/compare/v0.0.2...v0.1.0) (2018-12-13)
## [0.0.2](https://gitlab.com/openstapps/projectmanagement/compare/v0.0.1...v0.0.2) (2018-12-03)
### Features
* add issue template for features ([8ae1a51](https://gitlab.com/openstapps/projectmanagement/commit/8ae1a5166962c5d0b41b869c6021ddc456407022))
* add nyc configuration ([883ab9b](https://gitlab.com/openstapps/projectmanagement/commit/883ab9bfa55def9a0a8dd4ee5427c1eb9ad2960b))
- add issue template for features ([8ae1a51](https://gitlab.com/openstapps/projectmanagement/commit/8ae1a5166962c5d0b41b869c6021ddc456407022))
- add nyc configuration ([883ab9b](https://gitlab.com/openstapps/projectmanagement/commit/883ab9bfa55def9a0a8dd4ee5427c1eb9ad2960b))
## [0.0.1](https://gitlab.com/openstapps/projectmanagement/compare/19fd0f6e4cb8b44152333242aa17db84b2bd038a...v0.0.1) (2018-11-29)
### Features
* add projectmanagement and pack ([19fd0f6](https://gitlab.com/openstapps/projectmanagement/commit/19fd0f6e4cb8b44152333242aa17db84b2bd038a))
- add projectmanagement and pack ([19fd0f6](https://gitlab.com/openstapps/projectmanagement/commit/19fd0f6e4cb8b44152333242aa17db84b2bd038a))

View File

@@ -2,16 +2,16 @@
To contribute effectively to this or other Open StApps projects you should read the documentation in this repository first.
* What's the scope of one [project](../project-docs/workflow/PROJECT.md)?
* How to create [issues](../project-docs/workflow/ISSUES.md) in projects.
* How to [set up](../project-docs/SETUP.md) your machine?
* How to contribute code?
* What's the [branching model](../project-docsworkflow/BRANCHING.md)?
* How to write [code](../project-docs/workflow/CODING.md)?
* How to create [merge requests](../project-docs/workflow/MERGING.md)?
* How to write [documentation](../project-docs/workflow/DOCUMENTATION.md)?
* How to [version](../project-docs/workflow/VERSIONING.md) the code?
- What's the scope of one [project](../project-docs/workflow/PROJECT.md)?
- How to create [issues](../project-docs/workflow/ISSUES.md) in projects.
- How to [set up](../project-docs/SETUP.md) your machine?
- How to contribute code?
- What's the [branching model](../project-docsworkflow/BRANCHING.md)?
- How to write [code](../project-docs/workflow/CODING.md)?
- How to create [merge requests](../project-docs/workflow/MERGING.md)?
- How to write [documentation](../project-docs/workflow/DOCUMENTATION.md)?
- How to [version](../project-docs/workflow/VERSIONING.md) the code?
## Further resources
* [Docker cheat sheet](../project-docs/DOCKER_CHEAT_SHEET.md)
- [Docker cheat sheet](../project-docs/DOCKER_CHEAT_SHEET.md)

View File

@@ -1,6 +1,6 @@
# @openstapps/projectmanagement
[![pipeline status](https://img.shields.io/gitlab/pipeline/openstapps/projectmanagement.svg?style=flat-square)](https://gitlab.com/openstapps/projectmanagement/commits/master)
[![pipeline status](https://img.shields.io/gitlab/pipeline/openstapps/projectmanagement.svg?style=flat-square)](https://gitlab.com/openstapps/projectmanagement/commits/master)
[![npm](https://img.shields.io/npm/v/@openstapps/projectmanagement.svg?style=flat-square)](https://npmjs.com/package/@openstapps/projectmanagement)
[![license)](https://img.shields.io/npm/l/@openstapps/projectmanagement.svg?style=flat-square)](https://www.gnu.org/licenses/gpl-3.0.en.html)
[![documentation](https://img.shields.io/badge/documentation-online-blue.svg?style=flat-square)](https://openstapps.gitlab.io/projectmanagement)
@@ -21,7 +21,7 @@ Every school gets their own subgroup on GitLab inside the group `@openstapps`.
The technical name is the license plate of the school. This can be found in the [list of license plates](project-docs/SCHOOL_IDENTIFIERS.md).
The official name of the school is used as the group's name and a matching logo is picked to act as the group's logo - this should be a square one because of the way that GitLab handles/shows logos.
The official name of the school is used as the group's name and a matching logo is picked to act as the group's logo - this should be a square one because of the way that GitLab handles/shows logos.
#### Permissions on the group

View File

@@ -0,0 +1,2 @@
#!/usr/bin/env node
require('./lib/cli.js')

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +1,9 @@
{
"name": "@openstapps/projectmanagement",
"version": "0.25.0",
"description": "Main documentation and scripts for maintenance.",
"repository": {
"type": "git",
"url": "git@gitlab.com:openstapps/projectmanagement.git"
},
"scripts": {
"build": "npm run lint && npm run compile",
"check-configuration": "openstapps-configuration",
"compile": "rimraf lib && tsc && prepend lib/cli.js '#!/usr/bin/env node\n'",
"documentation": "typedoc --out docs --readme README.md --listInvalidSymbolLinks --entryPointStrategy expand src",
"prepublishOnly": "npm ci && npm run build && npm run test",
"preversion": "npm run prepublishOnly",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "nyc mocha --require ts-node/register 'test/**/*.spec.ts'",
"lint": "eslint --ext .ts src/"
},
"version": "2.1.0",
"license": "GPL-3.0-only",
"repository": "git@gitlab.com:openstapps/projectmanagement.git",
"author": "Karl-Philipp Wulfert <krlwlfrt@gmail.com>",
"contributors": [
"Anselm Stordeur <anselmstordeur@gmail.com>",
@@ -26,54 +12,64 @@
"Rainer Killinger <mail-openstapps@killinger.co>",
"Thea Schöbl <dev@theaninova.de>"
],
"license": "GPL-3.0-only",
"prettier": "@openstapps/prettier-config",
"main": "lib/common.js",
"bin": {
"openstapps-projectmanagement": "app.js"
},
"scripts": {
"build": "npm run lint && npm run compile",
"check-configuration": "openstapps-configuration",
"compile": "rimraf lib && tsc",
"documentation": "typedoc --out docs --readme README.md --listInvalidSymbolLinks --entryPointStrategy expand src",
"format:fix": "prettier --write .",
"lint": "eslint --ext .ts src/",
"prepublishOnly": "npm ci && npm run build && npm run test",
"preversion": "npm run prepublishOnly",
"push": "git push && git push origin \"v$npm_package_version\"",
"test": "nyc mocha --require ts-node/register 'test/**/*.spec.ts'",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md"
},
"dependencies": {
"@krlwlfrt/async-pool": "0.4.1",
"@openstapps/gitlab-api": "0.10.0",
"@openstapps/logger": "1.1.1",
"@slack/client": "5.0.2",
"@types/glob": "7.2.0",
"@types/mustache": "4.2.2",
"@types/node": "14.18.36",
"@types/tmp": "0.2.3",
"commander": "9.5.0",
"@openstapps/gitlab-api": "workspace:*",
"@openstapps/logger": "workspace:*",
"@slack/web-api": "6.8.1",
"commander": "10.0.0",
"date-fns": "2.29.3",
"glob": "8.1.0",
"moment": "2.29.4",
"mustache": "4.2.0",
"tmp": "0.2.1"
},
"devDependencies": {
"@openstapps/configuration": "0.33.0",
"@openstapps/eslint-config": "1.1.0",
"@openstapps/configuration": "workspace:*",
"@openstapps/eslint-config": "workspace:*",
"@openstapps/prettier-config": "workspace:*",
"@testdeck/mocha": "0.3.3",
"@types/chai": "4.3.4",
"@types/chai-as-promised": "7.1.5",
"@types/glob": "8.0.1",
"@types/mocha": "10.0.1",
"@typescript-eslint/eslint-plugin": "5.39.0",
"@typescript-eslint/parser": "5.39.0",
"@types/mustache": "4.2.2",
"@types/node": "18.15.3",
"@types/tmp": "0.2.3",
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"chai": "4.3.7",
"chai-as-promised": "7.1.1",
"conventional-changelog-cli": "2.2.2",
"eslint": "8.32.0",
"eslint": "8.33.0",
"eslint-config-prettier": "8.6.0",
"eslint-plugin-jsdoc": "39.6.4",
"eslint-plugin-jsdoc": "39.7.4",
"eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "44.0.2",
"eslint-plugin-unicorn": "45.0.2",
"mocha": "10.2.0",
"nyc": "15.1.0",
"prepend-file-cli": "1.0.6",
"prettier": "2.8.3",
"rimraf": "3.0.2",
"rimraf": "4.4.0",
"ts-node": "10.9.1",
"tslint": "6.1.3",
"typedoc": "0.22.18",
"typescript": "4.4.4"
},
"main": "lib/common.js",
"typings": "lib/common.d.ts",
"bin": {
"openstapps-projectmanagement": "lib/cli.js"
},
"nyc": {
"all": true,
"branches": 95,
@@ -98,5 +94,6 @@
"ts-node/register"
],
"statements": 95
}
},
"typings": "lib/common.d.ts"
}

View File

@@ -42,6 +42,6 @@ Please consult the [Docker documentation](https://docs.docker.com/engine/referen
## Further resources
* [An Exhaustive Guide to Writing Dockerfiles for Node.js Web Apps](https://blog.hasura.io/an-exhaustive-guide-to-writing-dockerfiles-for-node-js-web-apps-bbee6bd2f3c4)
* [Docker and Node.js Best Practices
](https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md)
- [An Exhaustive Guide to Writing Dockerfiles for Node.js Web Apps](https://blog.hasura.io/an-exhaustive-guide-to-writing-dockerfiles-for-node-js-web-apps-bbee6bd2f3c4)
- [Docker and Node.js Best Practices
](https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md)

View File

@@ -2,11 +2,11 @@
## Required tools/packages
* [SSH](https://docs.gitlab.com/ee/ssh/README.html)
* [Git](https://docs.gitlab.com/ee/gitlab-basics/start-using-git.html)
* [Docker](https://docs.gitlab.com/ee/user/project/container_registry.html) & Docker-Compose
* Node.js & NPM - be sure to install the "Fermium" (14.x) LTS version, might need a [PPA](https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions) or use NVM
* [NVM](https://github.com/creationix/nvm#installation) - if you want to use multiple different versions of node
- [SSH](https://docs.gitlab.com/ee/ssh/README.html)
- [Git](https://docs.gitlab.com/ee/gitlab-basics/start-using-git.html)
- [Docker](https://docs.gitlab.com/ee/user/project/container_registry.html) & Docker-Compose
- Node.js & NPM - be sure to install the "Fermium" (14.x) LTS version, might need a [PPA](https://github.com/nodesource/distributions/blob/master/README.md#installation-instructions) or use NVM
- [NVM](https://github.com/creationix/nvm#installation) - if you want to use multiple different versions of node
Example for Debian based distributions:
@@ -16,13 +16,13 @@ apt install ssh git docker docker-compose nodejs
## IDE - recommended choices
* [VSCode](https://code.visualstudio.com/)
* [Webstorm](https://www.jetbrains.com/webstorm/download/) - Educational or OpenSource License **cannot** be used
- [VSCode](https://code.visualstudio.com/)
- [Webstorm](https://www.jetbrains.com/webstorm/download/) - Educational or OpenSource License **cannot** be used
## Optional helpful tools
* Curl - for executing HTTP requests on the command line
* Postman or Insomnia - for executing HTTP requests with a GUI
- Curl - for executing HTTP requests on the command line
- Postman or Insomnia - for executing HTTP requests with a GUI
## Before you start (Windows only)
@@ -31,8 +31,8 @@ Depending on your preferred settings you could consider applying `git config cor
## Clone starter repositories
* [Minimal deployment](https://gitlab.com/openstapps/minimal-deployment) - contains backend, database, minimal connector, copy (from api) and app
* [Minimal connector](https://gitlab.com/openstapps/minimal-connector) - an example connector to learn the principles of connector development
- [Minimal deployment](https://gitlab.com/openstapps/minimal-deployment) - contains backend, database, minimal connector, copy (from api) and app
- [Minimal connector](https://gitlab.com/openstapps/minimal-connector) - an example connector to learn the principles of connector development
```shell
git clone git@gitlab.com:openstapps/minimal-deployment.git

View File

@@ -2,9 +2,9 @@
## Possible branch names
* `master`
* `develop`
* `$ID-$TITLE`
- `master`
- `develop`
- `$ID-$TITLE`
### `master`
@@ -22,4 +22,4 @@ Development of features, bugfixes or refactoring is done in branches referencing
## Further resources
* [Git - A successful Git branching model](http://nvie.com/posts/a-successful-git-branching-model/)
- [Git - A successful Git branching model](http://nvie.com/posts/a-successful-git-branching-model/)

View File

@@ -16,6 +16,6 @@ Inline comments should not explain what code from external projects is doing. Ad
## Further resources
* [Commit guidelines](COMMITS.md)
* [TypeScript coding guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines)
* [Licensing guidelines](LICENSING.md)
- [Commit guidelines](COMMITS.md)
- [TypeScript coding guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines)
- [Licensing guidelines](LICENSING.md)

View File

@@ -5,24 +5,24 @@
Commit subjects should match the following template:
> `TYPE`: `SUBJECT`
>
>
> `DESCRIPTION`
### `TYPE`
`TYPE` can have one of the following values:
| value | meaning |
| --- | --- |
| build | Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm) |
| ci | Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) |
| docs | Documentation only changes |
| feat | A new feature |
| fix | A bug fix |
| perf | A code change that improves performance |
| refactor | A code change that neither fixes a bug nor adds a feature |
| style | Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) |
| test | Adding missing tests or correcting existing tests |
| value | meaning |
| -------- | ----------------------------------------------------------------------------------------------------------- |
| build | Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm) |
| ci | Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs) |
| docs | Documentation only changes |
| feat | A new feature |
| fix | A bug fix |
| perf | A code change that improves performance |
| refactor | A code change that neither fixes a bug nor adds a feature |
| style | Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc) |
| test | Adding missing tests or correcting existing tests |
These are the [types](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#type), that angular uses. They are easily adaptable for all TypeScript based web related projects.
@@ -56,5 +56,5 @@ conventional-changelog -p angular -i CHANGELOG.md -s -r 0
## Further resources
* [Recommendations on commit messages](https://chris.beams.io/posts/git-commit/)
* [Versioning](VERSIONING.md)
- [Recommendations on commit messages](https://chris.beams.io/posts/git-commit/)
- [Versioning](VERSIONING.md)

View File

@@ -10,17 +10,17 @@ Code is annotated with [TypeDoc](https://typedoc.org/), which then can be used t
Please follow these guidelines to reduce redundance:
* The purpose of inline documentation is to explain what the line of code actually does without explaining syntax or external references. Example:
- The purpose of inline documentation is to explain what the line of code actually does without explaining syntax or external references. Example:
```typescript
// extend the template by the properties of the base template
templateBase.properties = mergeObjects(
templateBase.properties,
templates['base.template.json'].mappings._default_.properties
templates['base.template.json'].mappings._default_.properties,
);
```
* Follow the [recommendations](http://typedoc.org/guides/doccomments/) of `typedoc`, because it is used to generate documentation. Do not denote the types again in the documentation (`@param` and `@returns`), because they are already "documented" in the code itself. Example:
- Follow the [recommendations](http://typedoc.org/guides/doccomments/) of `typedoc`, because it is used to generate documentation. Do not denote the types again in the documentation (`@param` and `@returns`), because they are already "documented" in the code itself. Example:
```typescript
/**
@@ -39,8 +39,8 @@ async get<T>(key: string): Promise<T> {
### Inline Comments `//`
* Start inline comments with a lowercase letter and a space after the `//`
* Place the comment above the line that it is referencing
- Start inline comments with a lowercase letter and a space after the `//`
- Place the comment above the line that it is referencing
```typescript
// lorem ipsum
@@ -49,14 +49,14 @@ const lorem;
### Doc Comments `/**`
* Start with a capital letter
* Keep the first line short
* The first line should not end with a period, nor should it consist of multiple sentences
* The first line should be easily scannable
* If you want to comment more than one line, do a short summary in the first line, then continue after a blank line with the more detailed description
* Document all parameters in functions using `@param`
* `@param` must not contain a type annotation, just `@param name description`
* Do not include `@return`, as it is redundant information
- Start with a capital letter
- Keep the first line short
- The first line should not end with a period, nor should it consist of multiple sentences
- The first line should be easily scannable
- If you want to comment more than one line, do a short summary in the first line, then continue after a blank line with the more detailed description
- Document all parameters in functions using `@param`
- `@param` must not contain a type annotation, just `@param name description`
- Do not include `@return`, as it is redundant information
```typescript
/**
@@ -81,4 +81,4 @@ The path `.gitlab/issue_templates` can contain markdown files which act as templ
## Further resources
* [GitLab issue templates](https://gitlab.com/help/user/project/description_templates.md)
- [GitLab issue templates](https://gitlab.com/help/user/project/description_templates.md)

View File

@@ -6,4 +6,4 @@ Issues keep a discussion of the topic, are related to a [branch](BRANCHING.md),
## Further resources
* [Always start with an issue](https://about.gitlab.com/2016/03/03/start-with-an-issue/)
- [Always start with an issue](https://about.gitlab.com/2016/03/03/start-with-an-issue/)

View File

@@ -45,4 +45,4 @@ If the file is updated in a new year after its creation, the `<year>` should be
## Further resources
* [Coding style](CODING.md)
- [Coding style](CODING.md)

View File

@@ -7,8 +7,8 @@ A merge request can also gather the work of multiple issues.
Merge requests are used to merge the changes to the main branches (`master`, `develop`). Every merge request needs to be reviewed/commented by at least 2 other developers before they can be accepted. This ensure that all guidelines are followed and that the scope of the issue is matched.
Before any merge of an `issue`-branch into the according `master`-branch, the commits of the `issue`-branch shall be tidied up.
Unstage your commits from the `issue`-branch (`git reset master`). Create your new commit(s) and push them to the remote repository (`git push --force`).
Unstage your commits from the `issue`-branch (`git reset master`). Create your new commit(s) and push them to the remote repository (`git push --force`).
## Further resources
* [Commits](COMMITS.md)
- [Commits](COMMITS.md)

View File

@@ -33,5 +33,5 @@ For the contents and purpose of `.editorconfig`, `tsconfig.json` and `tslint.jso
## Further resources
* [Coding style](CODING.md)
* [Versioning](VERSIONING.md)
- [Coding style](CODING.md)
- [Versioning](VERSIONING.md)

View File

@@ -2,7 +2,7 @@
## NPM
All projects that use the [OpenStApps configuration](https://gitlab.com/openstapps/configuration) and implement the automatic publishing via GitLab CI can simply be published to the NPM registry by using the appropriate job. It uses the `NPM_AUTH_TOKEN` that is a [protected variable](https://gitlab.com/groups/openstapps/-/settings/ci_cd) of the OpenStApps group. To trigger this job, a new tag has to be created (on the master branch):
All projects that use the [OpenStApps configuration](https://gitlab.com/openstapps/configuration) and implement the automatic publishing via GitLab CI can simply be published to the NPM registry by using the appropriate job. It uses the `NPM_AUTH_TOKEN` that is a [protected variable](https://gitlab.com/groups/openstapps/-/settings/ci_cd) of the OpenStApps group. To trigger this job, a new tag has to be created (on the master branch):
### Use current [master branch](BRANCHING.md)
@@ -19,8 +19,8 @@ npm version (major|minor|patch)
After these steps there should 2 new commits:
* A version commit
* A changelog commit
- A version commit
- A changelog commit
Also a new git tag should be created.

View File

@@ -2,9 +2,9 @@
We use semantic version through `npm`.
* `npm version patch`: For fixes/patches
* `npm version minor`: For new features
* `npm version major`: For breaking changes in the API
- `npm version patch`: For fixes/patches
- `npm version minor`: For new features
- `npm version major`: For breaking changes in the API
Or directly with `git tag vMAJOR.MINOR.PATCH`.
@@ -12,4 +12,4 @@ This tag is set on the `develop`- (if present) or on the `master`-[branch](BRANC
## Further resources
* [Commit guidelines](COMMITS.md)
- [Commit guidelines](COMMITS.md)

View File

@@ -17,15 +17,15 @@
},
{
"matchUpdateTypes": ["major"],
"matchPackagePatterns": ["^@angular", "^@ionic", "^@types\/node$", "^got$"],
"matchPackagePatterns": ["^@angular", "^@ionic", "^@types/node$", "^got$"],
"enabled": false
},
{
"matchPackagePatterns": ["^@types\/geojson$"],
"matchPackagePatterns": ["^@types/geojson$"],
"allowedVersions": "1.0.6"
},
{
"matchPackagePatterns": ["^@elastic\/elasticsearch$"],
"matchPackagePatterns": ["^@elastic/elasticsearch$"],
"allowedVersions": "<6.0"
},
{
@@ -41,18 +41,12 @@
"allowedVersions": "<5.0"
},
{
"matchDepTypes": [
"peerDependencies"
],
"matchDepTypes": ["peerDependencies"],
"rangeStrategy": "replace"
}
],
"lockFileMaintenance": {
"enabled": true
},
"reviewers": [
"abcdev",
"jovankrunic",
"theaninova"
]
"reviewers": ["abcdev", "jovankrunic", "theaninova"]
}

View File

@@ -12,23 +12,9 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {asyncPool} from '@krlwlfrt/async-pool';
import {Api} from '@openstapps/gitlab-api';
import {Group, Project} from '@openstapps/gitlab-api/lib/types';
import {Project} from '@openstapps/gitlab-api/lib/types';
import {Logger} from '@openstapps/logger';
import {readFile, writeFile} from 'fs';
import {promisify} from 'util';
import {CONCURRENCY} from './configuration';
/**
* Promisified version of readFile
*/
export const readFilePromisified = promisify(readFile);
/**
* Promisified version of writeFile
*/
export const writeFilePromisified = promisify(writeFile);
/**
* Get projects for a list of groups
@@ -39,37 +25,10 @@ export const writeFilePromisified = promisify(writeFile);
export async function getProjects(api: Api, groups: number[]): Promise<Project[]> {
Logger.info(`Fetching all projects for specified groups (${groups.length})...`);
const projectResults = await asyncPool(CONCURRENCY, groups, async groupId => {
return api.getProjectsForGroup(groupId);
});
const projects = flatten2dArray(projectResults);
const projectResults = await Promise.all(groups.map(api.getProjectsForGroup));
const projects = projectResults.flat();
Logger.log(`Fetched ${projects.length} project(s).`);
return projects;
}
/**
* Get subgroups for a list of groups
*
* @param api GitLab API to make requests with
* @param groups List of groups
*/
export async function getSubGroups(api: Api, groups: number[]): Promise<Group[]> {
return flatten2dArray(
await asyncPool(CONCURRENCY, groups, async groupId => {
return api.getSubGroupsForGroup(groupId);
}),
);
}
/**
* Flatten 2d array
*
* @param array Flattened array
*/
export function flatten2dArray<T>(array: T[][]): T[] {
// eslint-disable-next-line unicorn/prefer-spread
return ([] as T[]).concat(...array);
}

View File

@@ -13,7 +13,9 @@
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Label} from '@openstapps/gitlab-api/lib/types';
import moment from 'moment';
import setHours from 'date-fns/setHours';
import nextThursday from 'date-fns/nextThursday';
import previousThursday from 'date-fns/previousThursday';
/**
* List of schools with their IDs
@@ -183,31 +185,11 @@ export const NOTE_PREFIX = '`openstapps/projectmanagement`';
*/
export const SLACK_CHANNEL = 'C762UG76Z';
/**
* Concurrency for async pool
*/
export const CONCURRENCY = 3;
/**
* Maximum depth for merge request reminders
*/
export const MAX_DEPTH_FOR_REMINDER = 2;
/**
* Next meeting
*/
export const NEXT_MEETING = moment()
.startOf('week')
// tslint:disable-next-line:no-magic-numbers
.hour(10)
// tslint:disable-next-line:no-magic-numbers
.day(3);
export const NEXT_MEETING = setHours(nextThursday(Date.now()), 10);
if (NEXT_MEETING.isBefore(moment())) {
NEXT_MEETING.add(1, 'week');
}
/**
* Last meeting
*/
export const LAST_MEETING = moment(NEXT_MEETING).subtract(1, 'week');
export const LAST_MEETING = setHours(previousThursday(Date.now()), 10);

View File

@@ -14,7 +14,7 @@
*/
import {existsSync, PathLike} from 'fs';
import path from 'path';
import {readFilePromisified} from '../common';
import {readFile} from 'fs/promises';
/**
* Get used version of a dependency of a project referenced by a path
@@ -27,7 +27,7 @@ export async function getUsedVersion(directoryPath: PathLike, dependency: string
throw new Error(`'package.json' does not exist in '${directoryPath}'. Not a Node.js project?`);
}
const buffer = await readFilePromisified(path.join(directoryPath.toString(), 'package.json'));
const buffer = await readFile(path.join(directoryPath.toString(), 'package.json'));
const content = buffer.toString();
const packageJson = JSON.parse(content);

View File

@@ -12,7 +12,6 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {asyncPool} from '@krlwlfrt/async-pool';
import {Api} from '@openstapps/gitlab-api';
import {
AccessLevel,
@@ -23,8 +22,8 @@ import {
User,
} from '@openstapps/gitlab-api/lib/types';
import {Logger} from '@openstapps/logger';
import {WebClient} from '@slack/client';
import {CONCURRENCY, GROUPS, MAX_DEPTH_FOR_REMINDER, NOTE_PREFIX, SLACK_CHANNEL} from '../configuration';
import {WebClient} from '@slack/web-api';
import {GROUPS, MAX_DEPTH_FOR_REMINDER, NOTE_PREFIX, SLACK_CHANNEL} from '../configuration';
/**
* Remind people of open merge requests
@@ -55,9 +54,9 @@ export async function remind(api: Api): Promise<void> {
// instantiate slack client
const client =
typeof process.env.SLACK_API_TOKEN !== 'undefined'
? new WebClient(process.env.SLACK_API_TOKEN)
: undefined;
typeof process.env.SLACK_API_TOKEN === 'undefined'
? undefined
: new WebClient(process.env.SLACK_API_TOKEN);
// get members of main group
const members = await api.getMembers(MembershipScope.GROUPS, GROUPS[0]);
@@ -75,115 +74,117 @@ export async function remind(api: Api): Promise<void> {
Logger.info(`Found ${maintainers.length} maintainer(s).`);
await asyncPool(CONCURRENCY, mergeRequests, async mergeRequest => {
// check if merge request is WIP
if (mergeRequest.work_in_progress) {
Logger.info(`Merge request '${mergeRequest.title}' is WIP.`);
await Promise.all(
mergeRequests.map(async mergeRequest => {
// check if merge request is WIP
if (mergeRequest.work_in_progress) {
Logger.info(`Merge request '${mergeRequest.title}' is WIP.`);
return;
}
// get merge request approval
const approval = await api.getMergeRequestApproval(mergeRequest.project_id, mergeRequest.iid);
// get merge request discussions
const discussions = await api.getMergeRequestDiscussions(mergeRequest.project_id, mergeRequest.iid);
// check if at least one of the discussions is unresolved
const hasUnresolvedDiscussions = discussions.some(discussion => {
return discussion.notes.some(note => {
return note.resolvable && (typeof note.resolved === 'undefined' || !note.resolved);
});
});
if (hasUnresolvedDiscussions) {
let recipient = mergeRequest.author.username;
if (typeof mergeRequest.assignee !== 'undefined' && mergeRequest.assignee !== null) {
recipient = mergeRequest.assignee.username;
return;
}
// create note in merge request
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`${NOTE_PREFIX} Please resolve pending discussions, @${recipient}!`,
);
// get merge request approval
const approval = await api.getMergeRequestApproval(mergeRequest.project_id, mergeRequest.iid);
return;
}
// get merge request discussions
const discussions = await api.getMergeRequestDiscussions(mergeRequest.project_id, mergeRequest.iid);
if (approval.merge_status === MergeRequestMergeStatus.CAN_BE_MERGED) {
if (approval.approvals_left > 0) {
Logger.warn(`Merge request '${mergeRequest.title}' needs more approvals!`);
// get possible appropers, prefixed with '@' and joined with commas
const possibleApprovers = maintainerUsernames
.filter(username => {
if (mergeRequest.assignee.username === username) {
return false;
}
if (username.includes('openstapps') || username.includes('kphilipp')) {
return false;
}
if (approval.approved_by.length === 0) {
return true;
}
return approval.approved_by.find(
(approver: {
/**
* Possible approver
*/
user: User;
}) => {
return approver.user.username !== username;
},
);
})
.map(username => `@${username}`)
.join(' ');
// send message to slack
await client?.chat.postMessage({
channel: SLACK_CHANNEL,
text: `Merge request '${mergeRequest.title}' needs more approvals! See ${mergeRequest.web_url}!`,
// check if at least one of the discussions is unresolved
const hasUnresolvedDiscussions = discussions.some(discussion => {
return discussion.notes.some(note => {
return note.resolvable && (typeof note.resolved === 'undefined' || !note.resolved);
});
});
// assign reviewers
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`/assign_reviewer ${possibleApprovers}`,
);
} else {
Logger.log(`Merge request '${mergeRequest.title}' is ready to be merged!`);
if (hasUnresolvedDiscussions) {
let recipient = mergeRequest.author.username;
// send message to slack
await client?.chat.postMessage({
channel: SLACK_CHANNEL,
text: `Merge request '${mergeRequest.title}' is ready to be merged! See ${mergeRequest.web_url}!`,
});
// prefix maintainers with '@' and join with commas
const possibleMergers = maintainerUsernames
.filter(username => {
return mergeRequest.assignee.username !== username;
})
.map(username => `@${username}`)
.join(', ');
if (typeof mergeRequest.assignee !== 'undefined' && mergeRequest.assignee !== null) {
recipient = mergeRequest.assignee.username;
}
// create note in merge request
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`${NOTE_PREFIX} Merge request is ready to be merged, ${possibleMergers}!`,
`${NOTE_PREFIX} Please resolve pending discussions, @${recipient}!`,
);
return;
}
}
});
if (approval.merge_status === MergeRequestMergeStatus.CAN_BE_MERGED) {
if (approval.approvals_left > 0) {
Logger.warn(`Merge request '${mergeRequest.title}' needs more approvals!`);
// get possible appropers, prefixed with '@' and joined with commas
const possibleApprovers = maintainerUsernames
.filter(username => {
if (mergeRequest.assignee.username === username) {
return false;
}
if (username.includes('openstapps') || username.includes('kphilipp')) {
return false;
}
if (approval.approved_by.length === 0) {
return true;
}
return approval.approved_by.find(
(approver: {
/**
* Possible approver
*/
user: User;
}) => {
return approver.user.username !== username;
},
);
})
.map(username => `@${username}`)
.join(' ');
// send message to slack
await client?.chat.postMessage({
channel: SLACK_CHANNEL,
text: `Merge request '${mergeRequest.title}' needs more approvals! See ${mergeRequest.web_url}!`,
});
// assign reviewers
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`/assign_reviewer ${possibleApprovers}`,
);
} else {
Logger.log(`Merge request '${mergeRequest.title}' is ready to be merged!`);
// send message to slack
await client?.chat.postMessage({
channel: SLACK_CHANNEL,
text: `Merge request '${mergeRequest.title}' is ready to be merged! See ${mergeRequest.web_url}!`,
});
// prefix maintainers with '@' and join with commas
const possibleMergers = maintainerUsernames
.filter(username => {
return mergeRequest.assignee.username !== username;
})
.map(username => `@${username}`)
.join(', ');
// create note in merge request
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`${NOTE_PREFIX} Merge request is ready to be merged, ${possibleMergers}!`,
);
}
}
}),
);
}

View File

@@ -12,7 +12,6 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {asyncPool} from '@krlwlfrt/async-pool';
import {Api} from '@openstapps/gitlab-api';
import {
Issue,
@@ -23,12 +22,16 @@ import {
User,
} from '@openstapps/gitlab-api/lib/types';
import {Logger} from '@openstapps/logger';
import moment from 'moment';
import {render} from 'mustache';
import path from 'path';
import {cwd} from 'process';
import {flatten2dArray, getProjects, readFilePromisified, writeFilePromisified} from '../common';
import {BOLD_LABELS, CONCURRENCY, GROUPS, LABEL_WEIGHTS, NEXT_MEETING} from '../configuration';
import {getProjects} from '../common';
import {BOLD_LABELS, GROUPS, LABEL_WEIGHTS, NEXT_MEETING} from '../configuration';
import differenceInWeeks from 'date-fns/differenceInWeeks';
import formatISO from 'date-fns/formatISO';
import format from 'date-fns/format';
import de from 'date-fns/locale/de';
import {readFile, writeFile} from 'fs/promises';
/**
* A structure for template compilation
@@ -188,13 +191,15 @@ export function getMergeRequestUrls(
* @param groups List of groups to get issues for
*/
export async function getIssues(api: Api, label: string, groups: number[]): Promise<Issue[]> {
const issueResults = await asyncPool(CONCURRENCY, groups, async groupId => {
return api.getIssues({
groupId: groupId,
});
});
const issueResults = await Promise.all(
groups.map(groupId =>
api.getIssues({
groupId: groupId,
}),
),
);
const issues = flatten2dArray(issueResults).filter(issue => {
const issues = issueResults.flat().filter(issue => {
return issue.labels.includes(label);
});
@@ -212,21 +217,23 @@ export async function getIssues(api: Api, label: string, groups: number[]): Prom
export async function getIssueBranches(api: Api, projects: Project[]): Promise<{[k: string]: number[]}> {
const projectBranches: {[k: string]: number[]} = {};
await asyncPool(CONCURRENCY, projects, async project => {
const branches = await api.getBranchesForProject(project.id);
await Promise.all(
projects.map(async project => {
const branches = await api.getBranchesForProject(project.id);
// extract issue number from branch
projectBranches[project.id] = branches
.map(branch => {
return branch.name.split('-')[0];
})
.filter(branchNameStart => {
return branchNameStart.match(/^[0-9]+$/);
})
.map(branchNameStart => {
return Number.parseInt(branchNameStart, 10);
});
});
// extract issue number from branch
projectBranches[project.id] = branches
.map(branch => {
return branch.name.split('-')[0];
})
.filter(branchNameStart => {
return branchNameStart.match(/^[0-9]+$/);
})
.map(branchNameStart => {
return Number.parseInt(branchNameStart, 10);
});
}),
);
return projectBranches;
}
@@ -240,14 +247,14 @@ export async function getIssueBranches(api: Api, projects: Project[]): Promise<{
export async function getIssuesGroupedByAssignees(api: Api, label: string): Promise<AssigneeWithIssues[]> {
const issuesByAssignee: IssuesGroupedByAssigneeId = {};
const groups = flatten2dArray(
await asyncPool(CONCURRENCY, GROUPS, async groupId => {
const groups = await Promise.all(
GROUPS.map(async groupId => {
const subGroups = await api.getSubGroupsForGroup(groupId);
return subGroups.map(group => {
return group.id;
});
}),
);
).then(it => it.flat());
groups.push(...groups, ...GROUPS);
const [issues, projects] = await Promise.all([getIssues(api, label, groups), getProjects(api, groups)]);
@@ -292,7 +299,7 @@ export async function getIssuesGroupedByAssignees(api: Api, label: string): Prom
}),
$mergeRequestUrl: getMergeRequestUrls(mergeRequests, issue.project_id, issue.iid)[0],
$project: issue.web_url.replace('https://gitlab.com/', '').split('/-/issues/')[0],
$weeksOpen: moment().diff(moment(issue.created_at), 'weeks'),
$weeksOpen: differenceInWeeks(Date.now(), new Date(issue.created_at)),
};
const issueWithMeta: IssueWithMeta = {
@@ -370,7 +377,7 @@ export async function getIssuesGroupedByAssignees(api: Api, label: string): Prom
* Get next meeting day
*/
export function getNextMeetingDay() {
const meetingDay = NEXT_MEETING.format('YYYY-MM-DD');
const meetingDay = formatISO(NEXT_MEETING, {representation: 'date'});
// log found meeting day
Logger.info(`Generating report for '${meetingDay}' of '${GROUPS.length}' group(s)...`);
@@ -388,35 +395,37 @@ export async function getMergeRequests(api: Api, projects: Project[]): Promise<M
const projectMergeRequests: MergeRequestsForProjects = {};
// iterate over projects
await asyncPool(CONCURRENCY, projects, async project => {
// check if project can have merge requests
if (!project.merge_requests_enabled) {
return;
}
await Promise.all(
projects.map(async project => {
// check if project can have merge requests
if (!project.merge_requests_enabled) {
return;
}
// get all merge requests for project
const mergeRequests = await api.getMergeRequests(
MembershipScope.PROJECTS,
project.id,
MergeRequestState.OPENED,
);
// get all merge requests for project
const mergeRequests = await api.getMergeRequests(
MembershipScope.PROJECTS,
project.id,
MergeRequestState.OPENED,
);
// extract issue number from merge request
projectMergeRequests[project.id] = mergeRequests
.map(mergeRequest => {
// keep information about web url too
return {issue_iid: mergeRequest.source_branch.split('-')[0], web_url: mergeRequest.web_url};
})
.filter(branchNameStartAndUrl => {
return branchNameStartAndUrl.issue_iid.match(/^[0-9]+$/);
})
.map(branchNameStartAndUrl => {
return {
issue_iid: Number.parseInt(branchNameStartAndUrl.issue_iid, 10),
web_url: branchNameStartAndUrl.web_url,
};
});
});
// extract issue number from merge request
projectMergeRequests[project.id] = mergeRequests
.map(mergeRequest => {
// keep information about web url too
return {issue_iid: mergeRequest.source_branch.split('-')[0], web_url: mergeRequest.web_url};
})
.filter(branchNameStartAndUrl => {
return branchNameStartAndUrl.issue_iid.match(/^[0-9]+$/);
})
.map(branchNameStartAndUrl => {
return {
issue_iid: Number.parseInt(branchNameStartAndUrl.issue_iid, 10),
web_url: branchNameStartAndUrl.web_url,
};
});
}),
);
return projectMergeRequests;
}
@@ -434,7 +443,7 @@ export async function generateReport(api: Api, label: string, template: string):
const structureForTemplate: StructureForTemplate = {
issuesByAssignee: issuesGroupedByAssignee,
meetingDay: getNextMeetingDay(),
timestamp: moment().format('LLL'),
timestamp: format(Date.now(), 'PPPPpp', {locale: de}),
};
return render(template, structureForTemplate);
@@ -449,7 +458,7 @@ export async function generateReport(api: Api, label: string, template: string):
export async function report(api: Api, label: string) {
const meetingDay = getNextMeetingDay();
const readReportFile = await readFilePromisified(
const readReportFile = await readFile(
// eslint-disable-next-line unicorn/prefer-module
path.resolve(__dirname, '..', '..', 'templates', 'report.md.mustache'),
);
@@ -462,7 +471,7 @@ export async function report(api: Api, label: string) {
filename = path.join(cwd(), 'reports', `${label}.md`);
}
await writeFilePromisified(filename, markdown);
await writeFile(filename, markdown);
Logger.ok(`Wrote file '${filename}'.`);
}

View File

@@ -12,7 +12,6 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {asyncPool} from '@krlwlfrt/async-pool';
import {Api} from '@openstapps/gitlab-api';
import {
AccessLevel,
@@ -24,9 +23,8 @@ import {
Scope,
} from '@openstapps/gitlab-api/lib/types';
import {Logger} from '@openstapps/logger';
import {flatten2dArray, getProjects} from '../common';
import {getProjects} from '../common';
import {
CONCURRENCY,
GROUPS,
NEEDED_LABELS,
NEEDED_MILESTONES,
@@ -44,51 +42,52 @@ import {
*/
export async function tidyIssuesWithoutMilestone(api: Api): Promise<void> {
// fetch issues without milestone from all groups
const issueResults = await asyncPool(CONCURRENCY, GROUPS, async groupId => {
return api.getIssues({
groupId: groupId,
milestone: 'No Milestone',
state: IssueState.OPENED,
});
});
// flatten structure, e.g. put all issues in one array
const issuesWithoutMilestone = flatten2dArray(issueResults);
const issuesWithoutMilestone = await Promise.all(
GROUPS.map(groupId =>
api.getIssues({
groupId: groupId,
milestone: 'No Milestone',
state: IssueState.OPENED,
}),
),
).then(it => it.flat());
Logger.info(`Found '${issuesWithoutMilestone.length}' issue(s) without milestone.`);
const milestoneCache: {[s: number]: Milestone[]} = {};
await asyncPool(CONCURRENCY, issuesWithoutMilestone, async issue => {
if (typeof milestoneCache[issue.project_id] === 'undefined') {
milestoneCache[issue.project_id] = await api.getMilestonesForProject(issue.project_id);
}
let milestoneId;
for (const milestone of milestoneCache[issue.project_id]) {
if (milestone.title === 'Meeting') {
milestoneId = milestone.id;
await Promise.all(
issuesWithoutMilestone.map(async issue => {
if (typeof milestoneCache[issue.project_id] === 'undefined') {
milestoneCache[issue.project_id] = await api.getMilestonesForProject(issue.project_id);
}
}
if (typeof milestoneId === 'undefined') {
Logger.warn(`Milestone 'Meeting' was not available for issue ${issue.title} (${issue.web_url}).`);
let milestoneId;
return;
}
for (const milestone of milestoneCache[issue.project_id]) {
if (milestone.title === 'Meeting') {
milestoneId = milestone.id;
}
}
await api.setMilestoneForIssue(issue, milestoneId);
if (typeof milestoneId === 'undefined') {
Logger.warn(`Milestone 'Meeting' was not available for issue ${issue.title} (${issue.web_url}).`);
Logger.log(`Milestone was set to 'Meeting' for issue ${issue.title} (${issue.web_url})`);
return;
}
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Milestone was set automatically to 'Meeting'.`,
);
});
await api.setMilestoneForIssue(issue, milestoneId);
Logger.log(`Milestone was set to 'Meeting' for issue ${issue.title} (${issue.web_url})`);
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Milestone was set automatically to 'Meeting'.`,
);
}),
);
Logger.ok('Tidied issues without milestones.');
}
@@ -102,15 +101,14 @@ export async function tidyIssuesWithoutMilestone(api: Api): Promise<void> {
*/
export async function tidyOpenIssuesWithoutMeetingLabel(api: Api): Promise<void> {
// fetch all open issues
const issueResults = await asyncPool(CONCURRENCY, GROUPS, async groupId => {
return api.getIssues({
groupId: groupId,
state: IssueState.OPENED,
});
});
// flatten structure, e.g. put all issues in one array
const openIssues = flatten2dArray(issueResults);
const openIssues = await Promise.all(
GROUPS.map(groupId =>
api.getIssues({
groupId: groupId,
state: IssueState.OPENED,
}),
),
).then(it => it.flat());
Logger.info(`Found ${openIssues.length} open issue(s).`);
@@ -121,20 +119,22 @@ export async function tidyOpenIssuesWithoutMeetingLabel(api: Api): Promise<void>
Logger.info(`Filtered ${openIssuesWithoutMeetingLabel.length} open issue(s) without label 'meeting'.`);
await asyncPool(CONCURRENCY, openIssuesWithoutMeetingLabel, async issue => {
if (issue.milestone !== null && issue.milestone.title === 'Backlog') {
Logger.info(`Skipping issue "${issue.title}" because it is in backlog.`);
await Promise.all(
openIssuesWithoutMeetingLabel.map(async issue => {
if (issue.milestone !== null && issue.milestone.title === 'Backlog') {
Logger.info(`Skipping issue "${issue.title}" because it is in backlog.`);
return;
}
return;
}
return api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Automatically adding label 'meeting'\n\n/label ~meeting`,
);
});
return api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Automatically adding label 'meeting'\n\n/label ~meeting`,
);
}),
);
Logger.ok(`Tidied open issues without label 'meeting'.`);
}
@@ -146,39 +146,43 @@ export async function tidyOpenIssuesWithoutMeetingLabel(api: Api): Promise<void>
* @param projects List of projects to tidy labels on
*/
export async function tidyLabels(api: Api, projects: Project[]): Promise<void> {
await asyncPool(CONCURRENCY, projects, async project => {
const labels = await api.getLabels(project.id);
await Promise.all(
projects.map(async project => {
const labels = await api.getLabels(project.id);
const neededLabels = [...NEEDED_LABELS];
// const extraneousLabels: Label[] = [];
const neededLabels = [...NEEDED_LABELS];
// const extraneousLabels: Label[] = [];
for (const label of labels) {
// let needed = false;
for (const label of labels) {
// let needed = false;
for (const [neededLabelIndex, neededLabel] of neededLabels.entries()) {
if (neededLabel.name.toLowerCase() === label.name.toLowerCase()) {
neededLabels.splice(neededLabelIndex, 1);
// needed = true;
for (const [neededLabelIndex, neededLabel] of neededLabels.entries()) {
if (neededLabel.name.toLowerCase() === label.name.toLowerCase()) {
neededLabels.splice(neededLabelIndex, 1);
// needed = true;
}
}
}
/* if (!needed) {
/* if (!needed) {
extraneousLabels.push(label);
} */
}
}
await asyncPool(CONCURRENCY, neededLabels, async neededLabel => {
await api.createLabel(project.id, neededLabel.name, neededLabel.description, neededLabel.color);
await Promise.all(
neededLabels.map(async neededLabel => {
await api.createLabel(project.id, neededLabel.name, neededLabel.description, neededLabel.color);
Logger.log(`Created label '${neededLabel.name}' in '${project.name_with_namespace}'.`);
});
Logger.log(`Created label '${neededLabel.name}' in '${project.name_with_namespace}'.`);
}),
);
// await asyncPool(2, extraneousLabels, async (extraneousLabel) => {
// await api.deleteLabel(project.id, extraneousLabel.name);
//
// Logger.log('Deleted label `' + extraneousLabel.name + '` from ' + project.name_with_namespace + '.');
// });
});
// await asyncPool(2, extraneousLabels, async (extraneousLabel) => {
// await api.deleteLabel(project.id, extraneousLabel.name);
//
// Logger.log('Deleted label `' + extraneousLabel.name + '` from ' + project.name_with_namespace + '.');
// });
}),
);
Logger.ok('Tidied labels.');
}
@@ -190,25 +194,29 @@ export async function tidyLabels(api: Api, projects: Project[]): Promise<void> {
* @param projects List of projects to tidy milestones on
*/
export async function tidyMilestones(api: Api, projects: Project[]): Promise<void> {
await asyncPool(CONCURRENCY, projects, async project => {
const milestones = await api.getMilestonesForProject(project.id);
const missingMilestones = [...NEEDED_MILESTONES];
await Promise.all(
projects.map(async project => {
const milestones = await api.getMilestonesForProject(project.id);
const missingMilestones = [...NEEDED_MILESTONES];
for (const milestone of milestones) {
const index = missingMilestones.indexOf(milestone.title);
for (const milestone of milestones) {
const index = missingMilestones.indexOf(milestone.title);
if (index >= 0) {
missingMilestones.splice(index, 1);
if (index >= 0) {
missingMilestones.splice(index, 1);
}
}
}
if (missingMilestones.length > 0 && !project.archived) {
await asyncPool(CONCURRENCY, missingMilestones, async milestone => {
await api.createMilestone(project.id, milestone);
Logger.log(`Created milestone '${milestone}' for project ${project.name_with_namespace}'.`);
});
}
});
if (missingMilestones.length > 0 && !project.archived) {
await Promise.all(
missingMilestones.map(async milestone => {
await api.createMilestone(project.id, milestone);
Logger.log(`Created milestone '${milestone}' for project ${project.name_with_namespace}'.`);
}),
);
}
}),
);
Logger.ok('Tidied milestones.');
}
@@ -220,23 +228,29 @@ export async function tidyMilestones(api: Api, projects: Project[]): Promise<voi
* @param projects List of projects to tidy milestones on
*/
export async function tidyProtectedBranches(api: Api, projects: Project[]): Promise<void> {
await asyncPool(CONCURRENCY, projects, async project => {
const branches = await api.getBranchesForProject(project.id);
await Promise.all(
projects.map(async project => {
const branches = await api.getBranchesForProject(project.id);
const protectableBranches = branches.filter(branch => {
return PROTECTED_BRANCHES.includes(branch.name);
});
const protectableBranches = branches.filter(branch => {
return PROTECTED_BRANCHES.includes(branch.name);
});
const unprotectedBranches = protectableBranches.filter(branch => {
return !branch.protected;
});
const unprotectedBranches = protectableBranches.filter(branch => {
return !branch.protected;
});
await asyncPool(CONCURRENCY, unprotectedBranches, async branch => {
await api.protectBranch(project.id, branch.name);
await Promise.all(
unprotectedBranches.map(async branch => {
await api.protectBranch(project.id, branch.name);
Logger.log(`Added protected branch '${branch.name}' in project '${project.name_with_namespace}'...`);
});
});
Logger.log(
`Added protected branch '${branch.name}' in project '${project.name_with_namespace}'...`,
);
}),
);
}),
);
Logger.ok('Tidied protected branches.');
}
@@ -248,44 +262,48 @@ export async function tidyProtectedBranches(api: Api, projects: Project[]): Prom
* @param projects List of projects to tidy protected tags on
*/
export async function tidyProtectedTags(api: Api, projects: Project[]): Promise<void> {
await asyncPool(CONCURRENCY, projects, async project => {
// TODO: move this to GitLab API
const protectedTags = (await api.makeGitLabAPIRequest(`projects/${project.id}/protected_tags`)) as Array<{
/**
* List of access levels to create a tag
*/
create_access_levels: Array<{
await Promise.all(
projects.map(async project => {
// TODO: move this to GitLab API
const protectedTags = (await api.makeGitLabAPIRequest(
`projects/${project.id}/protected_tags`,
)) as Array<{
/**
* Access level
* List of access levels to create a tag
*/
access_level: AccessLevel;
create_access_levels: Array<{
/**
* Access level
*/
access_level: AccessLevel;
/**
* Description of access level
*/
access_level_description: string;
}>;
/**
* Description of access level
* Name of the tag
*/
access_level_description: string;
name: string;
}>;
/**
* Name of the tag
*/
name: string;
}>;
if (
protectedTags.findIndex(protectedTag => {
return protectedTag.name === 'v*';
}) === -1
) {
await api.makeGitLabAPIRequest(`projects/${project.id}/protected_tags`, {
data: {
create_access_level: AccessLevel.Maintainer,
name: 'v*',
},
method: 'POST',
});
if (
protectedTags.findIndex(protectedTag => {
return protectedTag.name === 'v*';
}) === -1
) {
await api.makeGitLabAPIRequest(`projects/${project.id}/protected_tags`, {
data: {
create_access_level: AccessLevel.Maintainer,
name: 'v*',
},
method: 'POST',
});
Logger.log(`Added protected version tag in project '${project.name_with_namespace}'.`);
}
});
Logger.log(`Added protected version tag in project '${project.name_with_namespace}'.`);
}
}),
);
Logger.ok('Tidied protected tags.');
}
@@ -305,26 +323,32 @@ export async function tidySubGroupMembers(api: Api): Promise<void> {
groupIdsToSchool[SCHOOLS[school]] = school;
});
await asyncPool(CONCURRENCY, GROUPS.slice(1), async groupId => {
const members = await api.getMembers(MembershipScope.GROUPS, groupId);
const memberIds = new Set(members.map(member => member.id));
await Promise.all(
GROUPS.slice(1).map(async groupId => {
const members = await api.getMembers(MembershipScope.GROUPS, groupId);
const memberIds = new Set(members.map(member => member.id));
await asyncPool(CONCURRENCY, stappsMembers, async stappsMember => {
if (!memberIds.has(stappsMember.id)) {
await api.addMember(MembershipScope.GROUPS, groupId, stappsMember.id, AccessLevel.Developer);
await Promise.all(
stappsMembers.map(async stappsMember => {
if (!memberIds.has(stappsMember.id)) {
await api.addMember(MembershipScope.GROUPS, groupId, stappsMember.id, AccessLevel.Developer);
Logger.log(`Added '${stappsMember.name}' to group '${groupIdsToSchool[groupId]}'.`);
}
});
Logger.log(`Added '${stappsMember.name}' to group '${groupIdsToSchool[groupId]}'.`);
}
}),
);
await asyncPool(CONCURRENCY, members, async member => {
if (!stappsMemberIds.has(member.id)) {
await api.deleteMember(MembershipScope.GROUPS, groupId, member.id);
await Promise.all(
members.map(async member => {
if (!stappsMemberIds.has(member.id)) {
await api.deleteMember(MembershipScope.GROUPS, groupId, member.id);
Logger.log(`Deleted member '${member.name}' from group '${groupIdsToSchool[groupId]}'.`);
}
});
});
Logger.log(`Deleted member '${member.name}' from group '${groupIdsToSchool[groupId]}'.`);
}
}),
);
}),
);
Logger.ok(`Tidied 'sub' group members.`);
}
@@ -338,15 +362,14 @@ export async function tidySubGroupMembers(api: Api): Promise<void> {
*/
export async function tidyIssuesWithoutAssignee(api: Api): Promise<void> {
// fetch issues without milestone from all groups
const issueResults = await asyncPool(CONCURRENCY, GROUPS, async groupId => {
return api.getIssues({
groupId: groupId,
state: IssueState.OPENED,
});
});
// flatten structure, e.g. put all issues in one array
const issues = flatten2dArray(issueResults);
const issues = await Promise.all(
GROUPS.map(async groupId => {
return api.getIssues({
groupId: groupId,
state: IssueState.OPENED,
});
}),
).then(it => it.flat());
const issuesWithoutAssignee = issues.filter(issue => {
return issue.assignee === null;
@@ -354,18 +377,20 @@ export async function tidyIssuesWithoutAssignee(api: Api): Promise<void> {
Logger.info(`Found '${issuesWithoutAssignee.length}' issue(s) without assignee.`);
await asyncPool(CONCURRENCY, issuesWithoutAssignee, async issue => {
await api.setAssigneeForIssue(issue, issue.author.id);
await Promise.all(
issuesWithoutAssignee.map(async issue => {
await api.setAssigneeForIssue(issue, issue.author.id);
Logger.log(`Set assignee for '${issue.title}' to '${issue.author.name}'.`);
Logger.log(`Set assignee for '${issue.title}' to '${issue.author.name}'.`);
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Assignee was set automatically to author.`,
);
});
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Assignee was set automatically to author.`,
);
}),
);
Logger.ok('Tidied issues without assignee.');
}
@@ -378,12 +403,11 @@ export async function tidyIssuesWithoutAssignee(api: Api): Promise<void> {
* @param api GitLab API instance to use for the requests
*/
export async function tidyMergeRequestsWithoutAssignee(api: Api): Promise<void> {
const mergeRequestResults = await asyncPool(CONCURRENCY, GROUPS, async groupId => {
return api.getMergeRequests(MembershipScope.GROUPS, groupId, MergeRequestState.OPENED);
});
// flatten structure, e.g. put all issues in one array
const mergeRequests = flatten2dArray(mergeRequestResults);
const mergeRequests = await Promise.all(
GROUPS.map(async groupId => {
return api.getMergeRequests(MembershipScope.GROUPS, groupId, MergeRequestState.OPENED);
}),
).then(it => it.flat());
const mergeRequestsWithoutAssignee = mergeRequests.filter(mergeRequest => {
return mergeRequest.assignee === null;
@@ -391,18 +415,20 @@ export async function tidyMergeRequestsWithoutAssignee(api: Api): Promise<void>
Logger.info(`Found '${mergeRequestsWithoutAssignee.length}' merge requests without assignee.`);
await asyncPool(CONCURRENCY, mergeRequestsWithoutAssignee, async mergeRequest => {
await api.setAssigneeForMergeRequest(mergeRequest, mergeRequest.author.id);
await Promise.all(
mergeRequestsWithoutAssignee.map(async mergeRequest => {
await api.setAssigneeForMergeRequest(mergeRequest, mergeRequest.author.id);
Logger.log(`Set assignee for '${mergeRequest.title}' to '${mergeRequest.author.name}'.`);
Logger.log(`Set assignee for '${mergeRequest.title}' to '${mergeRequest.author.name}'.`);
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`${NOTE_PREFIX} Assignee was set automatically to author.`,
);
});
await api.createNote(
mergeRequest.project_id,
Scope.MERGE_REQUESTS,
mergeRequest.iid,
`${NOTE_PREFIX} Assignee was set automatically to author.`,
);
}),
);
Logger.ok('Tidied merge requests without assignee.');
}

View File

@@ -12,13 +12,11 @@
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {asyncPool} from '@krlwlfrt/async-pool';
import {Api} from '@openstapps/gitlab-api';
import {IssueState, Scope} from '@openstapps/gitlab-api/lib/types';
import {Logger} from '@openstapps/logger';
import moment from 'moment';
import {flatten2dArray} from '../common';
import {CONCURRENCY, GROUPS, LAST_MEETING, NOTE_PREFIX} from '../configuration';
import {GROUPS, LAST_MEETING, NOTE_PREFIX} from '../configuration';
import isBefore from 'date-fns/isBefore';
/**
* Remove label `meeting` from closed issues
@@ -26,34 +24,38 @@ import {CONCURRENCY, GROUPS, LAST_MEETING, NOTE_PREFIX} from '../configuration';
* @param api Instance of GitLabAPI to send requests with
*/
export async function unlabel(api: Api) {
const issueResults = await asyncPool(CONCURRENCY, GROUPS, async groupId => {
return api.getIssues({
groupId: groupId,
state: IssueState.CLOSED,
});
});
const issues = flatten2dArray(issueResults);
const issues = await Promise.all(
GROUPS.map(async groupId => {
return api.getIssues({
groupId: groupId,
state: IssueState.CLOSED,
});
}),
).then(it => it.flat());
Logger.log(`Fetched ${issues.length} closed issue(s).`);
await asyncPool(CONCURRENCY, issues, async issue => {
if (
issue.labels.includes('meeting') &&
issue.closed_at !== null &&
moment(issue.closed_at).isBefore(LAST_MEETING)
) {
Logger.info(`Issue ${issue.title} is closed before last meeting and has label "meeting". Removing it.`);
await Promise.all(
issues.map(async issue => {
if (
issue.labels.includes('meeting') &&
issue.closed_at !== null &&
isBefore(new Date(issue.closed_at), LAST_MEETING)
) {
Logger.info(
`Issue ${issue.title} is closed before last meeting and has label "meeting". Removing it.`,
);
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Removed label \`meeting\` automatically.
await api.createNote(
issue.project_id,
Scope.ISSUES,
issue.iid,
`${NOTE_PREFIX} Removed label \`meeting\` automatically.
/unlabel ~meeting`,
);
}
});
);
}
}),
);
Logger.ok('Label `meeting` has been removed from closed issues.');
}