Skip to content

Add npm trusted-publishing support + ci.yaml publish workflow#34

Merged
tkkhq merged 6 commits into
mainfrom
npm-trusted-publishing
Jul 7, 2026
Merged

Add npm trusted-publishing support + ci.yaml publish workflow#34
tkkhq merged 6 commits into
mainfrom
npm-trusted-publishing

Conversation

@tkkhq

@tkkhq tkkhq commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Makes the repo npm publish-compatible via npm trusted publishing (OIDC) — no long-lived NPM_TOKEN. The CLI is distributed as a thin npm wrapper (@kong/volcano-cli) around the existing cosign-signed GitHub Release binaries, and it is published from a stable-only publish-npm job inside publish-cli.yml.

Changes

  • package.json@kong/volcano-cli with bin: volcano → bin/volcano.js, files allowlist (published tarball is ~9 kB — no Go source or 10 MB binary), postinstall, publishConfig.access=public, and repository.url matching the GitHub repo (required for trusted publishing).
  • bin/volcano.js — launcher that execs the platform binary, forwarding args, stdio, and exit code; downloads on first run if the binary is missing. Unsupported platforms (e.g. Windows arm64) and the 0.0.0 dev version fail with a clean error instead of an unhandled rejection.
  • scripts/npm/download.js — maps platform → release target, downloads from the matching v<version> release, and verifies against that release's SHA256SUMS (pure Node, no cosign at install time). Skips the placeholder 0.0.0 version.
  • scripts/npm/install.js — postinstall hook (non-fatal so npm install still succeeds offline / with --ignore-scripts); quietly skips for 0.0.0 source checkouts.
  • .github/workflows/publish-cli.yml — new publish-npm job (needs: [resolve-release, publish-github-release], stable-only) that sets the version from the release tag, verifies the release assets exist, and runs npm publish via OIDC (id-token: write scoped to the job, npm@11). Publishing lives here (not a separate workflow) because npm's trusted publisher must be the workflow that directly runs npm publish — dispatched/reusable workflows are unsupported, and a release: published trigger would not fire for GITHUB_TOKEN-created releases.
  • README.md / .gitignore — npm install docs; ignore downloaded binaries + node_modules.

