-
Notifications
You must be signed in to change notification settings - Fork 54
fix: backfill the root CHANGELOG, and give it the gate the per-package ones never needed #562
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jo-duchan
wants to merge
2
commits into
main
Choose a base branch
from
docs/changelog-backfill-and-gate
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+225
−1
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -365,6 +365,38 @@ export function ignoredOnlyChangesets(files, ignored, read) { | |
| }) | ||
| } | ||
|
|
||
| /** | ||
| * Which added changesets still owe the root `CHANGELOG.md` an entry. | ||
| * | ||
| * Two changelogs exist and only one has a gate. The per-package `CHANGELOG.md` files are generated by | ||
| * `changeset version` and cannot be forgotten. The **root** `CHANGELOG.md` is hand-written, is what a | ||
| * self-hoster reads to decide whether to upgrade, and nothing checked it — so on 2026-08-15 it had been | ||
| * untouched for four days across 22 merged PRs, while all 22 carried a changeset. The rule was in | ||
| * CONTRIBUTING and the enforcement was in neither place. | ||
| * | ||
| * **Not every changeset earns an entry**, and forcing one would fill the file with noise a user cannot | ||
| * act on — half of this cycle's changesets are protocol typing with no observable behaviour. So a | ||
| * changeset opts out by saying so in its own body, on a line of its own: | ||
| * | ||
| * <!-- changelog: internal — protocol typing, nothing a user can observe --> | ||
| * | ||
| * The reason is required for the same purpose it is required on `no-changeset`: skipping is a decision | ||
| * somebody wrote down, not something that happens by forgetting. | ||
| * | ||
| * **What this covers, stated rather than implied:** a branch that touches a changeset — added, amended or | ||
| * renamed — and ships published source. It does **not** cover a branch with no changeset (its | ||
| * `no-changeset` reason answers the same question one layer up), a bot PR (the CI job is skipped for | ||
| * those, and a skipped required check passes), or a release branch (exempt by design). Nor does it read | ||
| * the entry: touching the file is what it checks, because no check can tell whether prose corresponds to | ||
| * a diff. The measured incident it ends — 22 merged PRs against a four-day-stale file — was 22 PRs that | ||
| * all carried changesets. The marker lives in the changeset | ||
| * rather than the PR body because it classifies *that change*, and because a PR carrying two changesets | ||
| * can need it for one of them. | ||
| */ | ||
| export function changelogEntryOwed(files, read) { | ||
| return files.filter((f) => !/^<!--\s*changelog:\s*internal\b.*-->$/m.test(read(f))) | ||
| } | ||
|
|
||
| function main() { | ||
| // `--audit [since]` walks merges instead of the current branch: the PR gate cannot help with | ||
| // anything already on main, and that is exactly how #410–#413 slipped through. Run at release | ||
|
|
@@ -568,6 +600,27 @@ function main() { | |
| process.exit(1) | ||
| } | ||
|
|
||
| // **`AMR`, not the `added` list above.** A PR that extends an existing unconsumed changeset with new | ||
| // behaviour shows up as `M` and never as `A`, and a rename is `R` — so keying this on `added` let the | ||
| // two most ordinary shapes of follow-up work escape. The audit half already counts `AMR` for exactly | ||
| // that reason. What this still cannot see is a branch with no changeset at all: a `no-changeset` | ||
| // reason answers the same question one layer up, and a bot PR skips the CI job entirely. | ||
| const touchedChangesets = git('diff', '--name-only', '--diff-filter=AMR', `${mergeBase}...HEAD`) | ||
| .split('\n') | ||
| .filter((f) => /^\.changeset\/.+\.md$/.test(f) && !/^\.changeset\/README\.md$/i.test(f)) | ||
| const owed = changelogEntryOwed(touchedChangesets, (f) => readFileSync(f, 'utf8')) | ||
| if (owed.length > 0 && !changed.includes('CHANGELOG.md')) { | ||
|
Comment on lines
+611
to
+612
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Do not accept deletion of the root changelog.
📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| console.error('Changeset added with no entry in the root CHANGELOG.md:\n') | ||
| for (const f of owed) console.error(` ${f}`) | ||
| console.error('\nThat file is what a self-hoster reads to decide whether to upgrade, and unlike the') | ||
| console.error('per-package changelogs nothing generates it. Add an entry under `## [Unreleased]`, in') | ||
| console.error('the section CONTRIBUTING lists — a breaking change needs `### Breaking Changes` and a') | ||
| console.error('`Migrate:` hint. If this change is not something a user can observe, say so in the') | ||
| console.error('changeset on a line of its own:\n') | ||
| console.error(' <!-- changelog: internal — reason -->') | ||
| process.exit(1) | ||
| } | ||
|
|
||
| if (added.length > 0) { | ||
| console.log(`Published source changed and ${added.length} changeset(s) added:`) | ||
| for (const f of added) console.log(` + ${f}`) | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Remove the unsupported
7.6 secondsclaim.The PR objective says this backfill removes unsupported timing claims, but this entry retains an exact duration. Unless this value is measured and maintained as a product guarantee, describe the ordering without a fixed duration.
Proposed wording
📝 Committable suggestion
🤖 Prompt for AI Agents