From 1ae244b7701dd161d351aeee30447d988aacf6a8 Mon Sep 17 00:00:00 2001 From: don-petry <36422719+don-petry@users.noreply.github.com> Date: Tue, 28 Apr 2026 10:56:39 -0500 Subject: [PATCH 1/3] fix(standards): pin auto-rebase stub to SHA to satisfy SonarCloud security gate --- standards/workflows/auto-rebase.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standards/workflows/auto-rebase.yml b/standards/workflows/auto-rebase.yml index 0e60e37c..3eeba9fb 100644 --- a/standards/workflows/auto-rebase.yml +++ b/standards/workflows/auto-rebase.yml @@ -38,5 +38,5 @@ jobs: permissions: contents: write # update-branch via GITHUB_TOKEN (may touch .github/workflows/) pull-requests: write # post comments on PRs - uses: petry-projects/.github/.github/workflows/auto-rebase-reusable.yml@v1 + uses: petry-projects/.github/.github/workflows/auto-rebase-reusable.yml@126c1441ee9cf040f2ce3ef0eda85d459b82f8e9 # v1 secrets: inherit From 95c494baac6873135aaabb5808241afb8d7c2c2a Mon Sep 17 00:00:00 2001 From: don-petry Date: Tue, 5 May 2026 20:37:56 -0500 Subject: [PATCH 2/3] ci: trigger CI with clean check-suite preferences From 5b0640cf088c1dad9302f7e0ffb5247903a9eebb Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Wed, 6 May 2026 11:05:03 +0000 Subject: [PATCH 3/3] fix(compliance): accept SHA-pinned reusable refs in centralized-stub check The canonical auto-rebase.yml stub now uses a SHA-pinned `uses:` reference instead of the mutable `@v1` tag. Update `check_centralized_workflow_stubs` to accept both `@<40-hex-SHA>` (preferred, satisfies SonarCloud) and `@v1` (legacy, still accepted for backwards compat). Update error messages and the function docblock accordingly. Also update `standards/ci-standards.md` line 514 to document the new preferred SHA-pinned format. Addresses Copilot review comments on PR #166. Co-authored-by: Don Petry --- scripts/compliance-audit.sh | 37 +++++++++++++++++++++++++------------ standards/ci-standards.md | 2 +- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/scripts/compliance-audit.sh b/scripts/compliance-audit.sh index bafd4f83..a0d0f3b4 100755 --- a/scripts/compliance-audit.sh +++ b/scripts/compliance-audit.sh @@ -670,14 +670,21 @@ check_ci_concurrency() { } # --------------------------------------------------------------------------- -# Check: Tier 1 centralized workflows must be thin caller stubs pinned to @v1 +# Check: Tier 1 centralized workflows must be thin caller stubs using an +# immutable SHA pin (preferred) or @v1 tag (legacy, still accepted). # # For each workflow that the org has centralized into a reusable workflow, # verify the downstream repo's copy is a stub that delegates via: +# uses: petry-projects/.github/.github/workflows/.yml@<40-hex-SHA> # v1 +# or (legacy, still accepted): # uses: petry-projects/.github/.github/workflows/.yml@v1 # +# SHA-pinned references are preferred because mutable tags (@v1) are flagged +# as Security Hotspots by SonarCloud. The canonical stub in +# standards/workflows/ uses the SHA-pinned format. +# # This prevents drift: a repo that copies the inline pre-centralization -# version (or pins to @main, or pins to an older tag) is flagged so it +# version (or pins to @main, or pins to an older SHA/tag) is flagged so it # can be re-synced from the standard. The central .github repo itself is # exempt because it owns the reusables and may legitimately reference # its own workflows by @main during release prep. @@ -726,20 +733,26 @@ check_centralized_workflow_stubs() { decoded=$(echo "$content" | base64 -d 2>/dev/null || echo "") [ -z "$decoded" ] && continue - # Required pattern: a non-comment line whose `uses:` value is exactly - # petry-projects/.github/.github/workflows/.yml@v1 - # Anchor to start-of-line + optional indent so a `# uses: ...` comment - # cannot satisfy the check. - local expected="petry-projects/\\.github/\\.github/workflows/${reusable}\\.yml@v1" - - if echo "$decoded" | grep -qE "^[[:space:]]*uses:[[:space:]]*${expected}([[:space:]]|$)"; then - continue # stub is correctly pinned to @v1 — compliant + # Accept two canonical forms — anchor to start-of-line + optional indent so + # a `# uses: ...` comment cannot satisfy the check. + # + # Preferred (SHA-pinned, satisfies SonarCloud security gate): + # uses: petry-projects/.github/.github/workflows/.yml@<40-hex-SHA> [# comment] + # Legacy (still accepted for backwards compatibility): + # uses: petry-projects/.github/.github/workflows/.yml@v1 + local base="petry-projects/\\.github/\\.github/workflows/${reusable}\\.yml" + + if echo "$decoded" | grep -qE "^[[:space:]]*uses:[[:space:]]*${base}@[0-9a-f]{40}([[:space:]]|$)"; then + continue # SHA-pinned reference to canonical reusable — compliant + fi + if echo "$decoded" | grep -qE "^[[:space:]]*uses:[[:space:]]*${base}@v1([[:space:]]|$)"; then + continue # @v1 tag reference — compliant (SHA-pinned preferred; see canonical stub) fi # Determine why it's non-compliant for a more actionable message. local why if echo "$decoded" | grep -qE "^[[:space:]]*uses:[[:space:]]*petry-projects/\\.github/\\.github/workflows/${reusable}\\.yml@"; then - why="references the reusable but is not pinned to \`@v1\` (org standard)" + why="references the reusable but is not pinned to a full commit SHA or \`@v1\` (org standard)" elif echo "$decoded" | grep -qF "petry-projects/.github/.github/workflows/${reusable}"; then why="references the reusable but the \`uses:\` line does not match the canonical stub" else @@ -747,7 +760,7 @@ check_centralized_workflow_stubs() { fi add_finding "$repo" "ci-workflows" "non-stub-$wf" "error" \ - "Centralized workflow \`$wf\` $why. Replace with the canonical stub from \`standards/workflows/${wf}\` which delegates to \`petry-projects/.github/.github/workflows/${reusable}.yml@v1\`." \ + "Centralized workflow \`$wf\` $why. Replace with the canonical stub from \`standards/workflows/${wf}\` which delegates to \`petry-projects/.github/.github/workflows/${reusable}.yml\` using a SHA-pinned reference (see the stub for the current SHA)." \ "standards/ci-standards.md#centralization-tiers" done } diff --git a/standards/ci-standards.md b/standards/ci-standards.md index d6ef37aa..7d6b6de0 100644 --- a/standards/ci-standards.md +++ b/standards/ci-standards.md @@ -525,7 +525,7 @@ On each run the workflow: **No secrets required** — uses `GITHUB_TOKEN` only. Dependabot PRs are excluded because `dependabot-rebase.yml` handles those. -**Compliance:** The compliance audit (`check_centralized_workflow_stubs`) verifies that repos adopting `auto-rebase.yml` use the canonical thin caller stub delegating to `petry-projects/.github/.github/workflows/auto-rebase-reusable.yml@v1`. +**Compliance:** The compliance audit (`check_centralized_workflow_stubs`) verifies that repos adopting `auto-rebase.yml` use the canonical thin caller stub delegating to `petry-projects/.github/.github/workflows/auto-rebase-reusable.yml` with a SHA-pinned reference (e.g. `@126c1441ee9cf040f2ce3ef0eda85d459b82f8e9 # v1`). The `@v1` mutable tag is still accepted for backwards compatibility but SHA-pinned references are preferred to satisfy SonarCloud's supply-chain security gate. ### 10. PR Review Mention (`pr-review-mention.yml`)