diff --git a/libraries/access-token-encryptor/.mocharc.cjs b/libraries/access-token-encryptor/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/libraries/access-token-encryptor/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/libraries/access-token-encryptor/.mocharc.json b/libraries/access-token-encryptor/.mocharc.json deleted file mode 100644 index c492858ff0..0000000000 --- a/libraries/access-token-encryptor/.mocharc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ui": "bdd", - "recursive": "true", - "reporter": "spec", - "require": "test/setup.js" -} diff --git a/libraries/access-token-encryptor/Jenkinsfile b/libraries/access-token-encryptor/Jenkinsfile new file mode 100644 index 0000000000..412fe33b39 --- /dev/null +++ b/libraries/access-token-encryptor/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/access-token-encryptor/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/access-token-encryptor monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/access-token-encryptor/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'access-token-encryptor-eslint', name: 'access-token-encryptor eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/access-token-encryptor/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/access-token-encryptor monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/access-token-encryptor monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/access-token-encryptor monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'access-token-encryptor test results', testResults: 'libraries/access-token-encryptor/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/access-token-encryptor/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/access-token-encryptor/package.json b/libraries/access-token-encryptor/package.json index b767f50cf5..4eb55c299d 100644 --- a/libraries/access-token-encryptor/package.json +++ b/libraries/access-token-encryptor/package.json @@ -22,6 +22,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "typescript": "^5.0.4" } diff --git a/libraries/access-token-encryptor/test/mocha-multi-reporters.cjs b/libraries/access-token-encryptor/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/libraries/access-token-encryptor/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/libraries/fetch-utils/.mocharc.cjs b/libraries/fetch-utils/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/libraries/fetch-utils/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/libraries/fetch-utils/.mocharc.json b/libraries/fetch-utils/.mocharc.json deleted file mode 100644 index c492858ff0..0000000000 --- a/libraries/fetch-utils/.mocharc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ui": "bdd", - "recursive": "true", - "reporter": "spec", - "require": "test/setup.js" -} diff --git a/libraries/fetch-utils/Jenkinsfile b/libraries/fetch-utils/Jenkinsfile new file mode 100644 index 0000000000..c056b8cecb --- /dev/null +++ b/libraries/fetch-utils/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/fetch-utils/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/fetch-utils monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/fetch-utils/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'fetch-utils-eslint', name: 'fetch-utils eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/fetch-utils/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/fetch-utils monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/fetch-utils monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/fetch-utils monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'fetch-utils test results', testResults: 'libraries/fetch-utils/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/fetch-utils/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/fetch-utils/package.json b/libraries/fetch-utils/package.json index 6b45b93f66..d106957245 100644 --- a/libraries/fetch-utils/package.json +++ b/libraries/fetch-utils/package.json @@ -22,6 +22,8 @@ "chai-as-promised": "^7.1.1", "express": "^4.21.2", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" }, "dependencies": { diff --git a/libraries/fetch-utils/test/mocha-multi-reporters.cjs b/libraries/fetch-utils/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/libraries/fetch-utils/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/libraries/logger/.mocharc.cjs b/libraries/logger/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/libraries/logger/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/libraries/logger/.mocharc.json b/libraries/logger/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/libraries/logger/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/libraries/logger/Jenkinsfile b/libraries/logger/Jenkinsfile new file mode 100644 index 0000000000..820844b1f3 --- /dev/null +++ b/libraries/logger/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/logger/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/logger monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/logger/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'logger-eslint', name: 'logger eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/logger/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/logger monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/logger monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/logger monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'logger test results', testResults: 'libraries/logger/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/logger/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/logger/package.json b/libraries/logger/package.json index 0e7fd2d0cc..653ea9403c 100644 --- a/libraries/logger/package.json +++ b/libraries/logger/package.json @@ -28,6 +28,8 @@ "devDependencies": { "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "sinon-chai": "^3.7.0", diff --git a/libraries/logger/test/mocha-multi-reporters.cjs b/libraries/logger/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/libraries/logger/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/libraries/metrics/.mocharc.cjs b/libraries/metrics/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/libraries/metrics/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/libraries/metrics/Jenkinsfile b/libraries/metrics/Jenkinsfile new file mode 100644 index 0000000000..c40a70807d --- /dev/null +++ b/libraries/metrics/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/metrics/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/metrics monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/metrics/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'metrics-eslint', name: 'metrics eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/metrics/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/metrics monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/metrics monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/metrics monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'metrics test results', testResults: 'libraries/metrics/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/metrics/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/metrics/package.json b/libraries/metrics/package.json index 19b566c2b0..295b24caa9 100644 --- a/libraries/metrics/package.json +++ b/libraries/metrics/package.json @@ -24,6 +24,8 @@ "bunyan": "^1.0.0", "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "typescript": "^5.0.4" @@ -32,7 +34,7 @@ "lint": "eslint --ext .js --ext .cjs --ext .ts --max-warnings 0 --format unix .", "lint:fix": "eslint --fix --ext .js --ext .cjs --ext .ts .", "test:unit": "mocha --exit test/**/*.{js,cjs}", - "test:acceptance": "mocha --reporter spec --recursive --exit --grep=$MOCHA_GREP test/acceptance", + "test:acceptance": "mocha --recursive --exit --grep=$MOCHA_GREP test/acceptance", "test": "npm run lint && npm run format && npm run types:check && npm run test:unit", "format": "prettier --list-different $PWD/'**/*.{js,cjs,ts}'", "format:fix": "prettier --write $PWD/'**/*.{js,cjs,ts}'", diff --git a/libraries/metrics/test/mocha-multi-reporters.cjs b/libraries/metrics/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/libraries/metrics/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/libraries/mongo-utils/Jenkinsfile b/libraries/mongo-utils/Jenkinsfile new file mode 100644 index 0000000000..b98430073b --- /dev/null +++ b/libraries/mongo-utils/Jenkinsfile @@ -0,0 +1,72 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/mongo-utils/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/mongo-utils monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/mongo-utils/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'mongo-utils-eslint', name: 'mongo-utils eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/mongo-utils/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/mongo-utils monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/mongo-utils monorepo npm run types:check' + } + } + } + } + } + post { + cleanup { + sh 'rm -rf libraries/mongo-utils/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/mongo-utils/package.json b/libraries/mongo-utils/package.json index 51e2148f45..055fb9b811 100644 --- a/libraries/mongo-utils/package.json +++ b/libraries/mongo-utils/package.json @@ -22,6 +22,8 @@ "devDependencies": { "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "sinon-chai": "^3.7.0", diff --git a/libraries/o-error/.mocharc.cjs b/libraries/o-error/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/libraries/o-error/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/libraries/o-error/Jenkinsfile b/libraries/o-error/Jenkinsfile new file mode 100644 index 0000000000..a2658d0870 --- /dev/null +++ b/libraries/o-error/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/o-error/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/o-error monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/o-error/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'o-error-eslint', name: 'o-error eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/o-error/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/o-error monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/o-error monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/o-error monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'o-error test results', testResults: 'libraries/o-error/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/o-error/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/o-error/package.json b/libraries/o-error/package.json index 48b376ae7b..b455c226cf 100644 --- a/libraries/o-error/package.json +++ b/libraries/o-error/package.json @@ -35,6 +35,8 @@ "@types/node": "^18.19.123", "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } } diff --git a/libraries/o-error/test/mocha-multi-reporters.cjs b/libraries/o-error/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/libraries/o-error/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/libraries/object-persistor/.mocharc.cjs b/libraries/object-persistor/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/libraries/object-persistor/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/libraries/object-persistor/.mocharc.json b/libraries/object-persistor/.mocharc.json deleted file mode 100644 index 9fe3c1982f..0000000000 --- a/libraries/object-persistor/.mocharc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ui": "bdd", - "recursive": "true", - "reporter": "spec", - "require": "./test/setup" -} diff --git a/libraries/object-persistor/Jenkinsfile b/libraries/object-persistor/Jenkinsfile new file mode 100644 index 0000000000..eb5f1b840f --- /dev/null +++ b/libraries/object-persistor/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/object-persistor/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/object-persistor monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/object-persistor/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'object-persistor-eslint', name: 'object-persistor eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/object-persistor/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/object-persistor monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/object-persistor monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/object-persistor monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'object-persistor test results', testResults: 'libraries/object-persistor/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/object-persistor/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/object-persistor/package.json b/libraries/object-persistor/package.json index 9af45359f4..ec0215f906 100644 --- a/libraries/object-persistor/package.json +++ b/libraries/object-persistor/package.json @@ -38,6 +38,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "mock-fs": "^5.2.0", "mongodb": "6.12.0", "sandboxed-module": "^2.0.4", diff --git a/libraries/object-persistor/test/mocha-multi-reporters.cjs b/libraries/object-persistor/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/libraries/object-persistor/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/libraries/overleaf-editor-core/.mocharc.cjs b/libraries/overleaf-editor-core/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/libraries/overleaf-editor-core/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/libraries/overleaf-editor-core/Jenkinsfile b/libraries/overleaf-editor-core/Jenkinsfile new file mode 100644 index 0000000000..91d0cc3c9d --- /dev/null +++ b/libraries/overleaf-editor-core/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/overleaf-editor-core/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/overleaf-editor-core monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/overleaf-editor-core/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'overleaf-editor-core-eslint', name: 'overleaf-editor-core eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/overleaf-editor-core/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/overleaf-editor-core monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/overleaf-editor-core monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/overleaf-editor-core monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'overleaf-editor-core test results', testResults: 'libraries/overleaf-editor-core/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/overleaf-editor-core/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/overleaf-editor-core/package.json b/libraries/overleaf-editor-core/package.json index dc6f8a75d9..03d1834ee4 100644 --- a/libraries/overleaf-editor-core/package.json +++ b/libraries/overleaf-editor-core/package.json @@ -21,6 +21,8 @@ "@types/path-browserify": "^1.0.3", "chai": "^3.3.0", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sinon": "^9.2.4", "typescript": "^5.0.4" }, diff --git a/libraries/overleaf-editor-core/test/mocha-multi-reporters.cjs b/libraries/overleaf-editor-core/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/libraries/overleaf-editor-core/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/libraries/promise-utils/.mocharc.cjs b/libraries/promise-utils/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/libraries/promise-utils/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/libraries/promise-utils/.mocharc.json b/libraries/promise-utils/.mocharc.json deleted file mode 100644 index 3be9ee53ae..0000000000 --- a/libraries/promise-utils/.mocharc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "ui": "bdd", - "recursive": "true", - "reporter": "spec" -} diff --git a/libraries/promise-utils/Jenkinsfile b/libraries/promise-utils/Jenkinsfile new file mode 100644 index 0000000000..08e63e3ac3 --- /dev/null +++ b/libraries/promise-utils/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/promise-utils/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/promise-utils monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/promise-utils/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'promise-utils-eslint', name: 'promise-utils eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/promise-utils/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/promise-utils monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/promise-utils monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/promise-utils monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'promise-utils test results', testResults: 'libraries/promise-utils/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/promise-utils/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/promise-utils/package.json b/libraries/promise-utils/package.json index 40f05b74cb..f7b3cb8400 100644 --- a/libraries/promise-utils/package.json +++ b/libraries/promise-utils/package.json @@ -19,6 +19,8 @@ "chai": "^4.3.10", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" }, "dependencies": { diff --git a/libraries/promise-utils/test/mocha-multi-reporters.cjs b/libraries/promise-utils/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/libraries/promise-utils/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/libraries/ranges-tracker/.mocharc.cjs b/libraries/ranges-tracker/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/libraries/ranges-tracker/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/libraries/ranges-tracker/Jenkinsfile b/libraries/ranges-tracker/Jenkinsfile new file mode 100644 index 0000000000..c94e6241dc --- /dev/null +++ b/libraries/ranges-tracker/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/ranges-tracker/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/ranges-tracker monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/ranges-tracker/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'ranges-tracker-eslint', name: 'ranges-tracker eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/ranges-tracker/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/ranges-tracker monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/ranges-tracker monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/ranges-tracker monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'ranges-tracker test results', testResults: 'libraries/ranges-tracker/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/ranges-tracker/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/ranges-tracker/package.json b/libraries/ranges-tracker/package.json index 8aa0a00606..ad502cd5b2 100644 --- a/libraries/ranges-tracker/package.json +++ b/libraries/ranges-tracker/package.json @@ -21,6 +21,8 @@ "devDependencies": { "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } } diff --git a/libraries/ranges-tracker/test/mocha-multi-reporters.cjs b/libraries/ranges-tracker/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/libraries/ranges-tracker/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/libraries/redis-wrapper/.mocharc.cjs b/libraries/redis-wrapper/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/libraries/redis-wrapper/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/libraries/redis-wrapper/.mocharc.json b/libraries/redis-wrapper/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/libraries/redis-wrapper/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/libraries/redis-wrapper/Jenkinsfile b/libraries/redis-wrapper/Jenkinsfile new file mode 100644 index 0000000000..f136b65606 --- /dev/null +++ b/libraries/redis-wrapper/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/redis-wrapper/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/redis-wrapper monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/redis-wrapper/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'redis-wrapper-eslint', name: 'redis-wrapper eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/redis-wrapper/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/redis-wrapper monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/redis-wrapper monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/redis-wrapper monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'redis-wrapper test results', testResults: 'libraries/redis-wrapper/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/redis-wrapper/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/redis-wrapper/package.json b/libraries/redis-wrapper/package.json index 2f15cb062f..39bcbb454c 100644 --- a/libraries/redis-wrapper/package.json +++ b/libraries/redis-wrapper/package.json @@ -36,6 +36,8 @@ "@overleaf/o-error": "*", "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "typescript": "^5.0.4" diff --git a/libraries/redis-wrapper/test/mocha-multi-reporters.cjs b/libraries/redis-wrapper/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/libraries/redis-wrapper/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/libraries/settings/Jenkinsfile b/libraries/settings/Jenkinsfile new file mode 100644 index 0000000000..042c0c6c18 --- /dev/null +++ b/libraries/settings/Jenkinsfile @@ -0,0 +1,72 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/settings/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/settings monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/settings/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'settings-eslint', name: 'settings eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/settings/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/settings monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/settings monorepo npm run types:check' + } + } + } + } + } + post { + cleanup { + sh 'rm -rf libraries/settings/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/settings/package.json b/libraries/settings/package.json index 5ddb514613..c0ed118391 100644 --- a/libraries/settings/package.json +++ b/libraries/settings/package.json @@ -16,6 +16,8 @@ }, "devDependencies": { "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } } diff --git a/libraries/stream-utils/.mocharc.cjs b/libraries/stream-utils/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/libraries/stream-utils/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/libraries/stream-utils/.mocharc.json b/libraries/stream-utils/.mocharc.json deleted file mode 100644 index 3be9ee53ae..0000000000 --- a/libraries/stream-utils/.mocharc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "ui": "bdd", - "recursive": "true", - "reporter": "spec" -} diff --git a/libraries/stream-utils/Jenkinsfile b/libraries/stream-utils/Jenkinsfile new file mode 100644 index 0000000000..69d6fabf32 --- /dev/null +++ b/libraries/stream-utils/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/stream-utils/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/stream-utils monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/stream-utils/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'stream-utils-eslint', name: 'stream-utils eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/stream-utils/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/stream-utils monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/stream-utils monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/stream-utils monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'stream-utils test results', testResults: 'libraries/stream-utils/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/stream-utils/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/stream-utils/package.json b/libraries/stream-utils/package.json index 686084a5e6..c197ff767e 100644 --- a/libraries/stream-utils/package.json +++ b/libraries/stream-utils/package.json @@ -19,6 +19,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } } diff --git a/libraries/stream-utils/test/mocha-multi-reporters.cjs b/libraries/stream-utils/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/libraries/stream-utils/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/libraries/validation-tools/Jenkinsfile b/libraries/validation-tools/Jenkinsfile new file mode 100644 index 0000000000..f19d14dd35 --- /dev/null +++ b/libraries/validation-tools/Jenkinsfile @@ -0,0 +1,82 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Install monorepo') { + steps { + retry(count: 3) { + sh 'make monorepo_setup' + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir libraries/validation-tools/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Lint') { + steps { + sh 'bin/run -w /overleaf/libraries/validation-tools monorepo npm run lint -- --format json --output-file reports/eslint.json' + } + post { + always { + sh """ + sed -i 's_"filePath":"/overleaf_"filePath":"/workspace_g' libraries/validation-tools/reports/eslint.json + """ + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'validation-tools-eslint', name: 'validation-tools eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'libraries/validation-tools/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + sh 'bin/run -w /overleaf/libraries/validation-tools monorepo npm run format' + } + } + stage('Typecheck') { + steps { + sh 'bin/run -w /overleaf/libraries/validation-tools monorepo npm run types:check' + } + } + stage('Test') { + steps { + retry(count: 3) { + sh 'bin/run -w /overleaf/libraries/validation-tools monorepo npm run test:ci' + } + } + } + } + } + } + post { + always { + junit checksName: 'validation-tools test results', testResults: 'libraries/validation-tools/reports/junit-*.xml' + } + cleanup { + sh 'rm -rf libraries/validation-tools/reports' + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/libraries/validation-tools/package.json b/libraries/validation-tools/package.json index c84fb217ce..a82bfc2519 100644 --- a/libraries/validation-tools/package.json +++ b/libraries/validation-tools/package.json @@ -16,7 +16,7 @@ "lint": "eslint --ext .js --ext .cjs --ext .ts --max-warnings 0 --format unix .", "lint:fix": "eslint --fix --ext .js --ext .cjs --ext .ts .", "test:ci": "npm run test:unit", - "test:unit": "vitest test/unit --isolate=false", + "test:unit": "vitest --config vitest.config.ts", "types:check": "tsc --noEmit" }, "dependencies": { diff --git a/libraries/validation-tools/vitest.config.ts b/libraries/validation-tools/vitest.config.ts new file mode 100644 index 0000000000..c19ff9733a --- /dev/null +++ b/libraries/validation-tools/vitest.config.ts @@ -0,0 +1,25 @@ +import { defineConfig, ViteUserConfig } from 'vitest/config' + +let reporterOptions: ViteUserConfig['test'] = {} +if (process.env.CI) { + reporterOptions = { + reporters: [ + 'default', + [ + 'junit', + { + classnameTemplate: `Unit tests.{filename}`, + }, + ], + ], + outputFile: 'reports/junit-vitest-unit.xml', + } +} +export default defineConfig({ + test: { + include: ['test/unit/**/*.test.{js,ts}'], + setupFiles: ['./test/setup.js'], + isolate: false, + ...reporterOptions, + }, +}) diff --git a/package-lock.json b/package-lock.json index 3c790f2cc9..30e42d79d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,6 +100,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "typescript": "^5.0.4" } @@ -184,6 +186,8 @@ "chai-as-promised": "^7.1.1", "express": "^4.21.2", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } }, @@ -200,6 +204,8 @@ "devDependencies": { "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "sinon-chai": "^3.7.0", @@ -229,6 +235,8 @@ "bunyan": "^1.0.0", "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "typescript": "^5.0.4" @@ -265,6 +273,8 @@ "devDependencies": { "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "sinon-chai": "^3.7.0", @@ -280,6 +290,8 @@ "@types/node": "^18.19.123", "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } }, @@ -316,6 +328,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "mock-fs": "^5.2.0", "mongodb": "6.12.0", "sandboxed-module": "^2.0.4", @@ -339,6 +353,8 @@ "@types/path-browserify": "^1.0.3", "chai": "^3.3.0", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sinon": "^9.2.4", "typescript": "^5.0.4" } @@ -394,6 +410,8 @@ "devDependencies": { "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } }, @@ -408,6 +426,8 @@ "chai": "^4.3.10", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } }, @@ -460,6 +480,8 @@ "devDependencies": { "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } }, @@ -476,6 +498,8 @@ "@overleaf/o-error": "*", "chai": "^4.3.6", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "typescript": "^5.0.4" @@ -491,6 +515,8 @@ "version": "3.0.0", "devDependencies": { "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } }, @@ -502,6 +528,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } }, @@ -50790,6 +50818,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sequelize-cli": "^6.6.0", "sinon": "^9.2.4", @@ -50832,6 +50862,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "request": "^2.88.2", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", @@ -50866,6 +50898,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "mock-fs": "^5.1.2", "node-fetch": "^2.7.0", "sandboxed-module": "^2.0.4", @@ -50894,7 +50928,9 @@ "devDependencies": { "chai": "^4.3.6", "chai-as-promised": "^7.1.1", - "mocha": "^11.1.0" + "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1" } }, "services/clsi-perf": { @@ -50915,6 +50951,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } }, @@ -50986,6 +51024,8 @@ "chai-as-promised": "^7.1.1", "esmock": "^2.6.3", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sinon": "~9.0.1", "sinon-chai": "^3.7.0", "typescript": "^5.0.4" @@ -51057,6 +51097,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "~2.0.4", "sinon": "~9.0.2", "sinon-chai": "^3.7.0", @@ -51133,6 +51175,8 @@ "chai-as-promised": "^7.1.1", "cluster-key-slot": "^1.0.5", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "sinon-chai": "^3.7.0", @@ -51164,6 +51208,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "mongodb": "6.12.0", "sandboxed-module": "2.0.4", "sinon": "9.0.2", @@ -51228,6 +51274,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } }, @@ -51259,6 +51307,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "sinon-chai": "^3.7.0", @@ -51393,6 +51443,8 @@ "chai-as-promised": "^7.1.1", "chai-exclude": "^2.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "node-fetch": "^2.7.0", "sinon": "^9.0.2", "swagger-client": "^3.10.0", @@ -51632,6 +51684,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } }, @@ -52162,6 +52216,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "nock": "^13.5.3", "sinon": "~9.0.1", "sinon-chai": "^3.7.0", @@ -52237,6 +52293,8 @@ "chai-as-promised": "^7.1.1", "cookie-signature": "^1.1.0", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "~0.3.0", "sinon": "^9.2.4", "sinon-chai": "^3.7.0", @@ -52290,6 +52348,8 @@ "chai-as-promised": "^7.1.1", "esmock": "^2.6.9", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "mongodb": "6.12.0", "sinon": "^9.2.4", "typescript": "^5.0.4" @@ -52328,6 +52388,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "typescript": "^5.0.4" @@ -52360,6 +52422,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "9.0.1", "sinon-chai": "^3.7.0", @@ -52485,6 +52549,8 @@ "chai-as-promised": "^7.1.1", "esmock": "^2.6.3", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sinon": "9.0.2", "sinon-chai": "^3.7.0", "typescript": "^5.0.4" @@ -52554,6 +52620,8 @@ "chai-as-promised": "^7.1.1", "chai-http": "^4.4.0", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "typescript": "^5.0.4" } }, diff --git a/server-ce/test/Jenkinsfile b/server-ce/test/Jenkinsfile index a03ca0da58..b0f45a3fd8 100644 --- a/server-ce/test/Jenkinsfile +++ b/server-ce/test/Jenkinsfile @@ -23,7 +23,7 @@ pipeline { timestamps() // Abort build after hitting first failure. parallelsAlwaysFailFast() - timeout(time: 15, unit: 'MINUTES') + timeout(time: 20, unit: 'MINUTES') } environment { BRANCH_NAME = "${GIT_BRANCH.replace('origin/', '')}" diff --git a/services/chat/.mocharc.cjs b/services/chat/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/services/chat/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/services/chat/.mocharc.json b/services/chat/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/services/chat/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/services/chat/Dockerfile b/services/chat/Dockerfile index 4c060946b3..e29c5c4989 100644 --- a/services/chat/Dockerfile +++ b/services/chat/Dockerfile @@ -13,12 +13,22 @@ RUN mkdir /home/node/.config && chown node:node /home/node/.config FROM base AS app COPY package.json package-lock.json /overleaf/ -COPY services/chat/package.json /overleaf/services/chat/ -COPY libraries/ /overleaf/libraries/ +COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json +COPY libraries/logger/package.json /overleaf/libraries/logger/package.json +COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json +COPY libraries/mongo-utils/package.json /overleaf/libraries/mongo-utils/package.json +COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json +COPY libraries/settings/package.json /overleaf/libraries/settings/package.json +COPY services/chat/package.json /overleaf/services/chat/package.json COPY patches/ /overleaf/patches/ RUN cd /overleaf && npm ci --quiet - +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/mongo-utils/ /overleaf/libraries/mongo-utils/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/settings/ /overleaf/libraries/settings/ COPY services/chat/ /overleaf/services/chat/ FROM app diff --git a/services/chat/Jenkinsfile b/services/chat/Jenkinsfile new file mode 100644 index 0000000000..3c9acb00ab --- /dev/null +++ b/services/chat/Jenkinsfile @@ -0,0 +1,125 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + DOCKER_COMPOSE_FLAGS = '-f docker-compose.ci.yml' + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Build') { + steps { + dir('services/chat') { + retry(count: 3) { + sh 'make build' + } + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir services/chat/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Push Branch Image') { + steps { + dir('services/chat') { + sh 'make push_branch' + } + } + } + stage('Shellcheck') { + steps { + dir('services/chat') { + sh 'make shellcheck' + } + } + } + stage('Lint') { + steps { + dir('services/chat') { + sh 'make lint_ci' + } + } + post { + always { + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'chat-eslint', name: 'chat eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'services/chat/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + dir('services/chat') { + sh 'make format_ci' + } + } + } + stage('Typecheck') { + steps { + dir('services/chat') { + sh 'make typecheck_ci' + } + } + } + stage('Test Unit') { + steps { + dir('services/chat') { + retry(count: 3) { + sh 'make test_unit' + } + } + } + } + stage('Test Acceptance') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance" + } + steps { + dir('services/chat') { + retry(count: 3) { + sh 'make test_acceptance' + } + } + } + } + } + } + stage('Push Production') { + steps { + dir('services/chat') { + sh 'make push' + } + } + } + } + post { + always { + junit checksName: 'chat test results', testResults: 'services/chat/reports/junit-*.xml' + } + cleanup { + dir('services/chat') { + sh 'make clean' + } + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/services/chat/Makefile b/services/chat/Makefile index 8b06470cc1..58b95620cf 100644 --- a/services/chat/Makefile +++ b/services/chat/Makefile @@ -27,14 +27,15 @@ clean: -docker rmi us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) -$(DOCKER_COMPOSE_TEST_UNIT) down --remove-orphans --rmi local --timeout 0 --volumes -$(DOCKER_COMPOSE_TEST_ACCEPTANCE) down --remove-orphans --rmi local --timeout 0 --volumes + -rm -rf reports/ HERE=$(shell pwd) -MONOREPO=$(shell cd ../../ && pwd) +export MONOREPO ?= $(shell cd ../../ && pwd) # Run the linting commands in the scope of the monorepo. # Eslint and prettier (plus some configs) are on the root. RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent -RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent +RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/chat/reports:/overleaf/services/chat/reports ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent # Same but from the top of the monorepo RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent @@ -70,7 +71,8 @@ lint: $(RUN_LINTING) lint lint_ci: - $(RUN_LINTING_CI) lint + -$(RUN_LINTING_CI) lint -- --format json --output-file reports/eslint.json + sed -i 's_"filePath":"/overleaf_"filePath":"$(MONOREPO)_g' reports/eslint.json lint_fix: $(RUN_LINTING) lint:fix @@ -137,10 +139,11 @@ build: tar: $(DOCKER_COMPOSE) up tar -publish: - - docker push $(DOCKER_REPO)/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push_branch: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME) .PHONY: clean \ format format_fix \ diff --git a/services/chat/docker-compose.ci.yml b/services/chat/docker-compose.ci.yml index ca087c4b6f..64e75ffc86 100644 --- a/services/chat/docker-compose.ci.yml +++ b/services/chat/docker-compose.ci.yml @@ -7,10 +7,12 @@ services: image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER user: node volumes: + - ./reports:/overleaf/services/chat/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it entrypoint: /overleaf/bin/shared/wait_for_it mongo:27017 --timeout=60 -- command: npm run test:unit:_run environment: + CI: MONGO_CONNECTION_STRING: mongodb://mongo/test-overleaf NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" @@ -23,6 +25,7 @@ services: build: . image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER environment: + CI: ELASTIC_SEARCH_DSN: es:9200 MONGO_HOST: mongo POSTGRES_HOST: postgres @@ -30,6 +33,7 @@ services: NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" volumes: + - ./reports:/overleaf/services/chat/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it depends_on: mongo: diff --git a/services/chat/package.json b/services/chat/package.json index b02f3408ea..1a81f0aaa1 100644 --- a/services/chat/package.json +++ b/services/chat/package.json @@ -9,8 +9,8 @@ "test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP", "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP", "nodemon": "node --watch app.js", - "test:acceptance:_run": "mocha --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js", - "test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js", + "test:acceptance:_run": "mocha --recursive --timeout 15000 --exit $@ test/acceptance/js", + "test:unit:_run": "mocha --recursive --exit $@ test/unit/js", "lint": "eslint --max-warnings 0 --format unix .", "format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'", "format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'", @@ -34,6 +34,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "request": "^2.88.2", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", diff --git a/services/chat/test/mocha-multi-reporters.cjs b/services/chat/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/services/chat/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/services/clsi/.mocharc.cjs b/services/clsi/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/services/clsi/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/services/clsi/.mocharc.json b/services/clsi/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/services/clsi/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/services/clsi/Dockerfile b/services/clsi/Dockerfile index 1ae3c4547c..105e674b31 100644 --- a/services/clsi/Dockerfile +++ b/services/clsi/Dockerfile @@ -17,12 +17,24 @@ RUN mkdir /home/node/.config && chown node:node /home/node/.config FROM base AS app COPY package.json package-lock.json /overleaf/ -COPY services/clsi/package.json /overleaf/services/clsi/ -COPY libraries/ /overleaf/libraries/ +COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json +COPY libraries/logger/package.json /overleaf/libraries/logger/package.json +COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json +COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json +COPY libraries/promise-utils/package.json /overleaf/libraries/promise-utils/package.json +COPY libraries/settings/package.json /overleaf/libraries/settings/package.json +COPY libraries/stream-utils/package.json /overleaf/libraries/stream-utils/package.json +COPY services/clsi/package.json /overleaf/services/clsi/package.json COPY patches/ /overleaf/patches/ RUN cd /overleaf && npm ci --quiet - +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/promise-utils/ /overleaf/libraries/promise-utils/ +COPY libraries/settings/ /overleaf/libraries/settings/ +COPY libraries/stream-utils/ /overleaf/libraries/stream-utils/ COPY services/clsi/ /overleaf/services/clsi/ FROM app diff --git a/services/clsi/Jenkinsfile b/services/clsi/Jenkinsfile new file mode 100644 index 0000000000..e8bf5226dd --- /dev/null +++ b/services/clsi/Jenkinsfile @@ -0,0 +1,125 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + DOCKER_COMPOSE_FLAGS = '-f docker-compose.ci.yml' + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Build') { + steps { + dir('services/clsi') { + retry(count: 3) { + sh 'make build' + } + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir services/clsi/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Push Branch Image') { + steps { + dir('services/clsi') { + sh 'make push_branch' + } + } + } + stage('Shellcheck') { + steps { + dir('services/clsi') { + sh 'make shellcheck' + } + } + } + stage('Lint') { + steps { + dir('services/clsi') { + sh 'make lint_ci' + } + } + post { + always { + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'clsi-eslint', name: 'clsi eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'services/clsi/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + dir('services/clsi') { + sh 'make format_ci' + } + } + } + stage('Typecheck') { + steps { + dir('services/clsi') { + sh 'make typecheck_ci' + } + } + } + stage('Test Unit') { + steps { + dir('services/clsi') { + retry(count: 3) { + sh 'make test_unit' + } + } + } + } + stage('Test Acceptance') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance" + } + steps { + dir('services/clsi') { + retry(count: 3) { + sh 'make test_acceptance' + } + } + } + } + } + } + stage('Push Production') { + steps { + dir('services/clsi') { + sh 'make push' + } + } + } + } + post { + always { + junit checksName: 'clsi test results', testResults: 'services/clsi/reports/junit-*.xml' + } + cleanup { + dir('services/clsi') { + sh 'make clean' + } + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/services/clsi/Makefile b/services/clsi/Makefile index 20273fc5d0..8f90e0dfca 100644 --- a/services/clsi/Makefile +++ b/services/clsi/Makefile @@ -27,15 +27,16 @@ clean: -docker rmi us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) -$(DOCKER_COMPOSE_TEST_UNIT) down --remove-orphans --rmi local --timeout 0 --volumes -$(DOCKER_COMPOSE_TEST_ACCEPTANCE) down --remove-orphans --rmi local --timeout 0 --volumes + -rm -rf reports/ -git clean -dfX cache compiles output HERE=$(shell pwd) -MONOREPO=$(shell cd ../../ && pwd) +export MONOREPO ?= $(shell cd ../../ && pwd) # Run the linting commands in the scope of the monorepo. # Eslint and prettier (plus some configs) are on the root. RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent -RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent +RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/clsi/reports:/overleaf/services/clsi/reports ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent # Same but from the top of the monorepo RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent @@ -71,7 +72,8 @@ lint: $(RUN_LINTING) lint lint_ci: - $(RUN_LINTING_CI) lint + -$(RUN_LINTING_CI) lint -- --format json --output-file reports/eslint.json + sed -i 's_"filePath":"/overleaf_"filePath":"$(MONOREPO)_g' reports/eslint.json lint_fix: $(RUN_LINTING) lint:fix @@ -138,10 +140,11 @@ build: tar: $(DOCKER_COMPOSE) up tar -publish: - - docker push $(DOCKER_REPO)/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push_branch: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME) .PHONY: clean \ format format_fix \ diff --git a/services/clsi/bin/acceptance_test b/services/clsi/bin/acceptance_test index fd2e5137b5..0750d76ac8 100644 --- a/services/clsi/bin/acceptance_test +++ b/services/clsi/bin/acceptance_test @@ -1,4 +1,4 @@ #!/bin/bash set -e; -MOCHA="node_modules/.bin/mocha --recursive --reporter spec --timeout 15000" +MOCHA="node_modules/.bin/mocha --recursive --timeout 15000" $MOCHA "$@" diff --git a/services/clsi/docker-compose.ci.yml b/services/clsi/docker-compose.ci.yml index 081ac2bc32..0e9c29270f 100644 --- a/services/clsi/docker-compose.ci.yml +++ b/services/clsi/docker-compose.ci.yml @@ -7,6 +7,7 @@ services: image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER command: npm run test:unit:_run environment: + CI: MONGO_CONNECTION_STRING: mongodb://mongo/test-overleaf NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" @@ -16,6 +17,7 @@ services: build: . image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER environment: + CI: ELASTIC_SEARCH_DSN: es:9200 MONGO_HOST: mongo POSTGRES_HOST: postgres @@ -32,6 +34,7 @@ services: SANDBOXED_COMPILES_HOST_DIR_COMPILES: $PWD/compiles SANDBOXED_COMPILES_HOST_DIR_OUTPUT: $PWD/output volumes: + - ./reports:/overleaf/services/clsi/reports - ./compiles:/overleaf/services/clsi/compiles - /var/run/docker.sock:/var/run/docker.sock command: npm run test:acceptance diff --git a/services/clsi/package.json b/services/clsi/package.json index 00e89b93d4..fb30e2b4e7 100644 --- a/services/clsi/package.json +++ b/services/clsi/package.json @@ -5,9 +5,9 @@ "main": "app.js", "scripts": { "start": "node app.js", - "test:acceptance:_run": "mocha --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js", + "test:acceptance:_run": "mocha --recursive --timeout 15000 --exit $@ test/acceptance/js", "test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP", - "test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js", + "test:unit:_run": "mocha --recursive --exit $@ test/unit/js", "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP", "nodemon": "node --watch app.js", "lint": "eslint --max-warnings 0 --format unix .", @@ -41,6 +41,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "mock-fs": "^5.1.2", "node-fetch": "^2.7.0", "sandboxed-module": "^2.0.4", diff --git a/services/clsi/test/mocha-multi-reporters.cjs b/services/clsi/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/services/clsi/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/services/contacts/.mocharc.cjs b/services/contacts/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/services/contacts/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/services/contacts/.mocharc.json b/services/contacts/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/services/contacts/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/services/contacts/Dockerfile b/services/contacts/Dockerfile index 58ab0ca8ee..f72764db69 100644 --- a/services/contacts/Dockerfile +++ b/services/contacts/Dockerfile @@ -13,12 +13,22 @@ RUN mkdir /home/node/.config && chown node:node /home/node/.config FROM base AS app COPY package.json package-lock.json /overleaf/ -COPY services/contacts/package.json /overleaf/services/contacts/ -COPY libraries/ /overleaf/libraries/ +COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json +COPY libraries/logger/package.json /overleaf/libraries/logger/package.json +COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json +COPY libraries/mongo-utils/package.json /overleaf/libraries/mongo-utils/package.json +COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json +COPY libraries/settings/package.json /overleaf/libraries/settings/package.json +COPY services/contacts/package.json /overleaf/services/contacts/package.json COPY patches/ /overleaf/patches/ RUN cd /overleaf && npm ci --quiet - +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/mongo-utils/ /overleaf/libraries/mongo-utils/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/settings/ /overleaf/libraries/settings/ COPY services/contacts/ /overleaf/services/contacts/ FROM app diff --git a/services/contacts/Jenkinsfile b/services/contacts/Jenkinsfile index 6a0aa9fd3b..cc2e0bbd9b 100644 --- a/services/contacts/Jenkinsfile +++ b/services/contacts/Jenkinsfile @@ -1,3 +1,5 @@ +// Autogenerated by build scripts. Do not edit. + pipeline { agent { node { @@ -7,16 +9,9 @@ pipeline { } options { timestamps() - parallelsAlwaysFailFast() - retry(3) timeout(time: 15, unit: 'MINUTES') } environment { - IMAGE_NAME = 'contacts' - PROJECT_NAME = 'contacts' - IMAGE_REPO = 'us-east1-docker.pkg.dev/overleaf-ops/ol-docker/contacts' - AR_REPO_LOCATION = 'us-east1' - AR_URL = 'us-east1-docker.pkg.dev/overleaf-ops/ol-docker' BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" @@ -25,61 +20,84 @@ pipeline { SHORT_SHA = "${GIT_COMMIT.take(7)}" } stages { - stage ('Build') { - steps { - dir ('services/contacts') { - sh 'make build' - } - } - } - stage ('Tests') { + stage('Stage 1') { parallel { - stage ('Push Branch Image') { + stage('Build') { steps { - dir ('services/contacts') { - sh 'docker push ${AR_URL}/${IMAGE_NAME}:${BRANCH_NAME}' + dir('services/contacts') { + retry(count: 3) { + sh 'make build' + } } } } - stage ('Shellcheck') { + stage('Create reports folder') { steps { - dir ('services/contacts') { + sh 'mkdir services/contacts/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Push Branch Image') { + steps { + dir('services/contacts') { + sh 'make push_branch' + } + } + } + stage('Shellcheck') { + steps { + dir('services/contacts') { sh 'make shellcheck' } } } - stage ('Lint') { + stage('Lint') { steps { - dir ('services/contacts') { + dir('services/contacts') { sh 'make lint_ci' } } + post { + always { + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'contacts-eslint', name: 'contacts eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'services/contacts/reports/eslint.json')] + } + } } - stage ('Format') { + stage('Format') { steps { - dir ('services/contacts') { + dir('services/contacts') { sh 'make format_ci' } } } - stage ('Typecheck') { + stage('Typecheck') { steps { - dir ('services/contacts') { + dir('services/contacts') { sh 'make typecheck_ci' } } } - stage ('Test Unit') { + stage('Test Unit') { steps { - dir ('services/contacts') { - sh 'make test_unit' + dir('services/contacts') { + retry(count: 3) { + sh 'make test_unit' + } } } } - stage ('Test Acceptance') { + stage('Test Acceptance') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance" + } steps { - dir ('services/contacts') { - sh 'make test_acceptance' + dir('services/contacts') { + retry(count: 3) { + sh 'make test_acceptance' + } } } } @@ -88,12 +106,15 @@ pipeline { stage('Push Production') { steps { dir('services/contacts') { - sh 'docker push ${AR_URL}/${IMAGE_NAME}:${BRANCH_NAME}-${BUILD_NUMBER}' + sh 'make push' } } } } post { + always { + junit checksName: 'contacts test results', testResults: 'services/contacts/reports/junit-*.xml' + } cleanup { dir('services/contacts') { sh 'make clean' diff --git a/services/contacts/Makefile b/services/contacts/Makefile index e32afc73ad..2e3192dd9c 100644 --- a/services/contacts/Makefile +++ b/services/contacts/Makefile @@ -27,14 +27,15 @@ clean: -docker rmi us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) -$(DOCKER_COMPOSE_TEST_UNIT) down --remove-orphans --rmi local --timeout 0 --volumes -$(DOCKER_COMPOSE_TEST_ACCEPTANCE) down --remove-orphans --rmi local --timeout 0 --volumes + -rm -rf reports/ HERE=$(shell pwd) -MONOREPO=$(shell cd ../../ && pwd) +export MONOREPO ?= $(shell cd ../../ && pwd) # Run the linting commands in the scope of the monorepo. # Eslint and prettier (plus some configs) are on the root. RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent -RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent +RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/contacts/reports:/overleaf/services/contacts/reports ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent # Same but from the top of the monorepo RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent @@ -70,7 +71,8 @@ lint: $(RUN_LINTING) lint lint_ci: - $(RUN_LINTING_CI) lint + -$(RUN_LINTING_CI) lint -- --format json --output-file reports/eslint.json + sed -i 's_"filePath":"/overleaf_"filePath":"$(MONOREPO)_g' reports/eslint.json lint_fix: $(RUN_LINTING) lint:fix @@ -137,10 +139,11 @@ build: tar: $(DOCKER_COMPOSE) up tar -publish: - - docker push $(DOCKER_REPO)/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push_branch: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME) .PHONY: clean \ format format_fix \ diff --git a/services/contacts/docker-compose.ci.yml b/services/contacts/docker-compose.ci.yml index ca087c4b6f..690a4fd39e 100644 --- a/services/contacts/docker-compose.ci.yml +++ b/services/contacts/docker-compose.ci.yml @@ -7,10 +7,12 @@ services: image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER user: node volumes: + - ./reports:/overleaf/services/contacts/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it entrypoint: /overleaf/bin/shared/wait_for_it mongo:27017 --timeout=60 -- command: npm run test:unit:_run environment: + CI: MONGO_CONNECTION_STRING: mongodb://mongo/test-overleaf NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" @@ -23,6 +25,7 @@ services: build: . image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER environment: + CI: ELASTIC_SEARCH_DSN: es:9200 MONGO_HOST: mongo POSTGRES_HOST: postgres @@ -30,6 +33,7 @@ services: NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" volumes: + - ./reports:/overleaf/services/contacts/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it depends_on: mongo: diff --git a/services/contacts/package.json b/services/contacts/package.json index 32dfa4e5ec..00e4859d81 100644 --- a/services/contacts/package.json +++ b/services/contacts/package.json @@ -6,9 +6,9 @@ "main": "app.js", "scripts": { "start": "node app.js", - "test:acceptance:_run": "mocha --loader=esmock --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js", + "test:acceptance:_run": "mocha --loader=esmock --recursive --timeout 15000 --exit $@ test/acceptance/js", "test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP", - "test:unit:_run": "mocha --loader=esmock --recursive --reporter spec --exit $@ test/unit/js", + "test:unit:_run": "mocha --loader=esmock --recursive --exit $@ test/unit/js", "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP", "nodemon": "node --watch app.js", "lint": "eslint --max-warnings 0 --format unix .", @@ -35,6 +35,8 @@ "chai-as-promised": "^7.1.1", "esmock": "^2.6.3", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sinon": "~9.0.1", "sinon-chai": "^3.7.0", "typescript": "^5.0.4" diff --git a/services/contacts/test/mocha-multi-reporters.cjs b/services/contacts/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/services/contacts/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/services/docstore/.mocharc.cjs b/services/docstore/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/services/docstore/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/services/docstore/.mocharc.json b/services/docstore/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/services/docstore/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/services/docstore/Dockerfile b/services/docstore/Dockerfile index 69c94fa740..524855ebf7 100644 --- a/services/docstore/Dockerfile +++ b/services/docstore/Dockerfile @@ -13,12 +13,28 @@ RUN mkdir /home/node/.config && chown node:node /home/node/.config FROM base AS app COPY package.json package-lock.json /overleaf/ -COPY services/docstore/package.json /overleaf/services/docstore/ -COPY libraries/ /overleaf/libraries/ +COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json +COPY libraries/logger/package.json /overleaf/libraries/logger/package.json +COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json +COPY libraries/mongo-utils/package.json /overleaf/libraries/mongo-utils/package.json +COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json +COPY libraries/object-persistor/package.json /overleaf/libraries/object-persistor/package.json +COPY libraries/promise-utils/package.json /overleaf/libraries/promise-utils/package.json +COPY libraries/settings/package.json /overleaf/libraries/settings/package.json +COPY libraries/stream-utils/package.json /overleaf/libraries/stream-utils/package.json +COPY services/docstore/package.json /overleaf/services/docstore/package.json COPY patches/ /overleaf/patches/ RUN cd /overleaf && npm ci --quiet - +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/mongo-utils/ /overleaf/libraries/mongo-utils/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/object-persistor/ /overleaf/libraries/object-persistor/ +COPY libraries/promise-utils/ /overleaf/libraries/promise-utils/ +COPY libraries/settings/ /overleaf/libraries/settings/ +COPY libraries/stream-utils/ /overleaf/libraries/stream-utils/ COPY services/docstore/ /overleaf/services/docstore/ FROM app diff --git a/services/docstore/Jenkinsfile b/services/docstore/Jenkinsfile new file mode 100644 index 0000000000..d65b9ea01c --- /dev/null +++ b/services/docstore/Jenkinsfile @@ -0,0 +1,125 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + DOCKER_COMPOSE_FLAGS = '-f docker-compose.ci.yml' + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Build') { + steps { + dir('services/docstore') { + retry(count: 3) { + sh 'make build' + } + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir services/docstore/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Push Branch Image') { + steps { + dir('services/docstore') { + sh 'make push_branch' + } + } + } + stage('Shellcheck') { + steps { + dir('services/docstore') { + sh 'make shellcheck' + } + } + } + stage('Lint') { + steps { + dir('services/docstore') { + sh 'make lint_ci' + } + } + post { + always { + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'docstore-eslint', name: 'docstore eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'services/docstore/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + dir('services/docstore') { + sh 'make format_ci' + } + } + } + stage('Typecheck') { + steps { + dir('services/docstore') { + sh 'make typecheck_ci' + } + } + } + stage('Test Unit') { + steps { + dir('services/docstore') { + retry(count: 3) { + sh 'make test_unit' + } + } + } + } + stage('Test Acceptance') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance" + } + steps { + dir('services/docstore') { + retry(count: 3) { + sh 'make test_acceptance' + } + } + } + } + } + } + stage('Push Production') { + steps { + dir('services/docstore') { + sh 'make push' + } + } + } + } + post { + always { + junit checksName: 'docstore test results', testResults: 'services/docstore/reports/junit-*.xml' + } + cleanup { + dir('services/docstore') { + sh 'make clean' + } + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/services/docstore/Makefile b/services/docstore/Makefile index e962102f17..2dce268782 100644 --- a/services/docstore/Makefile +++ b/services/docstore/Makefile @@ -27,14 +27,15 @@ clean: -docker rmi us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) -$(DOCKER_COMPOSE_TEST_UNIT) down --remove-orphans --rmi local --timeout 0 --volumes -$(DOCKER_COMPOSE_TEST_ACCEPTANCE) down --remove-orphans --rmi local --timeout 0 --volumes + -rm -rf reports/ HERE=$(shell pwd) -MONOREPO=$(shell cd ../../ && pwd) +export MONOREPO ?= $(shell cd ../../ && pwd) # Run the linting commands in the scope of the monorepo. # Eslint and prettier (plus some configs) are on the root. RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent -RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent +RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/docstore/reports:/overleaf/services/docstore/reports ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent # Same but from the top of the monorepo RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent @@ -70,7 +71,8 @@ lint: $(RUN_LINTING) lint lint_ci: - $(RUN_LINTING_CI) lint + -$(RUN_LINTING_CI) lint -- --format json --output-file reports/eslint.json + sed -i 's_"filePath":"/overleaf_"filePath":"$(MONOREPO)_g' reports/eslint.json lint_fix: $(RUN_LINTING) lint:fix @@ -137,10 +139,11 @@ build: tar: $(DOCKER_COMPOSE) up tar -publish: - - docker push $(DOCKER_REPO)/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push_branch: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME) .PHONY: clean \ format format_fix \ diff --git a/services/docstore/docker-compose.ci.yml b/services/docstore/docker-compose.ci.yml index 369cff74f6..60244b1480 100644 --- a/services/docstore/docker-compose.ci.yml +++ b/services/docstore/docker-compose.ci.yml @@ -7,10 +7,12 @@ services: image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER user: node volumes: + - ./reports:/overleaf/services/docstore/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it entrypoint: /overleaf/bin/shared/wait_for_it mongo:27017 --timeout=60 -- command: npm run test:unit:_run environment: + CI: MONGO_CONNECTION_STRING: mongodb://mongo/test-overleaf NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" @@ -23,6 +25,7 @@ services: build: . image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER environment: + CI: ELASTIC_SEARCH_DSN: es:9200 MONGO_HOST: mongo POSTGRES_HOST: postgres @@ -33,6 +36,7 @@ services: NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" volumes: + - ./reports:/overleaf/services/docstore/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it depends_on: mongo: diff --git a/services/docstore/package.json b/services/docstore/package.json index 8cc69a868c..e00b829194 100644 --- a/services/docstore/package.json +++ b/services/docstore/package.json @@ -5,9 +5,9 @@ "main": "app.js", "scripts": { "start": "node app.js", - "test:acceptance:_run": "mocha --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js", + "test:acceptance:_run": "mocha --recursive --timeout 15000 --exit $@ test/acceptance/js", "test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP", - "test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js", + "test:unit:_run": "mocha --recursive --exit $@ test/unit/js", "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP", "nodemon": "node --watch app.js", "lint": "eslint --max-warnings 0 --format unix .", @@ -40,6 +40,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "~2.0.4", "sinon": "~9.0.2", "sinon-chai": "^3.7.0", diff --git a/services/docstore/test/mocha-multi-reporters.cjs b/services/docstore/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/services/docstore/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/services/document-updater/.mocharc.cjs b/services/document-updater/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/services/document-updater/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/services/document-updater/.mocharc.json b/services/document-updater/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/services/document-updater/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/services/document-updater/Dockerfile b/services/document-updater/Dockerfile index da7657f5cd..147655394e 100644 --- a/services/document-updater/Dockerfile +++ b/services/document-updater/Dockerfile @@ -13,12 +13,30 @@ RUN mkdir /home/node/.config && chown node:node /home/node/.config FROM base AS app COPY package.json package-lock.json /overleaf/ -COPY services/document-updater/package.json /overleaf/services/document-updater/ -COPY libraries/ /overleaf/libraries/ +COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json +COPY libraries/logger/package.json /overleaf/libraries/logger/package.json +COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json +COPY libraries/mongo-utils/package.json /overleaf/libraries/mongo-utils/package.json +COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json +COPY libraries/overleaf-editor-core/package.json /overleaf/libraries/overleaf-editor-core/package.json +COPY libraries/promise-utils/package.json /overleaf/libraries/promise-utils/package.json +COPY libraries/ranges-tracker/package.json /overleaf/libraries/ranges-tracker/package.json +COPY libraries/redis-wrapper/package.json /overleaf/libraries/redis-wrapper/package.json +COPY libraries/settings/package.json /overleaf/libraries/settings/package.json +COPY services/document-updater/package.json /overleaf/services/document-updater/package.json COPY patches/ /overleaf/patches/ RUN cd /overleaf && npm ci --quiet - +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/mongo-utils/ /overleaf/libraries/mongo-utils/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/overleaf-editor-core/ /overleaf/libraries/overleaf-editor-core/ +COPY libraries/promise-utils/ /overleaf/libraries/promise-utils/ +COPY libraries/ranges-tracker/ /overleaf/libraries/ranges-tracker/ +COPY libraries/redis-wrapper/ /overleaf/libraries/redis-wrapper/ +COPY libraries/settings/ /overleaf/libraries/settings/ COPY services/document-updater/ /overleaf/services/document-updater/ FROM app diff --git a/services/document-updater/Jenkinsfile b/services/document-updater/Jenkinsfile new file mode 100644 index 0000000000..4fc65a036a --- /dev/null +++ b/services/document-updater/Jenkinsfile @@ -0,0 +1,125 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + DOCKER_COMPOSE_FLAGS = '-f docker-compose.ci.yml' + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Build') { + steps { + dir('services/document-updater') { + retry(count: 3) { + sh 'make build' + } + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir services/document-updater/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Push Branch Image') { + steps { + dir('services/document-updater') { + sh 'make push_branch' + } + } + } + stage('Shellcheck') { + steps { + dir('services/document-updater') { + sh 'make shellcheck' + } + } + } + stage('Lint') { + steps { + dir('services/document-updater') { + sh 'make lint_ci' + } + } + post { + always { + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'document-updater-eslint', name: 'document-updater eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'services/document-updater/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + dir('services/document-updater') { + sh 'make format_ci' + } + } + } + stage('Typecheck') { + steps { + dir('services/document-updater') { + sh 'make typecheck_ci' + } + } + } + stage('Test Unit') { + steps { + dir('services/document-updater') { + retry(count: 3) { + sh 'make test_unit' + } + } + } + } + stage('Test Acceptance') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance" + } + steps { + dir('services/document-updater') { + retry(count: 3) { + sh 'make test_acceptance' + } + } + } + } + } + } + stage('Push Production') { + steps { + dir('services/document-updater') { + sh 'make push' + } + } + } + } + post { + always { + junit checksName: 'document-updater test results', testResults: 'services/document-updater/reports/junit-*.xml' + } + cleanup { + dir('services/document-updater') { + sh 'make clean' + } + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/services/document-updater/Makefile b/services/document-updater/Makefile index d16c201e36..e23d5ce1ae 100644 --- a/services/document-updater/Makefile +++ b/services/document-updater/Makefile @@ -27,14 +27,15 @@ clean: -docker rmi us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) -$(DOCKER_COMPOSE_TEST_UNIT) down --remove-orphans --rmi local --timeout 0 --volumes -$(DOCKER_COMPOSE_TEST_ACCEPTANCE) down --remove-orphans --rmi local --timeout 0 --volumes + -rm -rf reports/ HERE=$(shell pwd) -MONOREPO=$(shell cd ../../ && pwd) +export MONOREPO ?= $(shell cd ../../ && pwd) # Run the linting commands in the scope of the monorepo. # Eslint and prettier (plus some configs) are on the root. RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent -RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent +RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/document-updater/reports:/overleaf/services/document-updater/reports ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent # Same but from the top of the monorepo RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent @@ -70,7 +71,8 @@ lint: $(RUN_LINTING) lint lint_ci: - $(RUN_LINTING_CI) lint + -$(RUN_LINTING_CI) lint -- --format json --output-file reports/eslint.json + sed -i 's_"filePath":"/overleaf_"filePath":"$(MONOREPO)_g' reports/eslint.json lint_fix: $(RUN_LINTING) lint:fix @@ -137,10 +139,11 @@ build: tar: $(DOCKER_COMPOSE) up tar -publish: - - docker push $(DOCKER_REPO)/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push_branch: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME) .PHONY: clean \ format format_fix \ diff --git a/services/document-updater/docker-compose.ci.yml b/services/document-updater/docker-compose.ci.yml index 73874aaf3f..143a0e5e7c 100644 --- a/services/document-updater/docker-compose.ci.yml +++ b/services/document-updater/docker-compose.ci.yml @@ -7,10 +7,12 @@ services: image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER user: node volumes: + - ./reports:/overleaf/services/document-updater/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it entrypoint: /overleaf/bin/shared/wait_for_it mongo:27017 --timeout=60 -- command: npm run test:unit:_run environment: + CI: MONGO_CONNECTION_STRING: mongodb://mongo/test-overleaf NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" @@ -29,6 +31,7 @@ services: build: . image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER environment: + CI: ELASTIC_SEARCH_DSN: es:9200 REDIS_HOST: redis_test QUEUES_REDIS_HOST: redis_test @@ -40,6 +43,7 @@ services: NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" volumes: + - ./reports:/overleaf/services/document-updater/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it depends_on: mongo: diff --git a/services/document-updater/package.json b/services/document-updater/package.json index bc2c1c6580..9d419cbf1d 100644 --- a/services/document-updater/package.json +++ b/services/document-updater/package.json @@ -5,9 +5,9 @@ "main": "app.js", "scripts": { "start": "node app.js", - "test:acceptance:_run": "mocha --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js", + "test:acceptance:_run": "mocha --recursive --timeout 15000 --exit $@ test/acceptance/js", "test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP", - "test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js", + "test:unit:_run": "mocha --recursive --exit $@ test/unit/js", "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP", "nodemon": "node --watch app.js", "benchmark:apply": "node benchmarks/apply", @@ -45,6 +45,8 @@ "chai-as-promised": "^7.1.1", "cluster-key-slot": "^1.0.5", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "^2.0.4", "sinon": "^9.2.4", "sinon-chai": "^3.7.0", diff --git a/services/document-updater/test/mocha-multi-reporters.cjs b/services/document-updater/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/services/document-updater/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/services/filestore/.mocharc.cjs b/services/filestore/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/services/filestore/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/services/filestore/.mocharc.json b/services/filestore/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/services/filestore/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/services/filestore/Dockerfile b/services/filestore/Dockerfile index c3e7c19ef7..6457b04c6b 100644 --- a/services/filestore/Dockerfile +++ b/services/filestore/Dockerfile @@ -15,12 +15,24 @@ RUN mkdir /home/node/.config && chown node:node /home/node/.config FROM base AS app COPY package.json package-lock.json /overleaf/ -COPY services/filestore/package.json /overleaf/services/filestore/ -COPY libraries/ /overleaf/libraries/ +COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json +COPY libraries/logger/package.json /overleaf/libraries/logger/package.json +COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json +COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json +COPY libraries/object-persistor/package.json /overleaf/libraries/object-persistor/package.json +COPY libraries/settings/package.json /overleaf/libraries/settings/package.json +COPY libraries/stream-utils/package.json /overleaf/libraries/stream-utils/package.json +COPY services/filestore/package.json /overleaf/services/filestore/package.json COPY patches/ /overleaf/patches/ RUN cd /overleaf && npm ci --quiet - +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/object-persistor/ /overleaf/libraries/object-persistor/ +COPY libraries/settings/ /overleaf/libraries/settings/ +COPY libraries/stream-utils/ /overleaf/libraries/stream-utils/ COPY services/filestore/ /overleaf/services/filestore/ FROM app diff --git a/services/filestore/Jenkinsfile b/services/filestore/Jenkinsfile new file mode 100644 index 0000000000..566164075c --- /dev/null +++ b/services/filestore/Jenkinsfile @@ -0,0 +1,152 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + DOCKER_COMPOSE_FLAGS = '-f docker-compose.ci.yml' + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Build') { + steps { + dir('services/filestore') { + retry(count: 3) { + sh 'make build' + } + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir services/filestore/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Push Branch Image') { + steps { + dir('services/filestore') { + sh 'make push_branch' + } + } + } + stage('Shellcheck') { + steps { + dir('services/filestore') { + sh 'make shellcheck' + } + } + } + stage('Lint') { + steps { + dir('services/filestore') { + sh 'make lint_ci' + } + } + post { + always { + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'filestore-eslint', name: 'filestore eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'services/filestore/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + dir('services/filestore') { + sh 'make format_ci' + } + } + } + stage('Typecheck') { + steps { + dir('services/filestore') { + sh 'make typecheck_ci' + } + } + } + stage('Test Unit') { + steps { + dir('services/filestore') { + retry(count: 3) { + sh 'make test_unit' + } + } + } + } + stage('Test Acceptance SHARD_01_') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance_shard_01_x" + MOCHA_GREP = "SHARD_01_" + } + steps { + dir('services/filestore') { + retry(count: 3) { + sh 'make test_acceptance' + } + } + } + } + stage('Test Acceptance SHARD_02_') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance_shard_02_x" + MOCHA_GREP = "SHARD_02_" + } + steps { + dir('services/filestore') { + retry(count: 3) { + sh 'make test_acceptance' + } + } + } + } + stage('Test Acceptance SHARD_03_') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance_shard_03_x" + MOCHA_GREP = "SHARD_03_" + } + steps { + dir('services/filestore') { + retry(count: 3) { + sh 'make test_acceptance' + } + } + } + } + } + } + stage('Push Production') { + steps { + dir('services/filestore') { + sh 'make push' + } + } + } + } + post { + always { + junit checksName: 'filestore test results', testResults: 'services/filestore/reports/junit-*.xml' + } + cleanup { + dir('services/filestore') { + sh 'make clean' + } + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/services/filestore/Makefile b/services/filestore/Makefile index db81b280ea..3ac96011c6 100644 --- a/services/filestore/Makefile +++ b/services/filestore/Makefile @@ -27,15 +27,16 @@ clean: -docker rmi us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) -$(DOCKER_COMPOSE_TEST_UNIT) down --remove-orphans --rmi local --timeout 0 --volumes -$(DOCKER_COMPOSE_TEST_ACCEPTANCE) down --remove-orphans --rmi local --timeout 0 --volumes + -rm -rf reports/ -git clean -dfX uploads template_files HERE=$(shell pwd) -MONOREPO=$(shell cd ../../ && pwd) +export MONOREPO ?= $(shell cd ../../ && pwd) # Run the linting commands in the scope of the monorepo. # Eslint and prettier (plus some configs) are on the root. RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent -RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent +RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/filestore/reports:/overleaf/services/filestore/reports ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent # Same but from the top of the monorepo RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent @@ -71,7 +72,8 @@ lint: $(RUN_LINTING) lint lint_ci: - $(RUN_LINTING_CI) lint + -$(RUN_LINTING_CI) lint -- --format json --output-file reports/eslint.json + sed -i 's_"filePath":"/overleaf_"filePath":"$(MONOREPO)_g' reports/eslint.json lint_fix: $(RUN_LINTING) lint:fix @@ -138,10 +140,11 @@ build: tar: $(DOCKER_COMPOSE) up tar -publish: - - docker push $(DOCKER_REPO)/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push_branch: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME) .PHONY: clean \ format format_fix \ diff --git a/services/filestore/docker-compose.ci.yml b/services/filestore/docker-compose.ci.yml index c9660b92a5..53c0a0cc3f 100644 --- a/services/filestore/docker-compose.ci.yml +++ b/services/filestore/docker-compose.ci.yml @@ -11,6 +11,7 @@ services: user: node command: npm run test:unit:_run environment: + CI: MONGO_CONNECTION_STRING: mongodb://mongo/test-overleaf NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" @@ -20,6 +21,7 @@ services: build: . image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER environment: + CI: ELASTIC_SEARCH_DSN: es:9200 MONGO_HOST: mongo POSTGRES_HOST: postgres @@ -45,6 +47,7 @@ services: GCS_USER_FILES_BUCKET_NAME: fake-gcs-user-files GCS_TEMPLATE_FILES_BUCKET_NAME: fake-gcs-template-files volumes: + - ./reports:/overleaf/services/filestore/reports - minio-certs:/certs depends_on: certs: diff --git a/services/filestore/package.json b/services/filestore/package.json index 7e234a12f5..5fae71d091 100644 --- a/services/filestore/package.json +++ b/services/filestore/package.json @@ -4,17 +4,17 @@ "private": true, "main": "app.js", "scripts": { - "test:acceptance:run": "mocha --recursive --reporter spec --timeout 15000 $@ test/acceptance/js", + "test:acceptance:run": "mocha --recursive --timeout 15000 $@ test/acceptance/js", "test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP", - "test:unit:run": "mocha --recursive --reporter spec $@ test/unit/js", + "test:unit:run": "mocha --recursive $@ test/unit/js", "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP", "start": "node app.js", "nodemon": "node --watch app.js", "lint": "eslint --max-warnings 0 --format unix .", "format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'", "format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'", - "test:acceptance:_run": "mocha --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js", - "test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js", + "test:acceptance:_run": "mocha --recursive --timeout 15000 --exit $@ test/acceptance/js", + "test:unit:_run": "mocha --recursive --exit $@ test/unit/js", "lint:fix": "eslint --fix .", "types:check": "tsc --noEmit" }, @@ -40,6 +40,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "mongodb": "6.12.0", "sandboxed-module": "2.0.4", "sinon": "9.0.2", diff --git a/services/filestore/test/mocha-multi-reporters.cjs b/services/filestore/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/services/filestore/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/services/history-v1/.mocharc.cjs b/services/history-v1/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/services/history-v1/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/services/history-v1/.mocharc.json b/services/history-v1/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/services/history-v1/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/services/history-v1/Dockerfile b/services/history-v1/Dockerfile index d2def3ced0..fb23158ca7 100644 --- a/services/history-v1/Dockerfile +++ b/services/history-v1/Dockerfile @@ -18,12 +18,32 @@ RUN mkdir /buckets && chown node:node /buckets FROM base AS app COPY package.json package-lock.json /overleaf/ -COPY services/history-v1/package.json /overleaf/services/history-v1/ -COPY libraries/ /overleaf/libraries/ +COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json +COPY libraries/logger/package.json /overleaf/libraries/logger/package.json +COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json +COPY libraries/mongo-utils/package.json /overleaf/libraries/mongo-utils/package.json +COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json +COPY libraries/object-persistor/package.json /overleaf/libraries/object-persistor/package.json +COPY libraries/overleaf-editor-core/package.json /overleaf/libraries/overleaf-editor-core/package.json +COPY libraries/promise-utils/package.json /overleaf/libraries/promise-utils/package.json +COPY libraries/redis-wrapper/package.json /overleaf/libraries/redis-wrapper/package.json +COPY libraries/settings/package.json /overleaf/libraries/settings/package.json +COPY libraries/stream-utils/package.json /overleaf/libraries/stream-utils/package.json +COPY services/history-v1/package.json /overleaf/services/history-v1/package.json COPY patches/ /overleaf/patches/ RUN cd /overleaf && npm ci --quiet - +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/mongo-utils/ /overleaf/libraries/mongo-utils/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/object-persistor/ /overleaf/libraries/object-persistor/ +COPY libraries/overleaf-editor-core/ /overleaf/libraries/overleaf-editor-core/ +COPY libraries/promise-utils/ /overleaf/libraries/promise-utils/ +COPY libraries/redis-wrapper/ /overleaf/libraries/redis-wrapper/ +COPY libraries/settings/ /overleaf/libraries/settings/ +COPY libraries/stream-utils/ /overleaf/libraries/stream-utils/ COPY services/history-v1/ /overleaf/services/history-v1/ FROM app diff --git a/services/history-v1/Jenkinsfile b/services/history-v1/Jenkinsfile new file mode 100644 index 0000000000..f68389ea1c --- /dev/null +++ b/services/history-v1/Jenkinsfile @@ -0,0 +1,125 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + DOCKER_COMPOSE_FLAGS = '-f docker-compose.ci.yml' + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Build') { + steps { + dir('services/history-v1') { + retry(count: 3) { + sh 'make build' + } + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir services/history-v1/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Push Branch Image') { + steps { + dir('services/history-v1') { + sh 'make push_branch' + } + } + } + stage('Shellcheck') { + steps { + dir('services/history-v1') { + sh 'make shellcheck' + } + } + } + stage('Lint') { + steps { + dir('services/history-v1') { + sh 'make lint_ci' + } + } + post { + always { + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'history-v1-eslint', name: 'history-v1 eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'services/history-v1/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + dir('services/history-v1') { + sh 'make format_ci' + } + } + } + stage('Typecheck') { + steps { + dir('services/history-v1') { + sh 'make typecheck_ci' + } + } + } + stage('Test Unit') { + steps { + dir('services/history-v1') { + retry(count: 3) { + sh 'make test_unit' + } + } + } + } + stage('Test Acceptance') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance" + } + steps { + dir('services/history-v1') { + retry(count: 3) { + sh 'make test_acceptance' + } + } + } + } + } + } + stage('Push Production') { + steps { + dir('services/history-v1') { + sh 'make push' + } + } + } + } + post { + always { + junit checksName: 'history-v1 test results', testResults: 'services/history-v1/reports/junit-*.xml' + } + cleanup { + dir('services/history-v1') { + sh 'make clean' + } + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/services/history-v1/Makefile b/services/history-v1/Makefile index a4ea5e329d..17159b7dfd 100644 --- a/services/history-v1/Makefile +++ b/services/history-v1/Makefile @@ -27,14 +27,15 @@ clean: -docker rmi us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) -$(DOCKER_COMPOSE_TEST_UNIT) down --remove-orphans --rmi local --timeout 0 --volumes -$(DOCKER_COMPOSE_TEST_ACCEPTANCE) down --remove-orphans --rmi local --timeout 0 --volumes + -rm -rf reports/ HERE=$(shell pwd) -MONOREPO=$(shell cd ../../ && pwd) +export MONOREPO ?= $(shell cd ../../ && pwd) # Run the linting commands in the scope of the monorepo. # Eslint and prettier (plus some configs) are on the root. RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent -RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent +RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/history-v1/reports:/overleaf/services/history-v1/reports ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent # Same but from the top of the monorepo RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent @@ -70,7 +71,8 @@ lint: $(RUN_LINTING) lint lint_ci: - $(RUN_LINTING_CI) lint + -$(RUN_LINTING_CI) lint -- --format json --output-file reports/eslint.json + sed -i 's_"filePath":"/overleaf_"filePath":"$(MONOREPO)_g' reports/eslint.json lint_fix: $(RUN_LINTING) lint:fix @@ -137,10 +139,11 @@ build: tar: $(DOCKER_COMPOSE) up tar -publish: - - docker push $(DOCKER_REPO)/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push_branch: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME) .PHONY: clean \ format format_fix \ diff --git a/services/history-v1/docker-compose.ci.yml b/services/history-v1/docker-compose.ci.yml index ba1208f85d..8c1cb792c6 100644 --- a/services/history-v1/docker-compose.ci.yml +++ b/services/history-v1/docker-compose.ci.yml @@ -10,10 +10,12 @@ services: image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER user: node volumes: + - ./reports:/overleaf/services/history-v1/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it entrypoint: /overleaf/bin/shared/wait_for_it mongo:27017 --timeout=60 -- command: npm run test:unit:_run environment: + CI: MONGO_CONNECTION_STRING: mongodb://mongo/test-overleaf NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" @@ -32,6 +34,7 @@ services: build: . image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER environment: + CI: ELASTIC_SEARCH_DSN: es:9200 REDIS_HOST: redis_test QUEUES_REDIS_HOST: redis_test @@ -53,6 +56,7 @@ services: NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" volumes: + - ./reports:/overleaf/services/history-v1/reports - minio-certs:/certs - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it depends_on: diff --git a/services/history-v1/package.json b/services/history-v1/package.json index 457123839f..c647c3088f 100644 --- a/services/history-v1/package.json +++ b/services/history-v1/package.json @@ -52,6 +52,8 @@ "chai-as-promised": "^7.1.1", "chai-exclude": "^2.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "node-fetch": "^2.7.0", "sinon": "^9.0.2", "swagger-client": "^3.10.0", @@ -66,8 +68,8 @@ "format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'", "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP", "test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP", - "test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js", - "test:acceptance:_run": "mocha --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js", + "test:unit:_run": "mocha --recursive --exit $@ test/unit/js", + "test:acceptance:_run": "mocha --recursive --timeout 15000 --exit $@ test/acceptance/js", "nodemon": "node --watch app.js", "migrate": "knex migrate:latest", "delete_old_chunks": "node storage/tasks/delete_old_chunks.js", diff --git a/services/history-v1/test/mocha-multi-reporters.cjs b/services/history-v1/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/services/history-v1/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/services/notifications/.mocharc.json b/services/notifications/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/services/notifications/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/services/notifications/Dockerfile b/services/notifications/Dockerfile index 4f768a4355..9dfd883422 100644 --- a/services/notifications/Dockerfile +++ b/services/notifications/Dockerfile @@ -13,12 +13,26 @@ RUN mkdir /home/node/.config && chown node:node /home/node/.config FROM base AS app COPY package.json package-lock.json /overleaf/ -COPY services/notifications/package.json /overleaf/services/notifications/ -COPY libraries/ /overleaf/libraries/ +COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json +COPY libraries/logger/package.json /overleaf/libraries/logger/package.json +COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json +COPY libraries/mongo-utils/package.json /overleaf/libraries/mongo-utils/package.json +COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json +COPY libraries/promise-utils/package.json /overleaf/libraries/promise-utils/package.json +COPY libraries/settings/package.json /overleaf/libraries/settings/package.json +COPY libraries/validation-tools/package.json /overleaf/libraries/validation-tools/package.json +COPY services/notifications/package.json /overleaf/services/notifications/package.json COPY patches/ /overleaf/patches/ RUN cd /overleaf && npm ci --quiet - +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/mongo-utils/ /overleaf/libraries/mongo-utils/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/promise-utils/ /overleaf/libraries/promise-utils/ +COPY libraries/settings/ /overleaf/libraries/settings/ +COPY libraries/validation-tools/ /overleaf/libraries/validation-tools/ COPY services/notifications/ /overleaf/services/notifications/ FROM app diff --git a/services/notifications/Jenkinsfile b/services/notifications/Jenkinsfile new file mode 100644 index 0000000000..4b3c354243 --- /dev/null +++ b/services/notifications/Jenkinsfile @@ -0,0 +1,125 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + DOCKER_COMPOSE_FLAGS = '-f docker-compose.ci.yml' + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Build') { + steps { + dir('services/notifications') { + retry(count: 3) { + sh 'make build' + } + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir services/notifications/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Push Branch Image') { + steps { + dir('services/notifications') { + sh 'make push_branch' + } + } + } + stage('Shellcheck') { + steps { + dir('services/notifications') { + sh 'make shellcheck' + } + } + } + stage('Lint') { + steps { + dir('services/notifications') { + sh 'make lint_ci' + } + } + post { + always { + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'notifications-eslint', name: 'notifications eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'services/notifications/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + dir('services/notifications') { + sh 'make format_ci' + } + } + } + stage('Typecheck') { + steps { + dir('services/notifications') { + sh 'make typecheck_ci' + } + } + } + stage('Test Unit') { + steps { + dir('services/notifications') { + retry(count: 3) { + sh 'make test_unit' + } + } + } + } + stage('Test Acceptance') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance" + } + steps { + dir('services/notifications') { + retry(count: 3) { + sh 'make test_acceptance' + } + } + } + } + } + } + stage('Push Production') { + steps { + dir('services/notifications') { + sh 'make push' + } + } + } + } + post { + always { + junit checksName: 'notifications test results', testResults: 'services/notifications/reports/junit-*.xml' + } + cleanup { + dir('services/notifications') { + sh 'make clean' + } + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/services/notifications/Makefile b/services/notifications/Makefile index 4b43ed1f57..05262acb69 100644 --- a/services/notifications/Makefile +++ b/services/notifications/Makefile @@ -27,14 +27,15 @@ clean: -docker rmi us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) -$(DOCKER_COMPOSE_TEST_UNIT) down --remove-orphans --rmi local --timeout 0 --volumes -$(DOCKER_COMPOSE_TEST_ACCEPTANCE) down --remove-orphans --rmi local --timeout 0 --volumes + -rm -rf reports/ HERE=$(shell pwd) -MONOREPO=$(shell cd ../../ && pwd) +export MONOREPO ?= $(shell cd ../../ && pwd) # Run the linting commands in the scope of the monorepo. # Eslint and prettier (plus some configs) are on the root. RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent -RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent +RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/notifications/reports:/overleaf/services/notifications/reports ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent # Same but from the top of the monorepo RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent @@ -70,7 +71,8 @@ lint: $(RUN_LINTING) lint lint_ci: - $(RUN_LINTING_CI) lint + -$(RUN_LINTING_CI) lint -- --format json --output-file reports/eslint.json + sed -i 's_"filePath":"/overleaf_"filePath":"$(MONOREPO)_g' reports/eslint.json lint_fix: $(RUN_LINTING) lint:fix @@ -137,10 +139,11 @@ build: tar: $(DOCKER_COMPOSE) up tar -publish: - - docker push $(DOCKER_REPO)/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push_branch: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME) .PHONY: clean \ format format_fix \ diff --git a/services/notifications/docker-compose.ci.yml b/services/notifications/docker-compose.ci.yml index 51ddbc503b..ebaa8b1409 100644 --- a/services/notifications/docker-compose.ci.yml +++ b/services/notifications/docker-compose.ci.yml @@ -7,11 +7,13 @@ services: image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER user: node volumes: + - ./reports:/overleaf/services/notifications/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it - ../../tsconfig.backend.json:/overleaf/tsconfig.backend.json entrypoint: /overleaf/bin/shared/wait_for_it mongo:27017 --timeout=60 -- command: npm run test:unit:_run environment: + CI: MONGO_CONNECTION_STRING: mongodb://mongo/test-overleaf NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" @@ -25,6 +27,7 @@ services: build: . image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER environment: + CI: ELASTIC_SEARCH_DSN: es:9200 MONGO_HOST: mongo POSTGRES_HOST: postgres @@ -32,6 +35,7 @@ services: NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" volumes: + - ./reports:/overleaf/services/notifications/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it - ../../tsconfig.backend.json:/overleaf/tsconfig.backend.json depends_on: diff --git a/services/notifications/vitest.config.acceptance.cjs b/services/notifications/vitest.config.acceptance.cjs index d7dcd4b951..93942ba54e 100644 --- a/services/notifications/vitest.config.acceptance.cjs +++ b/services/notifications/vitest.config.acceptance.cjs @@ -1,8 +1,24 @@ const { defineConfig } = require('vitest/config') +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporters: [ + 'default', + [ + 'junit', + { + classnameTemplate: `Acceptance tests.{filename}`, + }, + ], + ], + outputFile: 'reports/junit-vitest-acceptance.xml', + } +} module.exports = defineConfig({ test: { include: ['test/acceptance/js/**/*.test.{js,ts}'], isolate: false, + ...reporterOptions, }, }) diff --git a/services/notifications/vitest.config.unit.cjs b/services/notifications/vitest.config.unit.cjs index f113f2bb1d..0a6fecd2fa 100644 --- a/services/notifications/vitest.config.unit.cjs +++ b/services/notifications/vitest.config.unit.cjs @@ -1,9 +1,25 @@ const { defineConfig } = require('vitest/config') +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporters: [ + 'default', + [ + 'junit', + { + classnameTemplate: `Unit tests.{filename}`, + }, + ], + ], + outputFile: 'reports/junit-vitest-unit.xml', + } +} module.exports = defineConfig({ test: { include: ['test/unit/js/**/*.test.{js,ts}'], setupFiles: ['./test/setup.js'], isolate: false, + ...reporterOptions, }, }) diff --git a/services/project-history/.mocharc.cjs b/services/project-history/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/services/project-history/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/services/project-history/.mocharc.json b/services/project-history/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/services/project-history/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/services/project-history/Dockerfile b/services/project-history/Dockerfile index 5df30b2490..15bc7cab73 100644 --- a/services/project-history/Dockerfile +++ b/services/project-history/Dockerfile @@ -13,12 +13,30 @@ RUN mkdir /home/node/.config && chown node:node /home/node/.config FROM base AS app COPY package.json package-lock.json /overleaf/ -COPY services/project-history/package.json /overleaf/services/project-history/ -COPY libraries/ /overleaf/libraries/ +COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json +COPY libraries/logger/package.json /overleaf/libraries/logger/package.json +COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json +COPY libraries/mongo-utils/package.json /overleaf/libraries/mongo-utils/package.json +COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json +COPY libraries/overleaf-editor-core/package.json /overleaf/libraries/overleaf-editor-core/package.json +COPY libraries/promise-utils/package.json /overleaf/libraries/promise-utils/package.json +COPY libraries/redis-wrapper/package.json /overleaf/libraries/redis-wrapper/package.json +COPY libraries/settings/package.json /overleaf/libraries/settings/package.json +COPY libraries/stream-utils/package.json /overleaf/libraries/stream-utils/package.json +COPY services/project-history/package.json /overleaf/services/project-history/package.json COPY patches/ /overleaf/patches/ RUN cd /overleaf && npm ci --quiet - +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/mongo-utils/ /overleaf/libraries/mongo-utils/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/overleaf-editor-core/ /overleaf/libraries/overleaf-editor-core/ +COPY libraries/promise-utils/ /overleaf/libraries/promise-utils/ +COPY libraries/redis-wrapper/ /overleaf/libraries/redis-wrapper/ +COPY libraries/settings/ /overleaf/libraries/settings/ +COPY libraries/stream-utils/ /overleaf/libraries/stream-utils/ COPY services/project-history/ /overleaf/services/project-history/ FROM app diff --git a/services/project-history/Jenkinsfile b/services/project-history/Jenkinsfile new file mode 100644 index 0000000000..0f701650cd --- /dev/null +++ b/services/project-history/Jenkinsfile @@ -0,0 +1,125 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + DOCKER_COMPOSE_FLAGS = '-f docker-compose.ci.yml' + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Build') { + steps { + dir('services/project-history') { + retry(count: 3) { + sh 'make build' + } + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir services/project-history/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Push Branch Image') { + steps { + dir('services/project-history') { + sh 'make push_branch' + } + } + } + stage('Shellcheck') { + steps { + dir('services/project-history') { + sh 'make shellcheck' + } + } + } + stage('Lint') { + steps { + dir('services/project-history') { + sh 'make lint_ci' + } + } + post { + always { + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'project-history-eslint', name: 'project-history eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'services/project-history/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + dir('services/project-history') { + sh 'make format_ci' + } + } + } + stage('Typecheck') { + steps { + dir('services/project-history') { + sh 'make typecheck_ci' + } + } + } + stage('Test Unit') { + steps { + dir('services/project-history') { + retry(count: 3) { + sh 'make test_unit' + } + } + } + } + stage('Test Acceptance') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance" + } + steps { + dir('services/project-history') { + retry(count: 3) { + sh 'make test_acceptance' + } + } + } + } + } + } + stage('Push Production') { + steps { + dir('services/project-history') { + sh 'make push' + } + } + } + } + post { + always { + junit checksName: 'project-history test results', testResults: 'services/project-history/reports/junit-*.xml' + } + cleanup { + dir('services/project-history') { + sh 'make clean' + } + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/services/project-history/Makefile b/services/project-history/Makefile index 5393d0451a..5fdaa5de99 100644 --- a/services/project-history/Makefile +++ b/services/project-history/Makefile @@ -27,14 +27,15 @@ clean: -docker rmi us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) -$(DOCKER_COMPOSE_TEST_UNIT) down --remove-orphans --rmi local --timeout 0 --volumes -$(DOCKER_COMPOSE_TEST_ACCEPTANCE) down --remove-orphans --rmi local --timeout 0 --volumes + -rm -rf reports/ HERE=$(shell pwd) -MONOREPO=$(shell cd ../../ && pwd) +export MONOREPO ?= $(shell cd ../../ && pwd) # Run the linting commands in the scope of the monorepo. # Eslint and prettier (plus some configs) are on the root. RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent -RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/document-updater/app/js/types.ts:/overleaf/services/document-updater/app/js/types.ts ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent +RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/document-updater/app/js/types.ts:/overleaf/services/document-updater/app/js/types.ts --volume $(MONOREPO)/services/project-history/reports:/overleaf/services/project-history/reports ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent # Same but from the top of the monorepo RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent @@ -70,7 +71,8 @@ lint: $(RUN_LINTING) lint lint_ci: - $(RUN_LINTING_CI) lint + -$(RUN_LINTING_CI) lint -- --format json --output-file reports/eslint.json + sed -i 's_"filePath":"/overleaf_"filePath":"$(MONOREPO)_g' reports/eslint.json lint_fix: $(RUN_LINTING) lint:fix @@ -137,10 +139,11 @@ build: tar: $(DOCKER_COMPOSE) up tar -publish: - - docker push $(DOCKER_REPO)/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push_branch: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME) .PHONY: clean \ format format_fix \ diff --git a/services/project-history/docker-compose.ci.yml b/services/project-history/docker-compose.ci.yml index 73874aaf3f..d85afdc752 100644 --- a/services/project-history/docker-compose.ci.yml +++ b/services/project-history/docker-compose.ci.yml @@ -7,10 +7,12 @@ services: image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER user: node volumes: + - ./reports:/overleaf/services/project-history/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it entrypoint: /overleaf/bin/shared/wait_for_it mongo:27017 --timeout=60 -- command: npm run test:unit:_run environment: + CI: MONGO_CONNECTION_STRING: mongodb://mongo/test-overleaf NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" @@ -29,6 +31,7 @@ services: build: . image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER environment: + CI: ELASTIC_SEARCH_DSN: es:9200 REDIS_HOST: redis_test QUEUES_REDIS_HOST: redis_test @@ -40,6 +43,7 @@ services: NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" volumes: + - ./reports:/overleaf/services/project-history/reports - ../../bin/shared/wait_for_it:/overleaf/bin/shared/wait_for_it depends_on: mongo: diff --git a/services/project-history/package.json b/services/project-history/package.json index 688eb92929..120f6a6898 100644 --- a/services/project-history/package.json +++ b/services/project-history/package.json @@ -9,8 +9,8 @@ "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP", "start": "node app.js", "nodemon": "node --watch app.js", - "test:acceptance:_run": "mocha --loader=esmock --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js", - "test:unit:_run": "mocha --loader=esmock --recursive --reporter spec --exit $@ test/unit/js", + "test:acceptance:_run": "mocha --loader=esmock --recursive --timeout 15000 --exit $@ test/acceptance/js", + "test:unit:_run": "mocha --loader=esmock --recursive --exit $@ test/unit/js", "lint": "eslint --max-warnings 0 --format unix .", "format": "prettier --list-different $PWD/'**/{*.*js,*.ts}'", "format:fix": "prettier --write $PWD/'**/{*.*js,*.ts}'", @@ -45,6 +45,8 @@ "chai": "^4.3.6", "chai-as-promised": "^7.1.1", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "nock": "^13.5.3", "sinon": "~9.0.1", "sinon-chai": "^3.7.0", diff --git a/services/project-history/test/mocha-multi-reporters.cjs b/services/project-history/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/services/project-history/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/services/real-time/.mocharc.cjs b/services/real-time/.mocharc.cjs new file mode 100644 index 0000000000..863d299948 --- /dev/null +++ b/services/real-time/.mocharc.cjs @@ -0,0 +1,13 @@ +let reporterOptions = {} +if (process.env.CI) { + reporterOptions = { + reporter: '/overleaf/node_modules/mocha-multi-reporters', + 'reporter-options': ['configFile=./test/mocha-multi-reporters.cjs'], + } +} +const all = { + require: 'test/setup.js', + ...reporterOptions, +} + +module.exports = all diff --git a/services/real-time/.mocharc.json b/services/real-time/.mocharc.json deleted file mode 100644 index dc3280aa96..0000000000 --- a/services/real-time/.mocharc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "require": "test/setup.js" -} diff --git a/services/real-time/Dockerfile b/services/real-time/Dockerfile index fc9740961b..2214eeecdb 100644 --- a/services/real-time/Dockerfile +++ b/services/real-time/Dockerfile @@ -13,12 +13,22 @@ RUN mkdir /home/node/.config && chown node:node /home/node/.config FROM base AS app COPY package.json package-lock.json /overleaf/ -COPY services/real-time/package.json /overleaf/services/real-time/ -COPY libraries/ /overleaf/libraries/ +COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json +COPY libraries/logger/package.json /overleaf/libraries/logger/package.json +COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json +COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json +COPY libraries/redis-wrapper/package.json /overleaf/libraries/redis-wrapper/package.json +COPY libraries/settings/package.json /overleaf/libraries/settings/package.json +COPY services/real-time/package.json /overleaf/services/real-time/package.json COPY patches/ /overleaf/patches/ RUN cd /overleaf && npm ci --quiet - +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/redis-wrapper/ /overleaf/libraries/redis-wrapper/ +COPY libraries/settings/ /overleaf/libraries/settings/ COPY services/real-time/ /overleaf/services/real-time/ FROM app diff --git a/services/real-time/Jenkinsfile b/services/real-time/Jenkinsfile new file mode 100644 index 0000000000..7e8c3f5b16 --- /dev/null +++ b/services/real-time/Jenkinsfile @@ -0,0 +1,125 @@ +// Autogenerated by build scripts. Do not edit. + +pipeline { + agent { + node { + label 'jenkins-agent-web' + customWorkspace '/workspace' + } + } + options { + timestamps() + timeout(time: 15, unit: 'MINUTES') + } + environment { + BRANCH_NAME = "${env.CHANGE_BRANCH ? env.CHANGE_BRANCH : env.BRANCH_NAME}" + JENKINS_BUILD_NUMBER = "${BUILD_NUMBER}" + BUILD_NUMBER = "${SHORT_SHA}_${BUILD_NUMBER}" + DOCKER_COMPOSE_FLAGS = '-f docker-compose.ci.yml' + COMMIT_SHA = "${GIT_COMMIT}" + SHORT_SHA = "${GIT_COMMIT.take(7)}" + } + stages { + stage('Stage 1') { + parallel { + stage('Build') { + steps { + dir('services/real-time') { + retry(count: 3) { + sh 'make build' + } + } + } + } + stage('Create reports folder') { + steps { + sh 'mkdir services/real-time/reports' + } + } + } + } + stage('Stage 2') { + parallel { + stage('Push Branch Image') { + steps { + dir('services/real-time') { + sh 'make push_branch' + } + } + } + stage('Shellcheck') { + steps { + dir('services/real-time') { + sh 'make shellcheck' + } + } + } + stage('Lint') { + steps { + dir('services/real-time') { + sh 'make lint_ci' + } + } + post { + always { + recordIssues checksAnnotationScope: 'ALL', enabledForFailure: true, failOnError: true, id: 'real-time-eslint', name: 'real-time eslint', qualityGates: [[integerThreshold: 1, threshold: 1.0, type: 'TOTAL']], sourceCodeRetention: 'LAST_BUILD', tools: [esLint(pattern: 'services/real-time/reports/eslint.json')] + } + } + } + stage('Format') { + steps { + dir('services/real-time') { + sh 'make format_ci' + } + } + } + stage('Typecheck') { + steps { + dir('services/real-time') { + sh 'make typecheck_ci' + } + } + } + stage('Test Unit') { + steps { + dir('services/real-time') { + retry(count: 3) { + sh 'make test_unit' + } + } + } + } + stage('Test Acceptance') { + environment { + COMPOSE_PROJECT_NAME_TEST_ACCEPTANCE = "test_acceptance" + } + steps { + dir('services/real-time') { + retry(count: 3) { + sh 'make test_acceptance' + } + } + } + } + } + } + stage('Push Production') { + steps { + dir('services/real-time') { + sh 'make push' + } + } + } + } + post { + always { + junit checksName: 'real-time test results', testResults: 'services/real-time/reports/junit-*.xml' + } + cleanup { + dir('services/real-time') { + sh 'make clean' + } + sh 'make clean_jenkins -j10' + } + } +} \ No newline at end of file diff --git a/services/real-time/Makefile b/services/real-time/Makefile index ffa21ed9fc..8d2f11ac8b 100644 --- a/services/real-time/Makefile +++ b/services/real-time/Makefile @@ -27,14 +27,15 @@ clean: -docker rmi us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) -$(DOCKER_COMPOSE_TEST_UNIT) down --remove-orphans --rmi local --timeout 0 --volumes -$(DOCKER_COMPOSE_TEST_ACCEPTANCE) down --remove-orphans --rmi local --timeout 0 --volumes + -rm -rf reports/ HERE=$(shell pwd) -MONOREPO=$(shell cd ../../ && pwd) +export MONOREPO ?= $(shell cd ../../ && pwd) # Run the linting commands in the scope of the monorepo. # Eslint and prettier (plus some configs) are on the root. RUN_LINTING = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(HERE) node:22.18.0 npm run --silent -RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent +RUN_LINTING_CI = docker run --rm --volume $(MONOREPO)/.editorconfig:/overleaf/.editorconfig --volume $(MONOREPO)/.eslintignore:/overleaf/.eslintignore --volume $(MONOREPO)/.eslintrc:/overleaf/.eslintrc --volume $(MONOREPO)/.prettierignore:/overleaf/.prettierignore --volume $(MONOREPO)/.prettierrc:/overleaf/.prettierrc --volume $(MONOREPO)/tsconfig.backend.json:/overleaf/tsconfig.backend.json --volume $(MONOREPO)/services/real-time/reports:/overleaf/services/real-time/reports ci/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) npm run --silent # Same but from the top of the monorepo RUN_LINTING_MONOREPO = docker run --rm -v $(MONOREPO):$(MONOREPO) -w $(MONOREPO) node:22.18.0 npm run --silent @@ -70,7 +71,8 @@ lint: $(RUN_LINTING) lint lint_ci: - $(RUN_LINTING_CI) lint + -$(RUN_LINTING_CI) lint -- --format json --output-file reports/eslint.json + sed -i 's_"filePath":"/overleaf_"filePath":"$(MONOREPO)_g' reports/eslint.json lint_fix: $(RUN_LINTING) lint:fix @@ -137,10 +139,11 @@ build: tar: $(DOCKER_COMPOSE) up tar -publish: - - docker push $(DOCKER_REPO)/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME)-$(BUILD_NUMBER) +push_branch: + docker push us-east1-docker.pkg.dev/overleaf-ops/ol-docker/$(PROJECT_NAME):$(BRANCH_NAME) .PHONY: clean \ format format_fix \ diff --git a/services/real-time/docker-compose.ci.yml b/services/real-time/docker-compose.ci.yml index 1107b62bbf..7fdae09957 100644 --- a/services/real-time/docker-compose.ci.yml +++ b/services/real-time/docker-compose.ci.yml @@ -8,6 +8,7 @@ services: user: node command: npm run test:unit:_run environment: + CI: MONGO_CONNECTION_STRING: mongodb://mongo/test-overleaf NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" @@ -24,6 +25,7 @@ services: build: . image: ci/$PROJECT_NAME:$BRANCH_NAME-$BUILD_NUMBER environment: + CI: ELASTIC_SEARCH_DSN: es:9200 REDIS_HOST: redis_test QUEUES_REDIS_HOST: redis_test @@ -34,6 +36,8 @@ services: MOCHA_GREP: ${MOCHA_GREP} NODE_ENV: test NODE_OPTIONS: "--unhandled-rejections=strict" + volumes: + - ./reports:/overleaf/services/real-time/reports depends_on: redis_test: condition: service_healthy diff --git a/services/real-time/package.json b/services/real-time/package.json index 0d5fc558ec..37c8dd9e2b 100644 --- a/services/real-time/package.json +++ b/services/real-time/package.json @@ -5,9 +5,9 @@ "main": "app.js", "scripts": { "start": "node app.js", - "test:acceptance:_run": "mocha --recursive --reporter spec --timeout 15000 --exit $@ test/acceptance/js", + "test:acceptance:_run": "mocha --recursive --timeout 15000 --exit $@ test/acceptance/js", "test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP", - "test:unit:_run": "mocha --recursive --reporter spec --exit $@ test/unit/js", + "test:unit:_run": "mocha --recursive --exit $@ test/unit/js", "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP", "nodemon": "node --watch app.js", "lint": "eslint --max-warnings 0 --format unix .", @@ -42,6 +42,8 @@ "chai-as-promised": "^7.1.1", "cookie-signature": "^1.1.0", "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.2.1", + "mocha-multi-reporters": "^1.5.1", "sandboxed-module": "~0.3.0", "sinon": "^9.2.4", "sinon-chai": "^3.7.0", diff --git a/services/real-time/test/mocha-multi-reporters.cjs b/services/real-time/test/mocha-multi-reporters.cjs new file mode 100644 index 0000000000..69342c7bde --- /dev/null +++ b/services/real-time/test/mocha-multi-reporters.cjs @@ -0,0 +1,8 @@ +module.exports = { + reporterEnabled: 'spec, mocha-junit-reporter', + mochaJunitReporterReporterOptions: { + mochaFile: `reports/junit-mocha-${process.env.MOCHA_GREP}.xml`, + includePending: true, + jenkinsMode: true, + }, +} diff --git a/services/web/Dockerfile b/services/web/Dockerfile index 5e153ad42b..e33e56ed67 100644 --- a/services/web/Dockerfile +++ b/services/web/Dockerfile @@ -1,5 +1,6 @@ -# the base image is suitable for running web with /overleaf/services/web bind -# mounted +# This file was auto-generated, do not edit it directly. +# Instead run internal$ services/web/build_scripts + FROM node:22.18.0 AS base WORKDIR /overleaf/services/web @@ -22,8 +23,22 @@ RUN mkdir -p /overleaf/services/web/data/dumpFolder \ FROM base AS deps-prod COPY package.json package-lock.json /overleaf/ -COPY services/web/package.json /overleaf/services/web/ -COPY libraries/ /overleaf/libraries/ +COPY libraries/access-token-encryptor/package.json /overleaf/libraries/access-token-encryptor/package.json +COPY libraries/eslint-plugin/package.json /overleaf/libraries/eslint-plugin/package.json +COPY libraries/fetch-utils/package.json /overleaf/libraries/fetch-utils/package.json +COPY libraries/logger/package.json /overleaf/libraries/logger/package.json +COPY libraries/metrics/package.json /overleaf/libraries/metrics/package.json +COPY libraries/mongo-utils/package.json /overleaf/libraries/mongo-utils/package.json +COPY libraries/o-error/package.json /overleaf/libraries/o-error/package.json +COPY libraries/object-persistor/package.json /overleaf/libraries/object-persistor/package.json +COPY libraries/overleaf-editor-core/package.json /overleaf/libraries/overleaf-editor-core/package.json +COPY libraries/promise-utils/package.json /overleaf/libraries/promise-utils/package.json +COPY libraries/ranges-tracker/package.json /overleaf/libraries/ranges-tracker/package.json +COPY libraries/redis-wrapper/package.json /overleaf/libraries/redis-wrapper/package.json +COPY libraries/settings/package.json /overleaf/libraries/settings/package.json +COPY libraries/stream-utils/package.json /overleaf/libraries/stream-utils/package.json +COPY libraries/validation-tools/package.json /overleaf/libraries/validation-tools/package.json +COPY services/web/package.json /overleaf/services/web/package.json COPY patches/ /overleaf/patches/ RUN cd /overleaf && NODE_ENV=production npm ci --quiet @@ -41,7 +56,22 @@ FROM deps AS dev ARG SENTRY_RELEASE ENV SENTRY_RELEASE=$SENTRY_RELEASE -COPY services/web /overleaf/services/web +COPY libraries/access-token-encryptor/ /overleaf/libraries/access-token-encryptor/ +COPY libraries/eslint-plugin/ /overleaf/libraries/eslint-plugin/ +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/mongo-utils/ /overleaf/libraries/mongo-utils/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/object-persistor/ /overleaf/libraries/object-persistor/ +COPY libraries/overleaf-editor-core/ /overleaf/libraries/overleaf-editor-core/ +COPY libraries/promise-utils/ /overleaf/libraries/promise-utils/ +COPY libraries/ranges-tracker/ /overleaf/libraries/ranges-tracker/ +COPY libraries/redis-wrapper/ /overleaf/libraries/redis-wrapper/ +COPY libraries/settings/ /overleaf/libraries/settings/ +COPY libraries/stream-utils/ /overleaf/libraries/stream-utils/ +COPY libraries/validation-tools/ /overleaf/libraries/validation-tools/ +COPY services/web/ /overleaf/services/web/ # Build the latex parser RUN cd /overleaf/services/web && npm run 'lezer-latex:generate' @@ -62,7 +92,23 @@ RUN nice find /overleaf/services/web/public -name '*.js.map' -delete # copy source code and precompile pug images FROM deps-prod AS pug -COPY services/web /overleaf/services/web +COPY libraries/access-token-encryptor/ /overleaf/libraries/access-token-encryptor/ +COPY libraries/eslint-plugin/ /overleaf/libraries/eslint-plugin/ +COPY libraries/fetch-utils/ /overleaf/libraries/fetch-utils/ +COPY libraries/logger/ /overleaf/libraries/logger/ +COPY libraries/metrics/ /overleaf/libraries/metrics/ +COPY libraries/mongo-utils/ /overleaf/libraries/mongo-utils/ +COPY libraries/o-error/ /overleaf/libraries/o-error/ +COPY libraries/object-persistor/ /overleaf/libraries/object-persistor/ +COPY libraries/overleaf-editor-core/ /overleaf/libraries/overleaf-editor-core/ +COPY libraries/promise-utils/ /overleaf/libraries/promise-utils/ +COPY libraries/ranges-tracker/ /overleaf/libraries/ranges-tracker/ +COPY libraries/redis-wrapper/ /overleaf/libraries/redis-wrapper/ +COPY libraries/settings/ /overleaf/libraries/settings/ +COPY libraries/stream-utils/ /overleaf/libraries/stream-utils/ +COPY libraries/validation-tools/ /overleaf/libraries/validation-tools/ +COPY services/web/ /overleaf/services/web/ + # Omit Server Pro/CE specific scripts from SaaS image RUN rm /overleaf/services/web/modules/server-ce-scripts -rf RUN OVERLEAF_CONFIG=/overleaf/services/web/config/settings.overrides.saas.js nice npm run precompile-pug diff --git a/services/web/buildscript.txt b/services/web/buildscript.txt index 24a4717282..7d0529c3ec 100644 --- a/services/web/buildscript.txt +++ b/services/web/buildscript.txt @@ -1,5 +1,4 @@ web ---only-jenkins-include-file=True --dependencies= --docker-repos=us-east1-docker.pkg.dev/overleaf-ops/ol-docker --env-add=