From 89f24c3760a0872ef48148d3053a644d68b2c838 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 24 Jul 2026 15:37:26 +0200 Subject: [PATCH] ci: skip redundant build re-runs on same-repo PRs Bare push + pull_request triggers meant every commit was re-validated as it walked develop -> PR -> main. Guard the build job so same-repo PRs (develop->main releases, Dependabot PRs) rely on their branch's push run, which branch protection already reads per head SHA. Fork PRs still build, since fork branches don't fire push here. ci-success now treats a skipped build as a pass so main's required gate stays green without rebuilding. --- .github/workflows/ci.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c97c296..ac5e805 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,13 @@ permissions: jobs: shellcheck: + # Skip the redundant re-run for same-repo PRs. A branch push already ran this + # exact commit through CI, and branch protection reads status per head SHA + # regardless of the triggering event - so a develop->main release PR (or a + # Dependabot PR into develop) is already validated by its branch's push run. + # Fork PRs are the exception: a fork branch never fires `push` here, so the + # second clause keeps them building. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository runs-on: ubuntu-latest steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -22,6 +29,9 @@ jobs: shellcheck ssh-deploy test: + # Same fork-guard as shellcheck above: same-repo PRs re-test an already-green + # branch SHA, so skip them; fork PRs (no `push` event) still build. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository # Run on Linux (GNU userland) and macOS (BSD userland + bash 3.2) to back up # the portability claims. shellcheck above is OS-independent, so it stays Linux-only. strategy: @@ -39,3 +49,24 @@ jobs: run: brew install bats-core - name: Run tests run: bats test + + # Single stable gate that branch protection requires - not the concrete + # shellcheck/test job names, so the matrix can grow or be renamed without + # breaking the required check on main. + ci-success: + needs: [shellcheck, test] + if: always() + runs-on: ubuntu-latest + steps: + - name: Verify required jobs succeeded + run: | + # 'skipped' means a same-repo PR whose head SHA the branch push already + # validated (see the fork-guard on shellcheck/test) - treat it as a pass + # so the required ci-success gate still reports green without rebuilding. + for pair in "shellcheck=${{ needs.shellcheck.result }}" "test=${{ needs.test.result }}"; do + result="${pair#*=}" + if [ "$result" != "success" ] && [ "$result" != "skipped" ]; then + echo "::error::${pair%%=*} job did not succeed (result: $result)" + exit 1 + fi + done