Skip to content

New logchange.py script to simplify changelog in wizard#4413

Merged
janhoy merged 12 commits into
apache:mainfrom
janhoy:changelog-rc-improvements
May 12, 2026
Merged

New logchange.py script to simplify changelog in wizard#4413
janhoy merged 12 commits into
apache:mainfrom
janhoy:changelog-rc-improvements

Conversation

@janhoy
Copy link
Copy Markdown
Contributor

@janhoy janhoy commented May 11, 2026

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 the branching_versions phase — 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 and main until 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.py handles 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+:

  • RC1 (changelog/v<version>/ does not yet exist): calls gradlew logchangeRelease --releaseDate none --versionToRelease <version>, which moves all files from changelog/unreleased/ into the new version folder without writing a release date.
  • RC2+ (changelog/v<version>/ already exists): logchangeRelease would hard-fail here, so the script manually copies only the new files from changelog/unreleased/ into the existing version folder.

Both paths then run logchangeGenerate, strip the empty [unreleased] block from CHANGELOG.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)

  1. Writes release-date.txt to the version folder
  2. Regenerates CHANGELOG.md — now with the correct release date
  3. Commits to the release branch
  4. Finds all changelog-touching commits on the release branch not yet on the stable branch (git log stable..release -- changelog/ CHANGELOG.md)
  5. Cherry-picks them to stable and main:
    • commits touching changelog/unreleased/ use -X ours -X no-renames to preserve the target branch's own unreleased entries
    • other commits (version folder additions, CHANGELOG.md) are cherry-picked plainly so real conflicts are not silently discarded
  6. Optionally pushes all three branches (--push)

Wizard changes

  • Removed four old tasks: logchange_release, logchange_generate, validate_changelog_unreleased, push_changelog_to_branches
  • Added changelog_update_rc as the first task in the artifacts group (is_in_rc_loop: true) — handles both RC1 and RC2+ via the script
  • Re-added validate_changelog_unreleased after changelog_update_rc with --skip-sync-check (branches intentionally differ until forward-port runs)
  • Added forward_port_changelog as the first task in the publish group

Other 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-run available on both subcommands — no files or git state are touched
  • --git-remote overrides the push remote (default: origin)
  • --release-date YYYY-MM-DD overrides the date written at forward-port time (default: today); input is validated
  • Cherry-pick failures print a git cherry-pick --abort hint before exiting
  • Documented in dev-docs/changelog.adoc section 5.4 and dev-tools/scripts/README.md

@github-actions github-actions Bot added documentation Improvements or additions to documentation scripts labels May 11, 2026
@janhoy janhoy marked this pull request as draft May 11, 2026 12:45
@janhoy janhoy requested a review from Copilot May 11, 2026 13:13
@janhoy janhoy changed the title New changelogRelease.py script to simplify changelog in wizard New logchange.py script to simplify changelog in wizard May 11, 2026
@janhoy janhoy force-pushed the changelog-rc-improvements branch from c04be97 to d55ffda Compare May 11, 2026 13:16
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.py with prepare (RC loop) and forward-port (post-vote) subcommands to manage changelog file moves, CHANGELOG.md regeneration, committing, cherry-picking, and optional pushing.
  • Updated dev-tools/scripts/releaseWizard.yaml to replace the previous YAML-embedded shell one-liners with the new script-driven tasks.
  • Documented the new flow in dev-tools/scripts/README.md and dev-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.

Comment thread dev-tools/scripts/releaseWizard.yaml Outdated
Comment thread dev-tools/scripts/README.md Outdated
Copy link
Copy Markdown
Contributor

@dsmiley dsmiley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread dev-tools/scripts/README.md Outdated
Comment thread dev-tools/scripts/README.md Outdated
@janhoy
Copy link
Copy Markdown
Contributor Author

janhoy commented May 11, 2026

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 logchange.py

Tested against a real git repo at https://github.com/janhoy/changelogtest

Branch setup

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_1

Expected: 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 --commit

Expected: 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 --commit

Expected: 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-12

Expected:

  • Writes release-date.txt, regenerates CHANGELOG.md with date, commits to branch_10_1
  • Cherry-picks 5 changelog commits to branch_10x and main
  • On branch_10x: A and B deleted from unreleased, D and E land in v10.1.0/
  • On main: feature-c remains untouched in unreleased; A, B, D, E appear in v10.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 --push

Expected: 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 to git 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-12

Expected: 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."

@janhoy janhoy marked this pull request as ready for review May 11, 2026 23:27
Comment thread dev-tools/scripts/releaseWizard.yaml Outdated
janhoy added 8 commits May 12, 2026 12:40
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.
Remove the validate_changelog_unreleased step which has limited value at this stage
@janhoy janhoy force-pushed the changelog-rc-improvements branch from 93390ed to db03964 Compare May 12, 2026 11:09
@janhoy janhoy merged commit eeb457e into apache:main May 12, 2026
5 checks passed
@janhoy janhoy deleted the changelog-rc-improvements branch May 12, 2026 13:26
janhoy added a commit that referenced this pull request May 12, 2026
…ard (#4413)

Refactor the wizard to generate CHANGELOG.md inside RC loop instead of before
Move cherry-picking of the changelog commits to main and stable branch until after the vote

(cherry picked from commit eeb457e)
janhoy added a commit that referenced this pull request May 13, 2026
…ard (#4413)

Refactor the wizard to generate CHANGELOG.md inside RC loop instead of before
Move cherry-picking of the changelog commits to main and stable branch until after the vote

(cherry picked from commit eeb457e)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation no-changelog scripts

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants