ci(infra): wrap release-please PR titles in code fences - #5599
ci(infra): wrap release-please PR titles in code fences#5599Mason Daugherty (mdrxy) wants to merge 1 commit into
Conversation
Release-please PR titles and the matching release.yml run names now render as release(`<component>`): `<version>` (e.g. release(`deepagents-code`): `0.5.0`) so the package and version show as inline code on GitHub. The title is a machine-readable contract across the release pipeline, so the byte-format change is applied in lock-step to every producer and exact-match consumer: - Producer: release-please-config.json pull-request-title-pattern - Correlation keys: release.yml run-name, release-please.yml find_run_url and the pending-release guard's displayTitle match, release_comment_update.yml run-title re-discovery - Parsers: the sed version extraction strips backticks so the bare version still reaches release.yml for the pyproject check and git tag; all ten per-component commit matchers; the curated-notes title filters - Search: both in:title PR lookups in release.yml - release-notes.js parseReleaseTitle expects the backticked form - pr_lint.yml exempts release titles from the scope allowlist (a backticked scope is not in the allowlist and would otherwise fail) The scope-bypass gate in check_pr_scope_files.py keeps matching both title forms so an author-typed fake release title cannot escape the scope check, and parse_title_scopes strips backticks so the new form maps to the right package label. The outcome comment in release_comment_update.yml wraps titles in double backticks so the embedded code fences render as one code span.
| # (release(`deepagents-code`): `0.5.0`), which is not one of the | ||
| # allowlisted scopes below; the release pipeline validates those titles | ||
| # itself, so skip the scope check for them. | ||
| if: "!startsWith(github.event.pull_request.title, 'release(`')" |
There was a problem hiding this comment.
🟡 Prefix bypass disables all title validation
This condition skips the entire semantic-title check for any author-controlled title beginning with release(\``, not just the exact release-please shape. For example, a PR titled release(`not-a-package` with only release artifacts also passes the deliberately broad scope-file bypass, so no check validates its type, scope, separator, or version; after squash merge, the release workflow treats the subject as release-like and fails post-merge. Gate the exemption on an exact validated release title (and managed component), rather than this prefix alone.
(Refers to line 98)
Your feedback helps Open SWE learn. React with 👍 or 👎 to tell us if this review comment was useful.
| ANY_PACKAGE=false | ||
|
|
||
| if echo "$CHANGED" | grep -q "^libs/cli/CHANGELOG.md$" && echo "$COMMIT_MSG" | grep -qE "^release\(deepagents-cli\):"; then | ||
| if echo "$CHANGED" | grep -q "^libs/cli/CHANGELOG.md$" && echo "$COMMIT_MSG" | grep -qE "^release\(`deepagents-cli`\):"; then |
There was a problem hiding this comment.
🟡 Legacy release merges no longer dispatch
The version extractor immediately above deliberately accepts both legacy and backticked release subjects, but this and every other package guard now accept only the new form. There is currently an open old-format release PR (#5591, release(deepagents-code): 0.1.58); if it merges after this workflow lands but before release-please rewrites its title, RELEASE_VERSION is nonempty, none of these guards sets ANY_PACKAGE, and the workflow exits at the unmatched-package check without dispatching the release. Keep the optional-backtick compatibility consistent in the per-package matchers until old-format release PRs can no longer merge.
(Refers to line 192)
Your feedback helps Open SWE learn. React with 👍 or 👎 to tell us if this review comment was useful.
Release-please PR titles now wrap the component and version in code fences, so they render as
release(`deepagents-code`): `0.5.0`instead ofrelease(deepagents-code): 0.5.0.Before / after
release(deepagents-code): 0.5.0release(`deepagents-code`): `0.5.0`On GitHub, backticks in a PR title render as inline code, so the package and version now show in monospace.
Why the title is load-bearing here
A release-please title is not just a label in this repo — it is a machine-readable contract, and the exact byte format is matched across the release pipeline. This PR changes the producer and every exact-match consumer in one commit so none of the correlations silently always-miss (most of these guards are deliberately fail-open, so a drift would not error — it would just stop catching failures):
release-please-config.json'spull-request-title-pattern.release.yml'srun-name,release-please.yml'sfind_run_urland the pending-release guard'sdisplayTitle == titleequality, andrelease_comment_update.yml's run re-discovery all key on the same rendered string; all four are updated together.release-please.ymlpulls the version out of the squash-merge commit subject with asedcapture. That capture now strips the surrounding backticks, so the bare version (0.5.0) still flows torelease.ymlfor the pyproject version check and the git tag. This was the highest-risk capture-shift: without the change, the tag and version check would have picked up a leading backtick.release-please.yml.in:titlesearches inrelease.yml.release-notes.js'sparseReleaseTitleexpects the new form.Lint and scope-gate interplay
Two checks treat the title as input rather than a fixed string:
pr_lint.ymlvalidates titles against a scope allowlist, and a backticked component (`deepagents-code`) is not in that list, so release titles are now exempted from the scope check — the release pipeline validates them itself.check_pr_scope_files.pygates the scope-file bypass on arelease(...)title. That gate intentionally still matches both title forms: an author-typedrelease(cli): anythingmust keep failing the scope check, so the gate cannot become a bypass vector.parse_title_scopesnow strips the backticks so the real release title maps to the correct package label.The outcome comment on the release PR wraps the title in double backticks so the embedded code fences render as a single code span.
Verification
python -m pytest .github/scripts/tests, which also runs thenode --testrelease-notes tests) passes: 1046 passed.Test plan
python -m pytest .github/scripts/tests -q— 1046 passed..github/workflows/*.yml.sedextraction was exercised against bothrelease(`deepagents-code`): `0.5.0` (#1234)and the legacyrelease(deepagents): 0.5.0form and returns the bare version for each.