Skip to content

fix(release): let a recovery dispatch actually reach the build - #73

Merged
MotherSphere merged 1 commit into
mainfrom
fix/release-dispatch-chain
Aug 27, 2026
Merged

fix(release): let a recovery dispatch actually reach the build#73
MotherSphere merged 1 commit into
mainfrom
fix/release-dispatch-chain

Conversation

@MotherSphere

Copy link
Copy Markdown
Member

The first dispatch for v0.10.0 resolved the tag and then built nothing: target
succeeded, and build, sign and aur were all skipped.

A skipped job propagates transitively. release-please is skipped on a
dispatch, and target survives that only because of its own status-function
if: - which does not clear the inherited skip for the jobs downstream of it.
So they saw a skipped ancestor and skipped in turn, while the run reported
success.

Each job now states the dependencies it actually requires:

build:  needs.target.result == 'success'
sign:   needs.target.result == 'success' && needs.build.result == 'success'
aur:    needs.target.result == 'success' && needs.sign.result == 'success'

Naming every dependency matters as much as the fix. Guarding sign on target
alone would let it run after a FAILED build and try to sign assets that do not
exist, and guarding aur the same way would bump the AUR package to a release
with no signatures. The old if: conditions had that property for free by
hanging off release_created; the rewrite to a target job lost it.

Costs nothing on the push path, where all three ancestors succeed anyway - and
that path is already verified green on run 33117309249.

The first dispatch for v0.10.0 resolved the tag and then built nothing: `target`
succeeded, and `build`, `sign` and `aur` were all skipped.

A skipped job propagates transitively. `release-please` is skipped on a
dispatch, and `target` survives that only because of its own status-function
`if:` - which does not clear the inherited skip for the jobs downstream of it.
So they saw a skipped ancestor and skipped in turn, while the run reported
success.

Each job now states the dependencies it actually requires:

    build:  needs.target.result == 'success'
    sign:   needs.target.result == 'success' && needs.build.result == 'success'
    aur:    needs.target.result == 'success' && needs.sign.result == 'success'

Naming every dependency matters as much as the fix. Guarding `sign` on `target`
alone would let it run after a FAILED build and try to sign assets that do not
exist, and guarding `aur` the same way would bump the AUR package to a release
with no signatures. The old `if:` conditions had that property for free by
hanging off `release_created`; the rewrite to a `target` job lost it.

Costs nothing on the push path, where all three ancestors succeed anyway - and
that path is already verified green on run 33117309249.
@MotherSphere
MotherSphere merged commit 5e6b9ba into main Aug 27, 2026
5 checks passed
@MotherSphere
MotherSphere deleted the fix/release-dispatch-chain branch August 27, 2026 21:53
MotherSphere added a commit that referenced this pull request Aug 27, 2026
…build (#74)

The second recovery dispatch still built nothing, with the same shape as the
first: `target` succeeded and `build`, `sign` and `aur` skipped while the run
reported success. Naming the dependencies explicitly in #73 was necessary but
not sufficient.

A job `if:` that contains no status-check function gets an implicit `success()`
ANDed onto it, and that `success()` is evaluated over the whole ancestor graph
rather than the direct `needs`. `release-please` is skipped on a dispatch, so
the implicit `success()` was false and the job skipped no matter what the
explicit condition said.

The evidence was already in the file: `target` carries `!cancelled() &&
!failure()` and RAN despite the skipped ancestor, while `build` carried only
`needs.target.result == 'success'` and skipped even though `target` had
succeeded. Naming any status function suppresses the implicit one, so
`!cancelled()` on each downstream job lets the explicit conditions govern.

The explicit conditions from #73 are what make that safe to do: `!cancelled()`
alone would run these jobs after a FAILED dependency, which is exactly what the
per-dependency checks prevent. The two changes only work together.
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