From 16b17197f31f13c9e420e85bd196e4ea9a0aa8fb Mon Sep 17 00:00:00 2001 From: Lars Francke Date: Tue, 21 Jul 2026 14:19:20 +0200 Subject: [PATCH] fix(template): Make "Finished Build and Publish" gate reflect real build outcome The `finished` job is the single required status check for the build workflow. It had no `if:` clause, so a failed dependency caused GitHub to *skip* it rather than fail it - and branch protection treats a skipped required check as passing. A broken build (e.g. a failed publish-index-manifest) therefore became mergeable. Two fixes: - Add `if: always()` so the gate always runs and reports a real success/failure conclusion. - List every leaf job directly in `needs` and fail the gate on any `failure`/`cancelled` result. Previously publish-index-manifest was only a transitive dependency (via openshift-preflight-check), so its failure would not surface in `needs.*.result`. `skipped` is tolerated, since jobs skip legitimately on merge_group events, forks, and when detect-changes finds no relevant changes. Co-Authored-By: Claude Opus 4.8 (1M context) --- template/.github/workflows/build.yaml.j2 | 32 ++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/template/.github/workflows/build.yaml.j2 b/template/.github/workflows/build.yaml.j2 index de1ca64f..b110da63 100644 --- a/template/.github/workflows/build.yaml.j2 +++ b/template/.github/workflows/build.yaml.j2 @@ -372,13 +372,41 @@ jobs: # WARNING: Do not change the name unless you will also be changing the # Required Checks (in branch protections) in GitHub settings. name: Finished Build and Publish + # Run even when a dependency failed, was skipped or cancelled, so that this + # gate reflects the real outcome. Without `always()` a failed dependency + # would *skip* this job, and GitHub treats a skipped required check as + # passing - making a broken build mergeable. + if: always() + # List every leaf job directly. A transitive failure (e.g. a failed + # publish-index-manifest that skips openshift-preflight-check) does not + # surface as `failure` in `needs.*.result` unless the failing job is a + # direct dependency. needs: + - detect-changes - cargo-udeps - - openshift-preflight-check + - build-container-image + - publish-index-manifest + - provenance-oci + - provenance-quay - publish-helm-chart + - openshift-preflight-check runs-on: ubuntu-latest steps: - - run: echo "We are done here" + # Skipped dependencies are fine (jobs skip legitimately on merge_group + # events, forks, or when detect-changes finds no relevant changes). Only + # a failure or cancellation must fail this gate. + - name: Fail on any failed or cancelled dependency + env: + RESULTS: ${{ join(needs.*.result, ' ') }} + run: | + echo "Dependency results: $RESULTS" + for result in $RESULTS; do + if [ "$result" = "failure" ] || [ "$result" = "cancelled" ]; then + echo "::error::A required job did not succeed (result: $result)" + exit 1 + fi + done + echo "We are done here" notify: name: Failure Notification