mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-14 02:42:24 +03:00
feat(ci): publish to npm through Trusted Publishing (OIDC) by default (#11931)
* feat(ci): publish to npm through Trusted Publishing (OIDC) by default npm rejects provenance from self-hosted runners and is retiring tokens that bypass 2FA; v3.8.49 answered with staged publishing (WS1.3) so a leaked token could never publish alone — at the price of a manual `npm stage approve` per release. Trusted Publishing gives the same guarantee with no token at all: the github-hosted stage-npm job exchanges GitHub's id-token for a credential scoped to that run, provenance included, and the flow is automatic again as it was up to v3.8.48. publish_mode gains `auto` (the default, also the path for the release event); `staged` now runs only when asked for; `direct` stays as the emergency token fallback. Until the owner registers the Trusted Publisher on npmjs.com (diegosouzapw/OmniRoute, workflow npm-publish.yml) the automatic step fails with ENEEDAUTH and either other mode can be dispatched — documented in docs/ops/RELEASE_CHECKLIST.md. * docs(release): date the checklist for the Trusted Publishing change and drop the env-var claim check-deprecated-versions flags a touched doc whose header still says 2026-06-28 / v3.8.40; the fabricated-docs gate read the backticked NPM_TOKEN as an environment variable the code never reads (it is a repository secret).
This commit is contained in:
committed by
GitHub
parent
f907b5ea8e
commit
226538fa27
33
.github/workflows/npm-publish.yml
vendored
33
.github/workflows/npm-publish.yml
vendored
@@ -23,11 +23,12 @@ on:
|
||||
- next
|
||||
- historic
|
||||
publish_mode:
|
||||
description: "staged = npm stage publish (owner approves with 2FA after the staged boot-verify); direct = legacy immediate publish (emergency fallback only)"
|
||||
description: "auto = publish through npm Trusted Publishing (OIDC, no token, no 2FA prompt — the default); staged = npm stage publish (owner approves with 2FA); direct = legacy token publish (emergency fallback only)"
|
||||
required: false
|
||||
default: "staged"
|
||||
default: "auto"
|
||||
type: choice
|
||||
options:
|
||||
- auto
|
||||
- staged
|
||||
- direct
|
||||
workflow_call:
|
||||
@@ -407,8 +408,34 @@ jobs:
|
||||
fi
|
||||
npm --version
|
||||
|
||||
# Trusted Publishing (OIDC): npm mints a short-lived credential for THIS run from
|
||||
# GitHub's id-token — no NPM_TOKEN secret, no 2FA prompt, provenance included, and
|
||||
# it is the bypass npm sanctions now that tokens which skip 2FA are being retired
|
||||
# (gh.io/npm-gat-bypass2fa-deprecation). Requires the package's Trusted Publisher to
|
||||
# be configured on npmjs.com (owner: diegosouzapw/OmniRoute, workflow
|
||||
# npm-publish.yml) and a github-hosted runner — which is why this job exists.
|
||||
# Without that configuration `npm publish` fails with ENEEDAUTH: re-dispatch with
|
||||
# publish_mode=staged or direct. Automatic publishing was the flow up to v3.8.48;
|
||||
# v3.8.49 moved to staged (WS1.3) to keep a leaked token from publishing alone —
|
||||
# OIDC gives the same guarantee without the manual approve.
|
||||
- name: Publish to npm (Trusted Publishing / OIDC — automatic)
|
||||
if: github.event_name != 'workflow_dispatch' || inputs.publish_mode == 'auto'
|
||||
env:
|
||||
VERSION: ${{ needs.publish.outputs.version }}
|
||||
TAG: ${{ needs.publish.outputs.tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TARBALL="omniroute-${VERSION}.tgz"
|
||||
test -f "$TARBALL" || { echo "tarball $TARBALL did not arrive from the publish job" >&2; ls -la; exit 1; }
|
||||
# Deliberately NO NODE_AUTH_TOKEN in this step: npm >= 11.5 detects the GitHub
|
||||
# OIDC token itself. Always pass --tag explicitly (defense in depth: an older
|
||||
# VERSION can never claim `@latest`).
|
||||
npm publish "$TARBALL" --provenance --access public --tag "$TAG" --ignore-scripts
|
||||
echo "✅ Published omniroute@$VERSION (dist-tag=$TAG) via Trusted Publishing"
|
||||
|
||||
- name: Publish to npm (staged — owner approves with 2FA)
|
||||
if: github.event_name != 'workflow_dispatch' || inputs.publish_mode != 'direct'
|
||||
# Only on an explicit request now: Trusted Publishing below is the default.
|
||||
if: github.event_name == 'workflow_dispatch' && inputs.publish_mode == 'staged'
|
||||
env:
|
||||
VERSION: ${{ needs.publish.outputs.version }}
|
||||
TAG: ${{ needs.publish.outputs.tag }}
|
||||
|
||||
4
changelog.d/features/npm-trusted-publishing-oidc.md
Normal file
4
changelog.d/features/npm-trusted-publishing-oidc.md
Normal file
@@ -0,0 +1,4 @@
|
||||
- The npm publish is automatic again, through npm Trusted Publishing (OIDC): the hosted
|
||||
`stage-npm` job publishes with a short-lived credential minted from GitHub's id-token —
|
||||
no `NPM_TOKEN`, no 2FA prompt, provenance attached. `publish_mode=staged` (owner
|
||||
approves with 2FA) and `direct` (token) remain available on `workflow_dispatch`.
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
title: "Release Checklist"
|
||||
version: 3.8.40
|
||||
lastUpdated: 2026-06-28
|
||||
version: 3.8.51
|
||||
lastUpdated: 2026-08-28
|
||||
---
|
||||
|
||||
# Release Checklist
|
||||
|
||||
> **Last updated:** 2026-06-28 — v3.8.40
|
||||
> **Last updated:** 2026-08-28 — v3.8.51
|
||||
> Streamlined release flow that leverages Claude Code skills for automation.
|
||||
>
|
||||
> **Keep the queue/branch green between releases:** see [RELEASE_GREEN.md](./RELEASE_GREEN.md)
|
||||
@@ -37,7 +37,21 @@ npm run test:e2e # optional but recommended
|
||||
/capture-release-evidences-cc
|
||||
```
|
||||
|
||||
## npm Staged Publishing (default since v3.8.49 — WS1.3/D2)
|
||||
## npm Trusted Publishing (default since v3.8.51) — staged on request, direct as fallback
|
||||
|
||||
`npm-publish.yml` publishes through **npm Trusted Publishing (OIDC)** by default: the
|
||||
`stage-npm` job (github-hosted) exchanges GitHub's id-token for a short-lived npm
|
||||
credential for that run — no long-lived npm token in the repository secrets, no 2FA prompt, provenance attached.
|
||||
That is the bypass npm sanctions now that tokens which skip 2FA are being retired;
|
||||
it restores the fully automatic flow the project had up to v3.8.48 while keeping the
|
||||
WS1.3 guarantee (a leaked token cannot publish alone — there is no token).
|
||||
|
||||
**One-time setup (owner):** npmjs.com → package `omniroute` → Settings → *Trusted
|
||||
Publisher* → GitHub: owner `diegosouzapw`, repo `OmniRoute`, workflow `npm-publish.yml`
|
||||
(environment: none). Until that exists, the automatic step fails with `ENEEDAUTH`:
|
||||
re-dispatch with `publish_mode=staged` (below) or `direct`.
|
||||
|
||||
### Staged publishing (on request — `publish_mode=staged`)
|
||||
|
||||
The npm-publish workflow no longer publishes directly: it boots the packed tarball
|
||||
(`check:pack-boot`) and then runs `npm stage publish` — the exact bytes are parked on
|
||||
|
||||
Reference in New Issue
Block a user