Rollout

  1. Bootstrap (npm admin): first manual publish with a token to create @kong/volcano-cli (npm has no "pending publisher"; the package must exist before OIDC can be attached). Use a real version matching an existing GitHub Release, e.g. npm version 0.0.4 && npm publish --access public.
  2. Configure OIDC (via #ask-eng-enablement-guild): org Kong, repository volcano-cli, workflow file name publish-cli.yml (the file that runs npm publish).
  3. Until step 2 is done, the Publish to npm step is continue-on-error: true so releases stay green while it fails ENEEDAUTH. Remove continue-on-error once OIDC is live so real failures surface; after that, stable releases publish automatically with no further changes.

Verification

  • node --check on all JS; publish-cli.yml parses as valid YAML with the publish-npm job wired correctly
  • npm install → run against the real v0.0.4 release (downloaded, checksum-verified, ran volcano --version)
  • Verified clean errors for unsupported platforms and the 0.0.0 dev version; postinstall skips 0.0.0 quietly

Notes

  • Only stable vX.Y.Z releases publish to npm; nightlies/prereleases are skipped.
  • Install-time trust model (accepted): the npm path verifies the binary's SHA-256 against the release's SHA256SUMS over TLS rather than running cosign (which the shell installer does). This keeps the package dependency-free at install; npm provenance still attests the wrapper.

Distribute the volcano CLI via npm as a thin wrapper (@kong/volcano-cli):
- package.json with bin shim, files allowlist, postinstall, public access
- bin/volcano.js launcher execs the platform binary, forwarding args/exit code
- scripts/npm/download.js downloads + SHA256-verifies the binary from the
  matching GitHub Release; self-heals on first run if postinstall is skipped
- .github/workflows/ci.yaml publishes to npm via OIDC trusted publishing
  (id-token: write, no NPM_TOKEN) on stable release publish
- README + .gitignore updates
Copilot AI review requested due to automatic review settings July 6, 2026 20:26
@tkkhq tkkhq requested a review from a team as a code owner July 6, 2026 20:26

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an npm-distributed wrapper package (@kong/volcano-cli) that downloads a matching GitHub Release binary (verified via SHA256SUMS) and introduces a GitHub Actions workflow to publish that package to npm using trusted publishing (OIDC).

Changes:

  • Introduces an npm package (package.json) + launcher shim (bin/volcano.js) to run the platform-specific Release binary.
  • Adds Node scripts to download and SHA256-verify Release assets (scripts/npm/*) with a non-fatal postinstall hook.
  • Adds an npm publish workflow triggered by stable GitHub Releases (.github/workflows/ci.yaml) and updates docs/ignore rules.

Reviewed changes

Copilot reviewed 5 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
scripts/npm/install.js Adds non-fatal postinstall hook to download the CLI binary (or defer to first run).
scripts/npm/download.js Implements platform resolution, release URL construction, download, and SHA256 verification.
bin/volcano.js Adds launcher shim that downloads on demand and execs the native binary with argument/stdio passthrough.
package.json Defines @kong/volcano-cli package metadata, published files allowlist, scripts, and publish config.
.github/workflows/ci.yaml Adds OIDC-based npm publish workflow triggered by stable release: published.
README.md Documents npm installation flow and environment variable to skip postinstall download.
.gitignore Ignores downloaded platform binaries and node_modules/.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/npm/download.js Outdated
Comment thread scripts/npm/download.js
Comment thread scripts/npm/download.js
Comment thread .github/workflows/ci.yaml Outdated
tkkhq added 3 commits July 6, 2026 16:33
…write, pin npm

- download.js: select http/https client by URL scheme (supports http mirrors),
  reject unsupported schemes with a clear error
- download.js: remove partial temp file on download failure; clear destination
  before rename so force re-download / Windows overwrite works
- ci.yaml: pin npm to the 11 line instead of npm@latest for reproducibility
- Rename .github/workflows/ci.yaml -> publish-npm.yml (parallels
  publish-cli.yml; avoids confusion with the existing ci.yml Go checks)
- bin/volcano.js: handle unsupported platforms (e.g. win32-arm64, which passes
  the package.json os/cpu gate) with a clean error instead of an unhandled
  promise rejection; add a last-resort .catch() on main()
- publish-npm.yml: scope id-token: write to the publish job (least privilege);
  widen release-asset verification retries (~90s) to ride out the window where
  the release event can fire before all assets finish uploading
- download.js: hash the fully-written temp file instead of a mid-stream data
  listener; verifies exactly what landed on disk and avoids flowing-mode
  subtleties (#5)
- publish-npm.yml: verify assets with a ranged GET (first byte) instead of a
  HEAD request, confirming they are actually downloadable like postinstall does;
  GitHub honors Range so only 1 byte is fetched (#6)

@swkeever swkeever left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found one issue in the automatic npm publish path.

Comment thread .github/workflows/publish-npm.yml Outdated

@marckong marckong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

Careful, well-documented change making the repo npm publish-compatible via trusted publishing (OIDC). I traced asset naming and SHA256SUMS format against publish-cli.yml / install-volcano.sh and they line up (parseChecksum, TARGETS, and the v<version> tag mapping all match), and node --check passes on all three JS files.

Edge cases I'd normally hunt for are already handled: win32-arm64 caught by resolveTarget() throwing, non-fatal postinstall with first-run self-heal, signal re-raising, partial-download cleanup, and the 0.0.0 publish guard. No blocking bugs found.

Overall correctness: correct. Existing code/tests are unaffected and the patch is free of blocking issues. Just the one already-documented operational caveat: the one-time npm Trusted Publisher setup (Workflow filename: publish-npm.yml) must be configured or publishing will fail — expected, not a code defect.

Two optional non-blocking notes inline below.

Comment thread scripts/npm/install.js
Comment thread scripts/npm/download.js
Fold npm publishing into publish-cli.yml as a stable-only publish-npm job
instead of a standalone release-triggered workflow:
- npm's trusted publisher must be the workflow that directly runs npm publish;
  dispatched/reusable workflows are not supported, and a release: published
  trigger would not fire for GITHUB_TOKEN-created releases (swkeever)
- runs in the tag-push release run, needs publish-github-release so assets are
  already uploaded (no race); id-token: write scoped to the job
- continue-on-error during bootstrap so releases stay green until an npm admin
  does the manual first publish + configures OIDC (workflow file: publish-cli.yml)
- delete standalone .github/workflows/publish-npm.yml

Address marckong review (P3): skip download for placeholder version 0.0.0 so
maintainers running npm install in a source checkout see a quiet skip instead
of a failed-download warning (install.js), and the shim errors cleanly without
hitting a nonexistent v0.0.0 release (download.js).
@tkkhq

tkkhq commented Jul 7, 2026

Copy link
Copy Markdown
Contributor Author

Thanks both — all review feedback addressed:

@swkeever (blocking): release: published would not fire for GITHUB_TOKEN-created releases. Fixed by folding npm publish into a stable-only publish-npm job in publish-cli.yml (needs: [resolve-release, publish-github-release]) that runs npm publish directly in the tag-push release run — no release-event cascade, no dispatch, no asset-upload race. Configured trusted publisher = publish-cli.yml. (b96eac1)

@marckong (2 × P3): (1) postinstall now skips the placeholder 0.0.0 version quietly instead of warning, and the shim errors cleanly without fetching a nonexistent v0.0.0; (2) left the "no re-verify of existing binary" as-is by design (binary is renamed into place only after checksum passes; per-run re-hash would be a startup cost) — details in-thread. (b96eac1)

Rollout note: the Publish to npm step is continue-on-error: true so releases stay green until an npm admin does the first manual publish + configures OIDC on publish-cli.yml; that flag gets removed once trusted publishing is live.

@tkkhq tkkhq requested review from marckong and swkeever July 7, 2026 16:38

@swkeever swkeever left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found one workflow input issue.

Comment thread .github/workflows/publish-cli.yml Outdated
package-manager-cache is not a v4 input (added in v5), so it was silently
ignored. v4 only caches when 'cache' is set, which it is not here, so behavior
is unchanged; dropping the dead line.
@tkkhq tkkhq merged commit afd75cc into main Jul 7, 2026
8 checks passed
@tkkhq tkkhq deleted the npm-trusted-publishing branch July 7, 2026 18:10

@marckong marckong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Adds npm distribution via a thin wrapper package (@kong/volcano-cli) published through npm trusted publishing (OIDC) from a new stable-only publish-npm job in publish-cli.yml. The launcher shim + postinstall download and SHA-256-verify the platform binary from the matching GitHub release, with a self-healing first-run fallback.

Review

In solid shape — job wiring matches the resolve-release/publish-github-release outputs, checksum parsing matches the shasum -a 256 manifest generated by the release job, and edge cases (dev version 0.0.0, --ignore-scripts, Windows arm64 passing the os/cpu gate) all fail cleanly. One minor nit:

  • [P3] package-manager-cache (line 396) is not a valid actions/setup-node@v4 input — it was introduced in @v5, so on @v4 it's silently ignored (v4 doesn't cache by default anyway). Drop the line, or bump to setup-node@v5 if disabling a default cache was the intent.

Overall: correct — no blocking issues; existing jobs and release behavior are unaffected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants