Skip to content

🧪 npm publish dry-run #1

🧪 npm publish dry-run

🧪 npm publish dry-run #1

name: 🧪 npm publish dry-run
# Cascade-owned — every npm-publishing repo carries the byte-identical copy.
# Continuous validation of the RELEASE PATH between releases: a weekly cron
# walks the same chain npm-publish.yml runs (checkout → setup-and-install →
# build → scripts/fleet/npm-publish.mts --staged --dry-run), which packs the
# tarball and validates the manifest without touching the registry.
#
# WHY: a publish leg can rot silently for months when nothing exercises it —
# a package-manager pin that drops a subcommand, a stale firewall build that
# can't parse the registry endpoint, a manifest that stopped packing. Those
# only surface at release time, after the release markers are already cut,
# where the recovery is a burned version. A weekly red run here is a bug
# report; the same failure during a release is a burn.
#
# LEAST PRIVILEGE: no `npm-publish` environment and no `id-token: write`. A
# dry run uploads nothing, so it must not be able to mint a publish token.
on:
schedule:
# Weekly, Monday 09:17 UTC — offset from the top of the hour so the fleet
# does not stampede the runner pool.
- cron: '17 9 * * 1'
workflow_dispatch: {}
permissions:
contents: read
# One validation at a time; a queued second run adds nothing.
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
jobs:
dry-run:
runs-on: ubuntu-latest
timeout-minutes: 45
env:
# Socket Firewall + CLI auth for the sfw-wrapped setup + pnpm install —
# sfw and socket-cli read SOCKET_API_KEY from the org-wide secret.
SOCKET_API_KEY: ${{ secrets.SOCKET_API_TOKEN_FOR_CLI_AND_SFW }}
steps:
# First step must be the third-party actions/checkout (GitHub fetches it
# independently) to populate the workspace so the LOCAL
# ./.github/actions/* composite resolves.
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 (2026-05-15)
with:
fetch-depth: 1
# The bump derivation anchors on registry-latest + the last v-tag;
# a tagless shallow checkout derives from zero on a repo whose
# registry history is empty.
fetch-tags: true
persist-credentials: false
- name: Setup + install
uses: ./.github/actions/fleet/setup-and-install
- name: Build
run: pnpm run build
# The same staged-publish leg the real workflow runs, with --dry-run:
# packs every publishable package and validates its manifest, then
# stops before the upload. No --bump: the dry run must never derive a
# version or write a CHANGELOG.
- name: Dry-run staged publish
run: node scripts/fleet/npm-publish.mts --staged --dry-run