Skip to content

Commit fefdda5

Browse files
authored
chore(ci): harden GitHub Actions (#22)
## What does this PR do? Hardens our reusable workflows in response to GHSA-g7cv-rxg3-hmpx (the 2026-05-11 `@tanstack/*` npm supply-chain compromise). - Adds `permissions: {}` default-deny at workflow level on all 10 workflow files - Splits `publish.yml` into separate `build` and `publish` jobs so `id-token: write` (npm trusted-publisher OIDC) is scoped to a job that never executes project code; publish job uses `pnpm install --ignore-scripts` - Pins `actions/upload-artifact` (`043fb46d...`, v7.0.1) and `actions/download-artifact` (`3e5f45b2...`, v8.0.1) — new actions introduced by the publish.yml split - Re-pins `actions/checkout`, `pnpm/action-setup`, `actions/setup-node` in the new build job to match the SHA pins already used elsewhere in the file - Routes workflow inputs and event context through `env:` instead of `${{ }}` shell interpolation in `preview.yml`, `detect-agent.yml`, and `detect-agent-backfill.yml`; quotes `"$VAR"` to prevent word-splitting and glob expansion on label/glob inputs - Adds `if: github.repository_owner == 'bombshell-dev'` owner gate to `detect-agent.yml` and `detect-agent-backfill.yml` (other workflows already had it) - Adds `.github/dependabot.yml` for automated weekly SHA bumps on GitHub Actions, grouped into a single PR ## Type of change <!-- Check one. --> - [ ] Bug fix - [ ] Feature - [ ] Refactor (no behavior change) - [ ] Documentation - [ ] Performance improvement - [ ] Tests - [x] Chore (dependencies, CI, tooling) ## AI-generated code disclosure <!-- If any part of this PR was generated by AI tools (Copilot, Claude, GPT, Cursor, etc.), check the box. This is fine — we just need to know so reviewers can pay extra attention to edge cases. --> - [x] This PR includes AI-generated code
1 parent 9e12379 commit fefdda5

11 files changed

Lines changed: 86 additions & 18 deletions

.github/dependabot.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: github-actions
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
groups:
8+
actions:
9+
patterns:
10+
- "*"

.github/workflows/add-issue-to-project.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ on:
1010
description: 'The GitHub App Private Key for authenticating with the GitHub API'
1111
required: true
1212

13+
permissions: {}
14+
1315
jobs:
1416
issue:
1517
runs-on: ubuntu-latest

.github/workflows/build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ on:
55
push:
66
branches: [main]
77

8+
permissions: {}
9+
810
jobs:
911
build:
1012
runs-on: ubuntu-latest

.github/workflows/detect-agent-backfill.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ on:
1616
type: boolean
1717
required: false
1818

19+
permissions: {}
20+
1921
jobs:
2022
backfill:
23+
if: github.repository_owner == 'bombshell-dev'
2124
runs-on: ubuntu-latest
2225
permissions:
2326
issues: write
@@ -39,8 +42,7 @@ jobs:
3942
env:
4043
GH_TOKEN: ${{ github.token }}
4144
LABEL: ${{ inputs.LABEL }}
42-
REPO: ${{ github.repository }}
43-
run: gh label create $LABEL --repo $REPO --color "D93F0B" --description "PR author detected as automated" --force
45+
run: gh label create "$LABEL" --repo "$GITHUB_REPOSITORY" --color "D93F0B" --description "PR author detected as automated" --force
4446

4547
- name: Scan open PRs
4648
env:

.github/workflows/detect-agent.yml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ on:
2626
description: "Whether the PR author is classified as automated (true/false)"
2727
value: ${{ jobs.detect.outputs.is_agent }}
2828

29+
permissions: {}
30+
2931
jobs:
3032
detect:
33+
if: github.repository_owner == 'bombshell-dev'
3134
runs-on: ubuntu-latest
3235
outputs:
3336
classification: ${{ steps.analyze.outputs.CLASSIFICATION }}
@@ -59,7 +62,7 @@ jobs:
5962
fi
6063
# Check org membership
6164
if [[ "$BYPASS_MEMBERS" == "true" ]]; then
62-
if gh api repos/${{ github.repository }}/collaborators/$PR_AUTHOR --silent 2>/dev/null; then
65+
if gh api "repos/$GITHUB_REPOSITORY/collaborators/$PR_AUTHOR" --silent 2>/dev/null; then
6366
echo "skip=true" >> "$GITHUB_OUTPUT"
6467
fi
6568
fi
@@ -69,11 +72,10 @@ jobs:
6972
env:
7073
GH_TOKEN: ${{ github.token }}
7174
LABEL: ${{ inputs.LABEL }}
72-
REPO: ${{ github.repository }}
7375
PR_NUMBER: ${{ github.event.pull_request.number }}
7476
run: |
75-
gh label create $LABEL --repo $REPO --color "D93F0B" --description "PR author detected as automated" --force
76-
gh pr edit $PR_NUMBER --repo $REPO --add-label $LABEL
77+
gh label create "$LABEL" --repo "$GITHUB_REPOSITORY" --color "D93F0B" --description "PR author detected as automated" --force
78+
gh pr edit "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --add-label "$LABEL"
7779
7880
- name: Checkout
7981
if: steps.cache.outputs.cache-hit != 'true' && steps.bypass.outputs.is_bot != 'true' && steps.bypass.outputs.skip != 'true'
@@ -106,24 +108,23 @@ jobs:
106108
env:
107109
GH_TOKEN: ${{ github.token }}
108110
LABEL: ${{ inputs.LABEL }}
109-
REPO: ${{ github.repository }}
110-
run: gh label create $LABEL --repo $REPO --color "D93F0B" --description "PR author detected as automated" --force
111+
run: gh label create "$LABEL" --repo "$GITHUB_REPOSITORY" --color "D93F0B" --description "PR author detected as automated" --force
111112

112113
- name: Add label
113114
if: steps.cache.outputs.cache-hit != 'true' && steps.bypass.outputs.is_bot != 'true' && steps.bypass.outputs.skip != 'true' && steps.analyze.outputs.IS_AGENT == 'true'
114115
env:
115116
GH_TOKEN: ${{ github.token }}
116-
PR_NUMBER: ${{ github.event.pull_request.number }}
117-
REPO: ${{ github.repository }}
118117
LABEL: ${{ inputs.LABEL }}
119-
run: gh pr edit $PR_NUMBER --repo $REPO --add-label $LABEL
118+
PR_NUMBER: ${{ github.event.pull_request.number }}
119+
run: gh pr edit "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --add-label "$LABEL"
120120

121121
- name: Comment on PR
122122
if: steps.cache.outputs.cache-hit != 'true' && steps.bypass.outputs.is_bot != 'true' && steps.bypass.outputs.skip != 'true' && steps.analyze.outputs.IS_AGENT == 'true'
123123
env:
124124
GH_TOKEN: ${{ github.token }}
125125
COMMENT_BODY: ${{ steps.analyze.outputs.COMMENT }}
126-
run: gh pr comment ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --body "$COMMENT_BODY"
126+
PR_NUMBER: ${{ github.event.pull_request.number }}
127+
run: gh pr comment "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --body "$COMMENT_BODY"
127128

128129
- name: Create scan marker
129130
if: steps.cache.outputs.cache-hit != 'true' && steps.bypass.outputs.is_bot != 'true' && steps.bypass.outputs.skip != 'true'

.github/workflows/format.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ on:
1616
description: "The GitHub App Private Key for authenticating with the GitHub API"
1717
required: true
1818

19+
permissions: {}
20+
1921
jobs:
2022
format:
2123
if: github.repository_owner == 'bombshell-dev'

.github/workflows/mergebot.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ on:
4040
type: string
4141
required: false
4242

43+
permissions: {}
44+
4345
jobs:
4446
post-message:
4547
runs-on: ubuntu-latest

.github/workflows/move-issue-to-backlog.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ on:
1010
description: 'The GitHub App Private Key for authenticating with the GitHub API'
1111
required: true
1212

13+
permissions: {}
14+
1315
jobs:
1416
issue:
1517
runs-on: ubuntu-latest

.github/workflows/preview.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ on:
1313
required: false
1414
type: string
1515

16+
permissions: {}
17+
1618
jobs:
1719
preview:
1820
if: github.repository_owner == 'bombshell-dev'
@@ -45,4 +47,4 @@ jobs:
4547
env:
4648
TEMPLATE_GLOB: ${{ inputs.template }}
4749
PUBLISH_GLOB: ${{ inputs.publish }}
48-
run: pnpx pkg-pr-new publish $PUBLISH_GLOB --template $TEMPLATE_GLOB
50+
run: pnpx pkg-pr-new publish "$PUBLISH_GLOB" --template "$TEMPLATE_GLOB"

.github/workflows/publish.yml

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,54 @@ on:
1010
description: "The GitHub App Private Key for authenticating with the GitHub API"
1111
required: true
1212

13+
permissions: {}
14+
1315
jobs:
16+
build:
17+
if: github.repository_owner == 'bombshell-dev'
18+
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
steps:
22+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
23+
24+
- name: Setup PNPM
25+
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
26+
27+
- name: Setup Node
28+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
29+
with:
30+
node-version: 22
31+
cache: "pnpm"
32+
33+
- name: Update NPM
34+
# WORKAROUND: The latest version of npm breaks itself whilst installing itself
35+
# see https://github.com/npm/cli/issues/9151
36+
run: npm install -g npm@~11.10.0
37+
38+
- name: Install dependencies
39+
run: pnpm install
40+
41+
- name: Build
42+
run: pnpm run build
43+
44+
- name: Upload build artifacts
45+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
46+
with:
47+
name: build-output
48+
path: |
49+
packages/*/dist
50+
if-no-files-found: ignore
51+
retention-days: 1
52+
1453
publish:
54+
needs: build
1555
if: github.repository_owner == 'bombshell-dev'
1656
runs-on: ubuntu-latest
1757
permissions:
1858
contents: write
1959
pull-requests: write
2060
id-token: write
21-
2261
steps:
2362
- name: Generate a token
2463
id: bot-token
@@ -52,11 +91,13 @@ jobs:
5291
# see https://github.com/npm/cli/issues/9151
5392
run: npm install -g npm@~11.10.0
5493

55-
- name: Install dependencies
56-
run: pnpm install
94+
- name: Install dependencies (no scripts)
95+
run: pnpm install --ignore-scripts
5796

58-
- name: Build
59-
run: pnpm run build
97+
- name: Download build artifacts
98+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
99+
with:
100+
name: build-output
60101

61102
- name: Create Release Pull Request or Publish to npm
62103
id: changesets

0 commit comments

Comments
 (0)