From 7203205300ba1a5b85ca6eb7962b61ed689c4a5a Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 16 Apr 2026 16:23:52 +0200 Subject: [PATCH 01/46] perf(aws-serverless): Speed up Lambda layer build with tarball-based install MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace `file:` directory references with `npm pack` tarballs when installing @sentry/* packages into the Lambda layer's node_modules. Previously, `yarn install` used `file:` references to workspace packages with a fresh cache folder (to avoid stale cache issues), taking ~52s. With tarballs, yarn can use its global cache and the install completes in ~8s. Only transitive dependencies of @sentry/aws-serverless are packed (~5 packages), keeping the packing step fast. Total layer build time: ~97s → ~15s. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../scripts/buildLambdaLayer.ts | 111 ++++++++++++------ 1 file changed, 75 insertions(+), 36 deletions(-) diff --git a/packages/aws-serverless/scripts/buildLambdaLayer.ts b/packages/aws-serverless/scripts/buildLambdaLayer.ts index cca3b739bf6b..d49c6a249aca 100644 --- a/packages/aws-serverless/scripts/buildLambdaLayer.ts +++ b/packages/aws-serverless/scripts/buildLambdaLayer.ts @@ -2,7 +2,6 @@ import { nodeFileTrace } from '@vercel/nft'; import * as childProcess from 'child_process'; import * as fs from 'fs'; -import * as os from 'os'; import * as path from 'path'; import { version } from '../package.json'; @@ -22,21 +21,14 @@ function run(cmd: string, options?: childProcess.ExecSyncOptions): string { */ async function buildLambdaLayer(): Promise { console.log('Building Lambda layer.'); - buildPackageJson(); - console.log('Installing local @sentry/aws-serverless into build/aws/dist-serverless/nodejs.'); - // Use a temporary cache folder to avoid stale cache references to local file: packages. - // Yarn's global cache can contain outdated references to build artifacts from other - // @sentry/* packages (e.g., build/node_modules paths that no longer exist), causing - // ENOENT errors during file copying. - // The cache folder must be outside the monorepo to avoid recursive nesting when Yarn - // follows file: links and copies package directories. - const cacheFolder = path.join(os.tmpdir(), `sentry-lambda-build-cache-${Date.now()}`); - run(`yarn install --prod --cwd ./build/aws/dist-serverless/nodejs --cache-folder "${cacheFolder}"`); + const tarballDir = buildTarballsAndPackageJson(); + console.log('Installing @sentry/aws-serverless from tarballs into build/aws/dist-serverless/nodejs.'); + run('yarn install --prod --cwd ./build/aws/dist-serverless/nodejs'); await pruneNodeModules(); fs.rmSync('./build/aws/dist-serverless/nodejs/package.json', { force: true }); fs.rmSync('./build/aws/dist-serverless/nodejs/yarn.lock', { force: true }); - fs.rmSync(cacheFolder, { recursive: true, force: true }); + fs.rmSync(tarballDir, { recursive: true, force: true }); // The layer also includes `awslambda-auto.js`, a helper file which calls `Sentry.init()` and wraps the lambda // handler. It gets run when Node is launched inside the lambda, using the environment variable @@ -170,43 +162,90 @@ function getAllFiles(dir: string): string[] { return files; } -function buildPackageJson(): void { - console.log('Building package.json'); +/** + * Pack @sentry/* packages into tarballs and generate a package.json that references them. + * + * Using tarballs instead of `file:` directory references avoids stale yarn cache issues + * (where yarn's global cache retains outdated build artifact paths from previous builds) + * and allows us to use yarn's global cache for faster installs. + * + * Only packs packages that are transitive dependencies of @sentry/aws-serverless to keep + * the packing step fast. + */ +function buildTarballsAndPackageJson(): string { + const tarballDir = path.resolve('./build/aws/tarballs'); + fsForceMkdirSync(tarballDir); + const packagesDir = path.resolve(__dirname, '../..'); - const packageDirs = fs - .readdirSync(packagesDir, { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) - .map(dirent => dirent.name) - .filter(name => !name.startsWith('.')) // Skip hidden directories - .sort(); + const sentryPackages = collectSentryDependencies(packagesDir); + + console.log(`Packing ${sentryPackages.size} @sentry/* packages into tarballs.`); const resolutions: Record = {}; - for (const packageDir of packageDirs) { - const packageJsonPath = path.join(packagesDir, packageDir, 'package.json'); - if (fs.existsSync(packageJsonPath)) { - try { - const packageContent = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as { name?: string }; - const packageName = packageContent.name; - if (typeof packageName === 'string' && packageName) { - resolutions[packageName] = `file:../../../../../../packages/${packageDir}`; - } - } catch { - console.warn(`Warning: Could not read package.json for ${packageDir}`); - } - } + for (const [packageName, packageDir] of sentryPackages) { + run(`npm pack --pack-destination "${tarballDir}"`, { + cwd: path.join(packagesDir, packageDir), + stdio: 'pipe', + }); + const tarballName = `${packageName.replace('@', '').replace('/', '-')}-${version}.tgz`; + resolutions[packageName] = `file:${path.join(tarballDir, tarballName)}`; + } + + const awsServerlessTarball = resolutions['@sentry/aws-serverless']; + if (!awsServerlessTarball) { + throw new Error('Failed to pack @sentry/aws-serverless'); } const packageJson = { dependencies: { - '@sentry/aws-serverless': 'file:../../../../../../packages/aws-serverless', + '@sentry/aws-serverless': awsServerlessTarball, }, resolutions, }; fsForceMkdirSync('./build/aws/dist-serverless/nodejs'); - const packageJsonPath = './build/aws/dist-serverless/nodejs/package.json'; - fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); + fs.writeFileSync('./build/aws/dist-serverless/nodejs/package.json', JSON.stringify(packageJson, null, 2)); + + return tarballDir; +} + +/** + * Collect all @sentry/* and @sentry-internal/* packages that are transitive + * dependencies of @sentry/aws-serverless. + * Returns a Map of packageName -> directory name. + */ +function collectSentryDependencies(packagesDir: string): Map { + const result = new Map(); + + // Build a lookup of package name -> directory name + const nameToDir = new Map(); + for (const dirent of fs.readdirSync(packagesDir, { withFileTypes: true })) { + if (!dirent.isDirectory() || dirent.name.startsWith('.')) continue; + const pkgPath = path.join(packagesDir, dirent.name, 'package.json'); + if (!fs.existsSync(pkgPath)) continue; + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { name?: string }; + if (pkg.name) { + nameToDir.set(pkg.name, dirent.name); + } + } + + function collect(packageName: string): void { + if (result.has(packageName)) return; + const dir = nameToDir.get(packageName); + if (!dir) return; + result.set(packageName, dir); + const pkgPath = path.join(packagesDir, dir, 'package.json'); + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { dependencies?: Record }; + for (const dep of Object.keys(pkg.dependencies || {})) { + if (dep.startsWith('@sentry/') || dep.startsWith('@sentry-internal/')) { + collect(dep); + } + } + } + + collect('@sentry/aws-serverless'); + return result; } function replaceSDKSource(): void { From b57849c68e45e2ce10bd089d56300dd027a4418d Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 16 Apr 2026 16:40:07 +0200 Subject: [PATCH 02/46] chore(ci): Do not build AWS lambda layer in build step Instead, only build this before uploading artifacts, as we do not really need this before. --- .github/workflows/build.yml | 25 +++++++++++++++++++++++++ package.json | 3 ++- packages/aws-serverless/package.json | 4 ++-- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 544bb7900008..358cdad2e8a1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -165,6 +165,27 @@ jobs: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry-internal/browser-integration-tests') }} + job_verify_build_layer: + name: Verify Lambda layer build + needs: [job_get_metadata, job_build] + timeout-minutes: 10 + runs-on: ubuntu-24.04 + steps: + - name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) + uses: actions/checkout@v6 + with: + ref: ${{ env.HEAD_COMMIT }} + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version-file: 'package.json' + - name: Restore caches + uses: ./.github/actions/restore-cache + with: + dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Build Lambda layer + run: yarn build:layer + job_check_branches: name: Check PR branches needs: job_get_metadata @@ -319,6 +340,9 @@ jobs: - name: Pack tarballs run: yarn build:tarball + - name: Build Lambda layer + run: yarn build:layer + - name: Archive artifacts uses: actions/upload-artifact@v7 with: @@ -1134,6 +1158,7 @@ jobs: job_check_lockfile, job_check_format, job_circular_dep_check, + job_verify_build_layer, job_size_check, ] # Always run this, even if a dependent job failed diff --git a/package.json b/package.json index 3d211ca42067..694bfca665c0 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,9 @@ { "private": true, "scripts": { - "build": "node ./scripts/verify-packages-versions.js && nx run-many -t build:transpile build:types build:bundle build:layer", + "build": "node ./scripts/verify-packages-versions.js && nx run-many -t build:transpile build:types build:bundle", "build:bundle": "nx run-many -t build:bundle", + "build:layer": "nx run-many -t build:layer", "build:dev": "nx run-many -t build:types build:transpile", "build:dev:filter": "nx run-many -t build:dev -p", "build:transpile": "nx run-many -t build:transpile", diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json index 0e16d2caa192..becbd6b16ab7 100644 --- a/packages/aws-serverless/package.json +++ b/packages/aws-serverless/package.json @@ -80,9 +80,9 @@ "@vercel/nft": "^1.3.0" }, "scripts": { - "build": "run-p build:transpile build:types build:extension && run-s build:layer", + "build": "run-p build:transpile build:types", "build:extension": "rollup -c rollup.lambda-extension.config.mjs && yarn ts-node scripts/buildLambdaExtension.ts", - "build:layer": "rimraf build/aws && yarn ts-node scripts/buildLambdaLayer.ts", + "build:layer": "rimraf build/aws && yarn build:extension && yarn ts-node scripts/buildLambdaLayer.ts", "build:dev": "run-p build:transpile build:types", "build:transpile": "rollup -c rollup.npm.config.mjs", "build:types": "run-s build:types:core build:types:downlevel", From b26d4fb8a49722daf88b129cdb6ab13cbf74eadd Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 16 Apr 2026 16:43:00 +0200 Subject: [PATCH 03/46] Revert "perf(aws-serverless): Speed up Lambda layer build with tarball-based install" This reverts commit 7203205300ba1a5b85ca6eb7962b61ed689c4a5a. --- .../scripts/buildLambdaLayer.ts | 111 ++++++------------ 1 file changed, 36 insertions(+), 75 deletions(-) diff --git a/packages/aws-serverless/scripts/buildLambdaLayer.ts b/packages/aws-serverless/scripts/buildLambdaLayer.ts index d49c6a249aca..cca3b739bf6b 100644 --- a/packages/aws-serverless/scripts/buildLambdaLayer.ts +++ b/packages/aws-serverless/scripts/buildLambdaLayer.ts @@ -2,6 +2,7 @@ import { nodeFileTrace } from '@vercel/nft'; import * as childProcess from 'child_process'; import * as fs from 'fs'; +import * as os from 'os'; import * as path from 'path'; import { version } from '../package.json'; @@ -21,14 +22,21 @@ function run(cmd: string, options?: childProcess.ExecSyncOptions): string { */ async function buildLambdaLayer(): Promise { console.log('Building Lambda layer.'); - const tarballDir = buildTarballsAndPackageJson(); - console.log('Installing @sentry/aws-serverless from tarballs into build/aws/dist-serverless/nodejs.'); - run('yarn install --prod --cwd ./build/aws/dist-serverless/nodejs'); + buildPackageJson(); + console.log('Installing local @sentry/aws-serverless into build/aws/dist-serverless/nodejs.'); + // Use a temporary cache folder to avoid stale cache references to local file: packages. + // Yarn's global cache can contain outdated references to build artifacts from other + // @sentry/* packages (e.g., build/node_modules paths that no longer exist), causing + // ENOENT errors during file copying. + // The cache folder must be outside the monorepo to avoid recursive nesting when Yarn + // follows file: links and copies package directories. + const cacheFolder = path.join(os.tmpdir(), `sentry-lambda-build-cache-${Date.now()}`); + run(`yarn install --prod --cwd ./build/aws/dist-serverless/nodejs --cache-folder "${cacheFolder}"`); await pruneNodeModules(); fs.rmSync('./build/aws/dist-serverless/nodejs/package.json', { force: true }); fs.rmSync('./build/aws/dist-serverless/nodejs/yarn.lock', { force: true }); - fs.rmSync(tarballDir, { recursive: true, force: true }); + fs.rmSync(cacheFolder, { recursive: true, force: true }); // The layer also includes `awslambda-auto.js`, a helper file which calls `Sentry.init()` and wraps the lambda // handler. It gets run when Node is launched inside the lambda, using the environment variable @@ -162,90 +170,43 @@ function getAllFiles(dir: string): string[] { return files; } -/** - * Pack @sentry/* packages into tarballs and generate a package.json that references them. - * - * Using tarballs instead of `file:` directory references avoids stale yarn cache issues - * (where yarn's global cache retains outdated build artifact paths from previous builds) - * and allows us to use yarn's global cache for faster installs. - * - * Only packs packages that are transitive dependencies of @sentry/aws-serverless to keep - * the packing step fast. - */ -function buildTarballsAndPackageJson(): string { - const tarballDir = path.resolve('./build/aws/tarballs'); - fsForceMkdirSync(tarballDir); - +function buildPackageJson(): void { + console.log('Building package.json'); const packagesDir = path.resolve(__dirname, '../..'); - const sentryPackages = collectSentryDependencies(packagesDir); - - console.log(`Packing ${sentryPackages.size} @sentry/* packages into tarballs.`); + const packageDirs = fs + .readdirSync(packagesDir, { withFileTypes: true }) + .filter(dirent => dirent.isDirectory()) + .map(dirent => dirent.name) + .filter(name => !name.startsWith('.')) // Skip hidden directories + .sort(); const resolutions: Record = {}; - for (const [packageName, packageDir] of sentryPackages) { - run(`npm pack --pack-destination "${tarballDir}"`, { - cwd: path.join(packagesDir, packageDir), - stdio: 'pipe', - }); - const tarballName = `${packageName.replace('@', '').replace('/', '-')}-${version}.tgz`; - resolutions[packageName] = `file:${path.join(tarballDir, tarballName)}`; - } - - const awsServerlessTarball = resolutions['@sentry/aws-serverless']; - if (!awsServerlessTarball) { - throw new Error('Failed to pack @sentry/aws-serverless'); + for (const packageDir of packageDirs) { + const packageJsonPath = path.join(packagesDir, packageDir, 'package.json'); + if (fs.existsSync(packageJsonPath)) { + try { + const packageContent = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as { name?: string }; + const packageName = packageContent.name; + if (typeof packageName === 'string' && packageName) { + resolutions[packageName] = `file:../../../../../../packages/${packageDir}`; + } + } catch { + console.warn(`Warning: Could not read package.json for ${packageDir}`); + } + } } const packageJson = { dependencies: { - '@sentry/aws-serverless': awsServerlessTarball, + '@sentry/aws-serverless': 'file:../../../../../../packages/aws-serverless', }, resolutions, }; fsForceMkdirSync('./build/aws/dist-serverless/nodejs'); - fs.writeFileSync('./build/aws/dist-serverless/nodejs/package.json', JSON.stringify(packageJson, null, 2)); - - return tarballDir; -} - -/** - * Collect all @sentry/* and @sentry-internal/* packages that are transitive - * dependencies of @sentry/aws-serverless. - * Returns a Map of packageName -> directory name. - */ -function collectSentryDependencies(packagesDir: string): Map { - const result = new Map(); - - // Build a lookup of package name -> directory name - const nameToDir = new Map(); - for (const dirent of fs.readdirSync(packagesDir, { withFileTypes: true })) { - if (!dirent.isDirectory() || dirent.name.startsWith('.')) continue; - const pkgPath = path.join(packagesDir, dirent.name, 'package.json'); - if (!fs.existsSync(pkgPath)) continue; - const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { name?: string }; - if (pkg.name) { - nameToDir.set(pkg.name, dirent.name); - } - } - - function collect(packageName: string): void { - if (result.has(packageName)) return; - const dir = nameToDir.get(packageName); - if (!dir) return; - result.set(packageName, dir); - const pkgPath = path.join(packagesDir, dir, 'package.json'); - const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as { dependencies?: Record }; - for (const dep of Object.keys(pkg.dependencies || {})) { - if (dep.startsWith('@sentry/') || dep.startsWith('@sentry-internal/')) { - collect(dep); - } - } - } - - collect('@sentry/aws-serverless'); - return result; + const packageJsonPath = './build/aws/dist-serverless/nodejs/package.json'; + fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); } function replaceSDKSource(): void { From df7849c19604bed279b45d5ecdd0e34c4ad806ec Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 16 Apr 2026 17:26:51 +0200 Subject: [PATCH 04/46] ensure extension is run for tarball as well --- packages/aws-serverless/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json index becbd6b16ab7..a5d9e815e234 100644 --- a/packages/aws-serverless/package.json +++ b/packages/aws-serverless/package.json @@ -80,10 +80,10 @@ "@vercel/nft": "^1.3.0" }, "scripts": { - "build": "run-p build:transpile build:types", + "build": "run-p build:transpile build:types build:extension", "build:extension": "rollup -c rollup.lambda-extension.config.mjs && yarn ts-node scripts/buildLambdaExtension.ts", - "build:layer": "rimraf build/aws && yarn build:extension && yarn ts-node scripts/buildLambdaLayer.ts", - "build:dev": "run-p build:transpile build:types", + "build:layer": "rimraf build/aws && yarn ts-node scripts/buildLambdaLayer.ts", + "build:dev": "run-p build:transpile build:types build:extension", "build:transpile": "rollup -c rollup.npm.config.mjs", "build:types": "run-s build:types:core build:types:downlevel", "build:types:core": "tsc -p tsconfig.types.json", From 3500c6b19ffcb6e4fe64ca72f40b5ce10c56f265 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 16 Apr 2026 17:33:37 +0200 Subject: [PATCH 05/46] avoid build dev change --- packages/aws-serverless/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json index a5d9e815e234..cde6f4914bca 100644 --- a/packages/aws-serverless/package.json +++ b/packages/aws-serverless/package.json @@ -83,7 +83,7 @@ "build": "run-p build:transpile build:types build:extension", "build:extension": "rollup -c rollup.lambda-extension.config.mjs && yarn ts-node scripts/buildLambdaExtension.ts", "build:layer": "rimraf build/aws && yarn ts-node scripts/buildLambdaLayer.ts", - "build:dev": "run-p build:transpile build:types build:extension", + "build:dev": "run-p build:transpile build:types", "build:transpile": "rollup -c rollup.npm.config.mjs", "build:types": "run-s build:types:core build:types:downlevel", "build:types:core": "tsc -p tsconfig.types.json", From d8898a4d6f460a1d1d3dd417b32fa57dee5a47cc Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Fri, 17 Apr 2026 09:41:33 +0200 Subject: [PATCH 06/46] better dependency graph --- .github/workflows/build.yml | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 358cdad2e8a1..9e0dc4442d5b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,6 +48,9 @@ env: ${{ github.workspace }}/packages/ember/*.d.ts ${{ github.workspace }}/packages/gatsby/*.d.ts + CACHED_BUILD_LAYER_PATHS: | + ${{ github.workspace }}/packages/*/build/aws + BUILD_CACHE_TARBALL_KEY: tarball-${{ github.event.inputs.commit || github.sha }} # GH will use the first restore-key it finds that matches @@ -165,8 +168,8 @@ jobs: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry-internal/browser-integration-tests') }} - job_verify_build_layer: - name: Verify Lambda layer build + job_build_layer: + name: Build Lambda layer needs: [job_get_metadata, job_build] timeout-minutes: 10 runs-on: ubuntu-24.04 @@ -186,6 +189,15 @@ jobs: - name: Build Lambda layer run: yarn build:layer + - name: Upload build artifacts + uses: actions/upload-artifact@v7 + with: + name: build-layer-output + path: ${{ env.CACHED_BUILD_LAYER_PATHS }} + retention-days: 4 + compression-level: 6 + overwrite: true + job_check_branches: name: Check PR branches needs: job_get_metadata @@ -319,7 +331,7 @@ jobs: job_artifacts: name: Upload Artifacts - needs: [job_get_metadata, job_build] + needs: [job_get_metadata, job_build, job_build_layer] runs-on: ubuntu-24.04 # Build artifacts are only needed for releasing workflow. if: needs.job_get_metadata.outputs.is_release == 'true' @@ -337,12 +349,14 @@ jobs: with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Restore build layer artifacts + uses: actions/download-artifact@v7 + with: + name: build-layer-output + - name: Pack tarballs run: yarn build:tarball - - name: Build Lambda layer - run: yarn build:layer - - name: Archive artifacts uses: actions/upload-artifact@v7 with: @@ -926,7 +940,7 @@ jobs: # See: https://github.com/actions/runner/issues/2205 if: always() && needs.job_e2e_prepare.result == 'success' && needs.job_e2e_prepare.outputs.matrix != '{"include":[]}' - needs: [job_get_metadata, job_build, job_e2e_prepare] + needs: [job_get_metadata, job_build, job_build_layer, job_e2e_prepare] runs-on: ubuntu-24.04 timeout-minutes: 15 env: @@ -972,6 +986,12 @@ jobs: with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Restore build layer artifacts + uses: actions/download-artifact@v7 + if: matrix.test-application == 'aws-serverless' + with: + name: build-layer-output + - name: Restore tarball cache uses: actions/cache/restore@v5 id: restore-tarball-cache From 7ffc0b88a1bbc3b4a4dc72195990dc1d5c57ad19 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Fri, 17 Apr 2026 09:47:05 +0200 Subject: [PATCH 07/46] fix job --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9e0dc4442d5b..3947e2cbaac0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1178,7 +1178,7 @@ jobs: job_check_lockfile, job_check_format, job_circular_dep_check, - job_verify_build_layer, + job_build_layer, job_size_check, ] # Always run this, even if a dependent job failed From 7ca058dec5ef8eb1e7da79e1d429355d1aee6814 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Fri, 17 Apr 2026 10:01:16 +0200 Subject: [PATCH 08/46] only run layer build when needed --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3947e2cbaac0..9de650a6821b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -167,10 +167,14 @@ jobs: changed_browser_integration: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry-internal/browser-integration-tests') }} + changed_aws_serverless: + ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, + '@sentry/aws-serverless') }} job_build_layer: name: Build Lambda layer needs: [job_get_metadata, job_build] + if: needs.job_build.outputs.changed_aws_serverless == 'true' || github.event_name != 'pull_request' timeout-minutes: 10 runs-on: ubuntu-24.04 steps: From 943eb4b856f48080095d2adf05eec665020a9e59 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Fri, 17 Apr 2026 10:59:19 +0200 Subject: [PATCH 09/46] fix path --- .github/workflows/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9de650a6821b..f44657e125f6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,8 +48,9 @@ env: ${{ github.workspace }}/packages/ember/*.d.ts ${{ github.workspace }}/packages/gatsby/*.d.ts + # Avoid '*' here: upload-artifact flattens paths after the first wildcard (drops the packages/ prefix). CACHED_BUILD_LAYER_PATHS: | - ${{ github.workspace }}/packages/*/build/aws + ${{ github.workspace }}/packages/aws-serverless/build/aws BUILD_CACHE_TARBALL_KEY: tarball-${{ github.event.inputs.commit || github.sha }} From fc5fbff3217a4d7d9a87bdb855c0d79bd09c2a0d Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Fri, 17 Apr 2026 11:31:53 +0200 Subject: [PATCH 10/46] use path directly --- .github/workflows/build.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f44657e125f6..ca84c1fc0c5d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,9 +48,8 @@ env: ${{ github.workspace }}/packages/ember/*.d.ts ${{ github.workspace }}/packages/gatsby/*.d.ts - # Avoid '*' here: upload-artifact flattens paths after the first wildcard (drops the packages/ prefix). - CACHED_BUILD_LAYER_PATHS: | - ${{ github.workspace }}/packages/aws-serverless/build/aws + # Upload/download this directory only (no globs): must match pnpm link .../build/aws/dist-serverless/ in aws-serverless E2E. + CACHED_BUILD_LAYER_ARTIFACT_PATH: ${{ github.workspace }}/packages/aws-serverless/build/aws/dist-serverless BUILD_CACHE_TARBALL_KEY: tarball-${{ github.event.inputs.commit || github.sha }} @@ -198,7 +197,7 @@ jobs: uses: actions/upload-artifact@v7 with: name: build-layer-output - path: ${{ env.CACHED_BUILD_LAYER_PATHS }} + path: ${{ env.CACHED_BUILD_LAYER_ARTIFACT_PATH }} retention-days: 4 compression-level: 6 overwrite: true @@ -358,6 +357,7 @@ jobs: uses: actions/download-artifact@v7 with: name: build-layer-output + path: ${{ env.CACHED_BUILD_LAYER_ARTIFACT_PATH }} - name: Pack tarballs run: yarn build:tarball @@ -996,6 +996,7 @@ jobs: if: matrix.test-application == 'aws-serverless' with: name: build-layer-output + path: ${{ env.CACHED_BUILD_LAYER_ARTIFACT_PATH }} - name: Restore tarball cache uses: actions/cache/restore@v5 From cab77a91082d471ddaf9e725ba5a5e6794e7ba43 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Fri, 17 Apr 2026 11:47:21 +0200 Subject: [PATCH 11/46] ensure tarball depends on extension --- .github/workflows/build.yml | 16 ++++++---------- packages/aws-serverless/package.json | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ca84c1fc0c5d..40dceb2cb6d6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,18 +38,14 @@ env: # DEPENDENCY_CACHE_KEY: can't be set here because we don't have access to yarn.lock - # WARNING: this disables cross os caching as ~ and - # github.workspace evaluate to differents paths - # packages/utils/cjs and packages/utils/esm: Symlinks to the folders inside of `build`, needed for tests - CACHED_BUILD_PATHS: | + BUILD_PATHS: | ${{ github.workspace }}/dev-packages/*/build ${{ github.workspace }}/packages/*/build ${{ github.workspace }}/packages/*/lib ${{ github.workspace }}/packages/ember/*.d.ts ${{ github.workspace }}/packages/gatsby/*.d.ts - # Upload/download this directory only (no globs): must match pnpm link .../build/aws/dist-serverless/ in aws-serverless E2E. - CACHED_BUILD_LAYER_ARTIFACT_PATH: ${{ github.workspace }}/packages/aws-serverless/build/aws/dist-serverless + BUILD_LAYER_PATH: ${{ github.workspace }}/packages/aws-serverless/build/aws/dist-serverless BUILD_CACHE_TARBALL_KEY: tarball-${{ github.event.inputs.commit || github.sha }} @@ -136,7 +132,7 @@ jobs: uses: actions/upload-artifact@v7 with: name: build-output - path: ${{ env.CACHED_BUILD_PATHS }} + path: ${{ env.BUILD_PATHS }} retention-days: 4 compression-level: 6 overwrite: true @@ -197,7 +193,7 @@ jobs: uses: actions/upload-artifact@v7 with: name: build-layer-output - path: ${{ env.CACHED_BUILD_LAYER_ARTIFACT_PATH }} + path: ${{ env.BUILD_LAYER_PATH }} retention-days: 4 compression-level: 6 overwrite: true @@ -357,7 +353,7 @@ jobs: uses: actions/download-artifact@v7 with: name: build-layer-output - path: ${{ env.CACHED_BUILD_LAYER_ARTIFACT_PATH }} + path: ${{ env.BUILD_LAYER_PATH }} - name: Pack tarballs run: yarn build:tarball @@ -996,7 +992,7 @@ jobs: if: matrix.test-application == 'aws-serverless' with: name: build-layer-output - path: ${{ env.CACHED_BUILD_LAYER_ARTIFACT_PATH }} + path: ${{ env.BUILD_LAYER_PATH }} - name: Restore tarball cache uses: actions/cache/restore@v5 diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json index cde6f4914bca..14f58e143198 100644 --- a/packages/aws-serverless/package.json +++ b/packages/aws-serverless/package.json @@ -145,6 +145,23 @@ "{projectRoot}/build/aws" ], "cache": true + }, + "build:tarball": { + "inputs": [ + "production", + "^production" + ], + "dependsOn": [ + "build:transpile", + "^build:transpile", + "build:types", + "^build:types", + "build:extension" + ], + "outputs": [ + "{projectRoot}/*.tgz" + ], + "cache": true } } } From f1e1d9708943380fbab5b19ffcdc03626253180a Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Fri, 17 Apr 2026 11:49:14 +0200 Subject: [PATCH 12/46] build and cache extension --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 694bfca665c0..c0702e176bc5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": true, "scripts": { - "build": "node ./scripts/verify-packages-versions.js && nx run-many -t build:transpile build:types build:bundle", + "build": "node ./scripts/verify-packages-versions.js && nx run-many -t build:transpile build:types build:bundle build:extension", "build:bundle": "nx run-many -t build:bundle", "build:layer": "nx run-many -t build:layer", "build:dev": "nx run-many -t build:types build:transpile", From 19230d7f7def5604f15f1a1099931a4ba114031c Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Fri, 17 Apr 2026 11:57:45 +0200 Subject: [PATCH 13/46] avoid unnecessary build cache --- .github/workflows/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 40dceb2cb6d6..b88951916744 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,8 +41,6 @@ env: BUILD_PATHS: | ${{ github.workspace }}/dev-packages/*/build ${{ github.workspace }}/packages/*/build - ${{ github.workspace }}/packages/*/lib - ${{ github.workspace }}/packages/ember/*.d.ts ${{ github.workspace }}/packages/gatsby/*.d.ts BUILD_LAYER_PATH: ${{ github.workspace }}/packages/aws-serverless/build/aws/dist-serverless From 120b10da46107a0dcfd9ff1826fa903b7db86d82 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 09:35:00 +0200 Subject: [PATCH 14/46] chore(ci): Streamline tarball packaging & e2e test matrix generation --- .github/workflows/build.yml | 83 +++++++++++-------------------- .github/workflows/ci-metadata.yml | 22 ++++++++ 2 files changed, 52 insertions(+), 53 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c92fb6b05838..ed343bf49c34 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,7 +48,7 @@ env: ${{ github.workspace }}/packages/ember/*.d.ts ${{ github.workspace }}/packages/gatsby/*.d.ts - BUILD_CACHE_TARBALL_KEY: tarball-${{ github.event.inputs.commit || github.sha }} + BUILD_TARBALL_PATH: ${{ github.workspace }}/packages/*/*.tgz # GH will use the first restore-key it finds that matches # So it will start by looking for one from the same branch, else take the newest one it can find elsewhere @@ -298,7 +298,7 @@ jobs: job_artifacts: name: Upload Artifacts - needs: [job_get_metadata, job_build] + needs: [job_get_metadata, job_build, job_build_tarballs] runs-on: ubuntu-24.04 # Build artifacts are only needed for releasing workflow. if: needs.job_get_metadata.outputs.is_release == 'true' @@ -316,8 +316,10 @@ jobs: with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} - - name: Pack tarballs - run: yarn build:tarball + - name: Restore tarball artifacts + uses: actions/download-artifact@v7 + with: + name: tarball-output - name: Archive artifacts uses: actions/upload-artifact@v7 @@ -834,19 +836,16 @@ jobs: cd packages/remix yarn test:integration:ci - job_e2e_prepare: - name: Prepare E2E tests + job_build_tarballs: + name: Build tarballs # We want to run this if: # - The build job was successful, not skipped if: | always() && needs.job_build.result == 'success' needs: [job_get_metadata, job_build] - runs-on: ubuntu-24.04-large-js + runs-on: ubuntu-24.04 timeout-minutes: 15 - outputs: - matrix: ${{ steps.matrix.outputs.matrix }} - matrix-optional: ${{ steps.matrix-optional.outputs.matrix }} steps: - name: Check out base commit (${{ github.event.pull_request.base.sha }}) uses: actions/checkout@v6 @@ -876,33 +875,23 @@ jobs: - name: Build tarballs run: yarn build:tarball - - name: Stores tarballs in cache - uses: actions/cache/save@v5 + - name: Upload tarball artifacts + uses: actions/upload-artifact@v7 with: - path: ${{ github.workspace }}/packages/*/*.tgz - key: ${{ env.BUILD_CACHE_TARBALL_KEY }} - - - name: Determine which E2E test applications should be run - id: matrix - run: - yarn --silent ci:build-matrix --base=${{ (github.event_name == 'pull_request' && - github.event.pull_request.base.sha) || '' }} >> $GITHUB_OUTPUT - working-directory: dev-packages/e2e-tests - - - name: Determine which optional E2E test applications should be run - id: matrix-optional - run: - yarn --silent ci:build-matrix-optional --base=${{ (github.event_name == 'pull_request' && - github.event.pull_request.base.sha) || '' }} >> $GITHUB_OUTPUT - working-directory: dev-packages/e2e-tests + name: tarball-output + path: ${{ env.BUILD_TARBALL_PATH }} + retention-days: 4 + compression-level: 6 + overwrite: true job_e2e_tests: name: E2E ${{ matrix.label || matrix.test-application }} Test # We need to add the `always()` check here because the previous step has this as well :( # See: https://github.com/actions/runner/issues/2205 if: - always() && needs.job_e2e_prepare.result == 'success' && needs.job_e2e_prepare.outputs.matrix != '{"include":[]}' - needs: [job_get_metadata, job_build, job_e2e_prepare] + always() && needs.job_build_tarballs.result == 'success' && needs.job_get_metadata.outputs.e2e-matrix + !='{"include":[]}' + needs: [job_get_metadata, job_build, job_build_tarballs] runs-on: ubuntu-24.04 timeout-minutes: 15 env: @@ -916,7 +905,7 @@ jobs: E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false - matrix: ${{ fromJson(needs.job_e2e_prepare.outputs.matrix) }} + matrix: ${{ fromJson(needs.job_get_metadata.outputs.e2e-matrix) }} steps: - name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) uses: actions/checkout@v6 @@ -950,16 +939,10 @@ jobs: with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} - - name: Restore tarball cache - uses: actions/cache/restore@v5 - id: restore-tarball-cache + - name: Restore tarball artifacts + uses: actions/download-artifact@v7 with: - path: ${{ github.workspace }}/packages/*/*.tgz - key: ${{ env.BUILD_CACHE_TARBALL_KEY }} - - - name: Build tarballs if not cached - if: steps.restore-tarball-cache.outputs.cache-hit != 'true' - run: yarn build:tarball + name: tarball-output - name: Prepare e2e tests run: yarn test:prepare @@ -1030,10 +1013,10 @@ jobs: # We need to add the `always()` check here because the previous step has this as well :( # See: https://github.com/actions/runner/issues/2205 if: - always() && needs.job_get_metadata.outputs.is_release != 'true' && needs.job_e2e_prepare.result == 'success' && - needs.job_e2e_prepare.outputs.matrix-optional != '{"include":[]}' && (github.event_name != 'pull_request' || + always() && needs.job_get_metadata.outputs.is_release != 'true' && needs.job_build_tarballs.result == 'success' && + needs.job_get_metadata.outputs.e2e-matrix-optional != '{"include":[]}' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]' - needs: [job_get_metadata, job_build, job_e2e_prepare] + needs: [job_get_metadata, job_build, job_build_tarballs] runs-on: ubuntu-24.04 timeout-minutes: 15 env: @@ -1047,7 +1030,7 @@ jobs: E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false - matrix: ${{ fromJson(needs.job_e2e_prepare.outputs.matrix-optional) }} + matrix: ${{ fromJson(needs.job_get_metadata.outputs.e2e-matrix-optional) }} steps: - name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) @@ -1066,16 +1049,10 @@ jobs: with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} - - name: Restore tarball cache - uses: actions/cache/restore@v5 - id: restore-tarball-cache + - name: Restore tarball artifacts + uses: actions/download-artifact@v7 with: - path: ${{ github.workspace }}/packages/*/*.tgz - key: ${{ env.BUILD_CACHE_TARBALL_KEY }} - - - name: Build tarballs if not cached - if: steps.restore-tarball-cache.outputs.cache-hit != 'true' - run: yarn build:tarball + name: tarball-output - name: Prepare E2E tests run: yarn test:prepare diff --git a/.github/workflows/ci-metadata.yml b/.github/workflows/ci-metadata.yml index 0f39590bf167..b46e6bdb3f04 100644 --- a/.github/workflows/ci-metadata.yml +++ b/.github/workflows/ci-metadata.yml @@ -31,6 +31,12 @@ on: force_skip_cache: description: 'Whether to skip caching (schedule or ci-skip-cache label)' value: ${{ jobs.get_metadata.outputs.force_skip_cache }} + e2e-matrix: + description: 'The matrix of E2E test applications to run' + value: ${{ jobs.get_metadata.outputs.e2e-matrix }} + e2e-matrix-optional: + description: 'The matrix of optional E2E test applications to run' + value: ${{ jobs.get_metadata.outputs.e2e-matrix-optional }} jobs: get_metadata: @@ -70,6 +76,20 @@ jobs: any_code: - '!**/*.md' + - name: Determine which test applications should be run + id: matrix + run: + yarn --silent ci:build-matrix --base=${{ (github.event_name == 'pull_request' && + github.event.pull_request.base.sha) || '' }} >> $GITHUB_OUTPUT + working-directory: dev-packages/e2e-tests + + - name: Determine which optional E2E test applications should be run + id: matrix-optional + run: + yarn --silent ci:build-matrix-optional --base=${{ (github.event_name == 'pull_request' && + github.event.pull_request.base.sha) || '' }} >> $GITHUB_OUTPUT + working-directory: dev-packages/e2e-tests + outputs: commit_label: '${{ env.COMMIT_SHA }}: ${{ env.COMMIT_MESSAGE }}' # Note: These next three have to be checked as strings ('true'/'false')! @@ -87,3 +107,5 @@ jobs: force_skip_cache: ${{ github.event_name == 'schedule' || (github.event_name == 'pull_request' && contains(toJSON(github.event.pull_request.labels.*.name), 'ci-skip-cache')) }} + e2e-matrix: ${{ steps.matrix.outputs.matrix }} + e2e-matrix-optional: ${{ steps.matrix-optional.outputs.matrix }} From e21af8860fc311f1eaf22274c08248186e3e46fe Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 10:03:16 +0200 Subject: [PATCH 15/46] use npx for test matrix thing --- dev-packages/e2e-tests/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev-packages/e2e-tests/package.json b/dev-packages/e2e-tests/package.json index 25d87ad10a6e..e03c4f73b7bb 100644 --- a/dev-packages/e2e-tests/package.json +++ b/dev-packages/e2e-tests/package.json @@ -12,8 +12,8 @@ "test:prepare": "ts-node prepare.ts", "test:validate": "ts-node validate-packed-tarball-setup.ts", "clean": "rimraf tmp node_modules packed && yarn clean:test-applications && yarn clean:pnpm", - "ci:build-matrix": "ts-node ./lib/getTestMatrix.ts", - "ci:build-matrix-optional": "ts-node ./lib/getTestMatrix.ts --optional=true", + "ci:build-matrix": "npx ts-node ./lib/getTestMatrix.ts", + "ci:build-matrix-optional": "npx ts-node ./lib/getTestMatrix.ts --optional=true", "ci:copy-to-temp": "ts-node ./ciCopyToTemp.ts", "ci:pnpm-overrides": "ts-node ./ciPnpmOverrides.ts", "clean:test-applications": "rimraf --glob test-applications/**/{node_modules,dist,build,.next,.nuxt,.sveltekit,.react-router,.astro,.output,pnpm-lock.yaml,.last-run.json,test-results,.angular,event-dumps}", From 15bf4bf656a21ef82fe3a0acb0f40625b5995108 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 10:07:32 +0200 Subject: [PATCH 16/46] avoid glob usage so no dependencies are needed --- dev-packages/e2e-tests/lib/getTestMatrix.ts | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/dev-packages/e2e-tests/lib/getTestMatrix.ts b/dev-packages/e2e-tests/lib/getTestMatrix.ts index 86a4bda3e701..cd561de39ee2 100644 --- a/dev-packages/e2e-tests/lib/getTestMatrix.ts +++ b/dev-packages/e2e-tests/lib/getTestMatrix.ts @@ -1,8 +1,6 @@ import { execSync } from 'child_process'; import * as fs from 'fs'; -import { sync as globSync } from 'glob'; import * as path from 'path'; -import { dirname } from 'path'; import { parseArgs } from 'util'; interface MatrixInclude { @@ -52,9 +50,7 @@ function run(): void { // eslint-disable-next-line no-console console.error(`Parsed command line arguments: base=${base}, head=${head}, optional=${optional}`); - const testApplications = globSync('*/package.json', { - cwd: `${__dirname}/../test-applications`, - }).map(filePath => dirname(filePath)); + const testApplications = discoverTestApplicationDirs(); // For GitHub Action debugging (using stderr the 'matrix=...' output is not polluted) // eslint-disable-next-line no-console @@ -78,6 +74,17 @@ function run(): void { console.log(`matrix=${JSON.stringify({ include: includes })}`); } +/** Direct children of `test-applications/` that contain a `package.json` (replaces glob one-segment + package.json). */ +function discoverTestApplicationDirs(): string[] { + const appsRoot = path.join(__dirname, '..', 'test-applications'); + return fs + .readdirSync(appsRoot, { withFileTypes: true }) + .filter(entry => entry.isDirectory()) + .map(entry => entry.name) + .filter(name => fs.existsSync(path.join(appsRoot, name, 'package.json'))) + .sort(); +} + function addIncludesForTestApp( testApp: string, includes: MatrixInclude[], From 2d07da5e38e9118182d08ea3a1ae30c05e031143 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 10:19:41 +0200 Subject: [PATCH 17/46] avoid ts dependency for test matrix --- dev-packages/e2e-tests/README.md | 2 +- .../{getTestMatrix.ts => getTestMatrix.mjs} | 70 ++++++------------- dev-packages/e2e-tests/package.json | 4 +- 3 files changed, 23 insertions(+), 53 deletions(-) rename dev-packages/e2e-tests/lib/{getTestMatrix.ts => getTestMatrix.mjs} (76%) diff --git a/dev-packages/e2e-tests/README.md b/dev-packages/e2e-tests/README.md index 15de0fd49ee0..2ff4b0665cd3 100644 --- a/dev-packages/e2e-tests/README.md +++ b/dev-packages/e2e-tests/README.md @@ -198,7 +198,7 @@ try { ``` Test apps in the folder `test-applications` will be automatically picked up by CI in the job `job_e2e_tests` (in `.github/workflows/build.yml`). -The test matrix for CI is generated in `dev-packages/e2e-tests/lib/getTestMatrix.ts`. +The test matrix for CI is generated in `dev-packages/e2e-tests/lib/getTestMatrix.mjs`. For each test app, CI checks its dependencies (and devDependencies) to see if any of them have changed in the current PR (based on nx affected projects). For example, if something is changed in the browser package, only E2E test apps that depend on browser will run, while others will be skipped. diff --git a/dev-packages/e2e-tests/lib/getTestMatrix.ts b/dev-packages/e2e-tests/lib/getTestMatrix.mjs similarity index 76% rename from dev-packages/e2e-tests/lib/getTestMatrix.ts rename to dev-packages/e2e-tests/lib/getTestMatrix.mjs index cd561de39ee2..b8be7af5f528 100644 --- a/dev-packages/e2e-tests/lib/getTestMatrix.ts +++ b/dev-packages/e2e-tests/lib/getTestMatrix.mjs @@ -1,40 +1,21 @@ -import { execSync } from 'child_process'; -import * as fs from 'fs'; -import * as path from 'path'; -import { parseArgs } from 'util'; - -interface MatrixInclude { - /** The test application (directory) name. */ - 'test-application': string; - /** Optional override for the build command to run. */ - 'build-command'?: string; - /** Optional override for the assert command to run. */ - 'assert-command'?: string; - /** Optional label for the test run. If not set, defaults to value of `test-application`. */ - label?: string; -} +import { execSync } from 'node:child_process'; +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { parseArgs } from 'node:util'; -interface PackageJsonSentryTestConfig { - /** If this is true, the test app is optional. */ - optional?: boolean; - /** Variant configs that should be run in non-optional test runs. */ - variants?: Partial[]; - /** Variant configs that should be run in optional test runs. */ - optionalVariants?: Partial[]; - /** Skip this test app for matrix generation. */ - skip?: boolean; -} +const __dirname = path.dirname(fileURLToPath(import.meta.url)); /** - * This methods generates a matrix for the GitHub Actions workflow to run the E2E tests. - * It checks which test applications are affected by the current changes in the PR and then generates a matrix + * Generates a matrix for the GitHub Actions workflow to run the E2E tests. + * Checks which test applications are affected by the current changes in the PR and then generates a matrix * including all test apps that have at least one dependency that was changed in the PR. * If no `--base=xxx` is provided, it will output all test applications. * * If `--optional=true` is set, it will generate a matrix of optional test applications only. * Otherwise, these will be skipped. */ -function run(): void { +function run() { const { values } = parseArgs({ args: process.argv.slice(2), options: { @@ -63,7 +44,7 @@ function run(): void { : testApplications; const optionalMode = optional === 'true'; - const includes: MatrixInclude[] = []; + const includes = []; includedTestApplications.forEach(testApp => { addIncludesForTestApp(testApp, includes, { optionalMode }); @@ -75,7 +56,7 @@ function run(): void { } /** Direct children of `test-applications/` that contain a `package.json` (replaces glob one-segment + package.json). */ -function discoverTestApplicationDirs(): string[] { +function discoverTestApplicationDirs() { const appsRoot = path.join(__dirname, '..', 'test-applications'); return fs .readdirSync(appsRoot, { withFileTypes: true }) @@ -85,11 +66,7 @@ function discoverTestApplicationDirs(): string[] { .sort(); } -function addIncludesForTestApp( - testApp: string, - includes: MatrixInclude[], - { optionalMode }: { optionalMode: boolean }, -): void { +function addIncludesForTestApp(testApp, includes, { optionalMode }) { const packageJson = getPackageJson(testApp); const shouldSkip = packageJson.sentryTest?.skip || false; @@ -115,7 +92,7 @@ function addIncludesForTestApp( }); } -function getSentryDependencies(appName: string): string[] { +function getSentryDependencies(appName) { const packageJson = getPackageJson(appName); const dependencies = { @@ -126,11 +103,7 @@ function getSentryDependencies(appName: string): string[] { return Object.keys(dependencies).filter(key => key.startsWith('@sentry')); } -function getPackageJson(appName: string): { - dependencies?: { [key: string]: string }; - devDependencies?: { [key: string]: string }; - sentryTest?: PackageJsonSentryTestConfig; -} { +function getPackageJson(appName) { const fullPath = path.resolve(__dirname, '..', 'test-applications', appName, 'package.json'); if (!fs.existsSync(fullPath)) { @@ -140,19 +113,14 @@ function getPackageJson(appName: string): { return JSON.parse(fs.readFileSync(fullPath, 'utf8')); } -run(); - -function getAffectedTestApplications( - testApplications: string[], - { base = 'develop', head }: { base?: string; head?: string }, -): string[] { +function getAffectedTestApplications(testApplications, { base = 'develop', head }) { const additionalArgs = [`--base=${base}`]; if (head) { additionalArgs.push(`--head=${head}`); } - let affectedProjects: string[] = []; + let affectedProjects = []; try { affectedProjects = execSync(`yarn --silent nx show projects --affected ${additionalArgs.join(' ')}`) .toString() @@ -208,7 +176,7 @@ function getAffectedTestApplications( return Array.from(testAppsToRun); } -function getChangedTestApps(base: string, head?: string): false | Set { +function getChangedTestApps(base, head) { const changedFiles = execSync(`git diff --name-only ${base}${head ? `..${head}` : ''} -- .`, { encoding: 'utf-8', }) @@ -221,7 +189,7 @@ function getChangedTestApps(base: string, head?: string): false | Set { // eslint-disable-next-line no-console console.error(`Changed files since ${base}${head ? `..${head}` : ''}: ${JSON.stringify(changedFiles)}`); - const changedTestApps: Set = new Set(); + const changedTestApps = new Set(); const testAppsPrefix = 'dev-packages/e2e-tests/test-applications/'; for (const file of changedFiles) { @@ -240,3 +208,5 @@ function getChangedTestApps(base: string, head?: string): false | Set { return changedTestApps; } + +run(); diff --git a/dev-packages/e2e-tests/package.json b/dev-packages/e2e-tests/package.json index e03c4f73b7bb..11097e64ad9b 100644 --- a/dev-packages/e2e-tests/package.json +++ b/dev-packages/e2e-tests/package.json @@ -12,8 +12,8 @@ "test:prepare": "ts-node prepare.ts", "test:validate": "ts-node validate-packed-tarball-setup.ts", "clean": "rimraf tmp node_modules packed && yarn clean:test-applications && yarn clean:pnpm", - "ci:build-matrix": "npx ts-node ./lib/getTestMatrix.ts", - "ci:build-matrix-optional": "npx ts-node ./lib/getTestMatrix.ts --optional=true", + "ci:build-matrix": "node ./lib/getTestMatrix.mjs", + "ci:build-matrix-optional": "node ./lib/getTestMatrix.mjs --optional=true", "ci:copy-to-temp": "ts-node ./ciCopyToTemp.ts", "ci:pnpm-overrides": "ts-node ./ciPnpmOverrides.ts", "clean:test-applications": "rimraf --glob test-applications/**/{node_modules,dist,build,.next,.nuxt,.sveltekit,.react-router,.astro,.output,pnpm-lock.yaml,.last-run.json,test-results,.angular,event-dumps}", From b7953ea5637f4ac830d543eef5d5367739c5a2a4 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 10:28:00 +0200 Subject: [PATCH 18/46] use nx command via npx use correct nx version fix linting --- dev-packages/e2e-tests/lib/getTestMatrix.mjs | 22 +++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/dev-packages/e2e-tests/lib/getTestMatrix.mjs b/dev-packages/e2e-tests/lib/getTestMatrix.mjs index b8be7af5f528..7e1d34b91c3f 100644 --- a/dev-packages/e2e-tests/lib/getTestMatrix.mjs +++ b/dev-packages/e2e-tests/lib/getTestMatrix.mjs @@ -5,6 +5,18 @@ import { fileURLToPath } from 'node:url'; import { parseArgs } from 'node:util'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); +/** Repository root (this file lives in dev-packages/e2e-tests/lib/). */ +const REPO_ROOT = path.resolve(__dirname, '..', '..', '..'); + +/** Nx semver from root `package.json` (no `yarn install` required for matrix generation). */ +function getPinnedNxVersion() { + const rootPkg = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'package.json'), 'utf8')); + const raw = rootPkg.devDependencies?.nx ?? rootPkg.dependencies?.nx; + if (typeof raw !== 'string') { + throw new Error('Root package.json must declare nx in devDependencies or dependencies'); + } + return raw.replace(/^[\^~>=<]/, ''); +} /** * Generates a matrix for the GitHub Actions workflow to run the E2E tests. @@ -122,8 +134,12 @@ function getAffectedTestApplications(testApplications, { base = 'develop', head let affectedProjects = []; try { - affectedProjects = execSync(`yarn --silent nx show projects --affected ${additionalArgs.join(' ')}`) - .toString() + // CI may run this before `yarn install`; use npx with the same major.minor.patch as root package.json. + const nxVersion = getPinnedNxVersion(); + affectedProjects = execSync(`npx --yes nx@${nxVersion} show projects --affected ${additionalArgs.join(' ')}`, { + cwd: REPO_ROOT, + encoding: 'utf-8', + }) .split('\n') .map(line => line.trim()) .filter(Boolean); @@ -178,9 +194,9 @@ function getAffectedTestApplications(testApplications, { base = 'develop', head function getChangedTestApps(base, head) { const changedFiles = execSync(`git diff --name-only ${base}${head ? `..${head}` : ''} -- .`, { + cwd: REPO_ROOT, encoding: 'utf-8', }) - .toString() .split('\n') .map(line => line.trim()) .filter(Boolean); From 644dd41deb468e6f105cd9f4b3523a98a105421f Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 10:55:40 +0200 Subject: [PATCH 19/46] Revert "use nx command via npx" This reverts commit e2107f099dffb763fcdd95717ffe8b4ba7b7e002. --- dev-packages/e2e-tests/lib/getTestMatrix.mjs | 22 +++----------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/dev-packages/e2e-tests/lib/getTestMatrix.mjs b/dev-packages/e2e-tests/lib/getTestMatrix.mjs index 7e1d34b91c3f..b8be7af5f528 100644 --- a/dev-packages/e2e-tests/lib/getTestMatrix.mjs +++ b/dev-packages/e2e-tests/lib/getTestMatrix.mjs @@ -5,18 +5,6 @@ import { fileURLToPath } from 'node:url'; import { parseArgs } from 'node:util'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); -/** Repository root (this file lives in dev-packages/e2e-tests/lib/). */ -const REPO_ROOT = path.resolve(__dirname, '..', '..', '..'); - -/** Nx semver from root `package.json` (no `yarn install` required for matrix generation). */ -function getPinnedNxVersion() { - const rootPkg = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'package.json'), 'utf8')); - const raw = rootPkg.devDependencies?.nx ?? rootPkg.dependencies?.nx; - if (typeof raw !== 'string') { - throw new Error('Root package.json must declare nx in devDependencies or dependencies'); - } - return raw.replace(/^[\^~>=<]/, ''); -} /** * Generates a matrix for the GitHub Actions workflow to run the E2E tests. @@ -134,12 +122,8 @@ function getAffectedTestApplications(testApplications, { base = 'develop', head let affectedProjects = []; try { - // CI may run this before `yarn install`; use npx with the same major.minor.patch as root package.json. - const nxVersion = getPinnedNxVersion(); - affectedProjects = execSync(`npx --yes nx@${nxVersion} show projects --affected ${additionalArgs.join(' ')}`, { - cwd: REPO_ROOT, - encoding: 'utf-8', - }) + affectedProjects = execSync(`yarn --silent nx show projects --affected ${additionalArgs.join(' ')}`) + .toString() .split('\n') .map(line => line.trim()) .filter(Boolean); @@ -194,9 +178,9 @@ function getAffectedTestApplications(testApplications, { base = 'develop', head function getChangedTestApps(base, head) { const changedFiles = execSync(`git diff --name-only ${base}${head ? `..${head}` : ''} -- .`, { - cwd: REPO_ROOT, encoding: 'utf-8', }) + .toString() .split('\n') .map(line => line.trim()) .filter(Boolean); From b48b2aad1969ab9852816c7b2a0c0331b795b90f Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 10:58:39 +0200 Subject: [PATCH 20/46] run it in build step --- .github/workflows/build.yml | 24 ++++++++++++++++++++---- .github/workflows/ci-metadata.yml | 22 ---------------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ed343bf49c34..f24d0f32c96d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -138,6 +138,20 @@ jobs: compression-level: 6 overwrite: true + - name: Determine which test applications should be run + id: matrix + run: + yarn --silent ci:build-matrix --base=${{ (github.event_name == 'pull_request' && + github.event.pull_request.base.sha) || '' }} >> $GITHUB_OUTPUT + working-directory: dev-packages/e2e-tests + + - name: Determine which optional E2E test applications should be run + id: matrix-optional + run: + yarn --silent ci:build-matrix-optional --base=${{ (github.event_name == 'pull_request' && + github.event.pull_request.base.sha) || '' }} >> $GITHUB_OUTPUT + working-directory: dev-packages/e2e-tests + outputs: dependency_cache_key: ${{ steps.install_dependencies.outputs.cache_key }} changed_node_integration: @@ -164,6 +178,8 @@ jobs: changed_browser_integration: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry-internal/browser-integration-tests') }} + e2e-matrix: ${{ steps.matrix.outputs.matrix }} + e2e-matrix-optional: ${{ steps.matrix-optional.outputs.matrix }} job_check_branches: name: Check PR branches @@ -889,7 +905,7 @@ jobs: # We need to add the `always()` check here because the previous step has this as well :( # See: https://github.com/actions/runner/issues/2205 if: - always() && needs.job_build_tarballs.result == 'success' && needs.job_get_metadata.outputs.e2e-matrix + always() && needs.job_build_tarballs.result == 'success' && needs.job_build.outputs.e2e-matrix !='{"include":[]}' needs: [job_get_metadata, job_build, job_build_tarballs] runs-on: ubuntu-24.04 @@ -905,7 +921,7 @@ jobs: E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false - matrix: ${{ fromJson(needs.job_get_metadata.outputs.e2e-matrix) }} + matrix: ${{ fromJson(needs.job_build.outputs.e2e-matrix) }} steps: - name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) uses: actions/checkout@v6 @@ -1014,7 +1030,7 @@ jobs: # See: https://github.com/actions/runner/issues/2205 if: always() && needs.job_get_metadata.outputs.is_release != 'true' && needs.job_build_tarballs.result == 'success' && - needs.job_get_metadata.outputs.e2e-matrix-optional != '{"include":[]}' && (github.event_name != 'pull_request' || + needs.job_build.outputs.e2e-matrix-optional != '{"include":[]}' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]' needs: [job_get_metadata, job_build, job_build_tarballs] runs-on: ubuntu-24.04 @@ -1030,7 +1046,7 @@ jobs: E2E_TEST_SENTRY_PROJECT: 'sentry-javascript-e2e-tests' strategy: fail-fast: false - matrix: ${{ fromJson(needs.job_get_metadata.outputs.e2e-matrix-optional) }} + matrix: ${{ fromJson(needs.job_build.outputs.e2e-matrix-optional) }} steps: - name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) diff --git a/.github/workflows/ci-metadata.yml b/.github/workflows/ci-metadata.yml index b46e6bdb3f04..0f39590bf167 100644 --- a/.github/workflows/ci-metadata.yml +++ b/.github/workflows/ci-metadata.yml @@ -31,12 +31,6 @@ on: force_skip_cache: description: 'Whether to skip caching (schedule or ci-skip-cache label)' value: ${{ jobs.get_metadata.outputs.force_skip_cache }} - e2e-matrix: - description: 'The matrix of E2E test applications to run' - value: ${{ jobs.get_metadata.outputs.e2e-matrix }} - e2e-matrix-optional: - description: 'The matrix of optional E2E test applications to run' - value: ${{ jobs.get_metadata.outputs.e2e-matrix-optional }} jobs: get_metadata: @@ -76,20 +70,6 @@ jobs: any_code: - '!**/*.md' - - name: Determine which test applications should be run - id: matrix - run: - yarn --silent ci:build-matrix --base=${{ (github.event_name == 'pull_request' && - github.event.pull_request.base.sha) || '' }} >> $GITHUB_OUTPUT - working-directory: dev-packages/e2e-tests - - - name: Determine which optional E2E test applications should be run - id: matrix-optional - run: - yarn --silent ci:build-matrix-optional --base=${{ (github.event_name == 'pull_request' && - github.event.pull_request.base.sha) || '' }} >> $GITHUB_OUTPUT - working-directory: dev-packages/e2e-tests - outputs: commit_label: '${{ env.COMMIT_SHA }}: ${{ env.COMMIT_MESSAGE }}' # Note: These next three have to be checked as strings ('true'/'false')! @@ -107,5 +87,3 @@ jobs: force_skip_cache: ${{ github.event_name == 'schedule' || (github.event_name == 'pull_request' && contains(toJSON(github.event.pull_request.labels.*.name), 'ci-skip-cache')) }} - e2e-matrix: ${{ steps.matrix.outputs.matrix }} - e2e-matrix-optional: ${{ steps.matrix-optional.outputs.matrix }} From aaa69acc2306320a25bd704922bd40d700d8690b Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 11:05:35 +0200 Subject: [PATCH 21/46] fix linting --- .github/workflows/build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f24d0f32c96d..3fd3c1e921cc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -905,8 +905,7 @@ jobs: # We need to add the `always()` check here because the previous step has this as well :( # See: https://github.com/actions/runner/issues/2205 if: - always() && needs.job_build_tarballs.result == 'success' && needs.job_build.outputs.e2e-matrix - !='{"include":[]}' + always() && needs.job_build_tarballs.result == 'success' && needs.job_build.outputs.e2e-matrix !='{"include":[]}' needs: [job_get_metadata, job_build, job_build_tarballs] runs-on: ubuntu-24.04 timeout-minutes: 15 From 298e0740fd464eb921136d2ff797bd0e008ecbf4 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 11:45:53 +0200 Subject: [PATCH 22/46] better path handling for artifacts --- .github/workflows/build.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3fd3c1e921cc..ada24ecc778f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,7 +48,11 @@ env: ${{ github.workspace }}/packages/ember/*.d.ts ${{ github.workspace }}/packages/gatsby/*.d.ts - BUILD_TARBALL_PATH: ${{ github.workspace }}/packages/*/*.tgz + # upload-artifact globs drop the path through the first `*` (see upload-artifact + # README). Tarballs therefore land in the artifact as /*.tgz; download + # tarball-output into packages/ so they resolve to packages//*.tgz. + TARBALL_ARTIFACT_GLOB: packages/*/*.tgz + TARBALL_ARTIFACT_DOWNLOAD_PATH: ${{ github.workspace }}/packages # GH will use the first restore-key it finds that matches # So it will start by looking for one from the same branch, else take the newest one it can find elsewhere @@ -336,6 +340,7 @@ jobs: uses: actions/download-artifact@v7 with: name: tarball-output + path: ${{ env.TARBALL_ARTIFACT_DOWNLOAD_PATH }} - name: Archive artifacts uses: actions/upload-artifact@v7 @@ -895,7 +900,8 @@ jobs: uses: actions/upload-artifact@v7 with: name: tarball-output - path: ${{ env.BUILD_TARBALL_PATH }} + path: ${{ env.TARBALL_ARTIFACT_GLOB }} + if-no-files-found: error retention-days: 4 compression-level: 6 overwrite: true @@ -958,6 +964,7 @@ jobs: uses: actions/download-artifact@v7 with: name: tarball-output + path: ${{ env.TARBALL_ARTIFACT_DOWNLOAD_PATH }} - name: Prepare e2e tests run: yarn test:prepare @@ -1068,6 +1075,7 @@ jobs: uses: actions/download-artifact@v7 with: name: tarball-output + path: ${{ env.TARBALL_ARTIFACT_DOWNLOAD_PATH }} - name: Prepare E2E tests run: yarn test:prepare From 670bfe577520448b65b2edbba8953dbdae1c6b42 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 14:46:09 +0200 Subject: [PATCH 23/46] better nx cache --- .github/workflows/build.yml | 40 ++++++++++++------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ada24ecc778f..dc1d897f8b3d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,13 +54,8 @@ env: TARBALL_ARTIFACT_GLOB: packages/*/*.tgz TARBALL_ARTIFACT_DOWNLOAD_PATH: ${{ github.workspace }}/packages - # GH will use the first restore-key it finds that matches - # So it will start by looking for one from the same branch, else take the newest one it can find elsewhere - # We want to prefer the cache from the current develop branch, if we don't find any on the current branch - NX_CACHE_RESTORE_KEYS: | - nx-Linux-${{ github.ref }}-${{ github.event.inputs.commit || github.sha }} - nx-Linux-${{ github.ref }} - nx-Linux + # Ensure we only cache nx per-commit, so we do not cross-contaminate it + NX_CACHE_KEY: nx-Linux-${{ github.ref }}-${{ github.event.inputs.commit || github.sha }} # https://bsky.app/profile/joyeecheung.bsky.social/post/3lhy6o54fo22h # Apparently some of our CI failures are attributable to a corrupt v8 cache, causing v8 failures with: "Check failed: current == end_slot_index.". @@ -114,25 +109,17 @@ jobs: base: ${{ github.event.pull_request.base.sha }} head: ${{ env.HEAD_COMMIT }} - - name: NX cache - uses: actions/cache@v5 - # Disable cache when: - # - on release branches - # - when PR has `ci-skip-cache` label or on nightly builds - if: | - needs.job_get_metadata.outputs.is_release == 'false' && - needs.job_get_metadata.outputs.force_skip_cache == 'false' - with: - path: .nxcache - key: nx-Linux-${{ github.ref }}-${{ env.HEAD_COMMIT || github.sha }} - # On develop branch, we want to _store_ the cache (so it can be used by other branches), but never _restore_ from it - restore-keys: - ${{needs.job_get_metadata.outputs.is_base_branch == 'false' && env.NX_CACHE_RESTORE_KEYS || - 'nx-never-restore'}} - - name: Build packages run: yarn build + - name: Store NX cache + uses: actions/cache/save@v5 + # Only cache this per-PR to speed up CI. + if: github.event_name == 'pull_request' + with: + path: .nxcache + key: ${{ env.NX_CACHE_KEY }} + - name: Upload build artifacts uses: actions/upload-artifact@v7 with: @@ -885,13 +872,12 @@ jobs: uses: ./.github/actions/restore-cache with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} - - name: NX cache + + - name: Restore NX cache uses: actions/cache/restore@v5 with: path: .nxcache - key: nx-Linux-${{ github.ref }}-${{ env.HEAD_COMMIT }} - # On develop branch, we want to _store_ the cache (so it can be used by other branches), but never _restore_ from it - restore-keys: ${{ env.NX_CACHE_RESTORE_KEYS }} + key: ${{ env.NX_CACHE_KEY }} - name: Build tarballs run: yarn build:tarball From 49638b45caf27a17eda58cc1d761ca9f242fee28 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 14:51:50 +0200 Subject: [PATCH 24/46] cache per-branch --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dc1d897f8b3d..befaf3ad59eb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,8 +54,8 @@ env: TARBALL_ARTIFACT_GLOB: packages/*/*.tgz TARBALL_ARTIFACT_DOWNLOAD_PATH: ${{ github.workspace }}/packages - # Ensure we only cache nx per-commit, so we do not cross-contaminate it - NX_CACHE_KEY: nx-Linux-${{ github.ref }}-${{ github.event.inputs.commit || github.sha }} + # We cache NX per-PR for faster CI, other than this we do not want to rely on it + NX_CACHE_KEY: nx-Linux-${{ github.ref }} # https://bsky.app/profile/joyeecheung.bsky.social/post/3lhy6o54fo22h # Apparently some of our CI failures are attributable to a corrupt v8 cache, causing v8 failures with: "Check failed: current == end_slot_index.". From 3782d42f1152fa30918997ec82a25c92388c5789 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 14:57:48 +0200 Subject: [PATCH 25/46] reset cache before storing it??? --- .github/workflows/build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index befaf3ad59eb..ef66b0b6c611 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -109,6 +109,9 @@ jobs: base: ${{ github.event.pull_request.base.sha }} head: ${{ env.HEAD_COMMIT }} + - name: Cleanup NX cache + run: yarn nx reset + - name: Build packages run: yarn build From a6360e7f0700f91aa2459c08f02ef73a766bff8b Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 15:00:43 +0200 Subject: [PATCH 26/46] store cache in .nx and cache this?? --- .github/workflows/build.yml | 6 +++--- nx.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ef66b0b6c611..778d74588294 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -120,7 +120,7 @@ jobs: # Only cache this per-PR to speed up CI. if: github.event_name == 'pull_request' with: - path: .nxcache + path: .nx key: ${{ env.NX_CACHE_KEY }} - name: Upload build artifacts @@ -675,7 +675,7 @@ jobs: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} - name: Check for dts files that reference stuff in the temporary build folder run: | - if grep -r --include "*.d.ts" --exclude-dir ".nxcache" 'import("@sentry(-internal)?/[^/]*/build' .; then + if grep -r --include "*.d.ts" --exclude-dir ".nx" 'import("@sentry(-internal)?/[^/]*/build' .; then echo "Found illegal TypeScript import statement." exit 1 fi @@ -879,7 +879,7 @@ jobs: - name: Restore NX cache uses: actions/cache/restore@v5 with: - path: .nxcache + path: .nx key: ${{ env.NX_CACHE_KEY }} - name: Build tarballs diff --git a/nx.json b/nx.json index 7cd807e089fb..08faf7cf2e62 100644 --- a/nx.json +++ b/nx.json @@ -61,7 +61,7 @@ } }, "$schema": "./node_modules/nx/schemas/nx-schema.json", - "cacheDirectory": ".nxcache", + "cacheDirectory": ".nx/cache", "tui": { "autoExit": true }, From 1d0acab10399e9b1da0ed1f13b4a7c38e3e8f5df Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 16:41:53 +0200 Subject: [PATCH 27/46] no need to reset cache --- .github/workflows/build.yml | 3 --- .github/workflows/flaky-test-detector.yml | 12 ++++-------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 778d74588294..0b3b14b4cb21 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -109,9 +109,6 @@ jobs: base: ${{ github.event.pull_request.base.sha }} head: ${{ env.HEAD_COMMIT }} - - name: Cleanup NX cache - run: yarn nx reset - - name: Build packages run: yarn build diff --git a/.github/workflows/flaky-test-detector.yml b/.github/workflows/flaky-test-detector.yml index c0a8f1f720b1..973c3e296cdc 100644 --- a/.github/workflows/flaky-test-detector.yml +++ b/.github/workflows/flaky-test-detector.yml @@ -10,10 +10,7 @@ on: env: HEAD_COMMIT: ${{ github.event.inputs.commit || github.sha }} - NX_CACHE_RESTORE_KEYS: | - nx-Linux-${{ github.ref }}-${{ github.event.inputs.commit || github.sha }} - nx-Linux-${{ github.ref }} - nx-Linux + NX_CACHE_KEY: nx-Linux-${{ github.ref }} # Cancel in progress workflows on pull_requests. # https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value @@ -39,12 +36,11 @@ jobs: - name: Install dependencies run: yarn install --ignore-engines --frozen-lockfile - - name: NX cache + - name: Restore NX cache uses: actions/cache/restore@v5 with: - path: .nxcache - key: nx-Linux-${{ github.ref }}-${{ env.HEAD_COMMIT }} - restore-keys: ${{ env.NX_CACHE_RESTORE_KEYS }} + path: .nx + key: ${{ env.NX_CACHE_KEY }} - name: Build packages run: yarn build From a2bcf03874157289258acbc965215839d625e8e2 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 16:42:05 +0200 Subject: [PATCH 28/46] fix types cache for nestjs --- packages/nestjs/package.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/nestjs/package.json b/packages/nestjs/package.json index 625f8330a65f..29c313fc292f 100644 --- a/packages/nestjs/package.json +++ b/packages/nestjs/package.json @@ -85,5 +85,19 @@ "volta": { "extends": "../../package.json" }, + "nx": { + "targets": { + "build:types": { + "inputs": ["production", "^production"], + "dependsOn": ["^build:types"], + "outputs": [ + "{projectRoot}/build/types", + "{projectRoot}/build/types-ts3.8", + "{projectRoot}/*.d.ts" + ], + "cache": true + } + } + }, "sideEffects": false } From d583772d8ae53e76194160018e8656cc6d1ab880 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 16:47:46 +0200 Subject: [PATCH 29/46] small cleanup and improvements --- .github/workflows/build.yml | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0b3b14b4cb21..f84a20488e23 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,8 +28,6 @@ concurrency: env: HEAD_COMMIT: ${{ github.event.inputs.commit || github.sha }} - # WARNING: this disables cross os caching as ~ and - # github.workspace evaluate to differents paths CACHED_DEPENDENCY_PATHS: | ${{ github.workspace }}/node_modules ${{ github.workspace }}/packages/*/node_modules @@ -38,15 +36,10 @@ env: # DEPENDENCY_CACHE_KEY: can't be set here because we don't have access to yarn.lock - # WARNING: this disables cross os caching as ~ and - # github.workspace evaluate to differents paths - # packages/utils/cjs and packages/utils/esm: Symlinks to the folders inside of `build`, needed for tests - CACHED_BUILD_PATHS: | + BUILD_PATHS: | ${{ github.workspace }}/dev-packages/*/build ${{ github.workspace }}/packages/*/build - ${{ github.workspace }}/packages/*/lib - ${{ github.workspace }}/packages/ember/*.d.ts - ${{ github.workspace }}/packages/gatsby/*.d.ts + ${{ github.workspace }}/packages/*.d.ts # upload-artifact globs drop the path through the first `*` (see upload-artifact # README). Tarballs therefore land in the artifact as /*.tgz; download @@ -65,6 +58,7 @@ env: jobs: job_get_metadata: uses: ./.github/workflows/ci-metadata.yml + name: Get CI Metadata with: head_commit: ${{ github.event.inputs.commit || github.sha }} permissions: @@ -124,7 +118,7 @@ jobs: uses: actions/upload-artifact@v7 with: name: build-output - path: ${{ env.CACHED_BUILD_PATHS }} + path: ${{ env.BUILD_PATHS }} retention-days: 4 compression-level: 6 overwrite: true From e00bfb9ad67153bd804c391b39c931e4e35489e8 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Mon, 20 Apr 2026 16:48:15 +0200 Subject: [PATCH 30/46] fix linting --- packages/nestjs/package.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/nestjs/package.json b/packages/nestjs/package.json index 29c313fc292f..024e25cf3cce 100644 --- a/packages/nestjs/package.json +++ b/packages/nestjs/package.json @@ -88,8 +88,13 @@ "nx": { "targets": { "build:types": { - "inputs": ["production", "^production"], - "dependsOn": ["^build:types"], + "inputs": [ + "production", + "^production" + ], + "dependsOn": [ + "^build:types" + ], "outputs": [ "{projectRoot}/build/types", "{projectRoot}/build/types-ts3.8", From 17a5abe16a26cd41b4e08637027082b247408826 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Wed, 22 Apr 2026 11:31:49 +0200 Subject: [PATCH 31/46] full split fis check for bundles build fix expression fixes fix for extension dynamically build build_paths fixes fix e2e test cache nx per-run --- .github/workflows/build.yml | 119 ++++++++++++++++++---- package.json | 2 + scripts/ci-print-build-artifact-paths.mjs | 95 +++++++++++++++++ 3 files changed, 196 insertions(+), 20 deletions(-) create mode 100644 scripts/ci-print-build-artifact-paths.mjs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 53acd87b32c6..5f8da71e8b2b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -36,21 +36,24 @@ env: # DEPENDENCY_CACHE_KEY: can't be set here because we don't have access to yarn.lock - BUILD_PATHS: | - ${{ github.workspace }}/dev-packages/*/build - ${{ github.workspace }}/packages/*/build - ${{ github.workspace }}/packages/*.d.ts + # build-output artifact paths are computed in job_build (step output from + # yarn ci:print-build-artifact-paths — Nx merged outputs for build:transpile, build:types, build:extension). # upload-artifact globs drop the path through the first `*` (see upload-artifact # README). Tarballs therefore land in the artifact as /*.tgz; download # tarball-output into packages/ so they resolve to packages//*.tgz. TARBALL_ARTIFACT_GLOB: packages/*/*.tgz TARBALL_ARTIFACT_DOWNLOAD_PATH: ${{ github.workspace }}/packages - + BUILD_LAYER_PATH: ${{ github.workspace }}/packages/aws-serverless/build/aws/dist-serverless - # We cache NX per-PR for faster CI, other than this we do not want to rely on it - NX_CACHE_KEY: nx-Linux-${{ github.ref }} + # Same glob / download split as TARBALL_ARTIFACT_*: upload-artifact strips the path through + # the first `*`, so bundle trees are stored as /build/bundles/...; download into packages/. + BUNDLE_ARTIFACT_GLOB: packages/*/build/bundles + BUNDLE_ARTIFACT_DOWNLOAD_PATH: ${{ github.workspace }}/packages + + # We cache NX per CI run + NX_CACHE_KEY: nx-Linux-${{ github.run_id }} # https://bsky.app/profile/joyeecheung.bsky.social/post/3lhy6o54fo22h # Apparently some of our CI failures are attributable to a corrupt v8 cache, causing v8 failures with: "Check failed: current == end_slot_index.". @@ -67,7 +70,7 @@ jobs: pull-requests: read job_build: - name: Build + name: Install & Build needs: job_get_metadata runs-on: ubuntu-24.04 timeout-minutes: 15 @@ -106,7 +109,16 @@ jobs: head: ${{ env.HEAD_COMMIT }} - name: Build packages - run: yarn build + run: yarn build:ci + + - name: Compute build artifact paths from Nx + id: nx_build_paths + run: | + { + echo 'paths<> "$GITHUB_OUTPUT" - name: Store NX cache uses: actions/cache/save@v5 @@ -120,7 +132,7 @@ jobs: uses: actions/upload-artifact@v7 with: name: build-output - path: ${{ env.BUILD_PATHS }} + path: ${{ steps.nx_build_paths.outputs.paths }} retention-days: 4 compression-level: 6 overwrite: true @@ -174,7 +186,9 @@ jobs: job_build_layer: name: Build Lambda layer needs: [job_get_metadata, job_build] - if: needs.job_build.outputs.changed_aws_serverless == 'true' || github.event_name != 'pull_request' + if: + needs.job_build.outputs.changed_aws_serverless == 'true' || contains(needs.job_build.outputs.e2e-matrix, + 'aws-serverless') || github.event_name != 'pull_request' timeout-minutes: 10 runs-on: ubuntu-24.04 steps: @@ -190,6 +204,13 @@ jobs: uses: ./.github/actions/restore-cache with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + + - name: Restore NX cache + uses: actions/cache/restore@v5 + with: + path: .nx + key: ${{ env.NX_CACHE_KEY }} + - name: Build Lambda layer run: yarn build:layer @@ -202,6 +223,44 @@ jobs: compression-level: 6 overwrite: true + job_build_bundles: + name: Build bundles + needs: [job_get_metadata, job_build] + if: needs.job_build.outputs.changed_browser_integration == 'true' || github.event_name != 'pull_request' + timeout-minutes: 10 + runs-on: ubuntu-24.04 + steps: + - name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) + uses: actions/checkout@v6 + with: + ref: ${{ env.HEAD_COMMIT }} + - name: Set up Node + uses: actions/setup-node@v6 + with: + node-version-file: 'package.json' + - name: Restore caches + uses: ./.github/actions/restore-cache + with: + dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + + - name: Restore NX cache + uses: actions/cache/restore@v5 + with: + path: .nx + key: ${{ env.NX_CACHE_KEY }} + + - name: Build bundles + run: yarn build:bundle + + - name: Upload build artifacts + uses: actions/upload-artifact@v7 + with: + name: build-bundle-output + path: ${{ env.BUNDLE_ARTIFACT_GLOB }} + retention-days: 4 + compression-level: 6 + overwrite: true + job_check_branches: name: Check PR branches needs: job_get_metadata @@ -219,7 +278,7 @@ jobs: job_size_check: name: Size Check - needs: [job_get_metadata, job_build] + needs: [job_get_metadata, job_build, job_build_bundles] timeout-minutes: 15 runs-on: ubuntu-24.04 if: @@ -335,7 +394,7 @@ jobs: job_artifacts: name: Upload Artifacts - needs: [job_get_metadata, job_build, job_build_layer, job_build_tarballs] + needs: [job_get_metadata, job_build, job_build_layer, job_build_bundles, job_build_tarballs] runs-on: ubuntu-24.04 # Build artifacts are only needed for releasing workflow. if: needs.job_get_metadata.outputs.is_release == 'true' @@ -359,6 +418,12 @@ jobs: name: tarball-output path: ${{ env.TARBALL_ARTIFACT_DOWNLOAD_PATH }} + - name: Restore build bundle artifacts + uses: actions/download-artifact@v7 + with: + name: build-bundle-output + path: ${{ env.BUNDLE_ARTIFACT_DOWNLOAD_PATH }} + - name: Restore build layer artifacts uses: actions/download-artifact@v7 with: @@ -527,7 +592,7 @@ jobs: name: Playwright ${{ matrix.bundle }}${{ matrix.project && matrix.project != 'chromium' && format(' {0}', matrix.project) || ''}}${{ matrix.shard && format(' ({0}/{1})', matrix.shard, matrix.shards) || ''}} Tests - needs: [job_get_metadata, job_build] + needs: [job_get_metadata, job_build, job_build_bundles] if: needs.job_build.outputs.changed_browser_integration == 'true' || github.event_name != 'pull_request' runs-on: ubuntu-24.04-large-js timeout-minutes: 25 @@ -592,6 +657,12 @@ jobs: with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Restore build bundle artifacts + uses: actions/download-artifact@v7 + with: + name: build-bundle-output + path: ${{ env.BUNDLE_ARTIFACT_DOWNLOAD_PATH }} + - name: Install Playwright uses: ./.github/actions/install-playwright with: @@ -630,7 +701,7 @@ jobs: job_browser_loader_tests: name: PW ${{ matrix.bundle }} Tests - needs: [job_get_metadata, job_build] + needs: [job_get_metadata, job_build, job_build_bundles] if: needs.job_build.outputs.changed_browser_integration == 'true' || github.event_name != 'pull_request' runs-on: ubuntu-24.04 timeout-minutes: 15 @@ -660,6 +731,12 @@ jobs: with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Restore build bundle artifacts + uses: actions/download-artifact@v7 + with: + name: build-bundle-output + path: ${{ env.BUNDLE_ARTIFACT_DOWNLOAD_PATH }} + - name: Install Playwright uses: ./.github/actions/install-playwright with: @@ -987,18 +1064,17 @@ jobs: - name: Restore tarball artifacts uses: actions/download-artifact@v7 + with: + name: tarball-output + path: ${{ env.TARBALL_ARTIFACT_DOWNLOAD_PATH }} - name: Restore build layer artifacts uses: actions/download-artifact@v7 - if: matrix.test-application == 'aws-serverless' + if: matrix.test-application == 'aws-serverless' || matrix.test-application == 'aws-serverless-layer' with: name: build-layer-output path: ${{ env.BUILD_LAYER_PATH }} - with: - name: tarball-output - path: ${{ env.TARBALL_ARTIFACT_DOWNLOAD_PATH }} - - name: Prepare e2e tests run: yarn test:prepare working-directory: dev-packages/e2e-tests @@ -1164,6 +1240,9 @@ jobs: needs: [ job_build, + job_build_bundles, + job_build_layer, + job_build_tarballs, job_browser_unit_tests, job_bun_unit_tests, job_deno_unit_tests, diff --git a/package.json b/package.json index 62eb153018a3..943b39ae8476 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "private": true, "scripts": { "build": "node ./scripts/verify-packages-versions.js && nx run-many -t build:transpile build:types build:bundle build:extension", + "build:ci": "node ./scripts/verify-packages-versions.js && nx run-many -t build:transpile build:types build:extension", "build:bundle": "nx run-many -t build:bundle", "build:layer": "nx run-many -t build:layer", "build:dev": "nx run-many -t build:types build:transpile", @@ -12,6 +13,7 @@ "build:dev:watch": "nx run-many -t build:dev:watch", "build:tarball": "run-s clean:tarballs build:tarballs", "build:tarballs": "nx run-many -t build:tarball", + "ci:print-build-artifact-paths": "node ./scripts/ci-print-build-artifact-paths.mjs", "changelog": "ts-node ./scripts/get-commit-list.ts", "generate-changelog": "ts-node ./scripts/generate-changelog.ts", "circularDepCheck": "nx run-many -t circularDepCheck", diff --git a/scripts/ci-print-build-artifact-paths.mjs b/scripts/ci-print-build-artifact-paths.mjs new file mode 100644 index 000000000000..c90f4d31050b --- /dev/null +++ b/scripts/ci-print-build-artifact-paths.mjs @@ -0,0 +1,95 @@ +#!/usr/bin/env node +/** + * Prints multiline paths for actions/upload-artifact `path` (often wired via a prior step's + * `GITHUB_OUTPUT` `paths< yarn ci:print-build-artifact-paths + * (defaults to cwd when GITHUB_WORKSPACE is unset) + */ +import { execSync } from 'node:child_process'; +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const workspaceRoot = path.resolve(__dirname, '..'); +const graphPath = path.join(workspaceRoot, '.nx', 'ci-print-build-artifact-paths-graph.json'); + +const TARGETS = ['build:transpile', 'build:types', 'build:extension']; + +fs.mkdirSync(path.dirname(graphPath), { recursive: true }); +execSync(`yarn nx graph --file="${graphPath}"`, { + cwd: workspaceRoot, + stdio: ['ignore', 'pipe', 'inherit'], +}); + +const { graph } = JSON.parse(fs.readFileSync(graphPath, 'utf8')); +try { + fs.unlinkSync(graphPath); +} catch { + // ignore +} + +/** @type {Map>} key = `${kind}\0${suffix}` */ +const groups = new Map(); + +for (const node of Object.values(graph.nodes)) { + const root = node.data?.root; + if (!root || (!root.startsWith('packages/') && !root.startsWith('dev-packages/'))) { + continue; + } + + const [kind, pkg] = root.split('/'); + if (!kind || !pkg) { + continue; + } + + const targets = node.data?.targets || {}; + for (const targetName of TARGETS) { + const outputs = targets[targetName]?.outputs; + if (!Array.isArray(outputs)) { + continue; + } + + for (const output of outputs) { + const rel = output.replace(/\{projectRoot\}/g, root).replace(/\\/g, '/'); + const prefix = `${kind}/${pkg}/`; + if (!rel.startsWith(prefix)) { + throw new Error(`Unexpected Nx output (missing project prefix): ${rel}`); + } + const suffix = rel.slice(prefix.length); + const key = `${kind}\0${suffix}`; + if (!groups.has(key)) { + groups.set(key, new Set()); + } + groups.get(key).add(pkg); + } + } +} + +const ws = (process.env.GITHUB_WORKSPACE || workspaceRoot).replace(/\\/g, '/'); +const lines = new Set(); + +for (const [key, pkgSet] of groups) { + const [kind, suffix] = key.split('\0'); + const needsConcretePath = pkgSet.size === 1 && !suffix.includes('/') && !/[?*]/.test(suffix) && suffix === 'build'; + + if (needsConcretePath) { + const pkg = [...pkgSet][0]; + lines.add(`${ws}/${kind}/${pkg}/build`); + } else { + lines.add(`${ws}/${kind}/*/${suffix}`); + } +} + +process.stdout.write([...lines].sort((a, b) => a.localeCompare(b)).join('\n')); +if (lines.size) { + process.stdout.write('\n'); +} From b580d38645035be296460d10f63e6ec6cc46947e Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Wed, 22 Apr 2026 15:57:01 +0200 Subject: [PATCH 32/46] fix angular deps --- packages/angular/package.json | 5 +--- scripts/ci-print-build-artifact-paths.mjs | 34 +++++++++++++++++------ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/packages/angular/package.json b/packages/angular/package.json index 6e59e3588fdd..7169e8cf67ed 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -71,10 +71,7 @@ "^build:types" ], "outputs": [ - "{projectRoot}/build/esm2015", - "{projectRoot}/build/fesm2015", - "{projectRoot}/build/fesm2020", - "{projectRoot}/build/*.d.ts" + "{projectRoot}/build" ] } } diff --git a/scripts/ci-print-build-artifact-paths.mjs b/scripts/ci-print-build-artifact-paths.mjs index c90f4d31050b..9f1b692075b5 100644 --- a/scripts/ci-print-build-artifact-paths.mjs +++ b/scripts/ci-print-build-artifact-paths.mjs @@ -6,9 +6,11 @@ * every project under `packages/` and `dev-packages/`. * * Each line is an absolute path pattern suitable for @actions/glob (same style as the - * previous hand-maintained BUILD_PATHS list). Uses a wildcard in the package name segment - * plus a shared path suffix, except for the single-segment `build` output directory, which - * must stay concrete (`packages/deno/build`) so we do not match every package's `build/` tree. + * previous hand-maintained BUILD_PATHS list). If exactly one project declares a given + * output suffix, the path uses that package name (no glob in the package segment). If several + * projects share a suffix, a shared glob pattern under packages/ or dev-packages/ is used when + * safe. The lone path segment "build" is never turned into a broad glob (that would match + * every package); several projects with a top-level build output each get their own path. * * Usage: GITHUB_WORKSPACE= yarn ci:print-build-artifact-paths * (defaults to cwd when GITHUB_WORKSPACE is unset) @@ -77,16 +79,30 @@ for (const node of Object.values(graph.nodes)) { const ws = (process.env.GITHUB_WORKSPACE || workspaceRoot).replace(/\\/g, '/'); const lines = new Set(); +// A glob like packages + star + slash + "build" matches every package's build tree, so we +// never emit that when several projects each declare a top-level {projectRoot}/build output. +function isUnsafeSharedTopLevelBuildSuffix(suffix, pkgCount) { + return pkgCount > 1 && !suffix.includes('/') && !/[?*]/.test(suffix) && suffix === 'build'; +} + for (const [key, pkgSet] of groups) { const [kind, suffix] = key.split('\0'); - const needsConcretePath = pkgSet.size === 1 && !suffix.includes('/') && !/[?*]/.test(suffix) && suffix === 'build'; + const pkgs = [...pkgSet].sort((a, b) => a.localeCompare(b)); + const n = pkgs.length; + + if (n === 1) { + lines.add(`${ws}/${kind}/${pkgs[0]}/${suffix}`); + continue; + } - if (needsConcretePath) { - const pkg = [...pkgSet][0]; - lines.add(`${ws}/${kind}/${pkg}/build`); - } else { - lines.add(`${ws}/${kind}/*/${suffix}`); + if (isUnsafeSharedTopLevelBuildSuffix(suffix, n)) { + for (const pkg of pkgs) { + lines.add(`${ws}/${kind}/${pkg}/build`); + } + continue; } + + lines.add(`${ws}/${kind}/*/${suffix}`); } process.stdout.write([...lines].sort((a, b) => a.localeCompare(b)).join('\n')); From d714b3b538c718f95e851a5ce19e2cb173003000 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Wed, 22 Apr 2026 16:18:40 +0200 Subject: [PATCH 33/46] more unique cache key --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5f8da71e8b2b..23029facbd50 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,7 +53,7 @@ env: BUNDLE_ARTIFACT_DOWNLOAD_PATH: ${{ github.workspace }}/packages # We cache NX per CI run - NX_CACHE_KEY: nx-Linux-${{ github.run_id }} + NX_CACHE_KEY: nx-Linux-${{ github.head_ref || github.ref }}-${{ github.run_id }} # https://bsky.app/profile/joyeecheung.bsky.social/post/3lhy6o54fo22h # Apparently some of our CI failures are attributable to a corrupt v8 cache, causing v8 failures with: "Check failed: current == end_slot_index.". From dff1b97b2cf64072da311e63e2aed0fe2346fdf6 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Wed, 22 Apr 2026 16:19:32 +0200 Subject: [PATCH 34/46] rename artifcact --- .github/workflows/build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 23029facbd50..6449c5009640 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -41,7 +41,7 @@ env: # upload-artifact globs drop the path through the first `*` (see upload-artifact # README). Tarballs therefore land in the artifact as /*.tgz; download - # tarball-output into packages/ so they resolve to packages//*.tgz. + # build-tarball-output into packages/ so they resolve to packages//*.tgz. TARBALL_ARTIFACT_GLOB: packages/*/*.tgz TARBALL_ARTIFACT_DOWNLOAD_PATH: ${{ github.workspace }}/packages @@ -415,7 +415,7 @@ jobs: - name: Restore tarball artifacts uses: actions/download-artifact@v7 with: - name: tarball-output + name: build-tarball-output path: ${{ env.TARBALL_ARTIFACT_DOWNLOAD_PATH }} - name: Restore build bundle artifacts @@ -1001,7 +1001,7 @@ jobs: - name: Upload tarball artifacts uses: actions/upload-artifact@v7 with: - name: tarball-output + name: build-tarball-output path: ${{ env.TARBALL_ARTIFACT_GLOB }} if-no-files-found: error retention-days: 4 @@ -1065,7 +1065,7 @@ jobs: - name: Restore tarball artifacts uses: actions/download-artifact@v7 with: - name: tarball-output + name: build-tarball-output path: ${{ env.TARBALL_ARTIFACT_DOWNLOAD_PATH }} - name: Restore build layer artifacts @@ -1183,7 +1183,7 @@ jobs: - name: Restore tarball artifacts uses: actions/download-artifact@v7 with: - name: tarball-output + name: build-tarball-output path: ${{ env.TARBALL_ARTIFACT_DOWNLOAD_PATH }} - name: Prepare E2E tests From 97f5c7bc10c65edd91b4279bdb039108584285de Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Wed, 22 Apr 2026 16:21:31 +0200 Subject: [PATCH 35/46] better nx cache restoration --- .github/workflows/build.yml | 4 ++++ .github/workflows/flaky-test-detector.yml | 3 +++ 2 files changed, 7 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6449c5009640..174250cbebe3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,6 +55,10 @@ env: # We cache NX per CI run NX_CACHE_KEY: nx-Linux-${{ github.head_ref || github.ref }}-${{ github.run_id }} + # Restored .nx cache is unpacked on a different runner than it was saved on; allow Nx to use it. + # https://nx.dev/troubleshooting/unknown-local-cache + NX_REJECT_UNKNOWN_LOCAL_CACHE: '0' + # https://bsky.app/profile/joyeecheung.bsky.social/post/3lhy6o54fo22h # Apparently some of our CI failures are attributable to a corrupt v8 cache, causing v8 failures with: "Check failed: current == end_slot_index.". # This option both controls the `v8-compile-cache-lib` and `v8-compile-cache` packages. diff --git a/.github/workflows/flaky-test-detector.yml b/.github/workflows/flaky-test-detector.yml index 973c3e296cdc..d8d1cb7ce809 100644 --- a/.github/workflows/flaky-test-detector.yml +++ b/.github/workflows/flaky-test-detector.yml @@ -12,6 +12,9 @@ env: NX_CACHE_KEY: nx-Linux-${{ github.ref }} + # Restored .nx cache may come from another runner; see nx.dev/troubleshooting/unknown-local-cache + NX_REJECT_UNKNOWN_LOCAL_CACHE: '0' + # Cancel in progress workflows on pull_requests. # https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value concurrency: From 63c48e5bded8c48627f73e84563c574c02d6d008 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Wed, 22 Apr 2026 16:23:41 +0200 Subject: [PATCH 36/46] fixes for ci and size limit --- .github/workflows/build.yml | 16 +++++++++++----- .github/workflows/flaky-test-detector.yml | 5 +++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 174250cbebe3..1e84d713ded3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,7 +52,8 @@ env: BUNDLE_ARTIFACT_GLOB: packages/*/build/bundles BUNDLE_ARTIFACT_DOWNLOAD_PATH: ${{ github.workspace }}/packages - # We cache NX per CI run + # Task cache only (matches nx.json cacheDirectory). Omit .nx/workspace-data and .nx/daemon + # — not portable across runners and not needed for restore hits. NX_CACHE_KEY: nx-Linux-${{ github.head_ref || github.ref }}-${{ github.run_id }} # Restored .nx cache is unpacked on a different runner than it was saved on; allow Nx to use it. @@ -129,7 +130,7 @@ jobs: # Only cache this per-PR to speed up CI. if: github.event_name == 'pull_request' with: - path: .nx + path: .nx/cache key: ${{ env.NX_CACHE_KEY }} - name: Upload build artifacts @@ -212,7 +213,7 @@ jobs: - name: Restore NX cache uses: actions/cache/restore@v5 with: - path: .nx + path: .nx/cache key: ${{ env.NX_CACHE_KEY }} - name: Build Lambda layer @@ -250,7 +251,7 @@ jobs: - name: Restore NX cache uses: actions/cache/restore@v5 with: - path: .nx + path: .nx/cache key: ${{ env.NX_CACHE_KEY }} - name: Build bundles @@ -301,6 +302,11 @@ jobs: uses: ./.github/actions/restore-cache with: dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Restore build bundle artifacts + uses: actions/download-artifact@v7 + with: + name: build-bundle-output + path: ${{ env.BUNDLE_ARTIFACT_DOWNLOAD_PATH }} - name: Check bundle sizes uses: ./dev-packages/size-limit-gh-action with: @@ -996,7 +1002,7 @@ jobs: - name: Restore NX cache uses: actions/cache/restore@v5 with: - path: .nx + path: .nx/cache key: ${{ env.NX_CACHE_KEY }} - name: Build tarballs diff --git a/.github/workflows/flaky-test-detector.yml b/.github/workflows/flaky-test-detector.yml index d8d1cb7ce809..4e0c710cefc0 100644 --- a/.github/workflows/flaky-test-detector.yml +++ b/.github/workflows/flaky-test-detector.yml @@ -10,7 +10,8 @@ on: env: HEAD_COMMIT: ${{ github.event.inputs.commit || github.sha }} - NX_CACHE_KEY: nx-Linux-${{ github.ref }} + # Bump when changing cache path shape (was whole .nx, now .nx/cache only). + NX_CACHE_KEY: nx-Linux-${{ github.ref }}-cache-v2 # Restored .nx cache may come from another runner; see nx.dev/troubleshooting/unknown-local-cache NX_REJECT_UNKNOWN_LOCAL_CACHE: '0' @@ -42,7 +43,7 @@ jobs: - name: Restore NX cache uses: actions/cache/restore@v5 with: - path: .nx + path: .nx/cache key: ${{ env.NX_CACHE_KEY }} - name: Build packages From cc08ca3d5d3fad6039c9d331fb9e1970b5ade188 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Wed, 22 Apr 2026 16:59:36 +0200 Subject: [PATCH 37/46] fix nx cache config --- .github/workflows/build.yml | 22 ++++++++++++---------- .github/workflows/flaky-test-detector.yml | 11 +++++------ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1e84d713ded3..9e21a07c6ece 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,14 +52,8 @@ env: BUNDLE_ARTIFACT_GLOB: packages/*/build/bundles BUNDLE_ARTIFACT_DOWNLOAD_PATH: ${{ github.workspace }}/packages - # Task cache only (matches nx.json cacheDirectory). Omit .nx/workspace-data and .nx/daemon - # — not portable across runners and not needed for restore hits. NX_CACHE_KEY: nx-Linux-${{ github.head_ref || github.ref }}-${{ github.run_id }} - # Restored .nx cache is unpacked on a different runner than it was saved on; allow Nx to use it. - # https://nx.dev/troubleshooting/unknown-local-cache - NX_REJECT_UNKNOWN_LOCAL_CACHE: '0' - # https://bsky.app/profile/joyeecheung.bsky.social/post/3lhy6o54fo22h # Apparently some of our CI failures are attributable to a corrupt v8 cache, causing v8 failures with: "Check failed: current == end_slot_index.". # This option both controls the `v8-compile-cache-lib` and `v8-compile-cache` packages. @@ -130,7 +124,9 @@ jobs: # Only cache this per-PR to speed up CI. if: github.event_name == 'pull_request' with: - path: .nx/cache + path: | + .nx/cache + .nx/workspace-data key: ${{ env.NX_CACHE_KEY }} - name: Upload build artifacts @@ -213,7 +209,9 @@ jobs: - name: Restore NX cache uses: actions/cache/restore@v5 with: - path: .nx/cache + path: | + .nx/cache + .nx/workspace-data key: ${{ env.NX_CACHE_KEY }} - name: Build Lambda layer @@ -251,7 +249,9 @@ jobs: - name: Restore NX cache uses: actions/cache/restore@v5 with: - path: .nx/cache + path: | + .nx/cache + .nx/workspace-data key: ${{ env.NX_CACHE_KEY }} - name: Build bundles @@ -1002,7 +1002,9 @@ jobs: - name: Restore NX cache uses: actions/cache/restore@v5 with: - path: .nx/cache + path: | + .nx/cache + .nx/workspace-data key: ${{ env.NX_CACHE_KEY }} - name: Build tarballs diff --git a/.github/workflows/flaky-test-detector.yml b/.github/workflows/flaky-test-detector.yml index 4e0c710cefc0..847190944141 100644 --- a/.github/workflows/flaky-test-detector.yml +++ b/.github/workflows/flaky-test-detector.yml @@ -10,11 +10,8 @@ on: env: HEAD_COMMIT: ${{ github.event.inputs.commit || github.sha }} - # Bump when changing cache path shape (was whole .nx, now .nx/cache only). - NX_CACHE_KEY: nx-Linux-${{ github.ref }}-cache-v2 - - # Restored .nx cache may come from another runner; see nx.dev/troubleshooting/unknown-local-cache - NX_REJECT_UNKNOWN_LOCAL_CACHE: '0' + # Bump when changing what we persist under .nx (see main CI workflow). + NX_CACHE_KEY: nx-Linux-${{ github.ref }}-cache-v3 # Cancel in progress workflows on pull_requests. # https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value @@ -43,7 +40,9 @@ jobs: - name: Restore NX cache uses: actions/cache/restore@v5 with: - path: .nx/cache + path: | + .nx/cache + .nx/workspace-data key: ${{ env.NX_CACHE_KEY }} - name: Build packages From e3f2a7ef04c877a29d48d12c9e79175c52d1c5e4 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 23 Apr 2026 09:25:09 +0200 Subject: [PATCH 38/46] rename build back --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9e21a07c6ece..21cbf6d3553c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -69,7 +69,7 @@ jobs: pull-requests: read job_build: - name: Install & Build + name: Build needs: job_get_metadata runs-on: ubuntu-24.04 timeout-minutes: 15 From 85288bd9094e4a3d520fc847adf7a8ef00102e9f Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 23 Apr 2026 09:27:02 +0200 Subject: [PATCH 39/46] swap order --- .github/workflows/build.yml | 30 +++++++++++------------ .github/workflows/flaky-test-detector.yml | 6 ++--- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 21cbf6d3553c..33d0d5a7d2b1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -201,11 +201,6 @@ jobs: uses: actions/setup-node@v6 with: node-version-file: 'package.json' - - name: Restore caches - uses: ./.github/actions/restore-cache - with: - dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} - - name: Restore NX cache uses: actions/cache/restore@v5 with: @@ -214,6 +209,11 @@ jobs: .nx/workspace-data key: ${{ env.NX_CACHE_KEY }} + - name: Restore caches + uses: ./.github/actions/restore-cache + with: + dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Build Lambda layer run: yarn build:layer @@ -241,11 +241,6 @@ jobs: uses: actions/setup-node@v6 with: node-version-file: 'package.json' - - name: Restore caches - uses: ./.github/actions/restore-cache - with: - dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} - - name: Restore NX cache uses: actions/cache/restore@v5 with: @@ -254,6 +249,11 @@ jobs: .nx/workspace-data key: ${{ env.NX_CACHE_KEY }} + - name: Restore caches + uses: ./.github/actions/restore-cache + with: + dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Build bundles run: yarn build:bundle @@ -994,11 +994,6 @@ jobs: uses: actions/setup-node@v6 with: node-version-file: 'package.json' - - name: Restore caches - uses: ./.github/actions/restore-cache - with: - dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} - - name: Restore NX cache uses: actions/cache/restore@v5 with: @@ -1007,6 +1002,11 @@ jobs: .nx/workspace-data key: ${{ env.NX_CACHE_KEY }} + - name: Restore caches + uses: ./.github/actions/restore-cache + with: + dependency_cache_key: ${{ needs.job_build.outputs.dependency_cache_key }} + - name: Build tarballs run: yarn build:tarball diff --git a/.github/workflows/flaky-test-detector.yml b/.github/workflows/flaky-test-detector.yml index 847190944141..fc432ba13b23 100644 --- a/.github/workflows/flaky-test-detector.yml +++ b/.github/workflows/flaky-test-detector.yml @@ -34,9 +34,6 @@ jobs: with: node-version-file: 'package.json' cache: 'yarn' - - name: Install dependencies - run: yarn install --ignore-engines --frozen-lockfile - - name: Restore NX cache uses: actions/cache/restore@v5 with: @@ -45,6 +42,9 @@ jobs: .nx/workspace-data key: ${{ env.NX_CACHE_KEY }} + - name: Install dependencies + run: yarn install --ignore-engines --frozen-lockfile + - name: Build packages run: yarn build From 640fa4344f8542f27a34abfd01964d731f147c86 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 23 Apr 2026 09:30:37 +0200 Subject: [PATCH 40/46] fix artifacts --- .github/workflows/build.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 33d0d5a7d2b1..f43644da0270 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -440,9 +440,6 @@ jobs: name: build-layer-output path: ${{ env.BUILD_LAYER_PATH }} - - name: Pack tarballs - run: yarn build:tarball - - name: Archive artifacts uses: actions/upload-artifact@v7 with: From 5e3ed42c34d62fef8da6dc3b35b61c80ba72e782 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 23 Apr 2026 10:50:13 +0200 Subject: [PATCH 41/46] small fixes --- .github/workflows/build.yml | 1 - .github/workflows/flaky-test-detector.yml | 10 ------ packages/aws-serverless/package.json | 38 ++++------------------- 3 files changed, 6 insertions(+), 43 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f43644da0270..12950574938e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1269,7 +1269,6 @@ jobs: job_check_lockfile, job_check_format, job_circular_dep_check, - job_build_layer, job_size_check, ] # Always run this, even if a dependent job failed diff --git a/.github/workflows/flaky-test-detector.yml b/.github/workflows/flaky-test-detector.yml index fc432ba13b23..d74a82a667e5 100644 --- a/.github/workflows/flaky-test-detector.yml +++ b/.github/workflows/flaky-test-detector.yml @@ -10,9 +10,6 @@ on: env: HEAD_COMMIT: ${{ github.event.inputs.commit || github.sha }} - # Bump when changing what we persist under .nx (see main CI workflow). - NX_CACHE_KEY: nx-Linux-${{ github.ref }}-cache-v3 - # Cancel in progress workflows on pull_requests. # https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value concurrency: @@ -34,13 +31,6 @@ jobs: with: node-version-file: 'package.json' cache: 'yarn' - - name: Restore NX cache - uses: actions/cache/restore@v5 - with: - path: | - .nx/cache - .nx/workspace-data - key: ${{ env.NX_CACHE_KEY }} - name: Install dependencies run: yarn install --ignore-engines --frozen-lockfile diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json index 2929c9d489c5..619d31bd0b9d 100644 --- a/packages/aws-serverless/package.json +++ b/packages/aws-serverless/package.json @@ -80,11 +80,12 @@ "@vercel/nft": "^1.3.0" }, "scripts": { - "build": "run-p build:transpile build:types build:extension", + "build": "run-p build:transpile build:types", "build:extension": "rollup -c rollup.lambda-extension.config.mjs && yarn ts-node scripts/buildLambdaExtension.ts", "build:layer": "rimraf build/aws && yarn ts-node scripts/buildLambdaLayer.ts", "build:dev": "run-p build:transpile build:types", - "build:transpile": "rollup -c rollup.npm.config.mjs", + "build:transpile": "run-s build:transpile:npm build:extension", + "build:transpile:npm": "rollup -c rollup.npm.config.mjs", "build:types": "run-s build:types:core build:types:downlevel", "build:types:core": "tsc -p tsconfig.types.json", "build:types:downlevel": "yarn downlevel-dts build/npm/types build/npm/types-ts3.8 --to ts3.8", @@ -117,49 +118,22 @@ ], "outputs": [ "{projectRoot}/build/npm/esm", - "{projectRoot}/build/npm/cjs" - ] - }, - "build:extension": { - "inputs": [ - "production", - "^production" - ], - "dependsOn": [ - "^build:transpile" - ], - "outputs": [ + "{projectRoot}/build/npm/cjs", "{projectRoot}/build/lambda-extension" - ] - }, - "build:layer": { - "inputs": [ - "production", - "^production" - ], - "dependsOn": [ - "build:transpile", - "build:extension" - ], - "outputs": [ - "{projectRoot}/build/aws" ], "cache": true }, - "build:tarball": { + "build:layer": { "inputs": [ "production", "^production" ], "dependsOn": [ "build:transpile", - "^build:transpile", - "build:types", - "^build:types", "build:extension" ], "outputs": [ - "{projectRoot}/*.tgz" + "{projectRoot}/build/aws" ], "cache": true } From 3cfdd1e0f45db938d03bfe81e7e012ac676dfa68 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 23 Apr 2026 10:56:47 +0200 Subject: [PATCH 42/46] fixes --- .github/workflows/build.yml | 2 +- package.json | 4 ++-- packages/aws-serverless/package.json | 2 +- scripts/ci-print-build-artifact-paths.mjs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 12950574938e..88cf240d26c6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,7 +37,7 @@ env: # DEPENDENCY_CACHE_KEY: can't be set here because we don't have access to yarn.lock # build-output artifact paths are computed in job_build (step output from - # yarn ci:print-build-artifact-paths — Nx merged outputs for build:transpile, build:types, build:extension). + # yarn ci:print-build-artifact-paths — Nx merged outputs for build:transpile, and build:types). # upload-artifact globs drop the path through the first `*` (see upload-artifact # README). Tarballs therefore land in the artifact as /*.tgz; download diff --git a/package.json b/package.json index 28579d98905a..6e8c7fcf272c 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "private": true, "scripts": { - "build": "node ./scripts/verify-packages-versions.js && nx run-many -t build:transpile build:types build:bundle build:extension", - "build:ci": "node ./scripts/verify-packages-versions.js && nx run-many -t build:transpile build:types build:extension", + "build": "node ./scripts/verify-packages-versions.js && nx run-many -t build:transpile build:types build:bundle", + "build:ci": "node ./scripts/verify-packages-versions.js && nx run-many -t build:transpile build:types", "build:bundle": "nx run-many -t build:bundle", "build:layer": "nx run-many -t build:layer", "build:dev": "nx run-many -t build:types build:transpile", diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json index 619d31bd0b9d..e002a642e6c8 100644 --- a/packages/aws-serverless/package.json +++ b/packages/aws-serverless/package.json @@ -130,7 +130,7 @@ ], "dependsOn": [ "build:transpile", - "build:extension" + "build:types" ], "outputs": [ "{projectRoot}/build/aws" diff --git a/scripts/ci-print-build-artifact-paths.mjs b/scripts/ci-print-build-artifact-paths.mjs index 9f1b692075b5..690b995d78b2 100644 --- a/scripts/ci-print-build-artifact-paths.mjs +++ b/scripts/ci-print-build-artifact-paths.mjs @@ -2,7 +2,7 @@ /** * Prints multiline paths for actions/upload-artifact `path` (often wired via a prior step's * `GITHUB_OUTPUT` `paths< Date: Thu, 23 Apr 2026 12:52:32 +0200 Subject: [PATCH 43/46] more fixes --- .github/workflows/build.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 88cf240d26c6..0db1e68804d5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -978,11 +978,6 @@ jobs: runs-on: ubuntu-24.04 timeout-minutes: 15 steps: - - name: Check out base commit (${{ github.event.pull_request.base.sha }}) - uses: actions/checkout@v6 - if: github.event_name == 'pull_request' - with: - ref: ${{ github.event.pull_request.base.sha }} - name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }}) uses: actions/checkout@v6 with: From 4f8cd17b22ec8419883513fbcca9a3a7d29501eb Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 23 Apr 2026 13:22:42 +0200 Subject: [PATCH 44/46] fix gatsby nx config --- packages/gatsby/package.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index 3d0b6e7ed305..e374ff7667d2 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -84,5 +84,19 @@ "volta": { "extends": "../../package.json" }, + "nx": { + "targets": { + "build:transpile": { + "inputs": ["production", "^production"], + "outputs": [ + "{projectRoot}/build/esm", + "{projectRoot}/build/cjs", + "{projectRoot}/*.d.ts" + ], + "dependsOn": ["^build:transpile"], + "cache": true + } + } + }, "sideEffects": false } From d963894213709e2ed05d10bea309cf0fc8c3a877 Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 23 Apr 2026 13:25:29 +0200 Subject: [PATCH 45/46] remove condition for bundle build --- .github/workflows/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0db1e68804d5..37a031bd042d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -229,7 +229,6 @@ jobs: job_build_bundles: name: Build bundles needs: [job_get_metadata, job_build] - if: needs.job_build.outputs.changed_browser_integration == 'true' || github.event_name != 'pull_request' timeout-minutes: 10 runs-on: ubuntu-24.04 steps: From 334404e6fff1b374c3d98e3d1e46cddaa8ab0c2f Mon Sep 17 00:00:00 2001 From: Francesco Gringl-Novy Date: Thu, 23 Apr 2026 13:25:48 +0200 Subject: [PATCH 46/46] fix lint --- packages/gatsby/package.json | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/gatsby/package.json b/packages/gatsby/package.json index e374ff7667d2..840fdef5d4aa 100644 --- a/packages/gatsby/package.json +++ b/packages/gatsby/package.json @@ -87,14 +87,19 @@ "nx": { "targets": { "build:transpile": { - "inputs": ["production", "^production"], + "inputs": [ + "production", + "^production" + ], "outputs": [ "{projectRoot}/build/esm", "{projectRoot}/build/cjs", "{projectRoot}/*.d.ts" ], - "dependsOn": ["^build:transpile"], - "cache": true + "dependsOn": [ + "^build:transpile" + ], + "cache": true } } },