Gate the Docker push on all builds; require validate-release (#414 Q4) - #417
Merged
Conversation
Full publish atomicity (#414 Q4): github-release already needs every build, but build-docker built and pushed the image gated only on validate-release, so a failure in a different build (e.g. the executable) still let the image push - a partial publish. Docker is the terminal registry push in the fleet (no repo pushes two registries at once), so make build-docker need every other build: the image publishes only when all enabled builds passed. A skipped (disabled) build does not block, a failed one does. No needs cycle (nothing needs docker back). Documented as WORKFLOW.md D4.5. Also require validate-release in the release-task interface contract. It is the symmetric branch<->version entry gate (D2.2); the older repos carry that check as a step inside github-release instead, so the contract flags them to adopt the entry-gate job on their next re-vendor. #414 Q1 (symmetric backstop + main/develop whitelist) and Q2 (expect_release_ assets) were already implemented (validate-release / D2.2, publish-plan / D2.3, and the expect_release_assets input); Q3 landed in #415. Q4 is the remainder. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 23, 2026
Contributor
There was a problem hiding this comment.
Pull request overview
Updates the release/publish contract and canonical workflow snippet to prevent partial publishes by ensuring Docker pushes only occur after all other enabled builds have completed successfully, and records the new guarantee in the workflow contract.
Changes:
- Document D4.5: require publish atomicity across all enabled build targets (including Docker as the terminal registry push).
- Tighten the
build-release-task.ymlinterface contract to require avalidate-releasejob. - Update the canonical
build-release-task.ymlsnippet sobuild-dockerdepends on the other build jobs (to prevent Docker from pushing when another build failed).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| WORKFLOW.md | Adds D4.5 to document the “no partial publish” guarantee across build targets. |
| spec/files.json | Updates the interface contract for .github/workflows/build-release-task.yml to require validate-release. |
| catalog/snippets/workflows/build-release-task.yml | Gates build-docker on the other builds to prevent Docker pushes on partial failures. |
A skipped GitHub Actions dependency skips the dependent, so build-docker needing every build would be skipped whenever a target is disabled - breaking smoke PRs that build only the changed target. Guard build-docker's if with !failure() && !cancelled(): a failed build still skips docker (atomicity holds), but a skipped (disabled or unvendored) build is tolerated so docker still builds on smoke. Corrected the comment and D4.5 to describe this, not plain-needs semantics. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
catalog/snippets/workflows/build-release-task.yml:153
build-dockeris intended to tolerate skipped build jobs (disabled targets) while still blocking on failures, butif: ${{ inputs.enable_docker && !failure() && !cancelled() }}does not force evaluation when aneedsjob is skipped/failed. In that case GitHub Actions can skip the job before the expression is evaluated, reintroducing the smoke-build breakage this change is trying to fix. Includealways()(or explicitneeds.<job>.resultchecks) so the job can still run when dependencies are skipped, while!failure() && !cancelled()continues to block real failures/cancellation.
if: ${{ inputs.enable_docker && !failure() && !cancelled() }}
WORKFLOW.md:171
- D4.5 documents the docker gate as
!failure() && !cancelled(), but that alone is not sufficient to allowbuild-dockerto run when one of itsneedsjobs is skipped (disabled target) - the workflow needs analways()/needs.<job>.result-style override to avoid downstream skip. If the implementation is updated to include that override, D4.5 should be updated to match so the contract description stays accurate.
- **D4.5 A build failure blocks every publish target.** Input: a real publish where one enabled build fails. Output: nothing publishes - `github-release` needs every build, so a failed build skips it (no tag, no release), and the terminal registry pusher (Docker) needs every other build and guards its `if` with `!failure() && !cancelled()`, so a failed build skips docker too (no image push) while a disabled or unchanged target - skipped, not failed - still lets docker build on smoke. *Prevents: a partial publish, e.g. a Docker image pushed while the executable build failed and no release was cut.* A repo pushing two registry targets at once would need a build/publish split behind an all-builds gate, which none does today.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves the last open item of #414 (Q4), plus a contract bump.
Q4 - full publish atomicity.
github-releasealreadyneedsevery build, so the tag/release is atomic. Butbuild-dockerbuilt + pushed the image gated only onvalidate-release, so a failure in a different build (e.g. the executable) still let the image push - a partial publish. Docker is the terminal registry push in the fleet (no repo pushes two registries at once), sobuild-dockernowneedsevery other build: the image publishes only when all enabled builds passed. A skipped (disabled) build does not block, a failed one does. Noneedscycle - nothing needs docker back (verified: the graph is a DAG). Documented as D4.5.Contract. Require
validate-releasein the release-task interface contract. It is the symmetric branch<->version entry gate (D2.2); the older repos (PhotoCleaner/PlexCleaner) carry that check as a step insidegithub-release, so the contract now flags them to adopt the entry-gate job on their next re-vendor.Already done (not in this PR): #414 Q1 (symmetric backstop + main/develop whitelist) was already implemented - the symmetric check in
validate-release(D2.2) and the branch whitelist inpublish-plan-task.yml(D2.3). Q2 (expect_release_assets) already exists. Q3 landed in #415. This PR is the Q4 remainder + the contract bump.