Skip to content

Commit 571ca9e

Browse files
committed
ci: harden npm release pipeline
Publish job now stages the release (npm stage publish) for manual 2FA approval and installs no dependencies; build moved to a separate job. Least-privilege permissions, persist-credentials off, zizmor linting, 3-day dependency cooldown.
1 parent b2d5245 commit 571ca9e

10 files changed

Lines changed: 132 additions & 25 deletions

File tree

.github/actions/prepare-runner/action.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ runs:
44
using: composite
55
steps:
66
- name: Install Node.js
7-
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
7+
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
88
with:
99
node-version: 24
1010
- name: Enable Corepack and pnpm
@@ -13,10 +13,10 @@ runs:
1313
corepack enable
1414
corepack install
1515
- name: Enable pnpm cache
16-
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
16+
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
1717
with:
1818
node-version: 24
1919
cache: pnpm
2020
- name: Install dependencies
2121
shell: bash
22-
run: pnpm install --frozen-lockfile
22+
run: pnpm install --frozen-lockfile --ignore-scripts
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Lint CI workflows
2+
on:
3+
push:
4+
branches: ["main"]
5+
pull_request:
6+
branches: ["**"]
7+
concurrency:
8+
group: ${{ github.workflow }}-${{ github.ref }}
9+
cancel-in-progress: true
10+
11+
jobs:
12+
zizmor:
13+
runs-on: ubuntu-latest
14+
permissions:
15+
contents: read
16+
actions: read
17+
steps:
18+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
19+
with:
20+
persist-credentials: false
21+
- name: Run zizmor
22+
uses: zizmorcore/zizmor-action@6599ee8b7a49aef6a770f63d261d214911a7ce02 # v0.6.0
23+
with:
24+
advanced-security: false

.github/workflows/deploy-docs.yml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,19 @@ on:
55
branches: [main, docs]
66
workflow_dispatch:
77

8-
permissions:
9-
contents: read
10-
pages: write
11-
id-token: write
12-
138
concurrency:
149
group: pages
1510
cancel-in-progress: true
1611

1712
jobs:
1813
build:
1914
runs-on: ubuntu-latest
15+
permissions:
16+
contents: read
2017
steps:
21-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
18+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
19+
with:
20+
persist-credentials: false
2221

2322
- uses: ./.github/actions/prepare-runner
2423

@@ -32,6 +31,10 @@ jobs:
3231
deploy:
3332
needs: build
3433
runs-on: ubuntu-latest
34+
permissions:
35+
contents: read
36+
pages: write
37+
id-token: write
3538
environment:
3639
name: github-pages
3740
url: ${{ steps.deployment.outputs.page_url }}

.github/workflows/lint.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ concurrency:
1010
jobs:
1111
lint:
1212
runs-on: ubuntu-latest
13+
permissions:
14+
contents: read
1315
env:
1416
CI_RUN: true
1517
steps:
16-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
18+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
19+
with:
20+
persist-credentials: false
1721
- uses: ./.github/actions/prepare-runner
1822
- run: pnpm lint

.github/workflows/pkg-check.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@ concurrency:
1010
jobs:
1111
pkg-check:
1212
runs-on: ubuntu-latest
13+
permissions:
14+
contents: read
1315
env:
1416
CI_RUN: true
1517
steps:
16-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
18+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
19+
with:
20+
persist-credentials: false
1721
- uses: ./.github/actions/prepare-runner
1822
- run: pnpm --filter nanotags run build
1923
- run: pnpm --filter nanotags exec publint

