ci(release-pr): move the PR body to a file - #90
Conversation
Every release PR has shipped hard-wrapped prose, because the body was an inline YAML block and yamllint caps this file at 100 columns. The two rules were in direct conflict: the wrapping that keeps the workflow readable is what GitHub renders as a <br> in a pull request body, so the release PR reached its reader ragged. Exempting release-pr.yml from the column rule would trade a real lint on a 340-line release-critical workflow for prose formatting. A file gives up nothing: `body-path` takes precedence over `body`, and the body becomes a Markdown document that prettier, markdownlint and the unwrap hook already run over -- the same tooling the prose is being fixed to satisfy. The tag is substituted rather than interpolated, since `body-path` reads the file literally. It has already passed parse-version.sh, so it is three dot-separated runs of digits and carries no sed metacharacter. MD041 wants a top-level heading on line 1, which is a whole-document rule applied to a fragment. Handled the way cliff.toml already handles its own header: a markdownlint-configure-file directive, dropped at render time so lint scaffolding does not reach the pull request. Also corrects the first bullet. It claimed the run refreshes the Unreleased section; stamp-changelog.sh stamps the pending version as its own section, and the difference between those two is what this workflow's own comments exist to explain. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
PR Summary by QodoRender release PR bodies from a Markdown template
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #90 +/- ##
=======================================
Coverage 51.57% 51.57%
=======================================
Files 31 31
Lines 2092 2092
=======================================
Hits 1079 1079
Misses 1013 1013
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Code Review by Qodo🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)
Great, no issues found!Qodo reviewed your code and found no material issues that require reviewTip of the day💡 Did you know, you can group findings by type and pick your Finding display, from Minimal to Full |
Every release PR so far has shipped hard-wrapped prose — #83 is the current example. The cause is not GitHub and not the prose tooling; it is this workflow.
Why it happened
The body was an inline YAML block, and yamllint caps
release-pr.ymlat 100 columns. Those two rules are in direct conflict: the wrapping that keeps the workflow readable is exactly what GitHub renders as a<br>in a pull request body. Unwrapped in place, the longest paragraph is 208 characters.The prose tooling was never going to catch this either, on two counts. It was broken until #89, and even working it skips bot-authored pull requests by design — a bot's body comes from a template the pull request cannot change, so rewriting it there gets undone on the next release. Upstream is right about that, which is why the fix belongs here.
Why a file rather than a lint exemption
Adding
release-pr.ymlto yamllint's ignore list would trade a real column check on a 340-line release-critical workflow for prose formatting. That is the wrong direction.A file gives up nothing.
body-pathtakes precedence overbody, and the body becomes a Markdown document that prettier, markdownlint and the unwrap hook already run over — the same tooling the prose is being fixed to satisfy. The template stops being a special case.Details worth knowing
body-pathreads the file literally, so@RELEASE_TAG@is replaced bysed. The tag has already passedparse-version.sh, so it is three dot-separated runs of digits and carries nosedmetacharacter.cliff.tomlalready handles its own header fragment: amarkdownlint-configure-filedirective, dropped at render time so lint scaffolding never reaches the pull request.CHANGELOG.mdunreleased section". It does not —stamp-changelog.shstamps the pending version as its own section, and the difference between those two operations is what this workflow's own comments exist to explain. Flagging it separately since it is a content change rather than a formatting one; say the word and I will drop it.Test plan
RELEASE_TAG=v0.1.2. Asserted on the output: directive stripped (0 occurrences), no@RELEASE_TAG@left unsubstituted, no leading blank line, andunwrap-markdown-prose --fail-on-changeclean — so the rendered body carries no manual line breaks.prettier,markdownlintand the unwrap hook all pass on the new file, which is the point of moving it.actionlintclean,yamllintclean,make checkgreen.The end-to-end proof is the next release PR: its body should arrive as four paragraphs rather than eleven lines.
🤖 Generated with Claude Code