Skip to content

Commit 9f4c2ac

Browse files
ci(release): add npm publish workflow (Apache-2.0 core, provenance via staging)
npm provenance can't be generated locally (needs a CI OIDC id-token), and a bare `npm publish` would leak the GPL root LICENSE into the Apache-2.0 library tarball. This workflow publishes via scripts/pack-staging.sh --publish (clean Apache-2.0 staging dir) with id-token: write + NPM_TOKEN, on manual dispatch or a non-prerelease GitHub release. publishConfig already pins access:public + provenance:true. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 9a5a137 commit 9f4c2ac

1 file changed

Lines changed: 50 additions & 0 deletions

File tree

.github/workflows/publish-npm.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Publish to npm (Apache-2.0 core · provenance)
2+
3+
# Publishes the Apache-2.0 LIBRARY CORE to the npm registry WITH build provenance.
4+
#
5+
# Why this can't be done locally: npm provenance requires a CI OIDC id-token
6+
# (`Automatic provenance generation not supported for provider: null` when run
7+
# off a laptop). And the publish MUST go through scripts/pack-staging.sh so the
8+
# GPL-3.0 root LICENSE (the *application* license) never leaks into the
9+
# Apache-2.0 *library* tarball — npm force-includes a root LICENSE regardless of
10+
# the `files` allow-list (ADR-011). The staging script assembles a clean dir
11+
# whose only LICENSE is LICENSE-APACHE, then `npm publish --provenance`.
12+
#
13+
# Triggers: manual (workflow_dispatch) for the first/controlled publish, and
14+
# automatically when a NON-prerelease GitHub release is published.
15+
16+
on:
17+
workflow_dispatch:
18+
release:
19+
types: [published]
20+
21+
permissions:
22+
contents: read
23+
24+
jobs:
25+
publish:
26+
name: npm publish (staging dir · provenance)
27+
runs-on: ubuntu-latest
28+
# On the release trigger, skip prereleases (e.g. v2.0.0-beta → has a '-'),
29+
# which must never go to the `latest` dist-tag. Manual dispatch always runs.
30+
if: ${{ github.event_name == 'workflow_dispatch' || !contains(github.event.release.tag_name, '-') }}
31+
permissions:
32+
contents: read
33+
id-token: write # REQUIRED for npm build provenance (OIDC)
34+
steps:
35+
- uses: actions/checkout@v6
36+
- uses: actions/setup-node@v4
37+
with:
38+
node-version: "22"
39+
cache: "npm"
40+
registry-url: "https://registry.npmjs.org"
41+
- run: npm ci
42+
# pack-staging.sh --publish: build → assemble Apache-2.0-only staging dir
43+
# (no GPL LICENSE leak) → strip lifecycle scripts/devDeps → publish with
44+
# provenance + public access. publishConfig in package.json already pins
45+
# access:public + provenance:true; provenance succeeds here because the job
46+
# carries the OIDC id-token.
47+
- name: Publish Apache-2.0 core to npm (with provenance)
48+
run: bash scripts/pack-staging.sh --publish
49+
env:
50+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

0 commit comments

Comments
 (0)