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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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/13] 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