New logchange.py script to simplify changelog in wizard#4413
Conversation
c04be97 to
d55ffda
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces a dedicated dev-tools/scripts/changelogRelease.py helper and rewires the Release Wizard to use it so release managers can reliably update changelogs across RC respins (RC1 vs RC2+) and then forward-port changelog commits post-vote.
Changes:
- Added
dev-tools/scripts/changelogRelease.pywithprepare(RC loop) andforward-port(post-vote) subcommands to manage changelog file moves,CHANGELOG.mdregeneration, committing, cherry-picking, and optional pushing. - Updated
dev-tools/scripts/releaseWizard.yamlto replace the previous YAML-embedded shell one-liners with the new script-driven tasks. - Documented the new flow in
dev-tools/scripts/README.mdanddev-docs/changelog.adoc.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| dev-tools/scripts/releaseWizard.yaml | Removes old changelog todos and adds new RC-loop + publish-phase tasks that call changelogRelease.py. |
| dev-tools/scripts/README.md | Adds standalone usage documentation for changelogRelease.py. |
| dev-tools/scripts/changelogRelease.py | New script implementing prepare and forward-port changelog operations. |
| dev-docs/changelog.adoc | Updates release-manager documentation to describe the new script and workflow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
dsmiley
left a comment
There was a problem hiding this comment.
This seemed like kind of a refactor as much as it fixes a problem... albeit maybe not as there's still plenty of lines in the release wizard, especially because of the repeated & verbose description. I do appreciate the clarity when I'm the RM as to what's happening. Maybe LLMs will help us maintain all this repeated information as well as it generates tokens.
+1 from me
|
I asked claude to perform a full simulation in a fresh git repo. It constructed a git repo with three branches and various changelog files on the branches, and ran the commands. Results: Test scenarios for
|
| Branch | Contents in changelog/unreleased/ |
|---|---|
main |
feature-a, feature-b, feature-c |
branch_10x (stable) |
feature-a, feature-b (feature-c not backported) |
branch_10_1 (release) |
feature-a, feature-b, fix-d (release-only, not on stable or main) |
RC1: prepare
python3 dev-tools/scripts/logchange.py prepare \
--version 10.1.0 --release-branch branch_10_1Expected: runs gradlew logchangeRelease, moves all unreleased entries (A, B, D) to changelog/v10.1.0/, regenerates CHANGELOG.md, leaves uncommitted for review.
Result: ✅ All three files moved correctly. [unreleased] block stripped from CHANGELOG.md.
RC2: prepare after a new fix added
A new fix (fix-e) was committed to changelog/unreleased/ on branch_10_1 after RC1.
python3 dev-tools/scripts/logchange.py prepare \
--version 10.1.0 --release-branch branch_10_1 --commitExpected: detects v10.1.0/ already exists (RC2+ path), moves only fix-e, leaves A/B/D untouched.
Result: ✅ Only fix-e moved. Existing entries not duplicated. Committed automatically.
prepare idempotency: no new unreleased files
python3 dev-tools/scripts/logchange.py prepare \
--version 10.1.0 --release-branch branch_10_1 --commitExpected: nothing to move, logchangeGenerate produces no diff, nothing staged → no commit created.
Result: ✅ Clean NOP. Output: "Nothing staged — changelog is already up to date."
forward-port review run (no push)
python3 dev-tools/scripts/logchange.py forward-port \
--version 10.1.0 --release-branch branch_10_1 \
--stable-branch branch_10x --release-date 2026-05-12Expected:
- Writes
release-date.txt, regeneratesCHANGELOG.mdwith date, commits tobranch_10_1 - Cherry-picks 5 changelog commits to
branch_10xandmain - On
branch_10x: A and B deleted from unreleased, D and E land inv10.1.0/ - On
main: feature-c remains untouched in unreleased; A, B, D, E appear inv10.1.0/ - Release-only fix D causes no conflicts on either branch
- Nothing pushed
Result: ✅ All cherry-picks applied cleanly. main unreleased correctly retains only feature-c.
forward-port re-run with --push (idempotency + push test)
python3 dev-tools/scripts/logchange.py forward-port \
--version 10.1.0 --release-branch branch_10_1 \
--stable-branch branch_10x --release-date 2026-05-12 --pushExpected: detects all patches already applied, skips cherry-pick step, pushes all three branches.
Result: ✅ Output: "No changelog commits to forward-port — branch_10x is already up to date." All three branches pushed to GitHub.
Bug found and fixed during testing: the original commit detection used
git log A..B(SHA-based), which caused already-applied cherry-picks to be re-applied on a second run. Fixed by switching togit log --cherry-pick --right-only A...B(patch-id-based), making the command fully idempotent.
forward-port idempotency: everything already done
python3 dev-tools/scripts/logchange.py forward-port \
--version 10.1.0 --release-branch branch_10_1 \
--stable-branch branch_10x --release-date 2026-05-12Expected: release-date.txt already correct, no staged changes, no new commits to cherry-pick → complete NOP.
Result: ✅ "Nothing staged — release-date.txt and CHANGELOG.md were already up to date." and "No changelog commits to forward-port — branch_10x is already up to date."
Simplify wizard wrt logchange
The script handles both RC preparation and post-vote forward-porting, not just the logchangeRelease step, so 'logchange.py' is a better fit. Update all references in releaseWizard.yaml, changelog.adoc, and README.md.
…he recorded release date in changelog
Remove the validate_changelog_unreleased step which has limited value at this stage
93390ed to
db03964
Compare
Lightweight changelog process for RC2+
Problem
When an RC1 vote fails and a new RC is needed, the release wizard provided no structured path for updating the changelog. All changelog tasks (
logchange_release,logchange_generate,validate_changelog_unreleased,push_changelog_to_branches) lived in thebranching_versionsphase — outside the RC loop — meaning the release manager had to manually re-run complex multi-branch git operations with no guidance. There was also no clean way to defer forward-porting to stable andmainuntil after a successful vote.Additionally, those tasks embedded fragile shell one-liners directly in the YAML, making them hard to test, debug, or run independently of the wizard.
Solution
A new standalone Python script
dev-tools/scripts/logchange.pyhandles all changelog git operations. The wizard calls it, but it can also be run directly by the release manager at any time.prepare— run before each RC (in the RC loop)Automatically detects RC1 vs RC2+:
changelog/v<version>/does not yet exist): callsgradlew logchangeRelease --releaseDate none --versionToRelease <version>, which moves all files fromchangelog/unreleased/into the new version folder without writing a release date.changelog/v<version>/already exists):logchangeReleasewould hard-fail here, so the script manually copies only the new files fromchangelog/unreleased/into the existing version folder.Both paths then run
logchangeGenerate, strip the empty[unreleased]block fromCHANGELOG.md, and optionally commit (--commit). Nothing is pushed or cherry-picked — that is deferred to post-vote.forward-port— run once after a successful vote (in publish phase)release-date.txtto the version folderCHANGELOG.md— now with the correct release dategit log stable..release -- changelog/ CHANGELOG.md)main:changelog/unreleased/use-X ours -X no-renamesto preserve the target branch's own unreleased entriesCHANGELOG.md) are cherry-picked plainly so real conflicts are not silently discarded--push)Wizard changes
logchange_release,logchange_generate,validate_changelog_unreleased,push_changelog_to_brancheschangelog_update_rcas the first task in theartifactsgroup (is_in_rc_loop: true) — handles both RC1 and RC2+ via the scriptvalidate_changelog_unreleasedafterchangelog_update_rcwith--skip-sync-check(branches intentionally differ until forward-port runs)forward_port_changelogas the first task in thepublishgroupOther details
--commit(prepare) and--push(forward-port) are opt-in flags: the wizard passes them, but standalone use defaults to leaving changes for review first--dry-runavailable on both subcommands — no files or git state are touched--git-remoteoverrides the push remote (default:origin)--release-date YYYY-MM-DDoverrides the date written at forward-port time (default: today); input is validatedgit cherry-pick --aborthint before exitingdev-docs/changelog.adocsection 5.4 anddev-tools/scripts/README.md