Skip to content

Refuse to release a version older than the last one - #13

Merged
menjoo merged 1 commit into
mainfrom
release-monotonic
Aug 2, 2026
Merged

Refuse to release a version older than the last one#13
menjoo merged 1 commit into
mainfrom
release-monotonic

Conversation

@menjoo

@menjoo menjoo commented Aug 2, 2026

Copy link
Copy Markdown
Owner

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 only1.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.

Nothing caught it. 0.0.9 after 0.1.1 is valid semver, is not a snapshot,
and has no tag, so all four existing checks passed it -- and publishing
to Central is the irreversible half.

Two deliberate looseness choices, both to avoid half-implementing semver
precedence in bash. Only the numeric core is compared, and only for "not
older" rather than "strictly newer". The second 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 check above it. The residual
gap is 1.0.0-rc2 after 1.0.0, which is rare and ambiguous enough not to
be worth the machinery.

Field-wise numeric sort rather than sort -V, which is not portable and
orders pre-release versions wrongly anyway. Tested: 0.1.11 and 10.0.0
are correctly newer than 0.1.1, which lexicographic comparison gets
backwards.

The version input stays. It guards a different failure mode -- main not
being where you think, in either direction -- which a monotonicity check
does not subsume: if you believe main is on 0.1.2 and someone merged
0.2.0, this check passes and 0.2.0 ships. It is also what run-name reads
to title the run, and run-name is evaluated before any job so it cannot
read gradle.properties.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@menjoo
menjoo merged commit db81d02 into main Aug 2, 2026
3 checks passed
@menjoo
menjoo deleted the release-monotonic branch August 2, 2026 09:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant