workflows: _release-draft.yml@v0.2.0 fails on prep-PR merge; needs diagnostic #16
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#16
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptom
When PR #15 (
chore(release): v0.2.1prep PR) was merged to main, the consumer-shaperelease-draft.ymlautonomously fired (correct — theif:gate matchedrelease-prep/v0.2.1head ref) + called_release-draft.yml@v0.2.0. The reusable workflow failed (tasks 12863 + 12864). Same shape happened earlier on PR #13's close (tasks 12857 + 12858).Empirical state
draftouter step) + 12864 (create Forgejo draft releasejob) → bothfailureWorkaround used for v0.2.1 cut
Ran
scripts/draft-release.sh --version 0.2.1locally — draft created cleanly as id=111. Operator publishes manually. v0.2.1 ships; the dogfood-via-workflow path is broken for release-draft specifically.Investigation needed
What changed between local invocation and CI invocation:
FORGEJO_TOKEN=$FORGEJO_TOKEN_QUARTERMASTER+ script runs from current dirFORGEJO_TOKEN=${{ secrets.GITHUB_TOKEN }}+ script runs from.release-toolkit/scripts/(checked out at v0.2.0)Hypotheses (ranked by likelihood):
secrets.GITHUB_TOKENmay lackcontents: writescope needed for the Forgejo/releasesPOST. The reusable'spermissions:block listscontents: writebut maybe Forgejo's auto-injected token doesn't honor that onpull_request: closedeventsfrankenbit/release-toolkititself (toolkit-on-toolkit case)--config release-toolkit.ymlpath —release-toolkit.ymlexists at repo root + has correct content; unlikely to be the causeDisposition lean
(A) Reproduce + diagnose: trigger
release-draft.ymlmanually via workflow_dispatch (which IS supported in the consumer wrapper) withtag: v0.2.1→ captures the failure path with operator visibility. Then read the actual error from the Forgejo Actions UI.(B) If GITHUB_TOKEN scope is the issue: change
_release-draft.ymlto accept a token input from the consumer + the consumer can pass an explicit token from secrets — but that defeats the cleanness of the auto-flow.(C) v0.2.x release: ship the fix in v0.2.2 once diagnosed.
Cross-tracker
— QM, 2026-06-24, surfaced during v0.2.1 dogfood cut close.
n=3 worked instance: v0.3.0 cut hit the same failure (2026-06-24 20:48)
Recurrence on PR #25 (
chore(release): v0.3.0) merge: the autonomousrelease-draft.ymlfired correctly (theif:gate matchedrelease-prep/v0.3.0head ref) + called_release-draft.yml@v0.2.0. Failed identically to the v0.2.1 instances (tasks 12863 + 12864).Workaround used for v0.3.0 cut: ran
scripts/draft-release.sh --version 0.3.0locally — draft id=112 created cleanly at targetff328f69(PR #25 merge head). Operator clicked Publish; tag v0.3.0 published 2026-06-24T20:52:51+02:00.Recurrence count: n=3 worked instances now, all today:
The autonomous draft path has now failed every single time it's fired. Priority worth bumping — the manual fallback works but defeats the dogfood. Worth diagnosing via the disposition (A) workflow_dispatch path before the next minor cut, since v0.3.x patches are the natural place to ship the fix.
— QM, 2026-06-24, v0.3.0 cut close.
Root cause identified (v0.3.1 sprint diagnostic, n=2 confirmed)
Probed the actual task logs at
/srv/docker/forgejo/data/gitea/actions_log/frankenbit/release-toolkit/(Forgejo public API doesn't expose Actions task logs — observability gap orthogonal to this issue).Empirical pattern across both task 12863 (v0.2.1 autonomous on PR #15 close) AND task 12899 (manual workflow_dispatch v0.3.0 just fired)
Both runs show IDENTICAL skip:
The
install deps+normalize versionsteps DO NOT EXECUTE. No::set-output::marker, noyq 3.4.3fromcommand -v yq, noecho "version=0.3.0". The runner jumps from step 2 (checkout release-toolkit) straight to step 5 (run draft-release.sh), skipping steps 3 + 4.Since
normalize versionnever runs,steps.version.outputs.versionevaluates to empty string. The expression--version "${{ steps.version.outputs.version }}"resolves to--version "". The script's argument parser hits the empty value, treats--versionas missing, exits 1.Comparative probe
The successful
release-prepreusable (task 12891) ran on the SAME v0.2.0 reusable shape + the SAME runner image (forgejo-ci-go:latest) — its log showsyq 3.4.3+::set-output::markers normally. So the runner CAN execute multi-steprun:blocks correctly elsewhere. The skip is specific to the_release-draft.yml@v0.2.0step sequence.Suspected: act_runner / Forgejo Actions has a step-ordering bug specific to the v0.2.0 release-draft reusable's structure — likely the
id: version+env:combination on the normalize-version step or some other YAML-shape quirk that causes parser-level drop. (Not yet root-caused at the runner-software level; the symptom-level fix below sidesteps it.)Disposition for v0.3.1 fix
(A) Inline-collapse
normalize versioninto therun draft-release.shstep. Eliminates the cross-step output dependency that's failing to propagate. Same logic, single step. Adds an empty-version guard with actionable error.Forward-cycle implication
The fix lands in v0.3.1. Existing consumers (cellblock, the toolkit ITSELF) reference
@v0.2.0in their consumer-siderelease-draft.yml. For the fix to take effect, consumers must bump theiruses: ...@v0.2.0→uses: ...@v0.3.1after v0.3.1 ships. The toolkit's own consumer-side workflow gets that bump as part of v0.3.1 closing. cellblock + tmux-tell migrations would pick the bump up at adoption time (no urgent action needed).This is the standard chicken-and-egg dynamic for self-hosting release substrate. Worth a one-liner note in the v0.3.1 CHANGELOG so consumers know.
Plan
release-draft.yml(bump@v0.2.0→@v0.3.1in the same PR? Or after v0.3.1 ships?)Surfacing this comment before the PR opens so the diagnostic is captured even if I get pulled off mid-flight.
— Quartermaster, 2026-06-24 21:18, v0.3.1 sprint engagement post-sleep.
Diagnostic refinement — install-deps run-state is AMBIGUOUS from log
Surveyor cac0 surfaced a sharp catch on the prior comment's over-statement: I claimed "BOTH
install depsANDnormalize versionDO NOT EXECUTE" based on the 400ms gap with no visible output. Filed-rootcause-is-hypothesis discipline applies — that asserted certainty on two distinct steps without proving the install-deps half.Canonical-probe just done
install-depsbody has this structure:command -v "$tool" >/dev/nullproduces zero output by design (redirected)missing=()empty (pre-baked image), the if-block doesn't fire — zero outputforgejo-ci-go:latestimage has yq + jq + curl pre-bakedSo a silently-running install-deps with pre-baked deps looks identical in the log to a skipped install-deps step. The 400ms gap is the same either way.
What the canonical evidence DOES support:
checkout release-toolkitran (visible HEAD probe + matcher removal)normalize versionDID NOT execute (no::set-output::marker — if it had run, that marker would be visible per the comparative probe of successful task 12891)install depsstate — ambiguous (no log output either way for pre-baked deps; can't distinguish run-silently-no-op from skipped)run draft-release.shran (visible script invocation + error)Implications for the v0.3.1 fix (PR #26)
The fix correctly addresses the confirmed normalize-version skip (inline-collapse sidesteps the cross-step output dependency that's failing). For pre-baked-deps consumers (toolkit-on-toolkit + any consumer using
forgejo-ci-go:latest), the install-deps ambiguity doesn't bite — both branches produce a no-op.For external consumers without pre-baked yq/jq/curl, this is forward open: if install-deps was genuinely skipped, they'd hit
yq: command not foundfrom inside draft-release.sh at YAML-parse time. That would surface as a DIFFERENT failure shape (not "--version is required"), which we haven't seen yet because no external consumer has cut a release through the broken workflow.Disposition forward:
echo "[install-deps] checked yq=$YQ_OK jq=$JQ_OK curl=$CURL_OK"(or similar) so the install-deps run-state is visible in future logs, removing the ambiguity. Filing as separate follow-up tracker rather than scope-creeping PR #26.Discipline note (banking)
This is the filed-rootcause-is-hypothesis pattern playing out: my n=2 confirmed observation ("install-deps + normalize-version produce no log output") got wrapped in a stronger claim ("both DO NOT execute") that conflated "no observable output" with "confirmed skip." Surveyor's catch is the same shape as the per-discipline-pin promotion-threshold catches throughout this sprint — independent verification surfacing where my own diagnostic ran past the evidence.
— Quartermaster, 2026-06-24 21:32, post-Surveyor cac0 catch on PR #26.
AC tick (post-merge catchup)
Shipped via PR #26 (commit
7a1cb7c). Diagnostic refined via comments 73402 + 73426 (Surveyor cac0 catch on over-stated install-deps claim).Disposition (A) ACs
release-draft.ymldispatch withtag: v0.3.0) hit identical failure to the n=3 autonomous instances (12863, 12864 + the v0.3.0 prep-PR-merge fire)normalize versionstep DOES NOT execute (verified absent::set-output::marker per comparative probe of successful task 12891).steps.version.outputs.versionevaluates to empty → script bails with--version is required.7a1cb7c.::error::if normalization ever produces empty (defensive against future regressions)Deferred-conditional (surfaced during PR #26 review)
command -v "$tool" >/dev/nullproduces zero output by design → silently-running install-deps with pre-baked deps is indistinguishable from skipped install-deps in current log. Diagnostic refined in comment 73426; observability fix tracked as #29 (one-lineecho "[install-deps] checked: yq, jq, curl"across all 4 reusables to disambiguate run-state in future logs).uses: ...@v0.2.0→uses: ...@v0.3.1. Toolkit's own consumer-side wrapper bump is queued for v0.3.2 sprint (closes the chicken-and-egg via dogfood). External consumers pick it up at adoption time.Cross-tracker confirmation
Closed via PR #26 merge. AC + deferred-conditional summary recorded.
— QM, 2026-06-24, v0.3.1 post-publish AC-tick pass.
release-draft.ymlpasses emptyinputs.versionto reusable on pull_request.closed (new bug exposed by #16's v0.3.1 fix) #41release-draft.ymlpasses emptyinputs.versionto reusable on pull_request.closed (new bug exposed by #16's v0.3.1 fix) #41workflow_runsAPI can report success without actual job execution (trusted-proxy trap) #47quartermaster referenced this issue2026-06-27 14:43:40 +02:00