From 16daea27adf37018c57ea87e1ccbecc2b09edacf Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Tue, 5 Aug 2025 10:27:28 +0200 Subject: [PATCH] [server-ce] tests: optimize sharding (#27635) * [server-ce] tests: optimize sharding * [server-ce] tests: remove shard CE_CUSTOM_2 * [server-ce] tests: move project sharing tests onto a new shard Previously they were on their own CE_CUSTOM_1 shard. GitOrigin-RevId: de256e04f5956b4651a5dc4ab47cdb5972723c5d --- server-ce/test/Jenkinsfile | 24 +++++++++---------- server-ce/test/cypress.config.js | 32 +++++++++++++++++++++++++- server-ce/test/docker-compose.yml | 1 - server-ce/test/helpers/config.ts | 2 +- server-ce/test/project-sharing.spec.ts | 2 +- 5 files changed, 45 insertions(+), 16 deletions(-) diff --git a/server-ce/test/Jenkinsfile b/server-ce/test/Jenkinsfile index e64caef8b1..38d8b4d1d7 100644 --- a/server-ce/test/Jenkinsfile +++ b/server-ce/test/Jenkinsfile @@ -142,18 +142,6 @@ pipeline { } } } - stage('CE custom 2') { - environment { - CYPRESS_SHARD = "CE_CUSTOM_2" - COMPOSE_PROJECT_NAME = "test-ce-custom-2" - } - steps { - script { waitUntil { return job_npm_install_done && job_server_ce_build_done && job_prefetch_default_done && job_prefetch_custom_done } } - dir('server-ce/test') { - sh 'make test-e2e' - } - } - } stage('PRO default 1') { environment { @@ -215,6 +203,18 @@ pipeline { } } } + stage('PRO custom 4') { + environment { + CYPRESS_SHARD = "PRO_CUSTOM_4" + COMPOSE_PROJECT_NAME = "test-pro-custom-4" + } + steps { + script { waitUntil { return job_npm_install_done && job_server_pro_build_done && job_prefetch_default_done && job_prefetch_custom_done } } + dir('server-ce/test') { + sh 'make test-e2e' + } + } + } } } } diff --git a/server-ce/test/cypress.config.js b/server-ce/test/cypress.config.js index 07ea87bc83..5abd3da040 100644 --- a/server-ce/test/cypress.config.js +++ b/server-ce/test/cypress.config.js @@ -1,7 +1,37 @@ const { defineConfig } = require('cypress') const { readPdf, readFileInZip } = require('./helpers/read-file') +const fs = require('node:fs') -const specPattern = process.env.SPEC_PATTERN || './**/*.spec.{js,ts,tsx}' +if (process.env.CYPRESS_SHARD && !process.env.SPEC_PATTERN) { + // Running Cypress on all the specs is wasteful (~1min) when only few of them + // will have relevant tasks to run for a given shard. Filter the spec files + // based on the existence of the shard identifier in the spec source. + const files = [] + for (const name of fs.readdirSync('.')) { + if (!name.endsWith('.spec.ts')) continue + const src = fs.readFileSync(name, 'utf-8') + if (!src.includes('isExcludedBySharding(')) { + throw new Error( + `Spec ${name} is not using sharding. Add an appropriate "'if (isExcludedBySharding('...')) return" call.` + ) + } + if (!src.includes(process.env.CYPRESS_SHARD)) continue + files.push(name) + } + if (files.length === 0) { + throw new Error( + `Bad process.env.CYPRESS_SHARD=${process.env.CYPRESS_SHARD}; no spec files matched!` + ) + } + if (files.length === 1) { + // Cypress does not like `{single-file}`. Make this a special case. + process.env.SPEC_PATTERN = `./${files[0]}` + } else { + process.env.SPEC_PATTERN = `./{${files.join(',')}}` + } +} + +const specPattern = process.env.SPEC_PATTERN || './**/*.spec.ts' module.exports = defineConfig({ defaultCommandTimeout: 10_000, diff --git a/server-ce/test/docker-compose.yml b/server-ce/test/docker-compose.yml index 6d3728af6a..00ab290d68 100644 --- a/server-ce/test/docker-compose.yml +++ b/server-ce/test/docker-compose.yml @@ -76,7 +76,6 @@ services: CYPRESS_SHARD: CYPRESS_BASE_URL: http://sharelatex CYPRESS_FULL_FILESTORE_MIGRATION: - SPEC_PATTERN: '**/*.spec.{js,jsx,ts,tsx}' depends_on: sharelatex: condition: service_healthy diff --git a/server-ce/test/helpers/config.ts b/server-ce/test/helpers/config.ts index 9a2236d602..0576b93875 100644 --- a/server-ce/test/helpers/config.ts +++ b/server-ce/test/helpers/config.ts @@ -9,12 +9,12 @@ export function isExcludedBySharding( | 'LOCAL_ONLY' | 'CE_DEFAULT' | 'CE_CUSTOM_1' - | 'CE_CUSTOM_2' | 'PRO_DEFAULT_1' | 'PRO_DEFAULT_2' | 'PRO_CUSTOM_1' | 'PRO_CUSTOM_2' | 'PRO_CUSTOM_3' + | 'PRO_CUSTOM_4' ) { const SHARD = Cypress.env('SHARD') return SHARD && shard !== SHARD diff --git a/server-ce/test/project-sharing.spec.ts b/server-ce/test/project-sharing.spec.ts index 3971a4f481..b806248398 100644 --- a/server-ce/test/project-sharing.spec.ts +++ b/server-ce/test/project-sharing.spec.ts @@ -14,7 +14,7 @@ import { throttledRecompile } from './helpers/compile' import { beforeWithReRunOnTestRetry } from './helpers/beforeWithReRunOnTestRetry' describe('Project Sharing', function () { - if (isExcludedBySharding('PRO_CUSTOM_2')) return + if (isExcludedBySharding('PRO_CUSTOM_4')) return ensureUserExists({ email: 'user@example.com' }) startWith({ withDataDir: true, pro: true })