fix(examples): release-branch cuts the version the changelog names, and composes nothing #18

Merged
mikluko merged 3 commits from mikluko/octant/1718-written-version into main 2026-09-06 14:12:25 +00:00
mikluko commented 2026-09-06 11:29:19 +00:00 (Migrated from github.com)

What this does

examples/release-branch/ composed its pre-release tag from github.run_number
and from the branch name's last hyphenated segment. Both are wrong, and neither
is repaired here: composing at all is what was wrong. The action exists to
make everything downstream follow from the document, and the example went around
it. Writing 1.3.0-rc.2 in the heading is now what cuts v1.3.0-rc.2.

Supersedes #13, which rebuilt the example faithfully around the derivation.

The two guards

Both workflows cut the version the newest entry names. They differ in one word:

# release-branch.yaml                      # main.yaml
if: >-                                     if: >-
  ...prerelease == 'true' &&                 ...prerelease == 'false' &&
  ...already-tagged == 'false'               ...already-tagged == 'false'

prerelease and already-tagged are outputs the action already had. Dropping
-rc.2 from the heading is how the branch says the release is ready, so the
guard is what stops the branch taking the final tag off the trunk.

A push that changes no version cuts nothing. The run-number scheme cut a
candidate on every push, including a typo fix in a README; here the file
advances the sequence and pushing does not.

What that forced

prerelease-entry moves to the trunk invocation alone. A candidate is a heading
under this strategy now, so raising the check on the branch or on pull requests
would refuse the shape the strategy runs on.

The cost is stated rather than hidden: the check judges the whole document, so
switching it off to permit the newest heading permits a stale candidate below it
too. CHANGELOG.broken.md carries one, and the test holds only the trunk
invocation to reporting it.

The unguarded-suffix defect dies with the derivation rather than by an allowlist
in the trigger, so branches: ['release/*'] needs no stage enumeration and a
second stage costs no workflow change — the property the branch-name derivation
was reached for in the first place, now safe because nothing reads the name.

A scope decision, flagged

main.yaml gains the mirror step. The README already claimed the trunk cuts
the final tag without showing it, and the two guards are only legible as one word
apart when both are on the page. It is additive to a file this defect does not
otherwise touch.

Both steps push the tag rather than composing into an output, which is forced:
with nothing to compute, a step that only composed has no reason to exist.

Size

The example README goes from 295 lines on #13 (182 on main) to 122. The whole
ordinal, suffix, enumeration and stage-derivation argument is gone, because there
is no derivation left to defend.

Checks

go test ./..., go vet ./..., gofmt -l clean, go run ./cmd/gen-readme
idempotent. The examples are executed rather than described, so the per-invocation
finding lists in examples_test.go are what hold the README's tables honest.

No name, host, version or secret from any consuming repository appears; the diff
was audited by hand for it, per the standing rule that a denylist test would be
the disclosure it prevents.

## What this does `examples/release-branch/` composed its pre-release tag from `github.run_number` and from the branch name's last hyphenated segment. Both are wrong, and neither is repaired here: **composing at all is what was wrong.** The action exists to make everything downstream follow from the document, and the example went around it. Writing `1.3.0-rc.2` in the heading is now what cuts `v1.3.0-rc.2`. Supersedes #13, which rebuilt the example faithfully around the derivation. ## The two guards Both workflows cut the version the newest entry names. They differ in one word: ```yaml # release-branch.yaml # main.yaml if: >- if: >- ...prerelease == 'true' && ...prerelease == 'false' && ...already-tagged == 'false' ...already-tagged == 'false' ``` `prerelease` and `already-tagged` are outputs the action already had. Dropping `-rc.2` from the heading is how the branch says the release is ready, so the guard is what stops the branch taking the final tag off the trunk. **A push that changes no version cuts nothing.** The run-number scheme cut a candidate on every push, including a typo fix in a README; here the file advances the sequence and pushing does not. ## What that forced `prerelease-entry` moves to the trunk invocation alone. A candidate is a heading under this strategy now, so raising the check on the branch or on pull requests would refuse the shape the strategy runs on. The cost is stated rather than hidden: the check judges the whole document, so switching it off to permit the newest heading permits a stale candidate below it too. `CHANGELOG.broken.md` carries one, and the test holds only the trunk invocation to reporting it. The unguarded-suffix defect dies with the derivation rather than by an allowlist in the trigger, so `branches: ['release/*']` needs no stage enumeration and a second stage costs no workflow change — the property the branch-name derivation was reached for in the first place, now safe because nothing reads the name. ## A scope decision, flagged **`main.yaml` gains the mirror step.** The README already claimed the trunk cuts the final tag without showing it, and the two guards are only legible as one word apart when both are on the page. It is additive to a file this defect does not otherwise touch. Both steps push the tag rather than composing into an output, which is forced: with nothing to compute, a step that only composed has no reason to exist. ## Size The example README goes from 295 lines on #13 (182 on `main`) to 122. The whole ordinal, suffix, enumeration and stage-derivation argument is gone, because there is no derivation left to defend. ## Checks `go test ./...`, `go vet ./...`, `gofmt -l` clean, `go run ./cmd/gen-readme` idempotent. The examples are executed rather than described, so the per-invocation finding lists in `examples_test.go` are what hold the README's tables honest. No name, host, version or secret from any consuming repository appears; the diff was audited by hand for it, per the standing rule that a denylist test would be the disclosure it prevents.
Sign in to join this conversation.
No description provided.