From 41db43cc9f7272c957b2cb1cf0d4d05062b95bb4 Mon Sep 17 00:00:00 2001 From: Elisa Date: Tue, 19 May 2026 22:14:16 +0200 Subject: [PATCH 1/2] feat: pin GitHub Actions to SHA digests and add pin-check workflow --- .github/workflows/conventional-commits.yml | 6 ++-- .github/workflows/issues-add-to-project.yml | 2 +- .github/workflows/release-drafter.yaml | 2 +- .github/workflows/update-action-pins.yml | 25 +++++++++++++ common.mk | 39 ++++++++++++++++++++- example/renovate.json | 1 + 6 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/update-action-pins.yml diff --git a/.github/workflows/conventional-commits.yml b/.github/workflows/conventional-commits.yml index cc9c8dc..cb64826 100644 --- a/.github/workflows/conventional-commits.yml +++ b/.github/workflows/conventional-commits.yml @@ -13,7 +13,7 @@ jobs: name: PR Title runs-on: ubuntu-latest steps: - - uses: amannn/action-semantic-pull-request@v5 + - uses: amannn/action-semantic-pull-request@e32d7e603df1aa1ba07e981f2a23455dee596825 # v5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -33,9 +33,9 @@ jobs: name: Commit Messages runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: fetch-depth: 0 - - uses: wagoid/commitlint-github-action@v6 + - uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6 with: configFile: .commitlintrc.yml diff --git a/.github/workflows/issues-add-to-project.yml b/.github/workflows/issues-add-to-project.yml index 494eb52..4d5b4e2 100644 --- a/.github/workflows/issues-add-to-project.yml +++ b/.github/workflows/issues-add-to-project.yml @@ -13,7 +13,7 @@ jobs: name: Add issue to project runs-on: ubuntu-latest steps: - - uses: actions/add-to-project@v1.0.2 + - uses: actions/add-to-project@244f685bbc3b7adfa8466e08b698b5577571133e # v1.0.2 with: project-url: https://github.com/orgs/opendefensecloud/projects/3 github-token: ${{ secrets.ADD_TO_PROJECT_PAT }} diff --git a/.github/workflows/release-drafter.yaml b/.github/workflows/release-drafter.yaml index bdf5126..922e5f3 100644 --- a/.github/workflows/release-drafter.yaml +++ b/.github/workflows/release-drafter.yaml @@ -33,7 +33,7 @@ jobs: # echo "GHE_HOST=${GITHUB_SERVER_URL##https:\/\/}" >> $GITHUB_ENV # Drafts your next Release notes as Pull Requests are merged into "master" - - uses: release-drafter/release-drafter@v7 + - uses: release-drafter/release-drafter@c2e2804cc59f45f57076a99af580d0fedb697927 # v7 # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml # with: # config-name: my-config.yml diff --git a/.github/workflows/update-action-pins.yml b/.github/workflows/update-action-pins.yml new file mode 100644 index 0000000..a380f6b --- /dev/null +++ b/.github/workflows/update-action-pins.yml @@ -0,0 +1,25 @@ +name: Update Action Pins + +on: + pull_request: + paths: + - ".github/workflows/**" + +jobs: + check-pins: + name: Check action pins + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - name: Verify all actions are pinned to a SHA + run: | + unpinned=$(grep -rE '^\s+(- )?uses: ' .github/workflows/ \ + | grep -vE '^\s+(- )?uses: \.\/' \ + | grep -vE '@[0-9a-f]{40}($|\s)' || true) + if [[ -n "$unpinned" ]]; then + echo "::error::Found unpinned GitHub Actions (must use SHA digest, not tag):" + echo "$unpinned" + echo "" + echo "Run 'GITHUB_TOKEN=\$(gh auth token) update-action-pins .github/workflows/' to fix." + exit 1 + fi diff --git a/common.mk b/common.mk index e42e7a8..bb297c0 100644 --- a/common.mk +++ b/common.mk @@ -99,7 +99,8 @@ REPO_RULESET := { \ .PHONY: repo-settings repo-settings: ## Reconcile GitHub repository settings (labels, merge strategy, branch protection, security) - @REPO=$$($(GH) repo view --json nameWithOwner -q .nameWithOwner) || { echo "error: not a GitHub repository or gh not authenticated"; exit 1; }; \ + @$(GH) auth status >/dev/null 2>&1 || { echo "error: gh is not authenticated; run 'gh auth login'"; exit 1; }; \ + REPO=$$($(GH) repo view --json nameWithOwner -q .nameWithOwner) || { echo "error: not a GitHub repository"; exit 1; }; \ echo "Reconciling settings for $$REPO..."; \ \ echo " Syncing labels..."; \ @@ -130,8 +131,44 @@ repo-settings: ## Reconcile GitHub repository settings (labels, merge strategy, echo " Created new ruleset"; \ fi; \ \ + echo " Installing update-action-pins workflow..."; \ + mkdir -p .github/workflows; \ + printf '%s\n' \ + 'name: Update Action Pins' \ + '' \ + 'on:' \ + ' pull_request:' \ + ' paths:' \ + ' - ".github/workflows/**"' \ + '' \ + 'jobs:' \ + ' check-pins:' \ + ' name: Check action pins' \ + ' runs-on: ubuntu-latest' \ + ' steps:' \ + ' - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4' \ + ' - name: Verify all actions are pinned to a SHA' \ + ' run: |' \ + ' unpinned=$$(grep -rE ''^\s+(- )?uses: '' .github/workflows/ \' \ + ' | grep -vE ''^\s+(- )?uses: \.\/'' \' \ + ' | grep -vE ''@[0-9a-f]{40}($$|\s)'' || true)' \ + ' if [[ -n "$$unpinned" ]]; then' \ + ' echo "::error::Found unpinned GitHub Actions (must use SHA digest, not tag):"' \ + ' echo "$$unpinned"' \ + ' echo ""' \ + ' echo "Run '"'"'GITHUB_TOKEN=$$(gh auth token) update-action-pins .github/workflows/'"'"' to fix."' \ + ' exit 1' \ + ' fi' \ + > .github/workflows/update-action-pins.yml; \ + echo " Wrote .github/workflows/update-action-pins.yml"; \ + \ echo "Done." +.PHONY: update-action-pins +update-action-pins: ## Update GitHub Action pins to their latest commit SHA + @$(GH) auth status >/dev/null 2>&1 || { echo "error: gh is not authenticated; run 'gh auth login'"; exit 1; }; \ + GITHUB_TOKEN=$$(gh auth token) update-action-pins .github/workflows/ + ##@ General # The help target prints out all targets with their descriptions organized diff --git a/example/renovate.json b/example/renovate.json index 4f9adc6..4ae8040 100644 --- a/example/renovate.json +++ b/example/renovate.json @@ -3,6 +3,7 @@ "extends": [ "config:recommended" ], + "pinDigests": true, "customManagers": [ { "customType": "regex", From 86289cddab38b80a125da4822555914ac9948873 Mon Sep 17 00:00:00 2001 From: Elisa Date: Thu, 21 May 2026 10:11:28 +0200 Subject: [PATCH 2/2] refactor: move pinning workflow from inline to file --- .github/workflows/update-action-pins.yml | 2 ++ common.mk | 31 +++--------------------- 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/.github/workflows/update-action-pins.yml b/.github/workflows/update-action-pins.yml index a380f6b..7531952 100644 --- a/.github/workflows/update-action-pins.yml +++ b/.github/workflows/update-action-pins.yml @@ -11,6 +11,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Verify all actions are pinned to a SHA run: | unpinned=$(grep -rE '^\s+(- )?uses: ' .github/workflows/ \ diff --git a/common.mk b/common.mk index bb297c0..7fed409 100644 --- a/common.mk +++ b/common.mk @@ -133,33 +133,10 @@ repo-settings: ## Reconcile GitHub repository settings (labels, merge strategy, \ echo " Installing update-action-pins workflow..."; \ mkdir -p .github/workflows; \ - printf '%s\n' \ - 'name: Update Action Pins' \ - '' \ - 'on:' \ - ' pull_request:' \ - ' paths:' \ - ' - ".github/workflows/**"' \ - '' \ - 'jobs:' \ - ' check-pins:' \ - ' name: Check action pins' \ - ' runs-on: ubuntu-latest' \ - ' steps:' \ - ' - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4' \ - ' - name: Verify all actions are pinned to a SHA' \ - ' run: |' \ - ' unpinned=$$(grep -rE ''^\s+(- )?uses: '' .github/workflows/ \' \ - ' | grep -vE ''^\s+(- )?uses: \.\/'' \' \ - ' | grep -vE ''@[0-9a-f]{40}($$|\s)'' || true)' \ - ' if [[ -n "$$unpinned" ]]; then' \ - ' echo "::error::Found unpinned GitHub Actions (must use SHA digest, not tag):"' \ - ' echo "$$unpinned"' \ - ' echo ""' \ - ' echo "Run '"'"'GITHUB_TOKEN=$$(gh auth token) update-action-pins .github/workflows/'"'"' to fix."' \ - ' exit 1' \ - ' fi' \ - > .github/workflows/update-action-pins.yml; \ + _dev_kit_ver=$${DEV_KIT_VERSION:-main}; \ + curl --fail -sSL \ + "https://raw.githubusercontent.com/opendefensecloud/dev-kit/$$_dev_kit_ver/.github/workflows/update-action-pins.yml" \ + -o .github/workflows/update-action-pins.yml; \ echo " Wrote .github/workflows/update-action-pins.yml"; \ \ echo "Done."