Repository navigation
[PRODENG-3931] Assemble release notes from in-repo fragments - #694
Merged
Merged
Conversation
There is no published Launchpad release-notes page: https://docs.mirantis.com/mke/3.9/launchpad/lp-release-notes.html returns 404. The GitHub release body is the announcement surface, and nothing caused it to be written. Adds `.changes/`, one markdown fragment per change an operator needs to know about before upgrading, named after the ticket. The release job checks out the tree, concatenates the fragments in filename order under a "Release notes" heading, and passes the result to action-gh-release as `body_path`. GitHub's generated commit and contributor notes are appended below, so nothing is lost. Fragments are emitted verbatim, separated by a blank line, and own their own markdown: a note may run to several paragraphs, and continuation lines under a list marker would need indenting to stay in the list. When no fragment is present the body says so: _No release notes were recorded for this release._ rather than carrying an empty section. An empty section reads as "nothing notable changed", which is indistinguishable from "nobody wrote a fragment" — the first is a fact about the release, the second is a fact about the process, and they must not look the same. Failing the release outright was rejected: a release with genuinely no notable changes is legitimate and should not be blocked, and a gate would be satisfied by adding empty fragments to clear it. `.changes/` rather than `docs/release-notes/` because the fragments are build inputs consumed by the release workflow, not pages for a reader browsing `docs/`. `.changes/README.md` documents when to add a fragment, the format, that the reason for a change belongs in the note, and that fragments are removed when the next release is cut. The release job gains an `actions/checkout` step, SHA-pinned like the others, because it previously downloaded artifacts only and had no access to the repository. The build job already had its own checkout. First fragment records the PRODENG-3931 `metadata.name` validation change, which rejects configurations that previously applied. Which ticket owns this work is not yet settled, so the subject carries no ticket prefix. Written by AI: claude-opus-5 Signed-off-by: James Nesbitt <jnesbitt@mirantis.com>
james-nesbitt
added a commit
that referenced
this pull request
Nov 5, 2026
The release-note fragment mechanism is now PR #694 on PRODENG-3931, landing with the first change it announces. Carrying it here as well would put the same .changes/ content in two open PRs. This PR is draft pending DigiCert configuration that does not exist yet, so the mechanism would otherwise have been blocked behind an unrelated external dependency. Reverts the release-job checkout, the assembly step and the body_path. The build job keeps its own checkout, which predates both changes and is what the signing steps use. Written by AI: claude-opus-5 Signed-off-by: James Nesbitt <jnesbitt@mirantis.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The release workflow can merge changelog fragments into one paragraph when a fragment lacks a trailing newline, and the documentation incorrectly implies that valid dotted names are rejected.
2 open issues
What changed in this PR
Adds in-repository release-note fragments so Launchpad’s GitHub releases can announce operator-facing changes, starting with the metadata.name validation change in #687.
Changes:
- Assembles fragments in filename order into the release body while retaining GitHub-generated notes.
- Adds an explicit message when no fragments are present.
- Documents fragment conventions and manual cleanup, and adds the first upgrade notice.
| File | Description |
|---|---|
.github/workflows/release.yml |
Checks out the repository, assembles fragments, and supplies the release body. |
.changes/README.md |
Documents when to add fragments, their format, and cleanup after releases. |
.changes/PRODENG-3931.md |
Announces the breaking metadata.name validation change. |
Review effort: Balanced
Two review findings on the pull request, both confirmed by measurement
before changing anything.
A fragment that does not end with a newline ran into the next one. With
`First change.` (no trailing newline) followed by `Second change.`, the
assembled body contained
First change.
Second change.
which Markdown renders as one paragraph. The step now emits two newlines
after each fragment, so the separating blank line does not depend on how
the file happens to end. A fragment that does end with a newline gains a
blank line, which Markdown collapses. `.changes/README.md` records that a
trailing newline is not required.
The PRODENG-3931 note stated the validation rule too broadly. It said
names "containing" `/`, `\`, `.` or `..` are rejected. The validator in
PR #687 rejects a name that contains `/` or `\` anywhere, but only a name
that is exactly `.` or `..`:
if name == "." || name == ".." {
return false
}
return !strings.ContainsAny(name, `/\`) && ...
So `prod.eu` remains valid. The previous wording told operators that a
working configuration was about to stop applying. The fragment and the
worked example in `.changes/README.md` now distinguish the two cases, and
the README states why the distinction matters.
Written by AI: claude-opus-5
Signed-off-by: James Nesbitt <jnesbitt@mirantis.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.


What
Adds
.changes/, a directory of per-change release-note fragments, and makes the release workflow assemble them into the GitHub release body.This PR completes the release-note mechanism for PRODENG-3931. It lands with its first consumer:
.changes/PRODENG-3931.mdrecords themetadata.namevalidation change that PR #687 makes, so the breaking change and the note that announces it arrive together.Why
There is no published Launchpad release-notes page — https://docs.mirantis.com/mke/3.9/launchpad/lp-release-notes.html returns 404. The GitHub release body is the announcement surface, and nothing caused it to be written. PRODENG-3931 rejects configurations that previously applied; without somewhere for that to be announced, the first an operator learns of it is a failed upgrade.
How
.changes/PRODENG-NNNN.md— one markdown fragment per change an operator needs to know about before upgrading. No front-matter, no required heading, no category field; the ticket ID is the filename and appears nowhere else.## Release notesheading the workflow writes. The fragment owns its own markdown. A note may run to several paragraphs — continuation lines under a list marker would need indenting to stay in the list, so no marker is added.release.ymlgains anactions/checkoutin thereleasejob, which previously downloaded artifacts only and had no access to the tree, and passes the assembled file asbody_path.generate_release_notes: trueis kept, so GitHub's commit and contributor sections are appended below the notes rather than replaced..changes/README.mddocuments when a fragment is warranted and when it is not, the format, that the reason for a change belongs in the note, and that fragments are removed when the next release is cut..changes/rather thandocs/release-notes/: the fragments are build inputs consumed by the workflow, not pages for a reader browsingdocs/. Placing them underdocs/would imply they are published, which is the confusion that produced the 404 in the first place.A missing fragment is visible, not silent
With no fragments present the release body carries:
rather than an empty section. This is the point of the mechanism, not a detail of it. An empty section reads as nothing notable changed — which is indistinguishable from nobody wrote a fragment. The first is a fact about the release; the second is a fact about the process. A reader cannot tell them apart, and the one that needs attention is the one that looks fine.
Two stronger options were rejected:
Testing
The workflow cannot be run here — it triggers only on a tag push, and no tag was pushed. The assembly step was exercised by extracting its
run:body from the branch under test — not by reusing a script written against an earlier revision, and with an assertion that fails if the step is absent, since a silently-dropped step is the failure mode a change like this causes:The second case also confirms
README.mdis excluded by thePRODENG-*.mdglob rather than emitted as a note; the third confirms the unmatched-glob path is guarded rather than emitting a literal.changes/PRODENG-*.md.Also exercised with two real fragments — this PR's
PRODENG-3931.mdand thePRODENG-3935.mdwritten independently in #682 — to confirm a single-paragraph and a multi-paragraph note coexist and render as written, in filename order.yamllint -d relaxedreports 0 errors. A structural check over all six workflows reports no problems. All six action uses inrelease.ymlare SHA-pinned. No Go files are touched.Not scanned: no Aikido scan was run for this PR. Aikido authentication is failing across this batch; pending a retroactive scan.
Ordering
PR #687 carries the
metadata.namechange this fragment describes. If #687 merges first, its breaking change ships with a fragment nothing reads. Two further fragments are already written against this convention —PRODENG-3935.mdin #682 andPRODENG-3922.mdin progress — so the mechanism currently has three notes and no reader.Links
https://mirantis.jira.com/browse/PRODENG-3931
Checklist
yamllint -d relaxed— 0 errorsWritten by AI: claude-opus-5