diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock index 533cd389..3ae53ce2 100644 --- a/.github/workflows/actions.lock +++ b/.github/workflows/actions.lock @@ -15,6 +15,9 @@ workflows: - 'actions/upload-artifact@v7.0.2' - 'dtolnay/rust-toolchain@v1' - 'taiki-e/install-action@v2.88.0' + '.github/workflows/cicd-squabbler.yml': + - 'actions/checkout@v7.0.1' + - 'hyperpolymath/cicd-squabbler@1ab1507a424c9edfe6cb53dea4e33a2f3cc558e3' '.github/workflows/ci-health-sweep.yml': - 'actions/checkout@v7.0.1' - 'step-security/harden-runner@v2.22.3' diff --git a/.github/workflows/cicd-squabbler.yml b/.github/workflows/cicd-squabbler.yml new file mode 100644 index 00000000..b3be48c5 --- /dev/null +++ b/.github/workflows/cicd-squabbler.yml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: MPL-2.0 +# This workflow is managed by gh actions-lock. +# +# Independent squabbler canary: use the same-owner, commit-pinned action. +# Cross-owner reusable startup is blocked in this caller's effective Actions +# policy; this avoids silently equating a zero-job startup_failure to green. +# No administration token, no --apply, and no write permissions. +name: CICD Squabbler + +on: + pull_request: + push: + branches: [main] + schedule: + - cron: '17 7 * * 1' + workflow_dispatch: + +concurrency: + group: squabbler-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + attestations: read + +jobs: + chains: + name: Squabble chains (hard gate) + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Check out repository at the event SHA + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Install pinned and attested squabble + id: squabble + uses: hyperpolymath/cicd-squabbler/.github/actions/squabble@1ab1507a424c9edfe6cb53dea4e33a2f3cc558e3 + with: + args: "" + + - name: Audit dependency chains (fail closed) + env: + GH_TOKEN: ${{ github.token }} + REPO: ${{ github.repository }} + SQUABBLE_BIN: ${{ steps.squabble.outputs.path }} + run: | + set -uo pipefail + if [ ! -x "$SQUABBLE_BIN" ]; then + echo "::error::Pinned squabble did not install" + exit 1 + fi + rc=0 + "$SQUABBLE_BIN" chains ".=$REPO" --follow 1 | tee "$RUNNER_TEMP/squabble-chains.txt" || rc=$? + { + echo "### Squabble chains" + echo + echo '~~~' + cat "$RUNNER_TEMP/squabble-chains.txt" + echo '~~~' + echo + echo "Exit code: $rc; no remediation was applied." + } >> "$GITHUB_STEP_SUMMARY" + if [ "$rc" -eq 4 ]; then + echo "::error::Cycle or dead upstream blocked the CI dependency graph" + exit 1 + fi + if [ "$rc" -ne 0 ]; then + echo "::error::Squabble could not establish the CI dependency graph (exit $rc)" + exit 1 + fi