Skip to content

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

Open
tkkhq wants to merge 4 commits into
mainfrom
npm-trusted-publishing
Open

Add npm trusted-publishing support + ci.yaml publish workflow#34
tkkhq wants to merge 4 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) and adds the publish-npm.yml workflow that runs npm publish.

The CLI is distributed as a thin npm wrapper (@kong/volcano-cli) around the existing cosign-signed GitHub Release binaries — no long-lived NPM_TOKEN required.

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) 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).
  • scripts/npm/install.js — postinstall hook (non-fatal so npm install still succeeds offline / with --ignore-scripts).
  • .github/workflows/publish-npm.yml — publishes to npm via OIDC (id-token: write scoped to the publish job, GitHub-hosted runner, npm@11 for trusted-publishing support ≥ 11.5.1), version derived from the release tag, asset-existence guard, then npm publish. Triggers on stable release: published (+ workflow_dispatch). Named to parallel publish-cli.yml (CLI → GitHub releases, npm → registry) and avoid confusion with the existing ci.yml Go checks.
  • README.md / .gitignore — npm install docs; ignore downloaded binaries + node_modules.

Verification

  • node --check on all JS, npm pack --dry-run contents reviewed
  • Full npm install → run cycle against the real v0.0.4 release: downloaded, checksum-verified, ran volcano --version, confirmed exit-code passthrough
  • Verified unsupported-platform path returns a clean error + exit 1 (no unhandled rejection)

Follow-ups / notes

  • One-time npm setup: On npmjs.com → package Settings → Trusted Publisher, set Organization: Kong, Repository: volcano-cli, Workflow filename: publish-npm.yml (must match exactly, including extension). See https://docs.npmjs.com/trusted-publishers#troubleshooting.
  • Sequencing: npm publish runs after publish-cli.yml creates the GitHub Release (the npm package downloads those assets). Only stable vX.Y.Z releases publish to npm; nightlies are skipped (different asset naming). Can add a nightly dist-tag if wanted.
  • 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. Cosign verification in postinstall could be added later if desired.

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
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.


on:
# Fires when publish-cli.yml publishes the GitHub Release for a version tag.
release:

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.

The normal stable release path creates the GitHub Release from publish-cli.yml using GH_TOKEN: ${{ github.token }}. GitHub does not enqueue new workflow runs for events caused by GITHUB_TOKEN other than documented exceptions, and release is not one of them: https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/trigger-a-workflow#triggering-a-workflow-from-a-workflow. That means this release: published trigger will not run after the automated CLI release, so the npm package only publishes via manual workflow_dispatch. Please either publish npm from the existing release workflow after the assets are uploaded, dispatch this workflow explicitly (workflow_dispatch/repository_dispatch with the needed permissions), or create the release with a GitHub App/PAT if the release event should fan out.

@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
return;
}

const target = resolveTarget();

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.

[P3] When run in this repo (or before npm version sets a real version), pkg.version is 0.0.0, so ensureBinary() tries to fetch from the nonexistent v0.0.0 release and prints a download warning. Harmless since postinstall is non-fatal, but you could short-circuit when the version is 0.0.0 to avoid the noise for maintainers running npm install locally.

Comment thread scripts/npm/download.js
// against the release's SHA256SUMS manifest. Idempotent: no-op if present.
async function ensureBinary({ force = false } = {}) {
const dest = binaryPath();
if (!force && fs.existsSync(dest)) {

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.

[P3] ensureBinary (and the existsSync check in bin/volcano.js) skip checksum re-verification when the binary already exists, so a previously corrupt or truncated download won't self-heal on subsequent runs. Acceptable given the best-effort self-heal design — just noting the assumption.

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