Automate the post-release version bump - #12
Merged
Merged
Conversation
README's install snippets still said 0.1.1 after 0.1.1 shipped, because
step 3 of RELEASING.md was a list of commands someone had to remember.
set-docs-version.py rewrites them, and a Post-release workflow runs it
alongside set-version.sh and pushes a branch.
It anchors on dependency coordinates -- id("io.github.menjoo.cucumberkmp")
version "X" and io.github.menjoo.cucumberkmp:<module>:X -- rather than on
version numbers. That distinction is the point. Of the fifteen version
references in this repository, eight are historical: "0.1.0 was lost to
precisely this", "0.1.0 does not exist on Central", "the v0.1.0 tag
remains as a record", and doc-comment examples in two scripts. A
substitution blunt enough to catch the install snippets would erase the
record of the incident that step 5 of the release workflow exists to
prevent. Anchoring on the coordinate cannot reach prose at all.
It also refuses to be a silent no-op. If the anchors match nothing it
fails loudly rather than reporting success, because "documentation is
current" and "the patterns broke in a docs restructure" otherwise look
identical -- which is how a script like this rots unnoticed.
ARCHITECTURE.md is left alone. Its version references are prose, and its
status lines want a human sentence rather than a substitution.
The workflow pushes a branch and stops. It does not open the pull
request: one opened with GITHUB_TOKEN does not trigger workflow runs, so
with CI now required on main a bot-opened pull request would sit unable
to satisfy its own checks. A personal access token would buy the last
click for a long-lived credential, which is the trade RELEASING.md
already declines under "Why not one button". The summary links to the
compare page instead.
Python rather than bash, matching verify-publishable.py: anchored regex
with capture groups and per-line reporting is awkward in shell.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
menjoo
added a commit
that referenced
this pull request
Aug 2, 2026
`0.0.9` after `0.1.1` currently releases cleanly: it is valid semver, is not a `-SNAPSHOT`, and `v0.0.9` does not exist, so all four checks in "Check the version" pass it. Publishing to Central is the irreversible half, so that is worth closing. ## The comparison Two deliberate looseness choices, both to avoid half-implementing semver precedence in bash: - **Numeric core only** — `1.0.0-rc1` is compared as `1.0.0`. - **"Not older" rather than "strictly newer"** — this is what lets `1.0.0` follow `1.0.0-rc1`, which a strict-greater check would wrongly block. An exact repeat is already refused by the tag-exists check immediately above. Residual gap: `1.0.0-rc2` after `1.0.0` is allowed. Rare and ambiguous enough not to be worth the machinery. Field-wise numeric sort (`sort -t. -k1,1n -k2,2n -k3,3n`) rather than `sort -V`, which is not portable across GNU and BSD and orders pre-release versions wrongly regardless. ## Tested | Tags | Version | Result | |---|---|---| | `v0.1.0 v0.1.1` | `0.1.2`, `0.2.0`, `1.0.0` | allow | | `v0.1.0 v0.1.1` | `0.0.9`, `0.1.0` | **refuse** | | `v0.1.0 v0.1.1` | `0.1.11`, `10.0.0` | allow — lexicographic comparison gets both backwards | | `v0.1.0 v0.1.1` | `0.1.1` | allow — correctly deferred to the tag-exists check | | `… v1.0.0-rc1` | `1.0.0` | allow — the case a strict-greater check breaks | | none | anything | allow | ## Why the input stays It guards a different failure mode, so the new check does not subsume it: | Guard | Catches | |---|---| | `requested == committed` | main isn't where you think — **in either direction** | | monotonic vs latest tag | main went backwards | If you believe main is on 0.1.2 and someone merged 0.2.0, monotonicity passes and 0.2.0 ships. It is also what `run-name` reads. `run-name` is evaluated before any job starts and can only use the `github`, `inputs` and `vars` contexts, so it cannot read `gradle.properties` — dropping the input would put the Actions list back to a column of identical "Release" entries, which is what #8 was merged to fix. ## Ordering Independent of #11 and #12; touches a different region of `release.yml` than #12 does. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.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.
The README still says 0.1.1 now that 0.1.1 has shipped, because step 3 of
RELEASING.mdwas a listof commands someone had to remember. This makes it a workflow.
What it does
Actions → Post-release → Run workflow, entering the version just released. It:
set-docs-version.py <version>over the README's install snippetsset-version.sh <next>-SNAPSHOTpost-<version>and links to the Open a pull request page in its summarySimulated end to end against a clone: produces
README.md | 8 ++--andgradle.properties | 2 +-,which is what #7 did by hand.
Why it anchors on coordinates, not version numbers
set-docs-version.pymatches onlyid("io.github.menjoo.cucumberkmp") version "X"andio.github.menjoo.cucumberkmp:<module>:X.Of the fifteen version references in this repository, eight are historical and must never be
rewritten:
release.ymlverify-publishable.pyRELEASING.mdARCHITECTURE.mdv0.1.0tag remains as a record"get-version.sh,RELEASING.mdA substitution blunt enough to catch the install snippets would erase the record of the incident
that step 5 of the release workflow exists to prevent. Anchoring on the coordinate cannot reach
prose at all. Verified: the KSP plugin's
version "2.3.10"on the line above the plugin id isuntouched, and
ARCHITECTURE.mdcomes out byte-identical.It also fails loudly if the anchors match nothing, rather than reporting success — otherwise
"documentation is current" and "the patterns broke in a docs restructure" look the same, which is
how a script like this rots unnoticed.
ARCHITECTURE.mdis deliberately not rewritten. Its status lines want a human sentence.Why it doesn't open the pull request
A pull request opened with
GITHUB_TOKENdoes not trigger workflow runs — GitHub blocks that toprevent recursion. With CI now required on
main, a bot-opened pull request would sit permanentlyunable to satisfy its own checks. Opening it yourself is one click and makes CI run normally.
A PAT would buy that click for a long-lived credential, which is the trade
RELEASING.mdalreadydeclines under "Why not one button".
Notes
verify-publishable.py: anchored regex with capture groups andper-line reporting is awkward in shell.
contents: writeonly, inputs reach bash throughenv, actionsSHA-pinned.
Ordering
Merge after #11. The first real use is 0.1.2's post-release step.