fix(release): harden release_auto.sh against tag/mirror/branch/signing failure modes #1388

Merged
brenno merged 1 commit from hardening/release-auto-failure-modes into main 2026-08-08 21:40:54 +00:00
Owner

Wat

Doorlichting van scripts/release_auto.sh op faalmodi — met nadruk op de klasse die
een verse run overleeft maar --resume of een tweede machine breekt (zoals de
bad object type-bug van v0.4.1). Drie fixes geïmplementeerd; onderaan de volledige
audit met de afweging per punt.

Geïmplementeerd

1. Mirror-tag: een eigen, herstelbaar faalpunt (de grootste)

tag_and_push pushte origin én mirror en zette TAG_PUSHED=1 pas ná béíde.
Faalde de mirror-push:

  • meldde de ERR-trap onterecht "niets naar buiten" — terwijl de origin-tag de
    release-CI al startte;
  • sloeg --resume de mirror-push over (early-return op de bestaande origin-tag),
    dus de GitHub-tag landde nooit → windows-ophalen (workflow_dispatch --ref $TAG)
    vond de ref niet → de Windows-build draaide nooit → publiceren leverde geen
    SHA256SUMS → fase 3 stierf.

Dit is de grondoorzaak achter de terugkerende SHA256SUMS-404's.

Fix: aparte ensure_mirror_tag() (idempotent per remote); TAG_PUSHED=1 zodra
origin de tag heeft (vóór de mirror-stap, zodat de ERR-trap klopt); en zowel
tag_and_push als de "tag staat al op origin"-tak van resume_release borgen de
mirror-tag. --resume repareert nu een ontbrekende mirror-tag alsnog — ook op een
andere machine (haalt de tag zo nodig eerst van origin).

2. Verse-run fail-fast op een half-af gebleven release-branch

Bleef een release-branch op origin achter van een afgebroken poging, dan botste een
verse run pas laat op een non-fast-forward branch-push. Nu stopt hij vroeg (vóór het
wachtwoord en de build) met het --resume-advies.

3. macOS-ondertekening/notarisatie vóór de ~10 min build getoetst

notarize_macos.sh krijgt een --preflight-modus (identiteit + notary-profiel, via
notarytool history); preflight roept 'm aan bij een verse run. Een verdwenen
notary-profiel (v0.1.3-rc1) faalt nu vóór de build i.p.v. pas bij het inzenden ná de
build.

Test

Statische invarianten in release_auto_version_test.dart (leest het script, draait
geen bash — dus ook groen op de Windows-mirror-CI). Voor de mirror-klasse eerst rood
aangetoond tegen de onherstelde code, daarna groen:

  • ensure_mirror_tag is idempotent en pusht naar de mirror;
  • elke tag-route (tag_and_push + resume_release) borgt de mirror-tag;
  • TAG_PUSHED=1 staat vóór de mirror-stap;
  • locks voor de signing-preflight en de verse-run-branch-guard.

Poort & scans

  • make check lokaal groen (volledige suite + dekkingsvloer — die draaien niet in de
    CI-static-gate).
  • make check-secrets (gitleaks + trufflehog) en make sast (semgrep): geen
    bevindingen. shellcheck schoon.
  • DAST (ZAP) n.v.t.: geen webbundel of geserveerd oppervlak geraakt.

Bewaker

Bewust overgeslagen. Geen nieuw bestandsformaat, opslag, afhankelijkheid, nieuwe
vertrouwde partij of publieke belofte. De mirror-push is bestaand uitgaand verkeer
(de GitHub-spiegel), nu idempotent en herstelbaar gemaakt; geen nieuwe grens.

Volledige audit — overwogen faalmodi

Weggewerkt (hierboven): mirror-tag onafhankelijkheid + resume-herstel;
TAG_PUSHED-misrapportage bij mirror-fout; verse-run branch-collision; late
signing/notary-fout.

