From 0af6b365cef983935413ec6a9fb1ca911ca3b65b Mon Sep 17 00:00:00 2001 From: betegon Date: Thu, 29 Oct 2026 18:36:30 +0100 Subject: [PATCH 1/4] ci(cli): run E2E tests in parallel --- .github/workflows/test.yml | 47 +++++++++++++++++++++++- docs/operations/github-actions.md | 6 ++++ packages/cli/package.json | 1 + scripts/ci-projects.test.mjs | 60 +++++++++++++++++++++++++++++-- 4 files changed, 111 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 47402b236..14bda6903 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -214,6 +214,48 @@ jobs: git diff --exit-code [[ -z "$(git status --porcelain --untracked-files=all)" ]] + cli-e2e: + name: CLI E2E (Node 24) + needs: discover-projects + if: contains(fromJSON(needs.discover-projects.outputs.matrix).include.*.name, 'sentry') + runs-on: ubuntu-latest + timeout-minutes: 30 + env: + BRAINTRUST_API_KEY: ci-test-key + GITHUB_TOKEN: ci-test-token + HONEYCOMB_API_KEY: ci-test-key + SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} + SENTRY_OAUTH_CLIENT_SECRET: ci-test-secret + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + persist-credentials: false + - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: ${{ env.NODE_VERSION_22 }} + cache: pnpm + - run: cp .env.example .env.local + - run: pnpm install --frozen-lockfile + - name: Build project dependencies + run: pnpm --filter 'sentry^...' --if-present run build + - name: Build standalone CLI + run: pnpm --filter sentry run build + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + with: + node-version: ${{ env.NODE_VERSION_24 }} + cache: pnpm + - name: Run E2E tests on Node 24 + env: + SENTRY_CLI_BINARY: ${{ github.workspace }}/packages/cli/dist-bin/sentry-linux-x64 + run: | + test -x "$SENTRY_CLI_BINARY" + pnpm --filter sentry run test:e2e + - name: Check generated files + run: | + git diff --exit-code + [[ -z "$(git status --porcelain --untracked-files=all)" ]] + npm-runtime: name: NPM package (${{ matrix.name }}) needs: discover-projects @@ -290,6 +332,7 @@ jobs: project, npm-runtime, cli-asset-catalog, + cli-e2e, ] runs-on: ubuntu-latest steps: @@ -304,6 +347,7 @@ jobs: RUNTIME_COUNT: ${{ needs.discover-projects.outputs.runtime-count }} ASSET_CATALOG_RESULT: ${{ needs.cli-asset-catalog.result }} ASSET_CATALOG_SELECTED: ${{ contains(fromJSON(needs.discover-projects.outputs.matrix).include.*.name, 'sentry') }} + CLI_E2E_RESULT: ${{ needs.cli-e2e.result }} run: | [[ "$DISCOVER_RESULT" == success ]] [[ "$INSTALL_RESULT" == success ]] @@ -322,4 +366,5 @@ jobs: if [[ "$ASSET_CATALOG_SELECTED" == false ]]; then expected=skipped fi - [[ "$ASSET_CATALOG_RESULT" == "$expected" ]] + test "$ASSET_CATALOG_RESULT" = "$expected" + test "$CLI_E2E_RESULT" = "$expected" diff --git a/docs/operations/github-actions.md b/docs/operations/github-actions.md index b0e0484bb..a7a8bd7c7 100644 --- a/docs/operations/github-actions.md +++ b/docs/operations/github-actions.md @@ -21,6 +21,12 @@ discovery, installation, repository quality, and every selected project. Package-specific exceptions live in `package.json#sentryCi`; the standalone smoke-test suite remains in its own workflow. +`CLI E2E (Node 24)` runs independently of the CLI project job. It builds the +standalone CLI on Node 22, then builds the npm bundle and tests both on Node 24. +Unit tests and coverage remain in the project job. The final `test` gate +requires E2E to pass whenever the CLI is selected, and requires it to be skipped +otherwise. + ### deploy.yml Runs after a successful `Test` push run on `main`. Checks out the tested commit diff --git a/packages/cli/package.json b/packages/cli/package.json index 9e5f41a5c..eee8ddf72 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -51,6 +51,7 @@ "packageManager": "pnpm@10.11.0", "sentryCi": { "coverage": "coverage/lcov.info", + "e2e": false, "npmRuntime": "bundle", "policy": "ci:policy" }, diff --git a/scripts/ci-projects.test.mjs b/scripts/ci-projects.test.mjs index cc1396274..a0dcfaf92 100644 --- a/scripts/ci-projects.test.mjs +++ b/scripts/ci-projects.test.mjs @@ -43,8 +43,10 @@ describe("workspace CI selection", () => { assert.match(docsScripts[docs.prepare], /sentry run generate:schema/); assert.match(docsScripts[docs.prepare], /sentry run generate:docs/); const cli = matrix.include.find(({ name }) => name === "sentry"); + assert.equal(cli.build, "build"); + assert.equal(cli.test, "test:unit"); assert.equal(cli.policy, "ci:policy"); - assert.equal(cli.e2e, "test:e2e"); + assert.equal(cli.e2e, ""); assert.equal(cli.coverage, "packages/cli/coverage/lcov.info"); assert.equal( matrix.include.find(({ name }) => name === "@sentry/mcp-core").junit, @@ -174,7 +176,7 @@ describe("workspace CI selection", () => { assert.doesNotMatch(workflow, /matrix\.name == 'sentry-cli-docs'/); assert.match( workflow, - /needs:\s*\[\s*discover-projects,\s*install,\s*quality,\s*project,\s*npm-runtime,\s*cli-asset-catalog,?\s*\]/, + /needs:\s*\[\s*discover-projects,\s*install,\s*quality,\s*project,\s*npm-runtime,\s*cli-asset-catalog,\s*cli-e2e,?\s*\]/, ); assert.match( workflow, @@ -202,6 +204,20 @@ describe("workspace CI selection", () => { assert.doesNotMatch(workflow.split("\njobs:", 1)[0], /paths(?:-ignore)?:/); }); + it("runs CLI E2E independently after project discovery", () => { + const workflow = readFileSync( + resolve(root, ".github/workflows/test.yml"), + "utf8", + ); + const job = workflow.split("\n cli-e2e:\n")[1]?.split(/\n [\w-]+:\n/)[0]; + assert.ok(job); + assert.match(job, /\n needs: discover-projects\n/); + assert.match( + job, + /if: contains\(fromJSON\(needs\.discover-projects\.outputs\.matrix\)\.include\.\*\.name, 'sentry'\)/, + ); + }); + it("requires native asset-catalog success when selected and a skip otherwise", () => { const workflow = readFileSync( resolve(root, ".github/workflows/test.yml"), @@ -244,6 +260,7 @@ describe("workspace CI selection", () => { RUNTIME_RESULT: count === "0" ? "skipped" : "success", ASSET_CATALOG_RESULT: nativeResult, ASSET_CATALOG_SELECTED: String(selected), + CLI_E2E_RESULT: selected ? "success" : "skipped", }, }); assert.equal( @@ -254,6 +271,45 @@ describe("workspace CI selection", () => { } }); + it("requires CLI E2E success when selected and a skip otherwise", () => { + const workflow = readFileSync( + resolve(root, ".github/workflows/test.yml"), + "utf8", + ); + const gate = workflow.split("\n test:\n")[1]; + assert.ok(gate); + assert.match(gate, /CLI_E2E_RESULT: \$\{\{ needs\.cli-e2e\.result \}\}/); + const script = gate.split(" run: |\n")[1]; + assert.ok(script); + + for (const selected of [true, false]) { + const expected = selected ? "success" : "skipped"; + for (const status of ["success", "failure", "cancelled", "skipped"]) { + const result = spawnSync("bash", ["-euc", script], { + encoding: "utf8", + env: { + ...process.env, + DISCOVER_RESULT: "success", + INSTALL_RESULT: "success", + QUALITY_RESULT: "success", + PROJECT_COUNT: "1", + PROJECT_RESULT: "success", + RUNTIME_COUNT: selected ? "1" : "0", + RUNTIME_RESULT: expected, + ASSET_CATALOG_RESULT: expected, + ASSET_CATALOG_SELECTED: String(selected), + CLI_E2E_RESULT: status, + }, + }); + assert.equal( + result.status, + status === expected ? 0 : 1, + `selected=${selected}, e2e=${status}`, + ); + } + } + }); + it("requires safe metadata and a single owner of each specialized role", () => { assert.throws( () => From 2c1cde73a6c97f4a828bc2031987a482c2eff9ee Mon Sep 17 00:00:00 2001 From: betegon Date: Thu, 29 Oct 2026 20:47:31 +0100 Subject: [PATCH 2/4] ci(cli): remove unused E2E environment setup --- .github/workflows/test.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 14bda6903..8d3d50087 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -221,11 +221,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 env: - BRAINTRUST_API_KEY: ci-test-key - GITHUB_TOKEN: ci-test-token - HONEYCOMB_API_KEY: ci-test-key SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} - SENTRY_OAUTH_CLIENT_SECRET: ci-test-secret steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: @@ -235,7 +231,6 @@ jobs: with: node-version: ${{ env.NODE_VERSION_22 }} cache: pnpm - - run: cp .env.example .env.local - run: pnpm install --frozen-lockfile - name: Build project dependencies run: pnpm --filter 'sentry^...' --if-present run build From 756b806115166c38d08dee8bc2e92cdd9da96ad1 Mon Sep 17 00:00:00 2001 From: betegon Date: Fri, 30 Oct 2026 10:36:08 +0100 Subject: [PATCH 3/4] ci(cli): prepare E2E and unit inputs once --- .github/workflows/test.yml | 16 ++++++++++------ docs/operations/github-actions.md | 5 ++++- packages/cli/package.json | 10 ++++++++-- scripts/ci-projects.test.mjs | 6 ++++-- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8d3d50087..a867fe29f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -223,29 +223,33 @@ jobs: env: SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} steps: - - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@v7 with: node-version: ${{ env.NODE_VERSION_22 }} cache: pnpm - run: pnpm install --frozen-lockfile - name: Build project dependencies run: pnpm --filter 'sentry^...' --if-present run build + - run: pnpm --filter sentry run ci:prepare - name: Build standalone CLI - run: pnpm --filter sentry run build - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + run: pnpm --filter sentry run tsx script/build.ts --single + - uses: actions/setup-node@v7 with: node-version: ${{ env.NODE_VERSION_24 }} - cache: pnpm + - name: Build npm bundle + run: pnpm --filter sentry run tsx script/bundle.ts - name: Run E2E tests on Node 24 env: SENTRY_CLI_BINARY: ${{ github.workspace }}/packages/cli/dist-bin/sentry-linux-x64 run: | test -x "$SENTRY_CLI_BINARY" - pnpm --filter sentry run test:e2e + test -s packages/cli/dist/bin.cjs + test -s packages/cli/dist/index.cjs + pnpm --filter sentry exec vitest run test/e2e - name: Check generated files run: | git diff --exit-code diff --git a/docs/operations/github-actions.md b/docs/operations/github-actions.md index a7a8bd7c7..896b8691b 100644 --- a/docs/operations/github-actions.md +++ b/docs/operations/github-actions.md @@ -23,7 +23,10 @@ smoke-test suite remains in its own workflow. `CLI E2E (Node 24)` runs independently of the CLI project job. It builds the standalone CLI on Node 22, then builds the npm bundle and tests both on Node 24. -Unit tests and coverage remain in the project job. The final `test` gate +Dependencies and generated sources are prepared once per job. The CLI project +job runs typechecks, unit tests, and coverage without rebuilding the standalone +or repeating generation. Public build and test commands still prepare their own +inputs for local use. The final `test` gate requires E2E to pass whenever the CLI is selected, and requires it to be skipped otherwise. diff --git a/packages/cli/package.json b/packages/cli/package.json index eee8ddf72..71fc1aa0b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -50,10 +50,13 @@ }, "packageManager": "pnpm@10.11.0", "sentryCi": { + "build": false, "coverage": "coverage/lcov.info", "e2e": false, "npmRuntime": "bundle", - "policy": "ci:policy" + "policy": "ci:policy", + "test": "ci:test:unit", + "typecheck": "ci:typecheck" }, "scripts": { "tsx": "tsx --env-file-if-exists=.env.local --import ./script/require-shim.mjs", @@ -66,7 +69,7 @@ "lint": "pnpm -w exec oxlint --report-unused-disable-directives packages/cli && pnpm -w exec oxfmt --check packages/cli", "lint:fix": "pnpm -w exec oxlint --fix packages/cli && pnpm -w exec oxfmt --write packages/cli", "test": "pnpm run test:unit", - "test:unit": "pnpm run generate:docs && pnpm run generate:sdk && vitest run test/lib test/commands test/types test/script --coverage", + "test:unit": "pnpm run generate:docs && pnpm run generate:sdk && pnpm run ci:test:unit", "test:changed": "pnpm run generate:docs && pnpm run generate:sdk && vitest run --changed", "test:e2e": "pnpm tsx script/prepare-e2e-bundle.ts && vitest run test/e2e", "test:init-eval": "vitest run test/init-eval --testTimeout 600000", @@ -94,6 +97,9 @@ "check:doc-examples": "pnpm tsx script/check-doc-examples.ts", "check:installer-docs": "pnpm tsx script/check-installer-docs.ts", "check:destructive": "pnpm tsx script/check-destructive-commands.ts", + "ci:prepare": "pnpm run generate:schema && pnpm run generate:docs && pnpm run generate:sdk", + "ci:typecheck": "tsc --noEmit", + "ci:test:unit": "vitest run test/lib test/commands test/types test/script --coverage", "ci:policy": "pnpm run check:patches && pnpm run check:deps && pnpm run check:errors && pnpm run check:fragments && pnpm run check:docs-sections && pnpm run check:env-coverage && pnpm run check:stale-refs && pnpm run check:doc-examples && pnpm run check:installer-docs && pnpm run check:destructive" }, "devDependencies": { diff --git a/scripts/ci-projects.test.mjs b/scripts/ci-projects.test.mjs index a0dcfaf92..45fe2b9ac 100644 --- a/scripts/ci-projects.test.mjs +++ b/scripts/ci-projects.test.mjs @@ -43,8 +43,10 @@ describe("workspace CI selection", () => { assert.match(docsScripts[docs.prepare], /sentry run generate:schema/); assert.match(docsScripts[docs.prepare], /sentry run generate:docs/); const cli = matrix.include.find(({ name }) => name === "sentry"); - assert.equal(cli.build, "build"); - assert.equal(cli.test, "test:unit"); + assert.equal(cli.prepare, "ci:prepare"); + assert.equal(cli.build, ""); + assert.equal(cli.typecheck, "ci:typecheck"); + assert.equal(cli.test, "ci:test:unit"); assert.equal(cli.policy, "ci:policy"); assert.equal(cli.e2e, ""); assert.equal(cli.coverage, "packages/cli/coverage/lcov.info"); From 1b42251feb06944d17cdd89e029c26dae43727d0 Mon Sep 17 00:00:00 2001 From: betegon Date: Fri, 30 Oct 2026 13:39:49 +0100 Subject: [PATCH 4/4] ci(cli): reuse npm build setup and share Node pins --- .github/node-versions/20 | 1 + .github/node-versions/22 | 1 + .github/node-versions/24 | 1 + .github/workflows/cli-build.yml | 11 ++---- .github/workflows/test.yml | 65 +++++++++++++------------------ docs/operations/github-actions.md | 5 +++ scripts/ci-projects.test.mjs | 11 ++++-- 7 files changed, 48 insertions(+), 47 deletions(-) create mode 100644 .github/node-versions/20 create mode 100644 .github/node-versions/22 create mode 100644 .github/node-versions/24 diff --git a/.github/node-versions/20 b/.github/node-versions/20 new file mode 100644 index 000000000..ccc4c6c7f --- /dev/null +++ b/.github/node-versions/20 @@ -0,0 +1 @@ +20.20.2 diff --git a/.github/node-versions/22 b/.github/node-versions/22 new file mode 100644 index 000000000..b8b23ca93 --- /dev/null +++ b/.github/node-versions/22 @@ -0,0 +1 @@ +22.23.4 diff --git a/.github/node-versions/24 b/.github/node-versions/24 new file mode 100644 index 000000000..ce62013c3 --- /dev/null +++ b/.github/node-versions/24 @@ -0,0 +1 @@ +24.22.1 diff --git a/.github/workflows/cli-build.yml b/.github/workflows/cli-build.yml index 33ffe585c..733de89fe 100644 --- a/.github/workflows/cli-build.yml +++ b/.github/workflows/cli-build.yml @@ -16,9 +16,6 @@ permissions: env: SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} - NODE_VERSION_20: "20.20.2" - NODE_VERSION_22: "22.23.4" - NODE_VERSION_24: "24.22.1" jobs: nightly-version: @@ -58,7 +55,7 @@ jobs: - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - node-version: ${{ env.NODE_VERSION_22 }} + node-version-file: .github/node-versions/22 cache: pnpm - name: Install dependencies run: pnpm install --frozen-lockfile @@ -267,7 +264,7 @@ jobs: - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - node-version: ${{ env.NODE_VERSION_22 }} + node-version-file: .github/node-versions/22 cache: pnpm - name: Install dependencies run: pnpm install --frozen-lockfile @@ -303,7 +300,7 @@ jobs: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - node-version: ${{ matrix.node == 24 && env.NODE_VERSION_24 || matrix.node == 20 && env.NODE_VERSION_20 || env.NODE_VERSION_22 }} + node-version-file: .github/node-versions/${{ matrix.node }} - name: Download npm artifact uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: @@ -334,7 +331,7 @@ jobs: - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - node-version: ${{ env.NODE_VERSION_24 }} + node-version-file: .github/node-versions/24 cache: pnpm - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a867fe29f..004fbccb6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,11 +9,6 @@ on: permissions: contents: read -env: - NODE_VERSION_20: "20.20.2" - NODE_VERSION_22: "22.23.4" - NODE_VERSION_24: "24.22.1" - jobs: discover-projects: name: Discover projects @@ -24,14 +19,14 @@ jobs: runtime-matrix: ${{ steps.projects.outputs.runtime-matrix }} runtime-count: ${{ steps.projects.outputs.runtime-count }} steps: - - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + - uses: actions/checkout@v7 with: persist-credentials: false fetch-depth: 0 - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@v7 with: - node-version: ${{ env.NODE_VERSION_22 }} + node-version-file: .github/node-versions/22 - name: Build project matrix id: projects env: @@ -53,13 +48,13 @@ jobs: name: Install runs-on: ubuntu-latest steps: - - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@v7 with: - node-version: ${{ env.NODE_VERSION_22 }} + node-version-file: .github/node-versions/22 cache: pnpm - run: pnpm install --frozen-lockfile @@ -67,13 +62,13 @@ jobs: name: Repository quality runs-on: ubuntu-latest steps: - - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@v7 with: - node-version: ${{ env.NODE_VERSION_22 }} + node-version-file: .github/node-versions/22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm run test:ci-projects @@ -96,13 +91,13 @@ jobs: SENTRY_CLI_NO_TELEMETRY: "1" FOSSILIZE_SIGN: "n" steps: - - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@v7 with: - node-version: ${{ env.NODE_VERSION_22 }} + node-version-file: .github/node-versions/22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm --filter sentry run build -- --target darwin-arm64 @@ -127,13 +122,13 @@ jobs: SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} SENTRY_OAUTH_CLIENT_SECRET: ci-test-secret steps: - - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@v7 with: - node-version: ${{ env.NODE_VERSION_22 }} + node-version-file: .github/node-versions/22 cache: pnpm - run: cp .env.example .env.local - run: pnpm install --frozen-lockfile @@ -192,10 +187,10 @@ jobs: PROJECT_NAME: ${{ matrix.name }} CHECK_SCRIPT: ${{ matrix.policy }} run: pnpm --filter "$PROJECT_NAME" run "$CHECK_SCRIPT" - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@v7 if: matrix.e2e != '' with: - node-version: ${{ env.NODE_VERSION_24 }} + node-version-file: .github/node-versions/24 cache: pnpm - name: Run E2E tests on Node 24 if: matrix.e2e != '' @@ -229,7 +224,7 @@ jobs: - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 - uses: actions/setup-node@v7 with: - node-version: ${{ env.NODE_VERSION_22 }} + node-version-file: .github/node-versions/22 cache: pnpm - run: pnpm install --frozen-lockfile - name: Build project dependencies @@ -239,7 +234,7 @@ jobs: run: pnpm --filter sentry run tsx script/build.ts --single - uses: actions/setup-node@v7 with: - node-version: ${{ env.NODE_VERSION_24 }} + node-version-file: .github/node-versions/24 - name: Build npm bundle run: pnpm --filter sentry run tsx script/bundle.ts - name: Run E2E tests on Node 24 @@ -268,19 +263,15 @@ jobs: SENTRY_CLIENT_ID: ${{ vars.SENTRY_CLIENT_ID }} SENTRY_CLI_NO_TELEMETRY: "1" steps: - - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4 - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@v7 with: - node-version: ${{ env.NODE_VERSION_22 }} + node-version-file: .github/node-versions/22 cache: pnpm - run: pnpm install --frozen-lockfile - - name: Build package dependencies - env: - PROJECT_NAME: ${{ matrix.name }} - run: pnpm --filter "${PROJECT_NAME}^..." --if-present run build - name: Build and pack once on Node 22 env: BUILD_SCRIPT: ${{ matrix.npmRuntime }} @@ -295,25 +286,25 @@ jobs: test -s "${packages[0]}" [[ "$(stat -c %s "${packages[0]}")" -le 52428800 ]] mv "${packages[0]}" "$RUNNER_TEMP/npm-package/package.tgz" - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@v7 with: - node-version: ${{ env.NODE_VERSION_20 }} + node-version-file: .github/node-versions/20 - name: Validate packaged runtime on Node 20 env: RUNTIME_BIN: ${{ matrix.runtimeBin }} RUNTIME_PACKAGE: ${{ matrix.name }} run: bash scripts/validate-npm-runtime.sh - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@v7 with: - node-version: ${{ env.NODE_VERSION_22 }} + node-version-file: .github/node-versions/22 - name: Validate packaged runtime on Node 22 env: RUNTIME_BIN: ${{ matrix.runtimeBin }} RUNTIME_PACKAGE: ${{ matrix.name }} run: bash scripts/validate-npm-runtime.sh - - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 + - uses: actions/setup-node@v7 with: - node-version: ${{ env.NODE_VERSION_24 }} + node-version-file: .github/node-versions/24 - name: Validate packaged runtime on Node 24 env: RUNTIME_BIN: ${{ matrix.runtimeBin }} diff --git a/docs/operations/github-actions.md b/docs/operations/github-actions.md index 896b8691b..bf43f198a 100644 --- a/docs/operations/github-actions.md +++ b/docs/operations/github-actions.md @@ -21,6 +21,11 @@ discovery, installation, repository quality, and every selected project. Package-specific exceptions live in `package.json#sentryCi`; the standalone smoke-test suite remains in its own workflow. +`test.yml` and `cli-build.yml` read their exact Node 20, 22, and 24 versions +from `.github/node-versions/`. The npm runtime job calls the self-contained +`sentryCi.npmRuntime` build command once, then validates the same package on +all three Node versions. + `CLI E2E (Node 24)` runs independently of the CLI project job. It builds the standalone CLI on Node 22, then builds the npm bundle and tests both on Node 24. Dependencies and generated sources are prepared once per job. The CLI project diff --git a/scripts/ci-projects.test.mjs b/scripts/ci-projects.test.mjs index 45fe2b9ac..1f9e971d7 100644 --- a/scripts/ci-projects.test.mjs +++ b/scripts/ci-projects.test.mjs @@ -196,9 +196,14 @@ describe("workspace CI selection", () => { assert.match(workflow, /Validate packaged runtime on Node 20/); assert.match(workflow, /Validate packaged runtime on Node 22/); assert.match(workflow, /Validate packaged runtime on Node 24/); - assert.match(workflow, /NODE_VERSION_20: "20\.20\.2"/); - assert.match(workflow, /NODE_VERSION_22: "22\.23\.4"/); - assert.match(workflow, /NODE_VERSION_24: "24\.22\.1"/); + for (const major of [20, 22, 24]) { + const versionFile = `.github/node-versions/${major}`; + assert.ok(workflow.includes(`node-version-file: ${versionFile}`)); + assert.match( + readFileSync(resolve(root, versionFile), "utf8").trim(), + new RegExp(`^${major}\\.\\d+\\.\\d+$`), + ); + } assert.match(workflow, /RUNTIME_RESULT.*needs\.npm-runtime\.result/); assert.match(workflow, /name: Verify JUnit/); assert.match(workflow, /name: Verify coverage/);