.github/workflows/publish.yml

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,77 @@ on:
44
push:
55
tags:
66
- "[0-9]+.[0-9]+.[0-9]+"
7-
env:
8-
CI_RUN: true
7+
98
jobs:
10-
publish-npm:
9+
test:
1110
runs-on: ubuntu-latest
1211
permissions:
1312
contents: read
14-
id-token: write
13+
env:
14+
CI_RUN: true
1515
steps:
16-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
16+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
17+
with:
18+
persist-credentials: false
1719
- uses: ./.github/actions/prepare-runner
20+
- run: pnpm test
21+
22+
build: # Separate job so build-time dependencies can't publish
23+
runs-on: ubuntu-latest
24+
permissions:
25+
contents: read
26+
env:
27+
CI_RUN: true
28+
steps:
29+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
30+
with:
31+
persist-credentials: false
32+
- name: Install Node.js
33+
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
34+
with:
35+
node-version: 24
36+
package-manager-cache: false # Slower, but no cache poisoning risk
37+
- name: Enable Corepack and pnpm
38+
shell: bash
39+
run: |
40+
corepack enable
41+
corepack install
42+
- run: pnpm install --frozen-lockfile --ignore-scripts
1843
- run: pnpm --filter nanotags build
1944
- run: cp README.md LICENSE.md packages/nanotags/
20-
- run: pnpm --filter nanotags publish --no-git-checks --provenance
45+
- name: Upload build artifacts
46+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
47+
with:
48+
name: build-artifacts
49+
path: |
50+
packages/nanotags/dist/
51+
packages/nanotags/README.md
52+
packages/nanotags/LICENSE.md
53+
if-no-files-found: error
54+
retention-days: 1
55+
56+
publish: # The critical job: no dependencies installed at all
57+
runs-on: ubuntu-latest
58+
needs:
59+
- test
60+
- build
61+
permissions:
62+
contents: read
63+
id-token: write
64+
steps:
65+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
66+
with:
67+
persist-credentials: false
68+
- name: Download build artifacts
69+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
70+
with:
71+
name: build-artifacts
72+
path: packages/nanotags
73+
- name: Install Node.js
74+
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
75+
with:
76+
node-version: 26 # Bundles npm 11.17+, which has `npm stage`
77+
package-manager-cache: false
78+
- name: Stage npm release for manual approval
79+
working-directory: packages/nanotags
80+
run: npm stage publish --ignore-scripts

.github/workflows/size-limit.yml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,27 @@ concurrency:
77
group: ${{ github.workflow }}-${{ github.ref }}
88
cancel-in-progress: true
99

10-
permissions:
11-
pull-requests: write
12-
1310
jobs:
1411
sizecheck:
1512
runs-on: ubuntu-latest
13+
permissions:
14+
contents: read
15+
pull-requests: write
1616
env:
1717
CI_RUN: true
1818
CI_JOB_NUMBER: 1
1919
steps:
20-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
21-
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
20+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
21+
with:
22+
persist-credentials: false
23+
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
2224
with:
2325
node-version: 24
26+
package-manager-cache: false
2427
- shell: bash
2528
run: |
2629
corepack enable
27-
corepack prepare pnpm@latest --activate
30+
corepack install
2831
- uses: andresz1/size-limit-action@94bc357df29c36c8f8d50ea497c3e225c3c95d1d # v1.8.0
2932
with:
3033
github_token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/test.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ concurrency:
1010
jobs:
1111
test:
1212
runs-on: ubuntu-latest
13+
permissions:
14+
contents: read
1315
env:
1416
CI_RUN: true
1517
steps:
16-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
18+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
19+
with:
20+
persist-credentials: false
1721
- uses: ./.github/actions/prepare-runner
1822
- run: pnpm test

.github/workflows/typecheck.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ concurrency:
1010
jobs:
1111
typecheck:
1212
runs-on: ubuntu-latest
13+
permissions:
14+
contents: read
1315
env:
1416
CI_RUN: true
1517
steps:
16-
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
18+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
19+
with:
20+
persist-credentials: false
1721
- uses: ./.github/actions/prepare-runner
1822
- run: pnpm typecheck

pnpm-workspace.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
packages:
22
- "packages/*"
33
- "apps/*"
4+
minimumReleaseAge: 4320

0 commit comments

Comments
 (0)