Bewust laten staan, met reden:

  • Fase 3 auto-redispatch van publiceren (plan-#8): ontbreekt SHA256SUMS door
    een écht gefaalde upstream-job, dan dispatcht fase 3 die job niet opnieuw — hij
    stopt met het --resume-advies. De meest voorkomende grondoorzaak (ontbrekende
    mirror-tag) is met fix 1 weg; auto-redispatch voegt CI-dispatch-logica + risico toe
    en verdient een aparte, gerichte PR.
  • api() zonder retry: een transiente netwerkhik kan een stap afbreken. Bewust
    niet blind geretried — de POSTs (merge/dispatch/asset-upload) zijn niet idempotent,
    en de hele keten is al --resume-baar, dus een afbreking is herstelbaar, geen
    corruptie.
  • find_release_pr limit=50: bij >50 PR's sinds de release zou de titelmatch de
    PR kunnen missen. Praktisch nooit (resume gebeurt snel erna); niet aangeraakt.
  • wait_gate op de gecombineerde status: wacht op álle contexts (incl. linux-gate
    ~27 min) — correct vóór een release; de 75-min-timeout dekt de wachtrij.
  • Dubbele macOS-build (build-release + notarize's schone herbouw): bewust, voor
    een schoon App.framework-zegel; niet "gefixt".

Wil je de auto-redispatch (plan-#8) ook, dan doe ik dat als aparte PR.

🤖 Generated with Claude Code

## Wat Doorlichting van `scripts/release_auto.sh` op faalmodi — met nadruk op de klasse die een verse run overleeft maar `--resume` of een tweede machine breekt (zoals de `bad object type`-bug van v0.4.1). Drie fixes geïmplementeerd; onderaan de volledige audit met de afweging per punt. ## Geïmplementeerd ### 1. Mirror-tag: een eigen, herstelbaar faalpunt (de grootste) `tag_and_push` pushte origin én mirror en zette `TAG_PUSHED=1` pas ná **béíde**. Faalde de **mirror-push**: - meldde de ERR-trap onterecht "niets naar buiten" — terwijl de origin-tag de release-CI al startte; - sloeg `--resume` de mirror-push **over** (early-return op de bestaande origin-tag), dus de GitHub-tag landde nooit → `windows-ophalen` (`workflow_dispatch --ref $TAG`) vond de ref niet → de Windows-build draaide nooit → `publiceren` leverde geen `SHA256SUMS` → fase 3 stierf. Dit is de grondoorzaak achter de terugkerende `SHA256SUMS`-404's. **Fix:** aparte `ensure_mirror_tag()` (idempotent per remote); `TAG_PUSHED=1` zodra origin de tag heeft (vóór de mirror-stap, zodat de ERR-trap klopt); en zowel `tag_and_push` als de "tag staat al op origin"-tak van `resume_release` borgen de mirror-tag. `--resume` repareert nu een ontbrekende mirror-tag alsnog — ook op een andere machine (haalt de tag zo nodig eerst van origin). ### 2. Verse-run fail-fast op een half-af gebleven release-branch Bleef een release-branch op origin achter van een afgebroken poging, dan botste een verse run pas laat op een non-fast-forward branch-push. Nu stopt hij vroeg (vóór het wachtwoord en de build) met het `--resume`-advies. ### 3. macOS-ondertekening/notarisatie vóór de ~10 min build getoetst `notarize_macos.sh` krijgt een `--preflight`-modus (identiteit + notary-profiel, via `notarytool history`); `preflight` roept 'm aan bij een verse run. Een verdwenen notary-profiel (v0.1.3-rc1) faalt nu vóór de build i.p.v. pas bij het inzenden ná de build. ## Test Statische invarianten in `release_auto_version_test.dart` (leest het script, draait geen bash — dus ook groen op de Windows-mirror-CI). Voor de mirror-klasse eerst rood aangetoond tegen de onherstelde code, daarna groen: - `ensure_mirror_tag` is idempotent en pusht naar de mirror; - elke tag-route (`tag_and_push` + `resume_release`) borgt de mirror-tag; - `TAG_PUSHED=1` staat vóór de mirror-stap; - locks voor de signing-preflight en de verse-run-branch-guard. ## Poort & scans - `make check` lokaal groen (volledige suite + dekkingsvloer — die draaien niet in de CI-static-gate). - `make check-secrets` (gitleaks + trufflehog) en `make sast` (semgrep): geen bevindingen. `shellcheck` schoon. - DAST (ZAP) n.v.t.: geen webbundel of geserveerd oppervlak geraakt. ## Bewaker Bewust overgeslagen. Geen nieuw bestandsformaat, opslag, afhankelijkheid, nieuwe vertrouwde partij of publieke belofte. De mirror-push is bestaand uitgaand verkeer (de GitHub-spiegel), nu idempotent en herstelbaar gemaakt; geen nieuwe grens. ## Volledige audit — overwogen faalmodi **Weggewerkt (hierboven):** mirror-tag onafhankelijkheid + resume-herstel; `TAG_PUSHED`-misrapportage bij mirror-fout; verse-run branch-collision; late signing/notary-fout. **Bewust laten staan, met reden:** - **Fase 3 auto-redispatch van `publiceren` (plan-#8):** ontbreekt `SHA256SUMS` door een écht gefaalde upstream-job, dan dispatcht fase 3 die job niet opnieuw — hij stopt met het `--resume`-advies. De meest voorkomende grondoorzaak (ontbrekende mirror-tag) is met fix 1 weg; auto-redispatch voegt CI-dispatch-logica + risico toe en verdient een aparte, gerichte PR. - **`api()` zonder retry:** een transiente netwerkhik kan een stap afbreken. Bewust niet blind geretried — de POSTs (merge/dispatch/asset-upload) zijn niet idempotent, en de hele keten is al `--resume`-baar, dus een afbreking is herstelbaar, geen corruptie. - **`find_release_pr` `limit=50`:** bij >50 PR's sinds de release zou de titelmatch de PR kunnen missen. Praktisch nooit (resume gebeurt snel erna); niet aangeraakt. - **`wait_gate` op de gecombineerde status:** wacht op álle contexts (incl. linux-gate ~27 min) — correct vóór een release; de 75-min-timeout dekt de wachtrij. - **Dubbele macOS-build (`build-release` + notarize's schone herbouw):** bewust, voor een schoon `App.framework`-zegel; niet "gefixt". Wil je de auto-redispatch (plan-#8) ook, dan doe ik dat als aparte PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(release): harden release_auto.sh against tag/mirror/branch/signing failure modes
All checks were successful
scans / scans (pull_request) Successful in 4m29s
static-gate / static-gate (pull_request) Successful in 7m35s
linux-gate / gate-linux (pull_request) Successful in 27m20s
748d25fd8a
Na de bad-object-type-bug (v0.4.1) een bredere doorlichting van de faalmodi die een
verse run overleven maar --resume of een tweede machine breken. Drie fixes:

1. Mirror-tag als eigen, herstelbaar faalpunt (de grootste). tag_and_push pushte
   origin én mirror en zette TAG_PUSHED=1 pas ná béíde. Faalde de mirror-push, dan
   (a) meldde de ERR-trap onterecht "niets naar buiten" terwijl de origin-tag de
   release-CI al startte, en (b) sloeg --resume de mirror-push over (early-return op
   de bestaande origin-tag) — de GitHub-tag landde nooit, dus windows-ophalen
   (dispatch --ref $TAG) vond de ref niet, de Windows-build draaide nooit, publiceren
   leverde geen SHA256SUMS, en fase 3 stierf. Grondoorzaak achter de terugkerende
   SHA256SUMS-404's. Nu: aparte ensure_mirror_tag() (idempotent per remote);
   TAG_PUSHED=1 zodra origin de tag heeft (vóór de mirror-stap); en zowel tag_and_push
   als resume_release borgen de mirror-tag — --resume repareert 'm alsnog.

2. Verse-run fail-fast op een half-af gebleven release-branch. Bleef die op origin
   achter, dan botste een verse run pas laat op een non-fast-forward-push. Nu stopt
   hij vroeg (vóór wachtwoord/build) met het --resume-advies.

3. macOS-ondertekening vóór de ~10 min build getoetst. notarize_macos.sh krijgt een
   --preflight-modus (identiteit + notary-profiel via notarytool history); preflight
   roept 'm aan (verse run). Een verdwenen notary-profiel (v0.1.3-rc1) faalt nu vóór
   de build i.p.v. pas bij het inzenden.

Regressietoetsen in release_auto_version_test.dart (statische invarianten; voor de
mirror-klasse eerst rood aangetoond): ensure_mirror_tag idempotent + mirror-push,
elke tag-route borgt de mirror-tag, TAG_PUSHED vóór de mirror-stap, plus locks voor
de signing-preflight en de verse-run-branch-guard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brenno merged commit dfaa7d3b74 into main 2026-08-08 21:40:54 +00:00
brenno deleted branch hardening/release-auto-failure-modes 2026-08-08 21:40:55 +00:00
Sign in to join this conversation.
No description provided.