Skip to content

Commit 37c4194

Browse files
authored
Merge pull request #4962 from udecode/codex/auto-release-release-pr-fix
2 parents 5dc7c73 + a603d60 commit 37c4194

6 files changed

Lines changed: 91 additions & 6 deletions

File tree

.github/workflows/changeset-auto-release.yml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
).href;
3232
const {
3333
getChangesetReleaseType,
34-
hasChangesetFile,
34+
shouldManageAutoReleaseBlock,
3535
upsertAutoReleaseBlock,
3636
} = await import(helperUrl);
3737
@@ -43,8 +43,13 @@ jobs:
4343
per_page: 100,
4444
});
4545
46-
const hasChangeset = hasChangesetFile(files);
47-
const releaseType = getChangesetReleaseType(files);
46+
const hasChangeset = shouldManageAutoReleaseBlock({
47+
files,
48+
title: pullRequest.title ?? '',
49+
});
50+
const releaseType = hasChangeset
51+
? getChangesetReleaseType(files)
52+
: null;
4853
const currentBody = pullRequest.body ?? '';
4954
const nextBody = upsertAutoReleaseBlock(currentBody, {
5055
defaultChecked: releaseType === 'patch',

.github/workflows/ci.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,10 @@ jobs:
5858
name: CI
5959
runs-on: ubuntu-latest
6060
if: >-
61-
(github.event_name != 'pull_request' || github.event.pull_request.title != '[Release] Version packages') &&
62-
(github.event_name != 'push' || (
61+
github.event_name != 'push' || (
6362
github.event.head_commit.message != 'Version Packages' &&
6463
!contains(github.event.head_commit.message, '[skip ci]')
65-
))
64+
)
6665
6766
steps:
6867
- uses: actions/checkout@v4
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Release PR Auto-Release Fix
2+
3+
## Goal
4+
5+
Fix the follow-up release PR behavior after PR #4957:
6+
7+
- Do not add the managed `Auto release` checkbox to PRs whose title contains `Version packages`.
8+
- Unblock generated release PR auto-merge by letting the required `CI` check run instead of skipping it.
9+
- Remove the stray checkbox from PR #4961.
10+
11+
## Findings
12+
13+
- PR #4961 title is `[Release] Version packages`.
14+
- PR #4961 has auto-merge enabled, but `mergeStateStatus` is `BLOCKED`.
15+
- The active ruleset for `main` requires `CI` and `Vercel`.
16+
- PR #4961 has `Vercel` success and `CI` skipped.
17+
- `.github/workflows/ci.yml` skips pull requests whose title is exactly `[Release] Version packages`.
18+
- `.github/workflows/changeset-auto-release.yml` currently manages any PR with a `.changeset/*.md` filename, including generated release PRs that delete changesets.
19+
- `bun test tooling/scripts/auto-release-pr.test.mjs` failed before the helper export existed, then passed after adding the title guard helper.
20+
- Editing PR #4961 before this workflow fix lands triggers the old `Sync auto-release checkbox` workflow, which re-adds the block because it still runs on `[Release] Version packages`.
21+
22+
## Plan
23+
24+
1. [complete] Confirm the root cause with PR metadata and repo rulesets.
25+
2. [complete] Add helper coverage for release PR title detection and block removal.
26+
3. [complete] Skip checkbox management for `Version packages` PR titles.
27+
4. [complete] Let CI run on release PR pull_request events.
28+
5. [complete] Verify with targeted tests and repo checks.
29+
6. [in_progress] Commit, push, open PR.
30+
7. [pending] Clean up PR #4961 body after the workflow fix lands.
31+
32+
## Verification
33+
34+
- `bun test tooling/scripts/auto-release-pr.test.mjs` failed before implementation, then passed after the helper/workflow fix.
35+
- `node --check tooling/scripts/auto-release-pr.mjs && node --check tooling/scripts/auto-release-pr.test.mjs` passed.
36+
- `ruby -e 'require "yaml"; ...' .github/workflows/ci.yml .github/workflows/changeset-auto-release.yml` passed.
37+
- `git diff --check` passed.
38+
- `pnpm lint:fix` passed with no fixes.
39+
- `pnpm check` passed. Existing warning: `apps/www/src/registry/ui/footnote-node.tsx` hook dependency warning.

docs/solutions/workflow-issues/2026-04-24-changeset-pr-auto-release-checkbox.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ component: development_workflow
88
symptoms:
99
- Changeset PRs require a manual follow-up merge of the Version Packages PR.
1010
- Release intent is easy to miss when it only lives in chat or reviewer memory.
11+
- Auto-merge can be enabled but stay blocked when a required check is skipped.
1112
root_cause: missing_workflow_step
1213
resolution_type: workflow_improvement
1314
severity: medium
@@ -31,6 +32,7 @@ Changeset PRs create a follow-up `[Release] Version packages` PR after merge. Wh
3132
- Putting a static checkbox in the PR template would show up on every PR, including PRs with no changeset.
3233
- Adding only a comment would be easy to miss and harder to treat as the source of truth.
3334
- Auto-merging the release PR with the default `GITHUB_TOKEN` is risky because GitHub suppresses workflow runs triggered by that token, which can prevent the publish workflow from firing after the release PR merge.
35+
- Skipping CI for `[Release] Version packages` PRs leaves the required `CI` check skipped, so GitHub auto-merge stays blocked.
3436

3537
## Solution
3638

@@ -42,6 +44,8 @@ Use a managed PR-body checkbox plus release workflow enforcement:
4244
4. In the release workflow, inspect the merged PR associated with the push to `main`.
4345
5. If the merged PR has a checked managed checkbox and a changeset file, enable auto-merge on the generated release PR.
4446
6. Use `API_TOKEN_GITHUB` for the merge path so the follow-up publish workflow can run.
47+
7. Do not add the managed checkbox to PRs whose title contains `Version packages`.
48+
8. Let required checks run on release PRs; a skipped required check is not a mergeable check.
4549

4650
```yaml
4751
env:
@@ -61,10 +65,14 @@ The PR body is the right place for human release intent because it is visible be
6165

6266
Using the PAT is the critical bit. The release PR merge must create the normal push event that runs the publish path.
6367

68+
Generated release PRs are the output of that intent, not a new decision point. They should not get their own `Auto release` checkbox. If branch rules require `CI`, release PRs need a successful `CI` run rather than a skipped one.
69+
6470
## Prevention
6571

6672
- Keep dynamic release intent in a managed PR-body block, not only in comments.
6773
- Default low-risk patch release PRs to checked, but make `minor` and `major` releases an explicit opt-in.
74+
- Exclude PR titles containing `Version packages` from checkbox management.
75+
- Do not skip checks that branch rules require for release PR auto-merge.
6876
- For `pull_request_target`, only run trusted base-repo code and read untrusted PR data through the GitHub API.
6977
- Do not use default `GITHUB_TOKEN` for workflow-triggering release merges.
7078
- Add helper tests for checkbox preservation, changeset-file detection, and ignoring stray checkbox text outside the managed block.

tooling/scripts/auto-release-pr.mjs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const checkedAutoReleasePattern =
1212
/-\s*\[[xX]\]\s*(?:Auto release|Auto-merge the Version Packages PR after this PR lands\.)/;
1313
const changesetFrontmatterPattern = /^---\r?\n([\s\S]*?)\r?\n---/;
1414
const changesetReleaseTypePattern = /:\s*(major|minor|patch)\b/g;
15+
const versionPackagesTitlePattern = /\bVersion Packages\b/i;
1516

1617
export function hasChangesetFile(files) {
1718
return files.some((file) => {
@@ -43,6 +44,14 @@ export function isAutoReleaseChecked(body = '') {
4344
return checkedAutoReleasePattern.test(block);
4445
}
4546

47+
export function isVersionPackagesTitle(title = '') {
48+
return versionPackagesTitlePattern.test(title);
49+
}
50+
51+
export function shouldManageAutoReleaseBlock({ files, title }) {
52+
return !isVersionPackagesTitle(title) && hasChangesetFile(files);
53+
}
54+
4655
export function upsertAutoReleaseBlock(
4756
body,
4857
{ defaultChecked = false, hasChangeset }

tooling/scripts/auto-release-pr.test.mjs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
getChangesetReleaseType,
88
hasChangesetFile,
99
isAutoReleaseChecked,
10+
isVersionPackagesTitle,
11+
shouldManageAutoReleaseBlock,
1012
upsertAutoReleaseBlock,
1113
} from './auto-release-pr.mjs';
1214

@@ -23,6 +25,29 @@ test('detects real changeset files', () => {
2325
);
2426
});
2527

28+
test('detects Version packages release PR titles', () => {
29+
assert.equal(isVersionPackagesTitle('[Release] Version packages'), true);
30+
assert.equal(isVersionPackagesTitle('chore: Version Packages'), true);
31+
assert.equal(isVersionPackagesTitle('Fix media parser'), false);
32+
});
33+
34+
test('does not manage auto-release blocks on Version packages PRs', () => {
35+
assert.equal(
36+
shouldManageAutoReleaseBlock({
37+
files: ['.changeset/media-redos.md'],
38+
title: '[Release] Version packages',
39+
}),
40+
false
41+
);
42+
assert.equal(
43+
shouldManageAutoReleaseBlock({
44+
files: ['.changeset/media-redos.md'],
45+
title: 'Fix media parser',
46+
}),
47+
true
48+
);
49+
});
50+
2651
test('detects the highest changeset release type from PR file patches', () => {
2752
assert.equal(
2853
getChangesetReleaseType([

0 commit comments

Comments
 (0)