From c14e5507e63d9bae1b1e1ef18f683d5e6ee4b5fa Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 2 Sep 2026 19:20:58 +0200 Subject: [PATCH 1/9] chore(repo): Add dogfood-release skill --- .agents/skills/dogfood-release/SKILL.md | 184 ++++++++++++++++++++++++ agents.toml | 4 + 2 files changed, 188 insertions(+) create mode 100644 .agents/skills/dogfood-release/SKILL.md diff --git a/.agents/skills/dogfood-release/SKILL.md b/.agents/skills/dogfood-release/SKILL.md new file mode 100644 index 000000000000..88404939948a --- /dev/null +++ b/.agents/skills/dogfood-release/SKILL.md @@ -0,0 +1,184 @@ +--- +name: dogfood-release +description: Bump a just-published Sentry JS SDK version across the internal consumer repos (sentry, gib-potato, sentry-changelog, sentry-docs, chartcuterie), verify each one builds, and open a draft PR per repo. Use after publishing an SDK release, especially a prerelease, to catch breaking changes early. Trigger phrases include "dogfood this release", "dogfood the SDK", "bump the SDK in our repos", "roll out to the consumer repos". +argument-hint: ' # e.g. 11.0.0-beta.0' +--- + +# Dogfood an SDK release in the consumer repos + +Sentry runs the freshly published SDK in its own products before it goes stable. +This skill bumps one version across every internal consumer repo, proves each still +builds, and opens one draft PR per repo. + +## Requirements + +Local checkouts under `~/projects/`. Skip any repo that is missing and say so. +Do not clone: a missing checkout is the user's call. + +## The repos + +| Repo | Path | PM | Base | Sentry deps | Range style | +|---|---|---|---|---|---| +| `getsentry/sentry` | `~/projects/sentry` | pnpm | `master` | `@sentry/{browser,core,node,react}` | exact | +| `getsentry/gib-potato` | `~/projects/gib-potato` | `vp` (vite-plus) | `main` | `@sentry/{vue,bundler-plugins}` | caret | +| `getsentry/sentry-changelog` | `~/projects/sentry-changelog` | pnpm | `main` | `@sentry/nextjs` | caret | +| `getsentry/sentry-docs` | `~/projects/sentry-docs` | pnpm | `master` | `@sentry/{browser,nextjs}` | exact | +| `getsentry/chartcuterie` | `~/projects/chartcuterie` | yarn | `master` | `@sentry/{node,profiling-node}` | exact | + +Re-derive these each run rather than trusting the table. Deps and base branches drift. + +```bash +for d in sentry gib-potato sentry-changelog sentry-docs chartcuterie; do + cd ~/projects/$d || continue + echo "## $d base=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name)" + node -p "require('./package.json').packageManager || 'none'" + grep -E '"@sentry/[a-z-]+":' package.json +done +``` + +## Step 0: check the version is actually installable + +Two separate gates. Check both before touching any repo, because both have burned us. + +**1. Published to npm.** Craft publishes packages one at a time, so a green release +branch does not mean every package is up. + +```bash +npm view @sentry/core@ version --registry https://registry.npmjs.org +``` + +**2. Cleared Sentry's registry firewall.** Internal repos install through +`sfw.security.sentry.io`, which quarantines packages it has not scanned. A **brand new +package** in the release (one whose first-ever version is this release) will 403 there +even though it is fine on public npm. + +```bash +# every package the release added, plus one known-good control +curl -s -o /dev/null -w "%{http_code} \n" \ + https://sfw.security.sentry.io/npm//-/-.tgz +curl -s -o /dev/null -w "%{http_code} control @sentry/core\n" \ + https://sfw.security.sentry.io/npm/@sentry/core/-/core-.tgz +``` + +To find new packages, diff the dependency sets of the previous and new release: + +```bash +diff <(npm view @sentry/nextjs@ dependencies --registry https://registry.npmjs.org) \ + <(npm view @sentry/nextjs@ dependencies --registry https://registry.npmjs.org) +``` + +If a package 403s, **stop before installing**. Report which repos are blocked (any repo +whose dep tree reaches that package) and ask for it to be allowlisted. Carry on with the +repos that do not reach it. Do not work around the firewall. + +## Step 1: branch and bump + +One branch name across all repos, `ab/bump-sentry-` +(e.g. `ab/bump-sentry-11-beta-0`). Always branch off a **freshly fetched** base, never off +whatever the checkout was left on last time. + +Anchor the version replacement on the **old version string**, not the package name. Repos +carry unrelated `@sentry/*` packages (`@sentry/conventions`, `@sentry/toolbar`, +`@sentry/webpack-plugin`, `@sentry/jest-environment`) that must not move. Preserve the +existing range prefix: + +```bash +cd ~/projects/$d +git fetch origin $BASE --quiet +git checkout -B ab/bump-sentry- origin/$BASE +sed -i '' 's/"/"/g' package.json +node -e "JSON.parse(require('fs').readFileSync('package.json','utf8'))" # still valid JSON +git diff package.json +``` + +## Step 2: install with the repo's own package manager + +**Use the package manager the repo declares.** Reaching for a different one (or a +different major of the same one) rewrites unrelated parts of the lockfile: a stray npm +once re-expanded the bundled deps of `@tailwindcss/oxide-wasm32-wasi` in gib-potato and +buried the real change. + +- `packageManager` field in `package.json` is the source of truth. +- gib-potato is the exception worth remembering: it declares npm but is driven by + **vite-plus**, so use `node_modules/.bin/vp install`. +- Do a full install, not lockfile-only. The build in step 3 needs real `node_modules`. + +Then check the lockfile diff is Sentry-only. It should contain version moves and nothing +else: + +```bash +# npm +git diff package-lock.json | grep -o '^[-+] "node_modules/[^"]*"' | sort -u +# pnpm / yarn +git diff | grep -E '^[+-] ' | grep -viE 'sentry|opentelemetry' | head -40 +``` + +Anything unrelated in there means the wrong package manager ran. Reset the lockfile and +redo the install rather than committing the churn. + +## Step 3: build and adapt + +Build every repo. A prerelease exists precisely to break things, so expect fallout and +fix it in the consumer, following `MIGRATION.md` in `sentry-javascript`. + +| Repo | Verify with | +|---|---| +| sentry | `pnpm run typecheck`, `pnpm run build-production`, then `pnpm test-ci ` and `pnpm run lint:js ` | +| gib-potato | `node_modules/.bin/vp build` | +| sentry-changelog | `pnpm build` | +| sentry-docs | `pnpm build` | +| chartcuterie | `yarn build` | + +The `sentry` frontend is where migration work usually lands. Files that have needed edits +before: `static/app/bootstrap/initializeSdk.tsx`, +`static/app/serviceWorker/worker/initializeSentry.ts`, +`static/app/utils/performanceForSentry/index.tsx`, `static/app/views/issueList/overview.tsx`. +Run `pnpm exec oxfmt ` on anything you touch. + +Two things worth an explicit look on a v11 bump, both of which have bitten us: + +- **Moved entry points.** `withSentryConfig` moved to `@sentry/nextjs/config`, so + `next.config.mjs` in sentry-changelog and sentry-docs needs its import updated. +- **Span name changes.** Low-cardinality span names change what `beforeSendSpan` and any + dashboard or alert keyed on span names actually see. Flag this rather than silently + bumping. + +Also sanity-check what the lockfile *dropped*. A v11 bump should remove the OpenTelemetry +packages from repos that only use the browser SDK; if they are still there, something +resolved to the old major. + +## Step 4: commit, push, PR + +One commit per repo. Match each repo's own commit convention, which you can read off its +log (`git log origin/$BASE --oneline -20`); they differ (`chore(deps):`, `build(deps):`, +`build(js):`, plain `chore:`). Say what moved, and note any adaptation separately: + +``` +build(deps): Update @sentry/nextjs to + +withSentryConfig moved to the @sentry/nextjs/config entry point in . +Update the import in next.config.mjs. +``` + +Open every PR as a **draft**, `## What` / `## Why` only: + +```bash +gh pr create --draft --base $BASE \ + --title "" \ + --body "## What + +Update \`@sentry/x\` to . + +## Why + +Keep on the latest v11 prerelease so we catch breaking changes early." +``` + +## Report back + +A short table: repo, PR link, and what needed adapting. Call out explicitly: + +- repos skipped for a missing checkout, +- repos blocked by the registry firewall, and which package blocked them, +- any breaking change that needed a code fix, since that is the dogfooding signal and + usually belongs in `MIGRATION.md` if it is not there yet. diff --git a/agents.toml b/agents.toml index 12cd7e4ba56c..6e8b8f34a673 100644 --- a/agents.toml +++ b/agents.toml @@ -89,3 +89,7 @@ source = "path:.agents/skills/write-tests" [[skills]] name = "port-span-names" source = "path:.agents/skills/port-span-names" + +[[skills]] +name = "dogfood-release" +source = "path:.agents/skills/dogfood-release" From 55bd549a9e5e2a523fadf1d978a4446c677fc53c Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 2 Sep 2026 19:23:18 +0200 Subject: [PATCH 2/9] Trim skill to the version bump and add a repo selection step --- .agents/skills/dogfood-release/SKILL.md | 122 ++++++------------------ 1 file changed, 31 insertions(+), 91 deletions(-) diff --git a/.agents/skills/dogfood-release/SKILL.md b/.agents/skills/dogfood-release/SKILL.md index 88404939948a..c94a94799352 100644 --- a/.agents/skills/dogfood-release/SKILL.md +++ b/.agents/skills/dogfood-release/SKILL.md @@ -1,14 +1,12 @@ --- name: dogfood-release -description: Bump a just-published Sentry JS SDK version across the internal consumer repos (sentry, gib-potato, sentry-changelog, sentry-docs, chartcuterie), verify each one builds, and open a draft PR per repo. Use after publishing an SDK release, especially a prerelease, to catch breaking changes early. Trigger phrases include "dogfood this release", "dogfood the SDK", "bump the SDK in our repos", "roll out to the consumer repos". +description: Bump a just-published Sentry JS SDK version across the internal dogfooding repos (sentry, gib-potato, sentry-changelog, sentry-docs, chartcuterie) and open a draft PR per repo. Use after publishing an SDK release, especially a prerelease, to get it running in our own products early. Trigger phrases include "dogfood this release", "dogfood the SDK", "bump the SDK in our repos", "roll out to the consumer repos". argument-hint: ' # e.g. 11.0.0-beta.0' --- # Dogfood an SDK release in the consumer repos -Sentry runs the freshly published SDK in its own products before it goes stable. -This skill bumps one version across every internal consumer repo, proves each still -builds, and opens one draft PR per repo. +Bump one SDK version across the internal repos that run it, and open a draft PR per repo. ## Requirements @@ -36,42 +34,28 @@ for d in sentry gib-potato sentry-changelog sentry-docs chartcuterie; do done ``` -## Step 0: check the version is actually installable +## Step 1: ask which repos to bump -Two separate gates. Check both before touching any repo, because both have burned us. +Survey first so the question shows real state, then ask with **`AskUserQuestion`, +`multiSelect: true`**, one option per repo that has a local checkout. Label each option +with the repo name and put its current SDK version in the description, so it is obvious +which ones are already up to date. -**1. Published to npm.** Craft publishes packages one at a time, so a green release -branch does not mean every package is up. +Everything is selected by default in the UI; the user unticks what they want to skip. +Only bump the repos that come back selected. Do not ask per repo, one question covers all. -```bash -npm view @sentry/core@ version --registry https://registry.npmjs.org -``` +Skip this question only when the user already named the repos. -**2. Cleared Sentry's registry firewall.** Internal repos install through -`sfw.security.sentry.io`, which quarantines packages it has not scanned. A **brand new -package** in the release (one whose first-ever version is this release) will 403 there -even though it is fine on public npm. - -```bash -# every package the release added, plus one known-good control -curl -s -o /dev/null -w "%{http_code} \n" \ - https://sfw.security.sentry.io/npm//-/-.tgz -curl -s -o /dev/null -w "%{http_code} control @sentry/core\n" \ - https://sfw.security.sentry.io/npm/@sentry/core/-/core-.tgz -``` +## Step 2: check the version is on npm -To find new packages, diff the dependency sets of the previous and new release: +Craft publishes packages one at a time, so a green release branch does not mean every +package is up yet. ```bash -diff <(npm view @sentry/nextjs@ dependencies --registry https://registry.npmjs.org) \ - <(npm view @sentry/nextjs@ dependencies --registry https://registry.npmjs.org) +npm view @sentry/core@ version --registry https://registry.npmjs.org ``` -If a package 403s, **stop before installing**. Report which repos are blocked (any repo -whose dep tree reaches that package) and ask for it to be allowlisted. Carry on with the -repos that do not reach it. Do not work around the firewall. - -## Step 1: branch and bump +## Step 3: branch and bump One branch name across all repos, `ab/bump-sentry-` (e.g. `ab/bump-sentry-11-beta-0`). Always branch off a **freshly fetched** base, never off @@ -91,74 +75,34 @@ node -e "JSON.parse(require('fs').readFileSync('package.json','utf8'))" # stil git diff package.json ``` -## Step 2: install with the repo's own package manager - -**Use the package manager the repo declares.** Reaching for a different one (or a -different major of the same one) rewrites unrelated parts of the lockfile: a stray npm -once re-expanded the bundled deps of `@tailwindcss/oxide-wasm32-wasi` in gib-potato and -buried the real change. - -- `packageManager` field in `package.json` is the source of truth. -- gib-potato is the exception worth remembering: it declares npm but is driven by - **vite-plus**, so use `node_modules/.bin/vp install`. -- Do a full install, not lockfile-only. The build in step 3 needs real `node_modules`. - -Then check the lockfile diff is Sentry-only. It should contain version moves and nothing -else: - -```bash -# npm -git diff package-lock.json | grep -o '^[-+] "node_modules/[^"]*"' | sort -u -# pnpm / yarn -git diff | grep -E '^[+-] ' | grep -viE 'sentry|opentelemetry' | head -40 -``` - -Anything unrelated in there means the wrong package manager ran. Reset the lockfile and -redo the install rather than committing the churn. +## Step 4: install and build -## Step 3: build and adapt +Use the package manager the repo declares. The `packageManager` field in `package.json` +is the source of truth, with one exception: gib-potato declares npm but is driven by +**vite-plus**, so use `node_modules/.bin/vp install`. -Build every repo. A prerelease exists precisely to break things, so expect fallout and -fix it in the consumer, following `MIGRATION.md` in `sentry-javascript`. +Do a full install, not lockfile-only, then build: -| Repo | Verify with | +| Repo | Build with | |---|---| -| sentry | `pnpm run typecheck`, `pnpm run build-production`, then `pnpm test-ci ` and `pnpm run lint:js ` | +| sentry | `pnpm run typecheck` and `pnpm run build-production` | | gib-potato | `node_modules/.bin/vp build` | | sentry-changelog | `pnpm build` | | sentry-docs | `pnpm build` | | chartcuterie | `yarn build` | -The `sentry` frontend is where migration work usually lands. Files that have needed edits -before: `static/app/bootstrap/initializeSdk.tsx`, -`static/app/serviceWorker/worker/initializeSentry.ts`, -`static/app/utils/performanceForSentry/index.tsx`, `static/app/views/issueList/overview.tsx`. -Run `pnpm exec oxfmt ` on anything you touch. - -Two things worth an explicit look on a v11 bump, both of which have bitten us: - -- **Moved entry points.** `withSentryConfig` moved to `@sentry/nextjs/config`, so - `next.config.mjs` in sentry-changelog and sentry-docs needs its import updated. -- **Span name changes.** Low-cardinality span names change what `beforeSendSpan` and any - dashboard or alert keyed on span names actually see. Flag this rather than silently - bumping. +Confirm the lockfile diff is Sentry-only, version moves and nothing else. Unrelated +entries mean the wrong package manager ran, so reset the lockfile and redo the install +rather than committing the churn. -Also sanity-check what the lockfile *dropped*. A v11 bump should remove the OpenTelemetry -packages from repos that only use the browser SDK; if they are still there, something -resolved to the old major. +If a build breaks on an intentional SDK change, fix it in the consumer following +`MIGRATION.md` in `sentry-javascript`, and report it. -## Step 4: commit, push, PR +## Step 5: commit, push, PR One commit per repo. Match each repo's own commit convention, which you can read off its log (`git log origin/$BASE --oneline -20`); they differ (`chore(deps):`, `build(deps):`, -`build(js):`, plain `chore:`). Say what moved, and note any adaptation separately: - -``` -build(deps): Update @sentry/nextjs to - -withSentryConfig moved to the @sentry/nextjs/config entry point in . -Update the import in next.config.mjs. -``` +`build(js):`, plain `chore:`). Open every PR as a **draft**, `## What` / `## Why` only: @@ -176,9 +120,5 @@ Keep on the latest v11 prerelease so we catch breaking changes early." ## Report back -A short table: repo, PR link, and what needed adapting. Call out explicitly: - -- repos skipped for a missing checkout, -- repos blocked by the registry firewall, and which package blocked them, -- any breaking change that needed a code fix, since that is the dogfooding signal and - usually belongs in `MIGRATION.md` if it is not there yet. +A short table: repo, PR link, and whether anything needed adapting. Call out repos skipped +for a missing checkout, and any install or build that failed. From 1e452bc685e33ea4c6cdef67b4227d422e447237 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 2 Sep 2026 19:26:10 +0200 Subject: [PATCH 3/9] Make the skill work without a local checkout --- .agents/skills/dogfood-release/SKILL.md | 81 +++++++++++++++++-------- 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/.agents/skills/dogfood-release/SKILL.md b/.agents/skills/dogfood-release/SKILL.md index c94a94799352..bdf2002df88b 100644 --- a/.agents/skills/dogfood-release/SKILL.md +++ b/.agents/skills/dogfood-release/SKILL.md @@ -10,36 +10,53 @@ Bump one SDK version across the internal repos that run it, and open a draft PR ## Requirements -Local checkouts under `~/projects/`. Skip any repo that is missing and say so. -Do not clone: a missing checkout is the user's call. +Only `gh`, authenticated with push access to the `getsentry` org. No local checkout is +needed: this skill works against a checkout if one happens to exist, and clones into the +session scratchpad otherwise. ## The repos -| Repo | Path | PM | Base | Sentry deps | Range style | -|---|---|---|---|---|---| -| `getsentry/sentry` | `~/projects/sentry` | pnpm | `master` | `@sentry/{browser,core,node,react}` | exact | -| `getsentry/gib-potato` | `~/projects/gib-potato` | `vp` (vite-plus) | `main` | `@sentry/{vue,bundler-plugins}` | caret | -| `getsentry/sentry-changelog` | `~/projects/sentry-changelog` | pnpm | `main` | `@sentry/nextjs` | caret | -| `getsentry/sentry-docs` | `~/projects/sentry-docs` | pnpm | `master` | `@sentry/{browser,nextjs}` | exact | -| `getsentry/chartcuterie` | `~/projects/chartcuterie` | yarn | `master` | `@sentry/{node,profiling-node}` | exact | +| Repo | PM | Base | Sentry deps | Range style | +|---|---|---|---|---| +| `getsentry/sentry` | pnpm | `master` | `@sentry/{browser,core,node,react}` | exact | +| `getsentry/gib-potato` | `vp` (vite-plus) | `main` | `@sentry/{vue,bundler-plugins}` | caret | +| `getsentry/sentry-changelog` | pnpm | `main` | `@sentry/nextjs` | caret | +| `getsentry/sentry-docs` | pnpm | `master` | `@sentry/{browser,nextjs}` | exact | +| `getsentry/chartcuterie` | yarn 1 | `master` | `@sentry/{node,profiling-node}` | exact | -Re-derive these each run rather than trusting the table. Deps and base branches drift. +The table is a starting point, not the truth. Deps and base branches drift, so read the +real values off each repo. Without a checkout that costs one API call each: ```bash -for d in sentry gib-potato sentry-changelog sentry-docs chartcuterie; do - cd ~/projects/$d || continue - echo "## $d base=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name)" - node -p "require('./package.json').packageManager || 'none'" - grep -E '"@sentry/[a-z-]+":' package.json +for r in sentry gib-potato sentry-changelog sentry-docs chartcuterie; do + echo "## $r base=$(gh repo view getsentry/$r --json defaultBranchRef --jq .defaultBranchRef.name)" + gh api repos/getsentry/$r/contents/package.json --jq '.content' | base64 -d \ + | grep -E '"(packageManager|@sentry/[a-z-]+)":' done ``` +## Step 0: get a working tree + +A lockfile can only be regenerated by running the repo's package manager, so every repo +needs a working tree somewhere. Resolve one per repo, in this order: + +1. `$SENTRY_DOGFOOD_WORKSPACE/`, if that variable is set. +2. An existing checkout in a common parent (`~/projects`, `~/src`, `~/code`, `~/dev`, `~/workspace`) + whose `origin` remote matches the repo. Verify the remote, do not trust the directory name. +3. Otherwise clone into the session scratchpad: + +```bash +gh repo clone getsentry/$r "$SCRATCH/$r" -- --depth=1 --single-branch --branch $BASE +``` + +Note in the final report which repos were cloned fresh and which reused a checkout. + ## Step 1: ask which repos to bump Survey first so the question shows real state, then ask with **`AskUserQuestion`, -`multiSelect: true`**, one option per repo that has a local checkout. Label each option -with the repo name and put its current SDK version in the description, so it is obvious -which ones are already up to date. +`multiSelect: true`**, one option per repo. Label each option with the repo name and put +its current SDK version in the description, so it is obvious which ones are already up to +date. Ask before cloning anything, so nothing is fetched for a repo that gets unticked. Everything is selected by default in the UI; the user unticks what they want to skip. Only bump the repos that come back selected. Do not ask per repo, one question covers all. @@ -67,7 +84,7 @@ carry unrelated `@sentry/*` packages (`@sentry/conventions`, `@sentry/toolbar`, existing range prefix: ```bash -cd ~/projects/$d +cd "$DIR" # resolved in step 0 git fetch origin $BASE --quiet git checkout -B ab/bump-sentry- origin/$BASE sed -i '' 's/"/"/g' package.json @@ -81,7 +98,9 @@ Use the package manager the repo declares. The `packageManager` field in `packag is the source of truth, with one exception: gib-potato declares npm but is driven by **vite-plus**, so use `node_modules/.bin/vp install`. -Do a full install, not lockfile-only, then build: +How far to go depends on what the working tree cost you. + +**Reused checkout:** `node_modules` is already warm, so do a full install and build. | Repo | Build with | |---|---| @@ -91,9 +110,19 @@ Do a full install, not lockfile-only, then build: | sentry-docs | `pnpm build` | | chartcuterie | `yarn build` | -Confirm the lockfile diff is Sentry-only, version moves and nothing else. Unrelated -entries mean the wrong package manager ran, so reset the lockfile and redo the install -rather than committing the churn. +**Fresh clone:** a full install from cold is slow, and the draft PR's own CI is the real +gate anyway. Updating the lockfile is enough: + +- pnpm: `pnpm install --lockfile-only` +- npm: `npm install --package-lock-only` +- vp: `vp install` +- yarn 1 has no lockfile-only mode, so it needs a plain `yarn install` + +Say plainly in the report which repos were verified only by CI. + +Either way, confirm the lockfile diff is Sentry-only, version moves and nothing else. +Unrelated entries mean the wrong package manager ran, so reset the lockfile and redo the +install rather than committing the churn. If a build breaks on an intentional SDK change, fix it in the consumer following `MIGRATION.md` in `sentry-javascript`, and report it. @@ -120,5 +149,7 @@ Keep on the latest v11 prerelease so we catch breaking changes early." ## Report back -A short table: repo, PR link, and whether anything needed adapting. Call out repos skipped -for a missing checkout, and any install or build that failed. +A short table: repo, PR link, how it was verified (local build or CI only), and whether +anything needed adapting. Call out any install or build that failed. + +Delete scratchpad clones once their PRs are open. From 11968900002810dc14233e5e0f9acd58f1fa5c21 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 2 Sep 2026 19:35:29 +0200 Subject: [PATCH 4/9] Derive per-repo details instead of hardcoding them --- .agents/skills/dogfood-release/SKILL.md | 123 +++++++++++++----------- 1 file changed, 69 insertions(+), 54 deletions(-) diff --git a/.agents/skills/dogfood-release/SKILL.md b/.agents/skills/dogfood-release/SKILL.md index bdf2002df88b..e6dcfc7d8559 100644 --- a/.agents/skills/dogfood-release/SKILL.md +++ b/.agents/skills/dogfood-release/SKILL.md @@ -16,54 +16,65 @@ session scratchpad otherwise. ## The repos -| Repo | PM | Base | Sentry deps | Range style | -|---|---|---|---|---| -| `getsentry/sentry` | pnpm | `master` | `@sentry/{browser,core,node,react}` | exact | -| `getsentry/gib-potato` | `vp` (vite-plus) | `main` | `@sentry/{vue,bundler-plugins}` | caret | -| `getsentry/sentry-changelog` | pnpm | `main` | `@sentry/nextjs` | caret | -| `getsentry/sentry-docs` | pnpm | `master` | `@sentry/{browser,nextjs}` | exact | -| `getsentry/chartcuterie` | yarn 1 | `master` | `@sentry/{node,profiling-node}` | exact | +- `getsentry/sentry`: the main app, our biggest SDK consumer +- `getsentry/gib-potato`: internal Vue app +- `getsentry/sentry-changelog`: Next.js site +- `getsentry/sentry-docs`: Next.js site +- `getsentry/chartcuterie`: Node chart rendering service -The table is a starting point, not the truth. Deps and base branches drift, so read the -real values off each repo. Without a checkout that costs one API call each: +This list is the only thing worth hardcoding. Everything else about a repo (its base +branch, package manager, which `@sentry/*` packages it carries, how each one is ranged, +how it builds) changes without warning, so read it per run in step 1 instead of assuming. + +## Step 1: survey the repos + +Read the current state over the API first, so nothing is cloned for a repo that gets +unticked in step 2. Per repo, collect the default branch, `packageManager`, the `scripts`, +and every `@sentry/*` dependency with its current range: ```bash for r in sentry gib-potato sentry-changelog sentry-docs chartcuterie; do - echo "## $r base=$(gh repo view getsentry/$r --json defaultBranchRef --jq .defaultBranchRef.name)" - gh api repos/getsentry/$r/contents/package.json --jq '.content' | base64 -d \ - | grep -E '"(packageManager|@sentry/[a-z-]+)":' + echo "## $r base=$(gh repo view getsentry/$r --json defaultBranchRef --jq .defaultBranchRef.name)" + echo " lock: $(gh api repos/getsentry/$r/contents --jq '.[].name' | grep -xE 'package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?' | tr '\n' ' ')" + gh api repos/getsentry/$r/contents/package.json --jq .content | base64 -d | node -e ' + let s="";process.stdin.on("data",d=>s+=d).on("end",()=>{ + const p=JSON.parse(s), d={...p.dependencies,...p.devDependencies}; + console.log(" pm:", p.packageManager || "none"); + console.log(" build:", (p.scripts||{}).build || "none"); + for (const [k,v] of Object.entries(d)) if (k.startsWith("@sentry/")) console.log(` ${k}: ${v}`); + })' done ``` -## Step 0: get a working tree - -A lockfile can only be regenerated by running the repo's package manager, so every repo -needs a working tree somewhere. Resolve one per repo, in this order: - -1. `$SENTRY_DOGFOOD_WORKSPACE/`, if that variable is set. -2. An existing checkout in a common parent (`~/projects`, `~/src`, `~/code`, `~/dev`, `~/workspace`) - whose `origin` remote matches the repo. Verify the remote, do not trust the directory name. -3. Otherwise clone into the session scratchpad: +Three things to work out from that, rather than from memory: -```bash -gh repo clone getsentry/$r "$SCRATCH/$r" -- --depth=1 --single-branch --branch $BASE -``` +- **Which deps to bump.** Only the ones already on the SDK version you are moving off. + Repos also carry `@sentry/*` packages on their own release trains + (`@sentry/conventions`, `@sentry/toolbar`, `@sentry/webpack-plugin`, + `@sentry/jest-environment`); those must not move. +- **How each dep is ranged.** Some repos pin exactly, some use a caret, and a repo can + mix both. Take the prefix from the dep you are about to edit and keep it, rather than + applying one style across the repo or across the fleet. +- **Which package manager actually drives the repo.** Prefer `packageManager`, and fall + back to the lockfile when it is absent (chartcuterie has no field and a `yarn.lock`). + Then check what the `scripts` invoke: a repo whose `build` runs through another tool + (gib-potato declares npm but builds with `vp`, from its `vite-plus` dependency) has to + be installed with that tool too, or its lockfile is written by the wrong thing. -Note in the final report which repos were cloned fresh and which reused a checkout. +If a repo has no matching `@sentry/*` dep, it has nothing to bump. Say so and drop it. -## Step 1: ask which repos to bump +## Step 2: ask which repos to bump -Survey first so the question shows real state, then ask with **`AskUserQuestion`, -`multiSelect: true`**, one option per repo. Label each option with the repo name and put -its current SDK version in the description, so it is obvious which ones are already up to -date. Ask before cloning anything, so nothing is fetched for a repo that gets unticked. +Ask with **`AskUserQuestion`, `multiSelect: true`**, one option per repo. Label each option +with the repo name and put its current SDK version from step 1 in the description, so it +is obvious which ones are already up to date. Everything is selected by default in the UI; the user unticks what they want to skip. Only bump the repos that come back selected. Do not ask per repo, one question covers all. Skip this question only when the user already named the repos. -## Step 2: check the version is on npm +## Step 3: check the version is on npm Craft publishes packages one at a time, so a green release branch does not mean every package is up yet. @@ -72,19 +83,33 @@ package is up yet. npm view @sentry/core@ version --registry https://registry.npmjs.org ``` -## Step 3: branch and bump +## Step 4: get a working tree + +A lockfile can only be regenerated by running the repo's package manager, so every +selected repo needs a working tree. Resolve one per repo, in this order: + +1. `$SENTRY_DOGFOOD_WORKSPACE/`, if that variable is set. +2. An existing checkout in a common parent (`~/projects`, `~/src`, `~/code`, `~/dev`, `~/workspace`) + whose `origin` remote matches the repo. Verify the remote, do not trust the directory name. +3. Otherwise clone into the session scratchpad: + +```bash +gh repo clone getsentry/$r "$SCRATCH/$r" -- --depth=1 --single-branch --branch $BASE +``` + +Note in the final report which repos were cloned fresh and which reused a checkout. + +## Step 5: branch and bump One branch name across all repos, `ab/bump-sentry-` (e.g. `ab/bump-sentry-11-beta-0`). Always branch off a **freshly fetched** base, never off whatever the checkout was left on last time. -Anchor the version replacement on the **old version string**, not the package name. Repos -carry unrelated `@sentry/*` packages (`@sentry/conventions`, `@sentry/toolbar`, -`@sentry/webpack-plugin`, `@sentry/jest-environment`) that must not move. Preserve the -existing range prefix: +Anchor the version replacement on the **old version string** so only the deps identified in +step 1 move, and preserve each existing range prefix: ```bash -cd "$DIR" # resolved in step 0 +cd "$DIR" # resolved in step 4 git fetch origin $BASE --quiet git checkout -B ab/bump-sentry- origin/$BASE sed -i '' 's/"/"/g' package.json @@ -92,31 +117,21 @@ node -e "JSON.parse(require('fs').readFileSync('package.json','utf8'))" # stil git diff package.json ``` -## Step 4: install and build - -Use the package manager the repo declares. The `packageManager` field in `package.json` -is the source of truth, with one exception: gib-potato declares npm but is driven by -**vite-plus**, so use `node_modules/.bin/vp install`. - -How far to go depends on what the working tree cost you. +## Step 6: install and build -**Reused checkout:** `node_modules` is already warm, so do a full install and build. +Install with the package manager identified in step 1. How far to go depends on what the +working tree cost you. -| Repo | Build with | -|---|---| -| sentry | `pnpm run typecheck` and `pnpm run build-production` | -| gib-potato | `node_modules/.bin/vp build` | -| sentry-changelog | `pnpm build` | -| sentry-docs | `pnpm build` | -| chartcuterie | `yarn build` | +**Reused checkout:** `node_modules` is already warm, so do a full install, then run the +repo's own build script (and its typecheck script, where it has one). **Fresh clone:** a full install from cold is slow, and the draft PR's own CI is the real gate anyway. Updating the lockfile is enough: - pnpm: `pnpm install --lockfile-only` - npm: `npm install --package-lock-only` -- vp: `vp install` - yarn 1 has no lockfile-only mode, so it needs a plain `yarn install` +- anything else: use its normal install and accept the full cost Say plainly in the report which repos were verified only by CI. @@ -127,7 +142,7 @@ install rather than committing the churn. If a build breaks on an intentional SDK change, fix it in the consumer following `MIGRATION.md` in `sentry-javascript`, and report it. -## Step 5: commit, push, PR +## Step 7: commit, push, PR One commit per repo. Match each repo's own commit convention, which you can read off its log (`git log origin/$BASE --oneline -20`); they differ (`chore(deps):`, `build(deps):`, From ad45e916885dea4593c8338b96ed1c8aa490a280 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 2 Sep 2026 19:44:04 +0200 Subject: [PATCH 5/9] Drop unneeded commentary from the skill --- .agents/skills/dogfood-release/SKILL.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.agents/skills/dogfood-release/SKILL.md b/.agents/skills/dogfood-release/SKILL.md index e6dcfc7d8559..31dc67ec7338 100644 --- a/.agents/skills/dogfood-release/SKILL.md +++ b/.agents/skills/dogfood-release/SKILL.md @@ -22,10 +22,6 @@ session scratchpad otherwise. - `getsentry/sentry-docs`: Next.js site - `getsentry/chartcuterie`: Node chart rendering service -This list is the only thing worth hardcoding. Everything else about a repo (its base -branch, package manager, which `@sentry/*` packages it carries, how each one is ranged, -how it builds) changes without warning, so read it per run in step 1 instead of assuming. - ## Step 1: survey the repos Read the current state over the API first, so nothing is cloned for a repo that gets @@ -46,7 +42,7 @@ for r in sentry gib-potato sentry-changelog sentry-docs chartcuterie; do done ``` -Three things to work out from that, rather than from memory: +Three things to work out from that: - **Which deps to bump.** Only the ones already on the SDK version you are moving off. Repos also carry `@sentry/*` packages on their own release trains From cf1c161816fc372bb144b9af069a11d90a57ec07 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 2 Sep 2026 20:02:28 +0200 Subject: [PATCH 6/9] Address bugbot findings and drop the npm publish check --- .agents/skills/dogfood-release/SKILL.md | 44 ++++++++++++++----------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/.agents/skills/dogfood-release/SKILL.md b/.agents/skills/dogfood-release/SKILL.md index 31dc67ec7338..b26f39e09583 100644 --- a/.agents/skills/dogfood-release/SKILL.md +++ b/.agents/skills/dogfood-release/SKILL.md @@ -65,21 +65,15 @@ Ask with **`AskUserQuestion`, `multiSelect: true`**, one option per repo. Label with the repo name and put its current SDK version from step 1 in the description, so it is obvious which ones are already up to date. -Everything is selected by default in the UI; the user unticks what they want to skip. -Only bump the repos that come back selected. Do not ask per repo, one question covers all. +Nothing comes preselected, so the user ticks the repos they want bumped and anything left +unticked is skipped. Say that in the question text. A single question takes at most four +options and needs at least two, so split more repos than that across several questions in +the same call (five repos go three and two). -Skip this question only when the user already named the repos. +Only bump the repos that come back selected. Skip this step when the user already named +the repos. -## Step 3: check the version is on npm - -Craft publishes packages one at a time, so a green release branch does not mean every -package is up yet. - -```bash -npm view @sentry/core@ version --registry https://registry.npmjs.org -``` - -## Step 4: get a working tree +## Step 3: get a working tree A lockfile can only be regenerated by running the repo's package manager, so every selected repo needs a working tree. Resolve one per repo, in this order: @@ -93,9 +87,14 @@ selected repo needs a working tree. Resolve one per repo, in this order: gh repo clone getsentry/$r "$SCRATCH/$r" -- --depth=1 --single-branch --branch $BASE ``` +A checkout found this way may hold someone's uncommitted work, and `git checkout -B` +would carry it onto the new branch. Run `git status --porcelain` first; if it comes back +non-empty, leave that checkout untouched and clone into the scratchpad instead. Never +stash or discard work you did not create. + Note in the final report which repos were cloned fresh and which reused a checkout. -## Step 5: branch and bump +## Step 4: branch and bump One branch name across all repos, `ab/bump-sentry-` (e.g. `ab/bump-sentry-11-beta-0`). Always branch off a **freshly fetched** base, never off @@ -105,15 +104,22 @@ Anchor the version replacement on the **old version string** so only the deps id step 1 move, and preserve each existing range prefix: ```bash -cd "$DIR" # resolved in step 4 +cd "$DIR" # resolved in step 3 git fetch origin $BASE --quiet git checkout -B ab/bump-sentry- origin/$BASE -sed -i '' 's/"/"/g' package.json -node -e "JSON.parse(require('fs').readFileSync('package.json','utf8'))" # still valid JSON + +# node, not `sed -i`, whose in-place flag differs between BSD and GNU +node -e ' + const fs = require("fs"), [from, to] = process.argv.slice(1); + fs.writeFileSync("package.json", + fs.readFileSync("package.json", "utf8").split(`${from}"`).join(`${to}"`)); + JSON.parse(fs.readFileSync("package.json", "utf8")); // still valid JSON +' '' '' + git diff package.json ``` -## Step 6: install and build +## Step 5: install and build Install with the package manager identified in step 1. How far to go depends on what the working tree cost you. @@ -138,7 +144,7 @@ install rather than committing the churn. If a build breaks on an intentional SDK change, fix it in the consumer following `MIGRATION.md` in `sentry-javascript`, and report it. -## Step 7: commit, push, PR +## Step 6: commit, push, PR One commit per repo. Match each repo's own commit convention, which you can read off its log (`git log origin/$BASE --oneline -20`); they differ (`chore(deps):`, `build(deps):`, From b2cfa27961c21ba25a62e24aa81ce2e53f13ee1a Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 2 Sep 2026 20:03:23 +0200 Subject: [PATCH 7/9] Derive the branch prefix from the runner's GitHub login --- .agents/skills/dogfood-release/SKILL.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.agents/skills/dogfood-release/SKILL.md b/.agents/skills/dogfood-release/SKILL.md index b26f39e09583..528f3c2b53a1 100644 --- a/.agents/skills/dogfood-release/SKILL.md +++ b/.agents/skills/dogfood-release/SKILL.md @@ -96,9 +96,16 @@ Note in the final report which repos were cloned fresh and which reused a checko ## Step 4: branch and bump -One branch name across all repos, `ab/bump-sentry-` -(e.g. `ab/bump-sentry-11-beta-0`). Always branch off a **freshly fetched** base, never off -whatever the checkout was left on last time. +One branch name across all repos, `/bump-sentry-`, matching the +`/` convention these repos already use. Take the login from `gh`, never +hardcode a set of initials: + +```bash +BRANCH="$(gh api user --jq .login)/bump-sentry-" # e.g. jane/bump-sentry-11-beta-0 +``` + +Always branch off a **freshly fetched** base, never off whatever the checkout was left on +last time. Anchor the version replacement on the **old version string** so only the deps identified in step 1 move, and preserve each existing range prefix: @@ -106,7 +113,7 @@ step 1 move, and preserve each existing range prefix: ```bash cd "$DIR" # resolved in step 3 git fetch origin $BASE --quiet -git checkout -B ab/bump-sentry- origin/$BASE +git checkout -B "$BRANCH" origin/$BASE # node, not `sed -i`, whose in-place flag differs between BSD and GNU node -e ' From 6e1fc13ddd64150fe3fae5b5cda1399687a73f0c Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Thu, 3 Sep 2026 14:04:41 +0200 Subject: [PATCH 8/9] Default to bumping every repo and make consumer adaptation a real step --- .agents/skills/dogfood-release/SKILL.md | 62 ++++++++++++++++++------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/.agents/skills/dogfood-release/SKILL.md b/.agents/skills/dogfood-release/SKILL.md index 528f3c2b53a1..e99da6ae0a69 100644 --- a/.agents/skills/dogfood-release/SKILL.md +++ b/.agents/skills/dogfood-release/SKILL.md @@ -59,19 +59,21 @@ Three things to work out from that: If a repo has no matching `@sentry/*` dep, it has nothing to bump. Say so and drop it. -## Step 2: ask which repos to bump +## Step 2: ask which repos to skip -Ask with **`AskUserQuestion`, `multiSelect: true`**, one option per repo. Label each option -with the repo name and put its current SDK version from step 1 in the description, so it -is obvious which ones are already up to date. +The default is to bump every repo. `AskUserQuestion` cannot pre-tick options, so ask the +inverse: which repos to **skip**. An untouched question then means "bump all of them", +which is the default you want, and ticking a repo removes it. -Nothing comes preselected, so the user ticks the repos they want bumped and anything left -unticked is skipped. Say that in the question text. A single question takes at most four -options and needs at least two, so split more repos than that across several questions in -the same call (five repos go three and two). +Use **`multiSelect: true`**, one option per repo, labelled with the repo name and carrying +its current SDK version from step 1 in the description, so a repo that is already on the +target version is obvious. Make the question text say that unticked repos get bumped. -Only bump the repos that come back selected. Skip this step when the user already named -the repos. +A question takes at most four options and needs at least two, so split a longer list +across several questions in the same call (five repos go three and two). + +Bump every repo that does _not_ come back selected. Skip this step when the user already +named the repos. ## Step 3: get a working tree @@ -126,7 +128,7 @@ node -e ' git diff package.json ``` -## Step 5: install and build +## Step 5: install, build, and adapt Install with the package manager identified in step 1. How far to go depends on what the working tree cost you. @@ -148,8 +150,32 @@ Either way, confirm the lockfile diff is Sentry-only, version moves and nothing Unrelated entries mean the wrong package manager ran, so reset the lockfile and redo the install rather than committing the churn. -If a build breaks on an intentional SDK change, fix it in the consumer following -`MIGRATION.md` in `sentry-javascript`, and report it. +### Adapting the consumer + +A major or prerelease bump is meant to break things. Finding that breakage and fixing it +is the job, not a detour from it, so budget for code changes beyond the version numbers. + +**Read `MIGRATION.md` for the range you are crossing** before you start guessing at +errors. It is in `sentry-javascript`, and covers removed options, moved exports and +renamed build options. Note that a repo two or more prereleases behind crosses every +change in between, not just the newest one. + +**Run the typecheck as well as the build.** They fail on different things, and a build +that compiles can still be hiding type errors in files it does not check. + +**Check build config separately.** `next.config.*`, vite configs and the like are the +blind spot: they are often plain JavaScript, or typechecked under a module resolution +that cannot see the SDK's types, so a removed option sits there silently doing nothing +instead of erroring. Grep the config for every option name the guide lists as removed or +renamed, rather than trusting a green build. + +**Confirm a failure is yours before chasing it.** Re-run the same command on the base +branch without the bump. Consumer repos fail for their own reasons (a missing env var, a +broken hook, a full disk), and attributing those to the SDK wastes the run. + +**Report anything the guide missed.** A breaking change you had to reverse-engineer from +a type error is the most valuable thing this exercise produces. Say so explicitly, and +open a migration-guide PR against `sentry-javascript`. ## Step 6: commit, push, PR @@ -157,7 +183,9 @@ One commit per repo. Match each repo's own commit convention, which you can read log (`git log origin/$BASE --oneline -20`); they differ (`chore(deps):`, `build(deps):`, `build(js):`, plain `chore:`). -Open every PR as a **draft**, `## What` / `## Why` only: +Open every PR as a **draft**, `## What` / `## Why` only. When the bump needed code +changes, say what they were and why the new version required them, so a reviewer who does +not follow the SDK can tell the adaptation apart from the version numbers: ```bash gh pr create --draft --base $BASE \ @@ -173,7 +201,9 @@ Keep on the latest v11 prerelease so we catch breaking changes early." ## Report back -A short table: repo, PR link, how it was verified (local build or CI only), and whether -anything needed adapting. Call out any install or build that failed. +A short table: repo, PR link, how it was verified (local build or CI only), and what +needed adapting. Call out any install or build that failed, and list separately any +breaking change that was not in `MIGRATION.md`, with the migration-guide PR that fixes +that. Delete scratchpad clones once their PRs are open. From 24f2e55c8ccafb3008e1d2b01349cd8973027094 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Thu, 3 Sep 2026 14:33:29 +0200 Subject: [PATCH 9/9] Bump every dogfooding app by default instead of asking --- .agents/skills/dogfood-release/SKILL.md | 32 +++++++------------------ 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/.agents/skills/dogfood-release/SKILL.md b/.agents/skills/dogfood-release/SKILL.md index e99da6ae0a69..95571788ee42 100644 --- a/.agents/skills/dogfood-release/SKILL.md +++ b/.agents/skills/dogfood-release/SKILL.md @@ -22,10 +22,12 @@ session scratchpad otherwise. - `getsentry/sentry-docs`: Next.js site - `getsentry/chartcuterie`: Node chart rendering service +Bump all of them unless the user named a subset. + ## Step 1: survey the repos -Read the current state over the API first, so nothing is cloned for a repo that gets -unticked in step 2. Per repo, collect the default branch, `packageManager`, the `scripts`, +Read the current state over the API first, so nothing is cloned before you know what +each repo needs. Per repo, collect the default branch, `packageManager`, the `scripts`, and every `@sentry/*` dependency with its current range: ```bash @@ -59,23 +61,7 @@ Three things to work out from that: If a repo has no matching `@sentry/*` dep, it has nothing to bump. Say so and drop it. -## Step 2: ask which repos to skip - -The default is to bump every repo. `AskUserQuestion` cannot pre-tick options, so ask the -inverse: which repos to **skip**. An untouched question then means "bump all of them", -which is the default you want, and ticking a repo removes it. - -Use **`multiSelect: true`**, one option per repo, labelled with the repo name and carrying -its current SDK version from step 1 in the description, so a repo that is already on the -target version is obvious. Make the question text say that unticked repos get bumped. - -A question takes at most four options and needs at least two, so split a longer list -across several questions in the same call (five repos go three and two). - -Bump every repo that does _not_ come back selected. Skip this step when the user already -named the repos. - -## Step 3: get a working tree +## Step 2: get a working tree A lockfile can only be regenerated by running the repo's package manager, so every selected repo needs a working tree. Resolve one per repo, in this order: @@ -96,7 +82,7 @@ stash or discard work you did not create. Note in the final report which repos were cloned fresh and which reused a checkout. -## Step 4: branch and bump +## Step 3: branch and bump One branch name across all repos, `/bump-sentry-`, matching the `/` convention these repos already use. Take the login from `gh`, never @@ -113,7 +99,7 @@ Anchor the version replacement on the **old version string** so only the deps id step 1 move, and preserve each existing range prefix: ```bash -cd "$DIR" # resolved in step 3 +cd "$DIR" # resolved in step 2 git fetch origin $BASE --quiet git checkout -B "$BRANCH" origin/$BASE @@ -128,7 +114,7 @@ node -e ' git diff package.json ``` -## Step 5: install, build, and adapt +## Step 4: install, build, and adapt Install with the package manager identified in step 1. How far to go depends on what the working tree cost you. @@ -177,7 +163,7 @@ broken hook, a full disk), and attributing those to the SDK wastes the run. a type error is the most valuable thing this exercise produces. Say so explicitly, and open a migration-guide PR against `sentry-javascript`. -## Step 6: commit, push, PR +## Step 5: commit, push, PR One commit per repo. Match each repo's own commit convention, which you can read off its log (`git log origin/$BASE --oneline -20`); they differ (`chore(deps):`, `build(deps):`,