Skip to content

feat(npm): distribute the CLI via npm#46

Open
pjcdawkins wants to merge 2 commits intomainfrom
cli-126-distribute-cli-via-npm
Open

feat(npm): distribute the CLI via npm#46
pjcdawkins wants to merge 2 commits intomainfrom
cli-126-distribute-cli-via-npm

Conversation

@pjcdawkins
Copy link
Copy Markdown
Contributor

Summary

Adds the build and publish tooling for distributing the Upsun CLI as
an npm package, so users can run npm install -g upsun or npx upsun.

Implements the optionalDependencies pattern used by esbuild, swc,
biome, turbo, and similar tools. A thin wrapper package (upsun)
declares four platform-specific packages as optionalDependencies;
npm uses each package's os and cpu fields to install only the
matching one. The wrapper's bin script resolves that package at
runtime and execs the embedded binary, forwarding argv, stdio, exit
code, and signals. No postinstall script and no runtime download.

Packages produced per release:

Package Contents
upsun wrapper
@upsun/cli-linux-x64 Linux amd64 binary
@upsun/cli-linux-arm64 Linux arm64 binary
@upsun/cli-darwin macOS universal binary (x64 + arm64)
@upsun/cli-win32-x64 Windows amd64 binary

macOS uses the universal binary GoReleaser already builds, so a single
darwin package covers Apple Silicon and Intel.

publish.sh publishes the platform packages first, waits for them to
become queryable on the public registry, and only then publishes the
wrapper. The wait matters: npm publish returns success before the
package is visible to npm view, and any user running npx upsun in
that window gets a broken install in their npx cache that does not
self-heal.

Layout

  • npm/wrapper: shim package with bin/upsun.js
  • npm/platform-template: template for the per-platform packages
  • npm/scripts/build.sh: assembles tarballs from GoReleaser archives
  • npm/scripts/publish.sh: publishes platforms, waits, then wrapper
  • Makefile targets: npm-pack, npm-publish, npm-clean

Out of scope

A GitHub Actions workflow that runs make npm-pack && make npm-publish
after the existing release job will follow in a separate PR. That step
also needs an NPM_TOKEN automation token added to the repo secrets.

Verification

The current snapshot version was published to the public registry from
this branch as a seed; npx upsun --version resolves and runs the real
binary end to end. Build, install, exec, argv passthrough, exit-code
propagation all confirmed.

🤖 Generated with Claude Code

Adds the build and publish tooling for distributing the Upsun CLI as
an npm package, so users can run `npm install -g upsun` or `npx upsun`.

Implements the optionalDependencies pattern used by esbuild, swc, biome,
turbo, and similar tools. A thin wrapper package (`upsun`) declares
four platform-specific packages as optionalDependencies; npm uses each
package's `os` and `cpu` fields to install only the matching one. The
wrapper's bin script resolves that package at runtime and execs the
embedded binary, forwarding argv, stdio, exit code, and signals. No
postinstall script and no runtime download.

Packages produced per release:

  upsun                   wrapper
  @upsun/cli-linux-x64
  @upsun/cli-linux-arm64
  @upsun/cli-darwin       universal binary, x64 and arm64
  @upsun/cli-win32-x64

macOS uses the universal binary that GoReleaser already builds, so a
single darwin package covers both Apple Silicon and Intel.

publish.sh classifies each tarball by reading its package.json once
(wrapper = "upsun", everything else is a platform package), publishes
the platform packages, waits for them to become queryable on the
public registry, then publishes the wrapper. The wait matters: npm
publish returns success before the package is visible to npm view, and
any user running npx in that window gets a broken install in their
npx cache that does not self-heal.

Layout:
- npm/wrapper: shim package with bin/upsun.js
- npm/platform-template: template for the per-platform packages
- npm/scripts/build.sh: assembles tarballs from GoReleaser archives
- npm/scripts/publish.sh: classifies, publishes, waits, then wrapper
- Makefile targets: npm-pack, npm-publish, npm-clean

Verified end-to-end against the live registry: build, publish, install
via `npx upsun`, exec, argv passthrough, and exit-code propagation all
work.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 27, 2026 09:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds npm build/publish tooling to distribute the Upsun CLI via a wrapper package (upsun) plus platform-specific optionalDependency packages, enabling npm install -g upsun / npx upsun without postinstall downloads.

Changes:

  • Add npm wrapper package (bin shim + package metadata) that resolves the correct platform package at runtime and execs the embedded binary.
  • Add scripts to build npm tarballs from GoReleaser archives and publish them in a safe order (platforms first, then wrapper after propagation).
  • Add templates/docs + Makefile targets and ignore npm/dist/ output.

Reviewed changes

Copilot reviewed 8 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
npm/wrapper/package.json.tmpl Defines the upsun wrapper package and optionalDependencies on platform packages.
npm/wrapper/bin/upsun.js Runtime resolver/launcher for the embedded platform binary.
npm/wrapper/README.md Wrapper package README for npm consumers.
npm/scripts/build.sh Builds wrapper + platform npm packages from GoReleaser artifacts.
npm/scripts/publish.sh Publishes platform packages, waits for registry visibility, then publishes wrapper.
npm/platform-template/package.json.tmpl Template for per-platform package metadata (os/cpu gated).
npm/platform-template/README.md.tmpl Template README for per-platform packages.
npm/README.md Repository docs for npm distribution workflow.
Makefile Adds npm-pack, npm-publish, npm-clean targets.
.gitignore Ignores npm/dist/ build outputs.

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

Comment thread npm/scripts/build.sh Outdated
Comment thread npm/scripts/build.sh Outdated
Comment thread npm/scripts/publish.sh Outdated
Address review comments on PR #46:

- Replace declare -A associative arrays in build.sh and publish.sh
  with case-statement helpers and parallel arrays, so the scripts
  run on macOS's default /bin/bash (3.2).
- Stop swallowing chmod failures on Unix targets in build.sh; only
  the Windows binary, where the exec bit is meaningless, keeps
  || true.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

2 participants