From b47de74928dc00cf5e0047f11b5d36550fc2e93c Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 26 Aug 2024 10:45:36 -0400 Subject: [PATCH 01/15] docs(cloudflare): Fix spacing in README snippet (#13368) Fixes spacing in readme snippet --- packages/cloudflare/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/cloudflare/README.md b/packages/cloudflare/README.md index f7de52a56e88..398153563f1c 100644 --- a/packages/cloudflare/README.md +++ b/packages/cloudflare/README.md @@ -114,16 +114,16 @@ Currently only ESM handlers are supported. import * as Sentry from '@sentry/cloudflare'; export default withSentry( - (env) => ({ - dsn: env.SENTRY_DSN, + env => ({ + dsn: env.SENTRY_DSN, // Set tracesSampleRate to 1.0 to capture 100% of spans for tracing. - tracesSampleRate: 1.0, - }), - { - async fetch(request, env, ctx) { - return new Response('Hello World!'); - }, - } satisfies ExportedHandler + tracesSampleRate: 1.0, + }), + { + async fetch(request, env, ctx) { + return new Response('Hello World!'); + }, + } satisfies ExportedHandler, ); ``` From e6861cfd08addb1bd1b661067af539fec9e699f9 Mon Sep 17 00:00:00 2001 From: Catherine Lee <55311782+c298lee@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:58:41 -0400 Subject: [PATCH 02/15] feat(feedback): Improve error message for 403 errors (#13441) If the domain is not in `Allowed Domains` in the Sentry project settings, it would cause a 403 error. The default setting is `*` so this only occurs when the user changes these settings. Fixes https://github.com/getsentry/sentry-javascript/issues/9856 --- packages/feedback/src/core/sendFeedback.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/feedback/src/core/sendFeedback.ts b/packages/feedback/src/core/sendFeedback.ts index ca9875284c6e..c0b8ccaa2704 100644 --- a/packages/feedback/src/core/sendFeedback.ts +++ b/packages/feedback/src/core/sendFeedback.ts @@ -64,6 +64,12 @@ export const sendFeedback: SendFeedback = ( ); } + if (response && typeof response.statusCode === 'number' && response.statusCode === 403) { + return reject( + 'Unable to send Feedback. This could be because this domain is not in your list of allowed domains.', + ); + } + return reject( 'Unable to send Feedback. This could be because of network issues, or because you are using an ad-blocker', ); From 80a116bff448a86a7304fd3bc9156cf62d0746d0 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Tue, 27 Aug 2024 10:38:12 +0200 Subject: [PATCH 03/15] fix(replay): Ensure we publish replay CDN bundles (#13437) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Oops, we stopped publishing this, just noticed this while working on my hackweek project... 😬 --- .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 516b1d47b624..dab69b7bd194 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -344,7 +344,7 @@ jobs: name: ${{ github.sha }} path: | ${{ github.workspace }}/packages/browser/build/bundles/** - ${{ github.workspace }}/packages/replay/build/bundles/** + ${{ github.workspace }}/packages/replay-internal/build/bundles/** ${{ github.workspace }}/packages/replay-canvas/build/bundles/** ${{ github.workspace }}/packages/feedback/build/bundles/** ${{ github.workspace }}/packages/**/*.tgz From 6cb699910b7766139c69a3cd68ec80dc200ac07b Mon Sep 17 00:00:00 2001 From: Charly Gomez Date: Tue, 27 Aug 2024 11:15:54 +0200 Subject: [PATCH 04/15] test: Fix flaky csp test (#13376) --- .../suites/feedback/captureFeedbackCsp/init.js | 7 ------- .../suites/feedback/captureFeedbackCsp/subject.js | 4 ++++ .../suites/feedback/captureFeedbackCsp/template.html | 4 +--- .../suites/feedback/captureFeedbackCsp/test.ts | 4 ++-- 4 files changed, 7 insertions(+), 12 deletions(-) create mode 100644 dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/subject.js diff --git a/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/init.js b/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/init.js index 067dbec23fd4..27e5495f66a8 100644 --- a/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/init.js +++ b/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/init.js @@ -10,10 +10,3 @@ Sentry.init({ feedbackIntegration({ tags: { from: 'integration init' }, styleNonce: 'foo1234', scriptNonce: 'foo1234' }), ], }); - -document.addEventListener('securitypolicyviolation', () => { - const container = document.querySelector('#csp-violation'); - if (container) { - container.innerText = 'CSP Violation'; - } -}); diff --git a/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/subject.js b/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/subject.js new file mode 100644 index 000000000000..66adfd0f87d4 --- /dev/null +++ b/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/subject.js @@ -0,0 +1,4 @@ +window.__CSPVIOLATION__ = false; +document.addEventListener('securitypolicyviolation', () => { + window.__CSPVIOLATION__ = true; +}); diff --git a/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/template.html b/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/template.html index 919f372ef468..8039192f5787 100644 --- a/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/template.html +++ b/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/template.html @@ -7,7 +7,5 @@ content="style-src 'nonce-foo1234'; script-src sentry-test.io 'nonce-foo1234';" /> - -
- + diff --git a/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/test.ts b/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/test.ts index 95a8a2eacee8..bca9b498fed0 100644 --- a/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/test.ts +++ b/dev-packages/browser-integration-tests/suites/feedback/captureFeedbackCsp/test.ts @@ -79,6 +79,6 @@ sentryTest('should capture feedback', async ({ getLocalTestUrl, page }) => { }, platform: 'javascript', }); - const cspContainer = await page.locator('#csp-violation'); - expect(cspContainer).not.toContainText('CSP Violation'); + const cspViolation = await page.evaluate('window.__CSPVIOLATION__'); + expect(cspViolation).toBe(false); }); From 195482c8e2811a84cb003845a64992c69b64237b Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Tue, 27 Aug 2024 12:37:03 +0200 Subject: [PATCH 05/15] ci: Stabilize CI dependency cache key (#13401) Ensure it only changes if actual dependencies change. Previously, we would invalidate the dependency cache every time a package.json of the workspace changed in any way. This is defensive, but it also means that we also invalidate if one of these things happen: 1. A script or similar is added/edited for workspace package 2. A release is made, bumping internal dependency versions This change updates this to calculate the hash with a slightly more sophisticated approach, which should hopefully ensure we only actually bust the cache when a dependency _actually_ changes. This should lead to the dependency cache being re-used much more, because only rarely is an actual dependency changed. --------- Co-authored-by: Charly Gomez --- .../actions/install-dependencies/action.yml | 4 +- scripts/dependency-hash-key.js | 73 +++++++++++++++++++ 2 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 scripts/dependency-hash-key.js diff --git a/.github/actions/install-dependencies/action.yml b/.github/actions/install-dependencies/action.yml index 8cb80ac7440e..5fbf87c67d79 100644 --- a/.github/actions/install-dependencies/action.yml +++ b/.github/actions/install-dependencies/action.yml @@ -9,11 +9,9 @@ outputs: runs: using: "composite" steps: - # we use a hash of yarn.lock as our cache key, because if it hasn't changed, our dependencies haven't changed, - # so no need to reinstall them - name: Compute dependency cache key id: compute_lockfile_hash - run: echo "hash=dependencies-${{ hashFiles('yarn.lock', 'packages/*/package.json', 'dev-packages/*/package.json') }}" >> "$GITHUB_OUTPUT" + run: node ./scripts/dependency-hash-key.js >> "$GITHUB_OUTPUT" shell: bash - name: Check dependency cache diff --git a/scripts/dependency-hash-key.js b/scripts/dependency-hash-key.js new file mode 100644 index 000000000000..55e38e4a385e --- /dev/null +++ b/scripts/dependency-hash-key.js @@ -0,0 +1,73 @@ +const crypto = require('crypto'); +const fs = require('fs'); +const path = require('path'); + +/** + * Build a cache key for the dependencies of the monorepo. + * In addition to the content of the yarn.lock file, we also include + * dependencies of all workspace packages in the cache key. + * This ensures that we get a consistent cache key even if a dependency change does not affect + * the yarn.lock file. + */ +function outputDependencyCacheKey() { + const lockfileContent = fs.readFileSync(path.join(process.cwd(), 'yarn.lock'), 'utf8'); + + const hashParts = [lockfileContent]; + + const packageJson = require(path.join(process.cwd(), 'package.json')); + + const workspacePackages = packageJson.workspaces || []; + + // Get the package name (e.g. @sentry/browser) of all workspace packages + // we want to ignore their version numbers later + const workspacePackageNames = getWorkspacePackageNames(workspacePackages); + + // Add the dependencies of the workspace itself + hashParts.push(getNormalizedDependencies(packageJson, workspacePackageNames)); + + // Now for each workspace package, add the dependencies + workspacePackages.forEach(workspace => { + const packageJsonPath = path.join(process.cwd(), workspace, 'package.json'); + const packageJson = require(packageJsonPath); + hashParts.push(getNormalizedDependencies(packageJson, workspacePackageNames)); + }); + + const hash = crypto.createHash('md5').update(hashParts.join('\n')).digest('hex'); + // We log the output in a way that the GitHub Actions can append it to the output + // We prefix it with `dependencies-` so it is easier to identify in the logs + // eslint-disable-next-line no-console + console.log(`hash=dependencies-${hash}`); +} + +function getNormalizedDependencies(packageJson, workspacePackageNames) { + const { dependencies, devDependencies } = packageJson; + + const mergedDependencies = { + ...devDependencies, + ...dependencies, + }; + + const normalizedDependencies = {}; + + // Sort the keys to ensure a consistent order + Object.keys(mergedDependencies) + .sort() + .forEach(key => { + // If the dependency is a workspace package, ignore the version + // No need to invalidate a cache after every release + const version = workspacePackageNames.includes(key) ? '**workspace**' : mergedDependencies[key]; + normalizedDependencies[key] = version; + }); + + return JSON.stringify(normalizedDependencies); +} + +function getWorkspacePackageNames(workspacePackages) { + return workspacePackages.map(workspace => { + const packageJsonPath = path.join(process.cwd(), workspace, 'package.json'); + const packageJson = require(packageJsonPath); + return packageJson.name; + }); +} + +outputDependencyCacheKey(); From 5b9d3bbbadc728304e8a49bb17dd1d6e8d0bdc2e Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Tue, 27 Aug 2024 12:44:22 +0200 Subject: [PATCH 06/15] ci: Always run build on develop branch (#13404) Noticed this here: https://github.com/getsentry/sentry-javascript/actions/runs/10417249817, when merging a markdown-only PR into develop, CI will not fully run there. --- .github/workflows/build.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dab69b7bd194..3196f5bf1ddd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -127,7 +127,9 @@ jobs: runs-on: ubuntu-20.04 timeout-minutes: 15 if: | - needs.job_get_metadata.outputs.changed_any_code == 'true' && + needs.job_get_metadata.outputs.changed_any_code == 'true' || + needs.job_get_metadata.outputs.is_develop == 'true' || + needs.job_get_metadata.outputs.is_release == 'true' || (needs.job_get_metadata.outputs.is_gitflow_sync == 'false' && needs.job_get_metadata.outputs.has_gitflow_label == 'false') steps: - name: Check out base commit (${{ github.event.pull_request.base.sha }}) From ea847d158fdb434b07248f9cd0decdb69ff02160 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Tue, 27 Aug 2024 13:13:06 +0200 Subject: [PATCH 07/15] ci: Don't fail profiling bindings job on cache miss (#13464) --- .github/workflows/build.yml | 31 ++++++------------- .../browser-integration-tests/package.json | 2 +- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3196f5bf1ddd..39b024bd77dd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1418,6 +1418,11 @@ jobs: with: ref: ${{ env.HEAD_COMMIT }} + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + - name: Restore dependency cache uses: actions/cache/restore@v4 id: restore-dependencies @@ -1425,24 +1430,17 @@ jobs: path: ${{ env.CACHED_DEPENDENCY_PATHS }} key: ${{ needs.job_build.outputs.dependency_cache_key }} enableCrossOsArchive: true - fail-on-cache-miss: true - - name: Restore build cache - uses: actions/cache/restore@v4 - id: restore-build - with: - path: ${{ env.CACHED_BUILD_PATHS }} - key: ${{ needs.job_build.outputs.dependency_cache_key }} - enableCrossOsArchive: true - fail-on-cache-miss: true + - name: Install dependencies + env: + SKIP_PLAYWRIGHT_BROWSER_INSTALL: "1" + if: steps.restore-dependencies.outputs.cache-hit != 'true' + run: yarn install --ignore-engines --frozen-lockfile - name: Configure safe directory run: | git config --global --add safe.directory "*" - - name: Install yarn - run: npm i -g yarn@1.22.19 --force - - name: Increase yarn network timeout on Windows if: contains(matrix.os, 'windows') run: yarn config set network-timeout 600000 -g @@ -1454,15 +1452,6 @@ jobs: with: python-version: '3.8.10' - - name: Setup Node - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node }} - - - name: Install Dependencies - if: steps.restore-dependencies.outputs.cache-hit != 'true' - run: yarn install --frozen-lockfile --ignore-engines --ignore-scripts - - name: Setup (arm64| ${{ contains(matrix.container, 'alpine') && 'musl' || 'glibc' }}) if: matrix.arch == 'arm64' && !contains(matrix.container, 'alpine') && matrix.target_platform != 'darwin' run: | diff --git a/dev-packages/browser-integration-tests/package.json b/dev-packages/browser-integration-tests/package.json index 2e2e6cab12ab..dfd3b78c2c14 100644 --- a/dev-packages/browser-integration-tests/package.json +++ b/dev-packages/browser-integration-tests/package.json @@ -9,7 +9,7 @@ "private": true, "scripts": { "clean": "rimraf -g suites/**/dist loader-suites/**/dist tmp", - "install-browsers": "npx playwright install --with-deps", + "install-browsers": "[[ -z \"$SKIP_PLAYWRIGHT_BROWSER_INSTALL\" ]] && yarn install-browsers || echo 'Skipping browser installation'", "lint": "eslint . --format stylish", "fix": "eslint . --format stylish --fix", "type-check": "tsc", From c24f6d0c0e22f1b7609116952501bb8dd4a9aa87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:22:20 +0200 Subject: [PATCH 08/15] build(deps): Bump micromatch from 4.0.7 to 4.0.8 in /dev-packages/e2e-tests/test-applications/tanstack-router (#13472) Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.7 to 4.0.8.
Release notes

Sourced from micromatch's releases.

4.0.8

Ultimate release that fixes both CVE-2024-4067 and CVE-2024-4068. We consider the issues low-priority, so even if you see automated scanners saying otherwise, don't be scared.

Changelog

Sourced from micromatch's changelog.

[4.0.8] - 2024-08-22

  • backported CVE-2024-4067 fix (from v4.0.6) over to 4.x branch
Commits
  • 8bd704e 4.0.8
  • a0e6841 run verb to generate README documentation
  • 4ec2884 Merge branch 'v4' into hauserkristof-feature/v4.0.8
  • 03aa805 Merge pull request #266 from hauserkristof/feature/v4.0.8
  • 814f5f7 lint
  • 67fcce6 fix: CHANGELOG about braces & CVE-2024-4068, v4.0.5
  • 113f2e3 fix: CVE numbers in CHANGELOG
  • d9dbd9a feat: updated CHANGELOG
  • 2ab1315 fix: use actions/setup-node@v4
  • 1406ea3 feat: rework test to work on macos with node 10,12 and 14
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=micromatch&package-manager=npm_and_yarn&previous-version=4.0.7&new-version=4.0.8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/getsentry/sentry-javascript/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../tanstack-router/yarn.lock | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/tanstack-router/yarn.lock b/dev-packages/e2e-tests/test-applications/tanstack-router/yarn.lock index 67441f720060..75a09184cb81 100644 --- a/dev-packages/e2e-tests/test-applications/tanstack-router/yarn.lock +++ b/dev-packages/e2e-tests/test-applications/tanstack-router/yarn.lock @@ -150,6 +150,13 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@playwright/test@^1.44.1": + version "1.46.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.46.1.tgz#a8dfdcd623c4c23bb1b7ea588058aad41055c188" + integrity sha512-Fq6SwLujA/DOIvNC2EL/SojJnkKf/rAwJ//APpJJHRyMi1PdKrY3Az+4XNQ51N4RTbItbIByQ0jgd1tayq1aeA== + dependencies: + playwright "1.46.1" + "@rollup/rollup-android-arm-eabi@4.18.0": version "4.18.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27" @@ -268,6 +275,9 @@ "@sentry/types" "8.4.0" "@sentry/utils" "8.4.0" +"@sentry-internal/test-utils@link:../../../test-utils": + version "8.26.0" + "@sentry/browser@8.4.0": version "8.4.0" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.4.0.tgz#f4aa381eab212432d71366884693a36c2e3a1675" @@ -398,10 +408,10 @@ resolved "https://registry.yarnpkg.com/@tanstack/history/-/history-1.31.16.tgz#6b4947e967af3173ce4929d54d9cb97234646e32" integrity sha512-rahAZXlR879P7dngDH7BZwGYiODA9D5Hqo6nUHn9GAURcqZU5IW0ZiT54dPtV5EPES7muZZmknReYueDHs7FFQ== -"@tanstack/react-router@1.34.3": - version "1.34.3" - resolved "https://registry.yarnpkg.com/@tanstack/react-router/-/react-router-1.34.3.tgz#1152ca7deaaec93f519971911a816bc42011b6ba" - integrity sha512-0pB+4qnp+5snHu5T93gvFmLcpXuIfSEhXZG7ipf3Rq8kmv4y0DGwcbvgFLiYKSZ/3x58faE8U0MD6F9vR9JUtg== +"@tanstack/react-router@1.34.5": + version "1.34.5" + resolved "https://registry.yarnpkg.com/@tanstack/react-router/-/react-router-1.34.5.tgz#2c5bc5cd6b246f830ce586c51a87f95352481957" + integrity sha512-mOMbNHSJ1cAgRuJj9W35wteQL7zFiCNJYgg3QHkxj+obO9zQWiAwycFs0hQTRxqzGfC+jhVLJe1+cW93BhqKyA== dependencies: "@tanstack/history" "1.31.16" "@tanstack/react-store" "^0.2.1" @@ -636,6 +646,11 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" +fsevents@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" @@ -712,9 +727,9 @@ merge2@^1.3.0, merge2@^1.4.1: integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4: - version "4.0.7" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== dependencies: braces "^3.0.3" picomatch "^2.3.1" @@ -756,6 +771,20 @@ picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +playwright-core@1.46.1: + version "1.46.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.46.1.tgz#28f3ab35312135dda75b0c92a3e5c0e7edb9cc8b" + integrity sha512-h9LqIQaAv+CYvWzsZ+h3RsrqCStkBHlgo6/TJlFst3cOTlLghBQlJwPOZKQJTKNaD3QIB7aAVQ+gfWbN3NXB7A== + +playwright@1.46.1: + version "1.46.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.46.1.tgz#ea562bc48373648e10420a10c16842f0b227c218" + integrity sha512-oPcr1yqoXLCkgKtD5eNUPLiN40rYEM39odNpIb6VE6S7/15gJmA1NzVv6zJYusV0e7tzvkU/utBFNa/Kpxmwng== + dependencies: + playwright-core "1.46.1" + optionalDependencies: + fsevents "2.3.2" + postcss@^8.4.38: version "8.4.38" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" From 1caf420df3227eaef93c1d263f461b4891194cec Mon Sep 17 00:00:00 2001 From: Sigrid Huemer <32902192+s1gr1d@users.noreply.github.com> Date: Tue, 27 Aug 2024 14:16:56 +0200 Subject: [PATCH 09/15] feat(nuxt): Wrap config in nuxt context (#13457) To be able to use `useRuntimeConfig()` in the user-defined Sentry config file, it needs to be wrapped in a Nuxt context. Right now, this is only done on the client-side because the server-side is currently still in the `public` folder (this will be changed) and cannot use the virtual `#imports` import (`useRuntimeConfig` is imported from `#imports`) --- .../test-applications/nuxt-3/nuxt.config.ts | 7 ++++ .../nuxt-3/sentry.client.config.ts | 3 +- packages/nuxt/src/module.ts | 16 ++++++--- .../nuxt/src/runtime/plugins/sentry.client.ts | 36 ++++++++++--------- 4 files changed, 41 insertions(+), 21 deletions(-) diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3/nuxt.config.ts b/dev-packages/e2e-tests/test-applications/nuxt-3/nuxt.config.ts index 69b31a4214ec..0fcccd560af9 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3/nuxt.config.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3/nuxt.config.ts @@ -4,4 +4,11 @@ export default defineNuxtConfig({ imports: { autoImport: false, }, + runtimeConfig: { + public: { + sentry: { + dsn: 'https://public@dsn.ingest.sentry.io/1337', + }, + }, + }, }); diff --git a/dev-packages/e2e-tests/test-applications/nuxt-3/sentry.client.config.ts b/dev-packages/e2e-tests/test-applications/nuxt-3/sentry.client.config.ts index 5253d08c90f0..5c4e0f892ca8 100644 --- a/dev-packages/e2e-tests/test-applications/nuxt-3/sentry.client.config.ts +++ b/dev-packages/e2e-tests/test-applications/nuxt-3/sentry.client.config.ts @@ -1,8 +1,9 @@ import * as Sentry from '@sentry/nuxt'; +import { useRuntimeConfig } from '#imports'; Sentry.init({ environment: 'qa', // dynamic sampling bias to keep transactions - dsn: 'https://public@dsn.ingest.sentry.io/1337', + dsn: useRuntimeConfig().public.sentry.dsn, tunnel: `http://localhost:3031/`, // proxy server tracesSampleRate: 1.0, }); diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index da7fcf778366..5d529c99330c 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -26,10 +26,18 @@ export default defineNuxtModule({ addPluginTemplate({ mode: 'client', filename: 'sentry-client-config.mjs', - getContents: () => - `import "${buildDirResolver.resolve(`/${clientConfigFile}`)}"\n` + - 'import { defineNuxtPlugin } from "#imports"\n' + - 'export default defineNuxtPlugin(() => {})', + + // Dynamic import of config file to wrap it within a Nuxt context (here: defineNuxtPlugin) + // Makes it possible to call useRuntimeConfig() in the user-defined sentry config file + getContents: () => ` + import { defineNuxtPlugin } from "#imports"; + + export default defineNuxtPlugin({ + name: 'sentry-client-config', + async setup() { + await import("${buildDirResolver.resolve(`/${clientConfigFile}`)}") + } + });`, }); addPlugin({ src: moduleDirResolver.resolve('./runtime/plugins/sentry.client'), mode: 'client' }); diff --git a/packages/nuxt/src/runtime/plugins/sentry.client.ts b/packages/nuxt/src/runtime/plugins/sentry.client.ts index a6bcd0115528..95dc954c4b89 100644 --- a/packages/nuxt/src/runtime/plugins/sentry.client.ts +++ b/packages/nuxt/src/runtime/plugins/sentry.client.ts @@ -29,24 +29,28 @@ interface VueRouter { // Tree-shakable guard to remove all code related to tracing declare const __SENTRY_TRACING__: boolean; -export default defineNuxtPlugin(nuxtApp => { - // This evaluates to true unless __SENTRY_TRACING__ is text-replaced with "false", in which case everything inside - // will get tree-shaken away - if (typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__) { - const sentryClient = getClient(); +export default defineNuxtPlugin({ + name: 'sentry-client-integrations', + dependsOn: ['sentry-client-config'], + async setup(nuxtApp) { + // This evaluates to true unless __SENTRY_TRACING__ is text-replaced with "false", in which case everything inside + // will get tree-shaken away + if (typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__) { + const sentryClient = getClient(); - if (sentryClient && '$router' in nuxtApp) { - sentryClient.addIntegration( - browserTracingIntegration({ router: nuxtApp.$router as VueRouter, routeLabel: 'path' }), - ); + if (sentryClient && '$router' in nuxtApp) { + sentryClient.addIntegration( + browserTracingIntegration({ router: nuxtApp.$router as VueRouter, routeLabel: 'path' }), + ); + } } - } - nuxtApp.hook('app:created', vueApp => { - const sentryClient = getClient(); + nuxtApp.hook('app:created', vueApp => { + const sentryClient = getClient(); - if (sentryClient) { - sentryClient.addIntegration(vueIntegration({ app: vueApp })); - } - }); + if (sentryClient) { + sentryClient.addIntegration(vueIntegration({ app: vueApp })); + } + }); + }, }); From 66bf03bc91f28cb072e5893ea059879c07a835c5 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Tue, 27 Aug 2024 14:30:46 +0200 Subject: [PATCH 10/15] test(ci): Pin Node 22 unit test Node version (#13476) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's a bug in Node 22.7.0 with protobuf which we're running into: https://github.com/protobufjs/protobuf.js/issues/2025 Once the bug is fixed, we should revert this PR. h/t @lforst for figuring this out; I'm just merging it into develop 😅 --- .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 39b024bd77dd..37c3089f1d2e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -456,7 +456,8 @@ jobs: strategy: fail-fast: false matrix: - node: [14, 16, 18, 20, 22] + #TODO: unpin 22 once Node bug is fixed + node: [14, 16, 18, 20, '22.6.0'] steps: - name: Check out base commit (${{ github.event.pull_request.base.sha }}) uses: actions/checkout@v4 From aaaaa7d94a85bffb896fc1cca1fd9ff12f43074d Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Tue, 27 Aug 2024 15:18:21 +0200 Subject: [PATCH 11/15] ci: Don't fork bomb on yarn install (#13478) whoops --- dev-packages/browser-integration-tests/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-packages/browser-integration-tests/package.json b/dev-packages/browser-integration-tests/package.json index dfd3b78c2c14..ffd35696f14d 100644 --- a/dev-packages/browser-integration-tests/package.json +++ b/dev-packages/browser-integration-tests/package.json @@ -9,7 +9,7 @@ "private": true, "scripts": { "clean": "rimraf -g suites/**/dist loader-suites/**/dist tmp", - "install-browsers": "[[ -z \"$SKIP_PLAYWRIGHT_BROWSER_INSTALL\" ]] && yarn install-browsers || echo 'Skipping browser installation'", + "install-browsers": "[[ -z \"$SKIP_PLAYWRIGHT_BROWSER_INSTALL\" ]] && yarn npx playwright install --with-deps || echo 'Skipping browser installation'", "lint": "eslint . --format stylish", "fix": "eslint . --format stylish --fix", "type-check": "tsc", From 8ce9f7ce9a122bfe70d3c12ebfe50bba5d237037 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Tue, 27 Aug 2024 18:26:27 -0230 Subject: [PATCH 12/15] feat(replay): Upgrade rrweb packages to 2.26.0 (#13483) * [fix(rrdom): Ignore invalid DOM attributes when diffing](https://github.com/getsentry/rrweb/pull/213) * [fix: manual snapshot in rAF loop](https://github.com/getsentry/rrweb/pull/210) (thanks @ShinyChang) * [feat: Fix blocking dynamically added iframes](https://github.com/getsentry/rrweb/pull/212) --- .size-limit.js | 2 +- packages/replay-canvas/package.json | 2 +- packages/replay-internal/package.json | 4 +-- yarn.lock | 42 +++++++++++++-------------- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.size-limit.js b/.size-limit.js index 859ce741cc3d..2280b950c513 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -29,7 +29,7 @@ module.exports = [ path: 'packages/browser/build/npm/esm/index.js', import: createImport('init', 'browserTracingIntegration', 'replayIntegration'), gzip: true, - limit: '66 KB', + limit: '68 KB', modifyWebpackConfig: function (config) { const webpack = require('webpack'); config.plugins.push( diff --git a/packages/replay-canvas/package.json b/packages/replay-canvas/package.json index 4dd27ce4a18c..7bfeb7304d01 100644 --- a/packages/replay-canvas/package.json +++ b/packages/replay-canvas/package.json @@ -65,7 +65,7 @@ }, "homepage": "https://docs.sentry.io/platforms/javascript/session-replay/", "devDependencies": { - "@sentry-internal/rrweb": "2.25.0" + "@sentry-internal/rrweb": "2.26.0" }, "dependencies": { "@sentry-internal/replay": "8.26.0", diff --git a/packages/replay-internal/package.json b/packages/replay-internal/package.json index cf655cbf1a38..49ef6631c4d4 100644 --- a/packages/replay-internal/package.json +++ b/packages/replay-internal/package.json @@ -69,8 +69,8 @@ "devDependencies": { "@babel/core": "^7.17.5", "@sentry-internal/replay-worker": "8.26.0", - "@sentry-internal/rrweb": "2.25.0", - "@sentry-internal/rrweb-snapshot": "2.25.0", + "@sentry-internal/rrweb": "2.26.0", + "@sentry-internal/rrweb-snapshot": "2.26.0", "fflate": "^0.8.1", "jest-matcher-utils": "^29.0.0", "jsdom-worker": "^0.2.1" diff --git a/yarn.lock b/yarn.lock index 481175f8db61..a1a060119a64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8115,22 +8115,22 @@ dependencies: "@sentry-internal/rrweb-snapshot" "2.11.0" -"@sentry-internal/rrdom@2.25.0": - version "2.25.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/rrdom/-/rrdom-2.25.0.tgz#4be842f7f4efae383bbd5a9dcbbecc212d378d70" - integrity sha512-YTxGHnCdv6D2JVJ6YFezMsGOHLy7CM8x8qMaY3Yh3QTubFOjdGpcGJGITF/9Lkx+rFVCTdjL32cQu9NUgEJO8g== +"@sentry-internal/rrdom@2.26.0": + version "2.26.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrdom/-/rrdom-2.26.0.tgz#be3e4f14de56a6022aed3a00ac6ea2f2abe05d1c" + integrity sha512-QviUvwAPYDCmkeJsu3fx0pXlLBHwQLCKje9wuuhRVkmDL9dMbcCDa7+HhFa2V2UMXgZ7l6z/SMin2ymDReubSw== dependencies: - "@sentry-internal/rrweb-snapshot" "2.25.0" + "@sentry-internal/rrweb-snapshot" "2.26.0" "@sentry-internal/rrweb-snapshot@2.11.0": version "2.11.0" resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-snapshot/-/rrweb-snapshot-2.11.0.tgz#1af79130604afea989d325465b209ac015b27c9a" integrity sha512-1nP22QlplMNooSNvTh+L30NSZ+E3UcfaJyxXSMLxUjQHTGPyM1VkndxZMmxlKhyR5X+rLbxi/+RvuAcpM43VoA== -"@sentry-internal/rrweb-snapshot@2.25.0": - version "2.25.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-snapshot/-/rrweb-snapshot-2.25.0.tgz#f20bd20436edac24ed1075b47fc4773894739d97" - integrity sha512-7j90eSGFRS1YWcuo0bXPtV9oDdCQxutilyYbim/I09GA7kx4/d8OG8ryxQl6WWXW+E50x6dEpDsZXWMPkSleEg== +"@sentry-internal/rrweb-snapshot@2.26.0": + version "2.26.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-snapshot/-/rrweb-snapshot-2.26.0.tgz#cb70bf2c006bf59824806f567ae6ca23ba2aac3a" + integrity sha512-wWa+OxAHhoozIlt3kjhmfrsn/+POnJgktOe5WT95fakfyv56mGKXqh4mXx7HRzGEwq4bbkhtcPhfh2gbueSPcA== "@sentry-internal/rrweb-types@2.11.0": version "2.11.0" @@ -8139,12 +8139,12 @@ dependencies: "@sentry-internal/rrweb-snapshot" "2.11.0" -"@sentry-internal/rrweb-types@2.25.0": - version "2.25.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-types/-/rrweb-types-2.25.0.tgz#61662befc57ed7054a491eb35ad3deda7d66157c" - integrity sha512-sM2YdevhIRxQ/Kr89cfbNBO7/EFhycTmQT0NKg4owdKkIvuuqz1AhbRpMMdpJ4NJnos+h06VPObeXm6rcrffsw== +"@sentry-internal/rrweb-types@2.26.0": + version "2.26.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb-types/-/rrweb-types-2.26.0.tgz#0ba52a4e6f24238556134280b7cf77633bc68e21" + integrity sha512-og4X+OidRRc3bMuwfeio4UF8EcVFjtz/z0DDjpyV+0sH4LDoVoH1+Jlxbxl4WR83LALWMcsxV0UWYeXA5kfrOw== dependencies: - "@sentry-internal/rrweb-snapshot" "2.25.0" + "@sentry-internal/rrweb-snapshot" "2.26.0" "@types/css-font-loading-module" "0.0.7" "@sentry-internal/rrweb@2.11.0": @@ -8161,14 +8161,14 @@ fflate "^0.4.4" mitt "^3.0.0" -"@sentry-internal/rrweb@2.25.0": - version "2.25.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb/-/rrweb-2.25.0.tgz#0148f1904f1e9549f2c2cae209fe3d3fe891d3ec" - integrity sha512-0tgBI0CFpyO3Z3dw4IjS/D6AnQypro4dquRrcZZzqnMH65Vxw3yytGDtmvE/FzHzGC0vmKFTM+sTkzFY0bo+Bg== +"@sentry-internal/rrweb@2.26.0": + version "2.26.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/rrweb/-/rrweb-2.26.0.tgz#456a9ae1b48e87f086e4749346532879e9ac304c" + integrity sha512-J5db750QNlGdLrzbZwEVJgOtLwHtvh3a6VVxQ08G0yEZxqI7bdvcvxnvIXp8h+PwUk/S8yjoZwYgLFFDED3ePQ== dependencies: - "@sentry-internal/rrdom" "2.25.0" - "@sentry-internal/rrweb-snapshot" "2.25.0" - "@sentry-internal/rrweb-types" "2.25.0" + "@sentry-internal/rrdom" "2.26.0" + "@sentry-internal/rrweb-snapshot" "2.26.0" + "@sentry-internal/rrweb-types" "2.26.0" "@types/css-font-loading-module" "0.0.7" "@xstate/fsm" "^1.4.0" base64-arraybuffer "^1.0.1" From 60271f50ae1e687bba0f58656e5dc2cd0777dd9f Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 28 Aug 2024 08:29:41 +0200 Subject: [PATCH 13/15] fix(cdn): Do not mangle _metadata (#13426) Noticed that this is mangled on the `options` in the CDN, which it probably shouldn't be... --- dev-packages/rollup-utils/plugins/bundlePlugins.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev-packages/rollup-utils/plugins/bundlePlugins.mjs b/dev-packages/rollup-utils/plugins/bundlePlugins.mjs index ffc24f58174a..2ce35d1e6168 100644 --- a/dev-packages/rollup-utils/plugins/bundlePlugins.mjs +++ b/dev-packages/rollup-utils/plugins/bundlePlugins.mjs @@ -116,6 +116,8 @@ export function makeTerserPlugin() { '_integrations', // _meta is used to store metadata of replay network events '_meta', + // We store SDK metadata in the options + '_metadata', // Object we inject debug IDs into with bundler plugins '_sentryDebugIds', // These are used by instrument.ts in utils for identifying HTML elements & events From 3a1417fb4e244d3c4782059e67dd6235eaf13e2a Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 28 Aug 2024 09:00:27 +0200 Subject: [PATCH 14/15] ci: Update clear cache action to be smarter (#13405) Previously, we had a CI action to manually clear all caches. This PR adjusts this so this action can be used in a more granular way: * By default, the action will now delete caches of any PR runs that are successful, as well as any caches of release branches. * You can configure to also delete caches on the develop branch, and/or to also delete non-successful PR branches. Additionally, this action will run every midnight, to automatically clear completed/outdated stuff. The goal is to keep develop caches as long as possible, and clear out other caches, unless they failed (which indicates you may want to re-run some of the tests) and unless they are currently running (to not break ongoing tests). Ideally, we do not need to manually run this, but can rely on automated cleanup over night. --- .github/workflows/clear-cache.yml | 36 +++- .github/workflows/external-contributors.yml | 1 - .../clear-cache-gh-action/.eslintrc.cjs | 14 ++ dev-packages/clear-cache-gh-action/action.yml | 25 +++ dev-packages/clear-cache-gh-action/index.mjs | 183 ++++++++++++++++++ .../clear-cache-gh-action/package.json | 23 +++ package.json | 1 + 7 files changed, 280 insertions(+), 3 deletions(-) create mode 100644 dev-packages/clear-cache-gh-action/.eslintrc.cjs create mode 100644 dev-packages/clear-cache-gh-action/action.yml create mode 100644 dev-packages/clear-cache-gh-action/index.mjs create mode 100644 dev-packages/clear-cache-gh-action/package.json diff --git a/.github/workflows/clear-cache.yml b/.github/workflows/clear-cache.yml index 2946723fe6b8..5c327553e3b8 100644 --- a/.github/workflows/clear-cache.yml +++ b/.github/workflows/clear-cache.yml @@ -1,11 +1,43 @@ name: "Action: Clear all GHA caches" on: workflow_dispatch: + inputs: + clear_pending_prs: + description: Delete caches of pending PR workflows + type: boolean + default: false + clear_develop: + description: Delete caches on develop branch + type: boolean + default: false + clear_branches: + description: Delete caches on non-develop branches + type: boolean + default: true + schedule: + # Run every day at midnight + - cron: '0 0 * * *' jobs: clear-caches: name: Delete all caches runs-on: ubuntu-20.04 steps: - - name: Clear caches - uses: easimon/wipe-cache@v2 + - uses: actions/checkout@v4 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version-file: 'package.json' + + # TODO: Use cached version if possible (but never store cache) + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Delete GHA caches + uses: ./dev-packages/clear-cache-gh-action + with: + clear_pending_prs: ${{ inputs.clear_pending_prs }} + clear_develop: ${{ inputs.clear_develop }} + clear_branches: ${{ inputs.clear_branches }} + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/external-contributors.yml b/.github/workflows/external-contributors.yml index 50acb2be8e73..e01a1a66a589 100644 --- a/.github/workflows/external-contributors.yml +++ b/.github/workflows/external-contributors.yml @@ -25,7 +25,6 @@ jobs: uses: actions/setup-node@v4 with: node-version-file: 'package.json' - cache: 'yarn' - name: Install dependencies run: yarn install --frozen-lockfile diff --git a/dev-packages/clear-cache-gh-action/.eslintrc.cjs b/dev-packages/clear-cache-gh-action/.eslintrc.cjs new file mode 100644 index 000000000000..8c67e0037908 --- /dev/null +++ b/dev-packages/clear-cache-gh-action/.eslintrc.cjs @@ -0,0 +1,14 @@ +module.exports = { + extends: ['../../.eslintrc.js'], + parserOptions: { + sourceType: 'module', + ecmaVersion: 'latest', + }, + + overrides: [ + { + files: ['*.mjs'], + extends: ['@sentry-internal/sdk/src/base'], + }, + ], +}; diff --git a/dev-packages/clear-cache-gh-action/action.yml b/dev-packages/clear-cache-gh-action/action.yml new file mode 100644 index 000000000000..06493534b23e --- /dev/null +++ b/dev-packages/clear-cache-gh-action/action.yml @@ -0,0 +1,25 @@ +name: 'clear-cache-gh-action' +description: 'Clear caches of the GitHub repository.' +inputs: + github_token: + required: true + description: 'a github access token' + clear_develop: + required: false + default: "" + description: "If set, also clear caches from develop branch." + clear_branches: + required: false + default: "" + description: "If set, also clear caches from non-develop branches." + clear_pending_prs: + required: false + default: "" + description: "If set, also clear caches from pending PR workflow runs." + workflow_name: + required: false + default: "CI: Build & Test" + description: The workflow to clear caches for. +runs: + using: 'node20' + main: 'index.mjs' diff --git a/dev-packages/clear-cache-gh-action/index.mjs b/dev-packages/clear-cache-gh-action/index.mjs new file mode 100644 index 000000000000..b1cb75c5a5c0 --- /dev/null +++ b/dev-packages/clear-cache-gh-action/index.mjs @@ -0,0 +1,183 @@ +import * as core from '@actions/core'; + +import { context, getOctokit } from '@actions/github'; + +async function run() { + const { getInput } = core; + + const { repo, owner } = context.repo; + + const githubToken = getInput('github_token'); + const clearDevelop = inputToBoolean(getInput('clear_develop', { type: 'boolean' })); + const clearBranches = inputToBoolean(getInput('clear_branches', { type: 'boolean', default: true })); + const clearPending = inputToBoolean(getInput('clear_pending_prs', { type: 'boolean' })); + const workflowName = getInput('workflow_name'); + + const octokit = getOctokit(githubToken); + + await clearGithubCaches(octokit, { + repo, + owner, + clearDevelop, + clearPending, + clearBranches, + workflowName, + }); +} + +/** + * Clear caches. + * + * @param {ReturnType } octokit + * @param {{repo: string, owner: string, clearDevelop: boolean, clearPending: boolean, clearBranches: boolean, workflowName: string}} options + */ +async function clearGithubCaches(octokit, { repo, owner, clearDevelop, clearPending, clearBranches, workflowName }) { + let deletedCaches = 0; + let remainingCaches = 0; + + let deletedSize = 0; + let remainingSize = 0; + + /** @type {Map>} */ + const cachedPrs = new Map(); + /** @type {Map>} */ + const cachedWorkflows = new Map(); + + /** + * Clear caches. + * + * @param {{ref: string}} options + */ + const shouldClearCache = async ({ ref }) => { + // Do not clear develop caches if clearDevelop is false. + if (!clearDevelop && ref === 'refs/heads/develop') { + core.info('> Keeping cache because it is on develop.'); + return false; + } + + // There are two fundamental paths here: + // If the cache belongs to a PR, we need to check if the PR has any pending workflows. + // Else, we assume the cache belongs to a branch, where we do not check for pending workflows + const pullNumber = /^refs\/pull\/(\d+)\/merge$/.exec(ref)?.[1]; + const isPr = !!pullNumber; + + // Case 1: This is a PR, and we do not want to clear pending PRs + // In this case, we need to fetch all PRs and workflow runs to check them + if (isPr && !clearPending) { + const pr = + cachedPrs.get(pullNumber) || + (await octokit.rest.pulls.get({ + owner, + repo, + pull_number: pullNumber, + })); + cachedPrs.set(pullNumber, pr); + + const prBranch = pr.data.head.ref; + + // Check if PR has any pending workflows + const workflowRuns = + cachedWorkflows.get(prBranch) || + (await octokit.rest.actions.listWorkflowRunsForRepo({ + repo, + owner, + branch: prBranch, + })); + cachedWorkflows.set(prBranch, workflowRuns); + + // We only care about the relevant workflow + const relevantWorkflowRuns = workflowRuns.data.workflow_runs.filter(workflow => workflow.name === workflowName); + + const latestWorkflowRun = relevantWorkflowRuns[0]; + + core.info(`> Latest relevant workflow run: ${latestWorkflowRun.html_url}`); + + // No relevant workflow? Clear caches! + if (!latestWorkflowRun) { + core.info('> Clearing cache because no relevant workflow was found.'); + return true; + } + + // If the latest run was not successful, keep caches + // as either the run may be in progress, + // or failed - in which case we may want to re-run the workflow + if (latestWorkflowRun.conclusion !== 'success') { + core.info(`> Keeping cache because latest workflow is ${latestWorkflowRun.conclusion}.`); + return false; + } + + core.info(`> Clearing cache because latest workflow run is ${latestWorkflowRun.conclusion}.`); + return true; + } + + // Case 2: This is a PR, but we do want to clear pending PRs + // In this case, this cache should always be cleared + if (isPr) { + core.info('> Clearing cache of every PR workflow run.'); + return true; + } + + // Case 3: This is not a PR, and we want to clean branches + if (clearBranches) { + core.info('> Clearing cache because it is not a PR.'); + return true; + } + + // Case 4: This is not a PR, and we do not want to clean branches + core.info('> Keeping cache for non-PR workflow run.'); + return false; + }; + + for await (const response of octokit.paginate.iterator(octokit.rest.actions.getActionsCacheList, { + owner, + repo, + })) { + if (!response.data.length) { + break; + } + + for (const { id, ref, size_in_bytes } of response.data) { + core.info(`Checking cache ${id} for ${ref}...`); + + const shouldDelete = await shouldClearCache({ ref }); + + if (shouldDelete) { + core.info(`> Clearing cache ${id}...`); + + deletedCaches++; + deletedSize += size_in_bytes; + + await octokit.rest.actions.deleteActionsCacheById({ + owner, + repo, + cache_id: id, + }); + } else { + remainingCaches++; + remainingSize += size_in_bytes; + } + } + } + + const format = new Intl.NumberFormat('en-US', { + style: 'decimal', + }); + + core.info('Summary:'); + core.info(`Deleted ${deletedCaches} caches, freeing up ~${format.format(deletedSize / 1000 / 1000)} mb.`); + core.info(`Remaining ${remainingCaches} caches, using ~${format.format(remainingSize / 1000 / 1000)} mb.`); +} + +run(); + +function inputToBoolean(input) { + if (typeof input === 'boolean') { + return input; + } + + if (typeof input === 'string') { + return input === 'true'; + } + + return false; +} diff --git a/dev-packages/clear-cache-gh-action/package.json b/dev-packages/clear-cache-gh-action/package.json new file mode 100644 index 000000000000..492f4fc2b31e --- /dev/null +++ b/dev-packages/clear-cache-gh-action/package.json @@ -0,0 +1,23 @@ +{ + "name": "@sentry-internal/clear-cache-gh-action", + "description": "An internal Github Action to clear GitHub caches.", + "version": "8.26.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "private": true, + "main": "index.mjs", + "type": "module", + "scripts": { + "lint": "eslint . --format stylish", + "fix": "eslint . --format stylish --fix" + }, + "dependencies": { + "@actions/core": "1.10.1", + "@actions/github": "^5.0.0" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/package.json b/package.json index beba7d79d284..4b9ad0383c02 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ "dev-packages/overhead-metrics", "dev-packages/test-utils", "dev-packages/size-limit-gh-action", + "dev-packages/clear-cache-gh-action", "dev-packages/external-contributor-gh-action", "dev-packages/rollup-utils" ], From 4ccf251f56b3f41a9d538b8b32c79c99710d9b19 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 28 Aug 2024 09:51:23 +0200 Subject: [PATCH 15/15] ci: Store build output as artifacts instead of cache (#13487) This PR changes it so that the build output is kept as an artifact, not a cache. This way, this should never be lost on us. We keep the NX cache as before. I chose a retention period of 7 days, which means that after 7 days you could no longer re-run a workflow partially. IMHO that's a reasonable start, we can adjust this if needed. --- .github/actions/restore-cache/action.yml | 12 +++++------- .github/workflows/build.yml | 17 +++++++++-------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/.github/actions/restore-cache/action.yml b/.github/actions/restore-cache/action.yml index 848983376840..316d89dc1c26 100644 --- a/.github/actions/restore-cache/action.yml +++ b/.github/actions/restore-cache/action.yml @@ -11,15 +11,13 @@ runs: path: ${{ env.CACHED_DEPENDENCY_PATHS }} key: ${{ env.DEPENDENCY_CACHE_KEY }} - - name: Check build cache - uses: actions/cache/restore@v4 - id: build-cache + - name: Restore build artifacts + uses: actions/download-artifact@v4 with: - path: ${{ env.CACHED_BUILD_PATHS }} - key: ${{ env.BUILD_CACHE_KEY }} + name: build-output - name: Check if caches are restored uses: actions/github-script@v6 - if: steps.dep-cache.outputs.cache-hit != 'true' || steps.build-cache.outputs.cache-hit != 'true' + if: steps.dep-cache.outputs.cache-hit != 'true' with: - script: core.setFailed('Dependency or build cache could not be restored - please re-run ALL jobs.') + script: core.setFailed('Dependency cache could not be restored - please re-run ALL jobs.') diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 37c3089f1d2e..d0ae1a39c1d2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -48,7 +48,6 @@ env: ${{ github.workspace }}/packages/utils/cjs ${{ github.workspace }}/packages/utils/esm - BUILD_CACHE_KEY: build-cache-${{ github.event.inputs.commit || github.sha }} BUILD_CACHE_TARBALL_KEY: tarball-${{ github.event.inputs.commit || github.sha }} # GH will use the first restore-key it finds that matches @@ -160,13 +159,6 @@ jobs: base: ${{ github.event.pull_request.base.sha }} head: ${{ env.HEAD_COMMIT }} - - name: Check build cache - uses: actions/cache@v4 - id: cache_built_packages - with: - path: ${{ env.CACHED_BUILD_PATHS }} - key: ${{ env.BUILD_CACHE_KEY }} - - name: NX cache uses: actions/cache@v4 # Disable cache when: @@ -188,6 +180,15 @@ jobs: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} run: yarn build + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: build-output + path: ${{ env.CACHED_BUILD_PATHS }} + retention-days: 7 + compression-level: 6 + overwrite: true + outputs: dependency_cache_key: ${{ steps.install_dependencies.outputs.cache_key }} changed_node_integration: ${{ needs.job_get_metadata.outputs.changed_ci == 'true' || contains(steps.checkForAffected.outputs.affected, '@sentry-internal/node-integration-tests') }}