chore(release): v0.10.1 #132

Merged
alex merged 1 commit from release-prep/rolling into main 2026-06-26 22:20:19 +02:00
Member

Added

Idempotent cut pipeline (#128) — closes the partial-completion gap surfaced by Surveyor's df03/4a44 reconciliation of the v0.10.0 cut.

The artifact this closes

The v0.10.0 cut's task 13307 substantively completed the cut (manifest direct-pushed, release published) but got cancelled mid-flight when its own manifest push fired a new push:main event. The operator's manual re-run (task 13310) called Forgejo's release-create API, which returned 409 Conflict because v0.10.0 already existed — the workflow exit code reported failure even though the substrate was correct.

Partial-completion matrix

Per Surveyor 4a44 design point: the design handles the partial-completion case, not just full-completion. The cut path has two mutation surfaces — release creation + manifest update — and either can have completed independently when a workflow gets cancelled.

Release exists? Manifest at HEAD_SHA? Re-run action
No No Normal cut (no change from prior behavior)
Yes (matches expected draft state + target_commitish) No Release create: idempotent skip; manifest update proceeds
Yes (matches) Yes Release create: idempotent skip; manifest update: idempotent skip
Yes (differs from expected) * Release create: FAIL LOUD with diagnostic; operator must reconcile
No Yes Release create proceeds (recreates release at the manifest's state)

Each mutation surface decides independently. The re-run after a cancellation completes whatever remains; nothing fires a 409 against work already done.

What changed

  • scripts/lib/forgejo-api.sh: new forgejo_get_release_by_tag helper. Returns the release JSON on stdout if found, empty stdout if 404, exit 1 on other errors. Test seam FORGEJO_TEST_RELEASE_FILE mirrors the FORGEJO_TEST_PR_LOOKUP_FILE pattern from the Layer-2 test seam (line-consumed canned responses).
  • scripts/draft-release.sh: new pre-check before forgejo_create_release_draft queries existing release state. Decides between idempotent skip + machine-readable outputs (with new idempotent=1 marker), fail-loud on state mismatch, or fall through to create.
  • .forgejo/workflows/_release.yml cut path: new pre-check before the manifest write reads existing manifest's last_released_sha + compares with HEAD_SHA. If equal, skip the write/commit/push entirely.
  • tests/draft-release.bats: 5 new tests covering the matrix — no release (normal create), exists+matches-immediate (skip), exists+matches-draft (skip), exists+draft-mismatch (fail), exists+target_commitish-mismatch (fail).

Test count

326/326 bats green (was 321; +5 new idempotency tests).

What this does NOT do

  • Does NOT cover the cancel-mid-flight race that PRODUCED the v0.10.0 artifact (that's a Forgejo Actions concurrency question; this PR makes the re-run AFTER such a cancellation safe).
  • Does NOT make the cut undoable — idempotency is "if re-run, recognize already-done"; it's not "if mistake, undo."
  • Does NOT add bats coverage for the _release.yml manifest pre-check — workflow-level test seam is its own substrate change. The pre-check is small (~6 lines), uses jq -r '.last_released_sha // empty' (same pattern as the existing write block), and the failure mode is "skip the commit/push," which is benign if buggy (the workflow would re-do the commit, which is the prior behavior). Surveyor 4a44 design point on partial-completion still mutation-verified for the release-create surface, which is the load-bearing one.

Refs

  • Closes: #128

  • Empirical artifact: v0.10.0 cut run 253 (task 13310) failure 2026-06-26

  • Surveyor df03 + 4a44 reconciliation chain surfaced the partial-completion design requirement

  • Operator engagement 2026-06-26: "are the pipelines idempotent? Would it be possible to become them idempotent, if not already so?" — confirmed scope + sequencing

  • idempotent cut pipeline — pre-check existing release + manifest state (closes #128)

### Added **Idempotent cut pipeline** ([#128](https://git.frankenbit.de/frankenbit/release-toolkit/issues/128)) — closes the partial-completion gap surfaced by Surveyor's df03/4a44 reconciliation of the v0.10.0 cut. ## The artifact this closes The v0.10.0 cut's task 13307 substantively completed the cut (manifest direct-pushed, release published) but got cancelled mid-flight when its own manifest push fired a new push:main event. The operator's manual re-run (task 13310) called Forgejo's release-create API, which returned 409 Conflict because v0.10.0 already existed — the workflow exit code reported failure even though the substrate was correct. ## Partial-completion matrix Per Surveyor 4a44 design point: the design handles the partial-completion case, not just full-completion. The cut path has two mutation surfaces — release creation + manifest update — and either can have completed independently when a workflow gets cancelled. | Release exists? | Manifest at HEAD_SHA? | Re-run action | |---|---|---| | No | No | Normal cut (no change from prior behavior) | | Yes (matches expected draft state + target_commitish) | No | Release create: idempotent skip; manifest update proceeds | | Yes (matches) | Yes | Release create: idempotent skip; manifest update: idempotent skip | | Yes (differs from expected) | * | Release create: FAIL LOUD with diagnostic; operator must reconcile | | No | Yes | Release create proceeds (recreates release at the manifest's state) | Each mutation surface decides independently. The re-run after a cancellation completes whatever remains; nothing fires a 409 against work already done. ## What changed - **`scripts/lib/forgejo-api.sh`**: new `forgejo_get_release_by_tag` helper. Returns the release JSON on stdout if found, empty stdout if 404, exit 1 on other errors. Test seam `FORGEJO_TEST_RELEASE_FILE` mirrors the `FORGEJO_TEST_PR_LOOKUP_FILE` pattern from the Layer-2 test seam (line-consumed canned responses). - **`scripts/draft-release.sh`**: new pre-check before `forgejo_create_release_draft` queries existing release state. Decides between idempotent skip + machine-readable outputs (with new `idempotent=1` marker), fail-loud on state mismatch, or fall through to create. - **`.forgejo/workflows/_release.yml`** cut path: new pre-check before the manifest write reads existing manifest's `last_released_sha` + compares with `HEAD_SHA`. If equal, skip the write/commit/push entirely. - **`tests/draft-release.bats`**: 5 new tests covering the matrix — no release (normal create), exists+matches-immediate (skip), exists+matches-draft (skip), exists+draft-mismatch (fail), exists+target_commitish-mismatch (fail). ## Test count 326/326 bats green (was 321; +5 new idempotency tests). ## What this does NOT do - **Does NOT cover the cancel-mid-flight race** that PRODUCED the v0.10.0 artifact (that's a Forgejo Actions concurrency question; this PR makes the re-run AFTER such a cancellation safe). - **Does NOT make the cut undoable** — idempotency is "if re-run, recognize already-done"; it's not "if mistake, undo." - **Does NOT add bats coverage for the `_release.yml` manifest pre-check** — workflow-level test seam is its own substrate change. The pre-check is small (~6 lines), uses `jq -r '.last_released_sha // empty'` (same pattern as the existing write block), and the failure mode is "skip the commit/push," which is benign if buggy (the workflow would re-do the commit, which is the prior behavior). Surveyor 4a44 design point on partial-completion still mutation-verified for the release-create surface, which is the load-bearing one. ## Refs - **Closes**: [#128](https://git.frankenbit.de/frankenbit/release-toolkit/issues/128) - **Empirical artifact**: v0.10.0 cut run 253 (task 13310) failure 2026-06-26 - **Surveyor df03 + 4a44 reconciliation chain** surfaced the partial-completion design requirement - **Operator engagement 2026-06-26**: *"are the pipelines idempotent? Would it be possible to become them idempotent, if not already so?"* — confirmed scope + sequencing - idempotent cut pipeline — pre-check existing release + manifest state (closes #128)
quartermaster 2026-06-26 22:12:30 +02:00
release-bot changed title from chore(release): v0.11.0 to chore(release): v0.10.1 2026-06-26 22:18:56 +02:00
forgejo-actions force-pushed release-prep/rolling from 952f9b3bf5
All checks were successful
manifest-check / manifest-vs-tag consistency (pull_request) Successful in 4s
manifest-check / check (pull_request) Successful in 0s
to 3a97fea3c9
Some checks failed
release / decide + act (push) Successful in 5s
release / release (push) Has been cancelled
2026-06-26 22:18:57 +02:00
Compare
alex approved these changes 2026-06-26 22:20:17 +02:00
alex merged commit 3a97fea3c9 into main 2026-06-26 22:20:19 +02:00
alex deleted branch release-prep/rolling 2026-06-26 22:20:19 +02:00
Sign in to join this conversation.
No description provided.