Skip to content

Gate the Docker push on all builds; require validate-release (#414 Q4) - #417

Merged
ptr727 merged 2 commits into
developfrom
release-atomicity-and-validate-contract
Jul 23, 2026
Merged

Gate the Docker push on all builds; require validate-release (#414 Q4)#417
ptr727 merged 2 commits into
developfrom
release-atomicity-and-validate-contract

Conversation

@ptr727

@ptr727 ptr727 commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Resolves the last open item of #414 (Q4), plus a contract bump.

Q4 - full publish atomicity. github-release already needs every build, so the tag/release is atomic. But build-docker built + 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 build-docker now needs 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 (verified: the graph is a DAG). Documented as D4.5.

Contract. Require validate-release in 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 inside github-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 in publish-plan-task.yml (D2.3). Q2 (expect_release_assets) already exists. Q3 landed in #415. This PR is the Q4 remainder + the contract bump.

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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.yml interface contract to require a validate-release job.
  • Update the canonical build-release-task.yml snippet so build-docker depends 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.

Comment thread catalog/snippets/workflows/build-release-task.yml Outdated
Comment thread WORKFLOW.md Outdated
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>
Copilot AI review requested due to automatic review settings July 23, 2026 23:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-docker is intended to tolerate skipped build jobs (disabled targets) while still blocking on failures, but if: ${{ inputs.enable_docker && !failure() && !cancelled() }} does not force evaluation when a needs job 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. Include always() (or explicit needs.<job>.result checks) 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 allow build-docker to run when one of its needs jobs is skipped (disabled target) - the workflow needs an always()/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.

@ptr727
ptr727 merged commit a0903e3 into develop Jul 23, 2026
7 checks passed
@ptr727
ptr727 deleted the release-atomicity-and-validate-contract branch July 23, 2026 23:33
ptr727 added a commit that referenced this pull request Jul 23, 2026
…e reconciliation (#418)

Carries #413 (PhotoCleaner registry), #415 (Q3 action-pin SHA masking), #416 (PlexCleaner #880 canonical prose fixes), #417 (Q4 docker atomicity + validate-release contract). Merge commit, no release.
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.

2 participants