|
| 1 | +--- |
| 2 | +name: release-catalyst-patch |
| 3 | +description: > |
| 4 | + Release a single Catalyst package patch in isolation, without bundling it with |
| 5 | + other queued changesets in the open Version Packages PR. Use when the user says |
| 6 | + "/release-catalyst-patch", "isolate a patch release", "publish only one package", |
| 7 | + or wants to ship a single package's changeset ahead of the normal release cadence. |
| 8 | + Performs the full flow locally (`changeset version`, build, `changeset publish`, |
| 9 | + push, GitHub release) so the remaining queued changesets stay untouched in the |
| 10 | + Version Packages PR. |
| 11 | +--- |
| 12 | + |
| 13 | +# Release Catalyst Patch (single-package isolation) |
| 14 | + |
| 15 | +The Changesets GitHub Action picks one mode per push to `canary`: if any unconsumed |
| 16 | +changesets exist, it opens/refreshes the Version Packages PR and **does not** publish. |
| 17 | +That's why we publish locally — we keep the other changesets in `.changeset/` so the |
| 18 | +Version Packages PR still tracks them, but we ship just the one we want now. |
| 19 | + |
| 20 | +Execute stages in order. Pause for user input where indicated. **Never execute the |
| 21 | +`changeset publish` command yourself** — provide it to the user to run. |
| 22 | + |
| 23 | +## Stage 0: Confirm scope |
| 24 | + |
| 25 | +Identify the changeset to release and the target package + version. |
| 26 | + |
| 27 | +```bash |
| 28 | +ls .changeset/ |
| 29 | +git log --oneline -10 # find the PR/commit that added the changeset |
| 30 | +cat .changeset/<changeset-file>.md # confirm the package + bump type |
| 31 | +npm view <package> version dist-tags # confirm current published state |
| 32 | +``` |
| 33 | + |
| 34 | +Confirm with the user: |
| 35 | +- Which `.changeset/*.md` file is being released |
| 36 | +- The target package and the resulting version (e.g., `1.0.2` → `1.0.3`) |
| 37 | +- That **all other** changesets in `.changeset/` should remain queued for the next regular release |
| 38 | + |
| 39 | +If the package has notes in the [Package-specific notes](#package-specific-notes) section |
| 40 | +below, review them before continuing. |
| 41 | + |
| 42 | +## Stage 1: Branch + quarantine |
| 43 | + |
| 44 | +Work on a release branch so the workflow doesn't trigger mid-flow. |
| 45 | + |
| 46 | +```bash |
| 47 | +git switch canary && git pull |
| 48 | +git switch -c release/<package>-<new-version> |
| 49 | +``` |
| 50 | + |
| 51 | +Move the **other** changesets **outside** the repo. A subdirectory inside `.changeset/` |
| 52 | +gets parsed as a malformed changeset by the CLI and crashes `changeset version`: |
| 53 | + |
| 54 | +```bash |
| 55 | +mkdir -p /tmp/changeset-hold |
| 56 | +mv .changeset/<other-1>.md .changeset/<other-2>.md ... /tmp/changeset-hold/ |
| 57 | +ls .changeset/ # should leave only config.json + the one changeset to release |
| 58 | +``` |
| 59 | + |
| 60 | +## Stage 2: Run `changeset version` |
| 61 | + |
| 62 | +Requires `GITHUB_TOKEN` because the repo uses `@changesets/changelog-github`. The `gh` |
| 63 | +CLI token works. |
| 64 | + |
| 65 | +```bash |
| 66 | +pnpm install --frozen-lockfile |
| 67 | +GITHUB_TOKEN=$(gh auth token) pnpm changeset version |
| 68 | +``` |
| 69 | + |
| 70 | +Restore the held changesets immediately: |
| 71 | + |
| 72 | +```bash |
| 73 | +mv /tmp/changeset-hold/*.md .changeset/ |
| 74 | +rmdir /tmp/changeset-hold |
| 75 | +``` |
| 76 | + |
| 77 | +Verify the diff: |
| 78 | + |
| 79 | +```bash |
| 80 | +git status |
| 81 | +git diff packages/<package>/package.json packages/<package>/CHANGELOG.md |
| 82 | +``` |
| 83 | + |
| 84 | +Expect: bumped `package.json`, new CHANGELOG entry, deleted only the one changeset. |
| 85 | +The other changesets should be back in `.changeset/` and untouched. |
| 86 | + |
| 87 | +## Stage 3: Build |
| 88 | + |
| 89 | +Run the root build. Turborepo handles env passthrough from `.env.local` via the |
| 90 | +pipeline config, so package builds get the variables they need without manual sourcing. |
| 91 | + |
| 92 | +```bash |
| 93 | +pnpm build |
| 94 | +``` |
| 95 | + |
| 96 | +If a package has build-time secrets that must be present, see the |
| 97 | +[Package-specific notes](#package-specific-notes) section for verification steps. |
| 98 | + |
| 99 | +## Stage 4: Commit |
| 100 | + |
| 101 | +```bash |
| 102 | +git add -A |
| 103 | +git commit -m "Version Packages (\`canary\`)" |
| 104 | +``` |
| 105 | + |
| 106 | +Match the message format the changesets bot uses, since this is a manual stand-in for it. |
| 107 | + |
| 108 | +## Stage 5: Hand the publish command to the user |
| 109 | + |
| 110 | +**Do not run `changeset publish` from the agent.** Publishing to npm is a destructive, |
| 111 | +externally-visible action that should be performed by the user. |
| 112 | + |
| 113 | +Have the user confirm they're logged in, then run the publish themselves. The CLI will |
| 114 | +prompt them interactively for the npm OTP. |
| 115 | + |
| 116 | +```bash |
| 117 | +npm whoami # expect their npm username |
| 118 | +pnpm exec changeset publish # prompts for OTP interactively |
| 119 | +``` |
| 120 | + |
| 121 | +`changeset publish` is per-package version-aware: it only publishes packages whose local |
| 122 | +`package.json` is ahead of npm. Since only one package was bumped, only it ships. It |
| 123 | +also creates a local git tag like `@bigcommerce/<package>@<version>`. |
| 124 | + |
| 125 | +Wait for the user to confirm the publish completed before continuing. |
| 126 | + |
| 127 | +## Stage 6: Verify npm state |
| 128 | + |
| 129 | +```bash |
| 130 | +npm view <package> version |
| 131 | +npm view <package> dist-tags |
| 132 | +``` |
| 133 | + |
| 134 | +`latest` should point to the new version. If it doesn't (rare — only happens if |
| 135 | +`publishConfig.tag` is set), advise the user to fix with: |
| 136 | + |
| 137 | +```bash |
| 138 | +npm dist-tag add <package>@<version> latest |
| 139 | +``` |
| 140 | + |
| 141 | +## Stage 7: Fast-forward canary and push |
| 142 | + |
| 143 | +This requires a direct push to the protected default branch. **Pause and ask for explicit |
| 144 | +user authorization** before pushing — the user's "never push directly to main/master/production" |
| 145 | +rule guards against this even though the changesets bot does the same thing during normal |
| 146 | +releases. |
| 147 | + |
| 148 | +```bash |
| 149 | +git switch canary |
| 150 | +git fetch origin canary |
| 151 | +git log --oneline origin/canary..canary # should be 1 ahead |
| 152 | +git log --oneline canary..origin/canary # should be 0 behind |
| 153 | +git merge --ff-only release/<package>-<new-version> |
| 154 | +``` |
| 155 | + |
| 156 | +If you're 1 ahead and 0 behind, default `git push` rejects non-fast-forward updates, |
| 157 | +which gives the same safety as `--ff-only` on the push side. Apple's git build (≤2.50.x) |
| 158 | +does not accept `--ff-only` as a push flag — `git push origin canary` is correct here. |
| 159 | + |
| 160 | +If a hook blocks the agent push, hand these commands to the user: |
| 161 | + |
| 162 | +```bash |
| 163 | +git push origin canary |
| 164 | +git push origin "@bigcommerce/<package>@<new-version>" |
| 165 | +``` |
| 166 | + |
| 167 | +## Stage 8: Create the GitHub release manually |
| 168 | + |
| 169 | +CI runs `changeset publish` after the canary push, finds the version already on npm, |
| 170 | +and no-ops. Because the action only creates GitHub releases for packages it actually |
| 171 | +publishes, **no release is created automatically** in this flow. Make it manually. |
| 172 | + |
| 173 | +Extract the new CHANGELOG section (everything after the `## <version>` heading up to |
| 174 | +the next `## ` heading) into a notes file. Then: |
| 175 | + |
| 176 | +```bash |
| 177 | +gh release create "@bigcommerce/<package>@<new-version>" \ |
| 178 | + --repo bigcommerce/catalyst \ |
| 179 | + --title "@bigcommerce/<package>@<new-version>" \ |
| 180 | + --notes-file /tmp/release-notes.md |
| 181 | +``` |
| 182 | + |
| 183 | +Match the body format of prior releases — just the `### Patch Changes` / |
| 184 | +`### Minor Changes` heading and the bullets, no version heading at the top. Compare |
| 185 | +against an existing release: |
| 186 | + |
| 187 | +```bash |
| 188 | +gh release view "@bigcommerce/catalyst-core@<some-prior-version>" --repo bigcommerce/catalyst --json body |
| 189 | +``` |
| 190 | + |
| 191 | +## Stage 9: Final validation |
| 192 | + |
| 193 | +```bash |
| 194 | +git fetch origin canary |
| 195 | +git log --oneline origin/canary -3 # version commit on canary |
| 196 | +git ls-remote --tags origin "@bigcommerce/<package>@<new-version>" # tag on origin |
| 197 | +gh release view "@bigcommerce/<package>@<new-version>" --repo bigcommerce/catalyst --json tagName,isDraft,isPrerelease |
| 198 | +gh run list --workflow=changesets-release.yml --limit 1 # CI run succeeded |
| 199 | +gh pr list --search "Version Packages (canary)" --state open --json number,headRefName,updatedAt # Version Packages PR refreshed |
| 200 | +git fetch origin changeset-release/canary |
| 201 | +git show --stat origin/changeset-release/canary | head -20 # confirm only the other changesets remain |
| 202 | +npm view <package> version dist-tags |
| 203 | +``` |
| 204 | + |
| 205 | +Report: |
| 206 | +- Published version + dist-tag |
| 207 | +- Canary commit SHA |
| 208 | +- Tag pushed |
| 209 | +- GitHub release URL |
| 210 | +- Confirmation that the Version Packages PR now contains **only** the other changesets — the released one has been dropped from its scope. |
| 211 | + |
| 212 | +## Stage 10: Cleanup |
| 213 | + |
| 214 | +```bash |
| 215 | +git branch -d release/<package>-<new-version> |
| 216 | +``` |
| 217 | + |
| 218 | +## Package-specific notes |
| 219 | + |
| 220 | +### `@bigcommerce/create-catalyst` |
| 221 | + |
| 222 | +The CLI build (`tsup` via the package's `tsup.config.ts`) inlines `CLI_SEGMENT_WRITE_KEY` |
| 223 | +at build time, falling back to the placeholder `'not-a-valid-segment-write-key'` if the |
| 224 | +env var is missing. After Stage 3, verify the real key was embedded: |
| 225 | + |
| 226 | +```bash |
| 227 | +grep -c "not-a-valid-segment-write-key" packages/create-catalyst/dist/index.js |
| 228 | +# expect: 0 |
| 229 | +``` |
| 230 | + |
| 231 | +If `1`, the env var wasn't loaded. Confirm `CLI_SEGMENT_WRITE_KEY` exists in `.env.local`, |
| 232 | +and that the turbo pipeline for `build` declares it under `env` or `passThroughEnv` in |
| 233 | +`turbo.json`. Re-run `pnpm build` after fixing. |
0 commit comments