Skip to content

Commit 08e9b1b

Browse files
authored
chore: SHA-pin all actions + gate Dependabot auto-merge on tests (#22)
* Harden CI: SHA-pin all actions, gate Dependabot auto-merge on tests Supply-chain consistency pass to match eloquent-publishing (PR #37) and markdown (PR #21). - Pin all 11 GitHub Actions `uses:` refs to full-length commit SHAs (tag kept as trailing comment); SHAs resolved via the GitHub API and verified identical to the sibling repos' pins. - Rewrite dependabot-auto-merge to wait for the test suite to pass on the PR head SHA before merging (minor/patch only; majors stay manual). Deliberately no branch protection: fix-php-code-style-issues.yml and update-changelog.yml push to main via git-auto-commit-action, which required checks on main would break. No source changes. * auto-merge: pin merge to validated head SHA (--match-head-commit) Closes a head-SHA race: Dependabot rebases PRs, so polling run conclusion for HEAD_SHA then merging current HEAD could merge an untested head if a rebase landed in between. --match-head-commit refuses the merge unless HEAD still equals the SHA whose test run we validated.
1 parent d06f3a5 commit 08e9b1b

5 files changed

Lines changed: 51 additions & 27 deletions

File tree

.github/workflows/dependabot-auto-merge.yml

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,56 @@ name: dependabot-auto-merge
22
on: pull_request_target
33

44
permissions:
5-
pull-requests: write
65
contents: write
6+
pull-requests: write
77

88
jobs:
99
dependabot:
1010
runs-on: ubuntu-latest
11-
timeout-minutes: 5
11+
timeout-minutes: 30
1212
if: ${{ github.actor == 'dependabot[bot]' }}
1313
steps:
14-
1514
- name: Dependabot metadata
1615
id: metadata
17-
uses: dependabot/fetch-metadata@v3.1.0
16+
uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0
1817
with:
1918
github-token: "${{ secrets.GITHUB_TOKEN }}"
2019

21-
- name: Auto-merge Dependabot PRs for semver-minor updates
22-
if: ${{steps.metadata.outputs.update-type == 'version-update:semver-minor'}}
23-
run: gh pr merge --auto --merge "$PR_URL"
24-
env:
25-
PR_URL: ${{github.event.pull_request.html_url}}
26-
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
27-
28-
- name: Auto-merge Dependabot PRs for semver-patch updates
29-
if: ${{steps.metadata.outputs.update-type == 'version-update:semver-patch'}}
30-
run: gh pr merge --auto --merge "$PR_URL"
20+
# Gate auto-merge on the test suite passing, then merge.
21+
#
22+
# We deliberately do NOT rely on branch protection / required status
23+
# checks: fix-php-code-style-issues.yml and update-changelog.yml push
24+
# directly to main via git-auto-commit-action, and required checks on
25+
# main would block those pushes. Instead we wait for the test workflow
26+
# run on this PR's head SHA to finish, and only merge if it succeeded.
27+
# Only semver-minor and semver-patch updates are auto-merged; majors
28+
# require manual review.
29+
- name: Auto-merge minor/patch updates after tests pass
30+
if: ${{ contains(fromJSON('["version-update:semver-minor", "version-update:semver-patch"]'), steps.metadata.outputs.update-type) }}
3131
env:
32-
PR_URL: ${{github.event.pull_request.html_url}}
33-
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
32+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33+
REPO: ${{ github.repository }}
34+
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
35+
PR_URL: ${{ github.event.pull_request.html_url }}
36+
run: |
37+
set -euo pipefail
38+
ok=false
39+
for _ in $(seq 1 40); do
40+
run=$(gh run list --repo "$REPO" --workflow run-tests.yml --limit 30 \
41+
--json headSha,status,conclusion \
42+
--jq "[.[] | select(.headSha == \"$HEAD_SHA\")][0] // {}")
43+
status=$(printf '%s' "$run" | jq -r '.status // "queued"')
44+
if [ "$status" = "completed" ]; then
45+
[ "$(printf '%s' "$run" | jq -r '.conclusion')" = "success" ] && ok=true
46+
break
47+
fi
48+
echo "waiting for test suite (status=${status})…"
49+
sleep 30
50+
done
51+
if [ "$ok" != "true" ]; then
52+
echo "::error::Test suite did not pass for ${HEAD_SHA}; not auto-merging."
53+
exit 1
54+
fi
55+
# --match-head-commit refuses the merge if Dependabot rebased the PR
56+
# after we validated HEAD_SHA, so we never merge an untested head.
57+
gh pr merge --merge --match-head-commit "$HEAD_SHA" "$PR_URL"

.github/workflows/fix-php-code-style-issues.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ jobs:
1515

1616
steps:
1717
- name: Checkout code
18-
uses: actions/checkout@v6
18+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
1919
with:
2020
ref: ${{ github.head_ref }}
2121

2222
- name: Fix PHP code style issues
23-
uses: aglipanci/laravel-pint-action@2.6
23+
uses: aglipanci/laravel-pint-action@36de00d5f5a8a4e12d443e01671daa12a18f4c79 # 2.6
2424

2525
- name: Commit changes
26-
uses: stefanzweifel/git-auto-commit-action@v7
26+
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7
2727
with:
2828
commit_message: Fix styling

.github/workflows/phpstan.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@ jobs:
1616

1717
steps:
1818
- name: Checkout code
19-
uses: actions/checkout@v6
19+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
2020
with:
2121
ref: ${{ github.head_ref }}
2222

2323
- name: Setup PHP
24-
uses: shivammathur/setup-php@v2
24+
uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # v2
2525
with:
2626
php-version: '8.2'
2727
coverage: none
2828

2929
- name: Install composer dependencies
30-
uses: ramsey/composer-install@v4
30+
uses: ramsey/composer-install@5c2bcf28d7b060ef3c601d7b476d5430a7b46c27 # v4
3131

3232
- name: Run PHPStan
3333
run: vendor/bin/phpstan --error-format=github

.github/workflows/run-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ jobs:
2626

2727
steps:
2828
- name: Checkout code
29-
uses: actions/checkout@v6
29+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
3030

3131
- name: Setup PHP
32-
uses: shivammathur/setup-php@v2
32+
uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # v2
3333
with:
3434
php-version: ${{ matrix.php }}
3535
extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo

.github/workflows/update-changelog.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@ jobs:
1414

1515
steps:
1616
- name: Checkout code
17-
uses: actions/checkout@v6
17+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
1818
with:
1919
ref: main
2020

2121
- name: Update Changelog
22-
uses: stefanzweifel/changelog-updater-action@v1
22+
uses: stefanzweifel/changelog-updater-action@a938690fad7edf25368f37e43a1ed1b34303eb36 # v1
2323
with:
2424
latest-version: ${{ github.event.release.name }}
2525
release-notes: ${{ github.event.release.body }}
2626

2727
- name: Commit updated CHANGELOG
28-
uses: stefanzweifel/git-auto-commit-action@v7
28+
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7
2929
with:
3030
branch: main
3131
commit_message: Update CHANGELOG

0 commit comments

Comments
 (0)