ci: fix changelog ordering for modpublisher's own tag/release publishing - #7
Merged
Conversation
modpublisher's `changelog = file("CHANGELOG.md")` (Archie/build.gradle.kts)
reads that file straight off disk at publish time - it has no idea about git
tags or PRs. release-notes.yaml is reactive: it only generates a release's
changelog entry *after* seeing its tag pushed, landing it via a PR that needs
a human merge. If modpublisher creates the tag as part of the same
`./gradlew publish*` invocation that reads `changelog`, that's a hard
ordering conflict, not a race that sometimes loses - the entry can't exist
yet. And if that invocation runs in CI under the default GITHUB_TOKEN, the
tag it creates won't even fire release-notes.yaml at all, per GitHub's
anti-recursion rule for that token.
Adds a `generateChangelog` Gradle task that runs generate_release_notes.py
synchronously, writing Archie/CHANGELOG.md right before any publish task
reads it - `publishCurseforge`/`publishModrinth`/`publishGitHub`/`publishMod`
all now `dependsOn` it. No GitHub Actions dependency, so it works locally or
in CI regardless of token/trigger semantics.
Since the release tag doesn't exist yet at this point, the script gains
`--range-end` (defaults to `--new-tag`, matching the existing post-tag
behavior) so a real ref like HEAD can be walked while `--new-tag` carries the
not-yet-real intended version for display/heading purposes. `--posts-dir` is
now optional - the Gradle task only regenerates the changelog, not the news
post, which has no such ordering requirement and stays release-notes.yaml's
job.
Verified via `./gradlew publishCurseforge/publishModrinth/publishGitHub/
publishMod --dry-run` (generateChangelog appears once, correctly ordered
before each) and a real `./gradlew generateChangelog` run against this
repo's actual full history (no tag exists yet, so it exercised the
root-commit fallback too) - reverted the resulting CHANGELOG.md back to its
stub afterward since that was a verification run, not a real release.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
KP2048
marked this pull request as ready for review
August 6, 2026 21:38
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.
Summary
Follow-up to #6 (already merged). This commit landed on the
changelog-automationbranch after #6 had already merged, so it never made it into1.21.x— re-opening it here on a fresh branch off current1.21.x(cherry-picked cleanly, no conflicts).modpublisher'schangelog = file("CHANGELOG.md")(Archie/build.gradle.kts) reads that file straight off disk at publish time — it has no idea about git tags or PRs.release-notes.yaml(from #6) is reactive: it only generates a release's changelog entry after seeing the tag pushed, landing it via a PR that needs a human merge. Ifmodpublishercreates the tag itself as part of the same./gradlew publish*invocation that readschangelog, that's a hard ordering conflict (not a race — the entry structurally can't exist yet), and if that invocation runs in CI under the defaultGITHUB_TOKEN, the tag it creates won't even firerelease-notes.yamlat all (GitHub's anti-recursion rule for that token).Fixed by adding a
generateChangelogGradle task (Archie/build.gradle.kts) thatpublishCurseforge/publishModrinth/publishGitHub/publishModalldependsOn— it regeneratesCHANGELOG.mdsynchronously, right before any publish task reads it, with no GitHub Actions dependency at all (works locally or in CI regardless of token/trigger semantics).release-notes.yamlstill owns thedocs/newsblog post, which has no such ordering requirement.Since the release tag doesn't exist yet at this point,
.github/scripts/generate_release_notes.pygains--range-end(defaults to--new-tag, matching the existing post-tag behavior) so a real ref likeHEADcan be walked while--new-tagcarries the not-yet-real intended version for display/heading purposes.--posts-diris now optional — the Gradle task only regenerates the changelog, not the news post.Test plan
1.21.x(no conflicts, diff scoped to exactly the 3 intended files)./gradlew publishCurseforge/publishModrinth/publishGitHub/publishMod --dry-runre-verified against current1.21.xtip —generateChangelogcorrectly ordered before each:common:compileKotlinclean./gradlew generateChangelogfor real once to verify end-to-end (see ci: automated changelog + release-notes blog post on tag #6's history), then reverted the resultingCHANGELOG.md🤖 Generated with Claude Code