Repository navigation
ci: fail the release run on a missing tag and reject markup in release notes - #164
Merged
Merged
Conversation
…t markup in release notes release-please reads the merged release pull request body as HTML. A generic in a BREAKING CHANGE footer (or backticked in a subject) opens an element that is never closed, two of them drop later components from the body, and those components get no release or tag while the run still succeeds. The manifest on main already names their new versions, and the dependent publish workflows then time out waiting for the crate. The release run now fails after both phases when a package in the config has a manifest version with no tag. A commit-text job rejects the markup on the pull request. Both are checked against release-please's own body parser, which showed that backticks do not protect. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The lint misses implicit breaking-change notes from ! subjects, and tag verification rejects legitimate unreleased bootstrap versions.
2 open issues
What changed in this PR
This PR hardens release automation against the skipped component releases seen in #160, adding commit-text validation and a post-run tag check.
Changes:
- Reject markup in breaking-change footers and backticked commit subjects.
- Fail release runs when configured manifest versions lack tags.
- Add regression tests and document the failure mode and repair procedure.
| File | Description |
|---|---|
| DEVELOPMENT.md | Documents markup restrictions, tag verification, and release repair. |
| .github/workflows/ci.yml | Adds pull-request commit-text validation. |
| .github/release/release.test.cjs | Tests verification ordering and failure propagation. |
| .github/release/release.cjs | Runs tag verification after release and proposal creation. |
| .github/release/check-release.test.cjs | Tests tag checks and release-body markup handling. |
| .github/release/check-release-tags.cjs | Detects configured manifest versions without tags. |
| .github/release/check-commit-text.cjs | Scans commit messages for unsafe release-note markup. |
Review effort: Balanced
… version a changelog records Review of the release guard found two gaps. The commit-text lint re-read the BREAKING CHANGE footer syntax itself, so it missed that a ! subject is a breaking note and enters the release body unescaped, and that an explicit footer replaces that note. It now takes the notes from release-please's parseConventionalCommits, so the lint and the release agree by construction. The CI job installs the release tooling for that. The tag check demanded a tag for every manifest version, so registering a crate at a bootstrap version in a chore commit would fail the next release run before its first release exists. A tag is now owed only to a version the package's CHANGELOG.md records, which the release pull request writes in the same commit that sets the version; the tree's two bootstrap crates are the regression. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… depending on release state Review of the release guard found that the tag lister was never exercised: every test injected a replacement. It read the legacy octokit.repos alias, which the locked @octokit/rest 20 still provides (checked against the real client and the live repository), but the rest namespace is the one the client documents. The lister now uses it, and a test exercises the real lister with a fake client, and asserts the locked client exposes the endpoint where the lister reads it. The verification test required the tree to keep an unreleased bootstrap package, so it would have failed once every crate had released. It now loops over whatever is recorded or unrecorded, and the fixed bootstrap fixture carries the distinction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Review of the release guard found that the check reads the push's checkout while the release phase loads the live default branch, so a release pull request merged while a run waits or starts could be released by this run and verified against older files. The check now runs only when the branch tip was the checkout both before the release phase began and after it ended, and otherwise notes that it was skipped. The skipped case is not a gap: the workflow serializes runs, and the run for the newer push checks out the newer revision and makes the same check. Both the trailing-checkout and the moved-during-the-phase cases are regressions, and removing either half of the condition fails one. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.


Prevents a repeat of the #160 release, where release-please skipped three components and reported success.
Cause. release-please reads the merged release PR body as HTML. A
BREAKING CHANGE:footer is copied into it unescaped, and a subject is escaped except inside backticks. A generic such asKey<A>opens an element that is never closed, and two of them swallow the sections after them. Those components got no tag or release, and their crates.io publishes never ran.Changes
check-release-tags.cjs: after both phases,release.cjsfails if any package in the config has a manifest version with no tag. The run now fails when this happens, and lists the missing tags.check-commit-text.cjsand acommit textCI job: reject angle-bracket markup in aBREAKING CHANGE:footer or inside backticks in a subject. Addresses such asCo-authored-bytrailers are allowed.DEVELOPMENT.md: documents both and the repair.Verification. The lint is tested against release-please's own
PullRequestBody.parse: flagged and backticked footers lose components, andKey[A]keeps all of them. Backticks do not protect. The tag check passes on the current tree, and removing theverifycall fails two tests. The lint flags exactly the five commits in the last 40 on main that carried generics.Commit scope is
ci:, so it triggers no release.