Skip to content

POC: publish pup to npm - #879

Draft
tedkahwaji wants to merge 1 commit into
DataDog:mainfrom
tedkahwaji:teddy.kahwaji/npm-distribution
Draft

tedkahwaji wants to merge 1 commit into
DataDog:mainfrom
tedkahwaji:teddy.kahwaji/npm-distribution

Conversation

@tedkahwaji

Copy link
Copy Markdown
Contributor

Why

pup installs through Homebrew or a manual download from GitHub releases. Many developer and agent environments already have Node.js, and npx is the lowest-friction way to run a CLI there: one command, no package manager setup, nothing to put on PATH. This POC publishes pup to npm so that npx @datadog/pup <command> works.

What

Follows the per-platform optionalDependencies pattern used by esbuild and Biome:

  • npm/pup: the @datadog/pup root package. A small Node.js launcher (bin/pup.js) resolves the platform package for the host, runs its binary with arguments passed through, propagates the exit code, and forwards SIGINT/SIGTERM/SIGHUP so a supervisor that signals only the launcher still stops pup. If the platform package is missing (for example --omit=optional), it exits 1 with guidance.
  • Platform packages @datadog/pup-{darwin-arm64,darwin-x64,linux-arm64,linux-x64,win32-x64} with os/cpu set, so npm installs only the matching one. These match the release matrix exactly. Linux binaries are static musl builds, so no libc field is needed.
  • npm/scripts/build-packages.js: builds all packages from the GitHub release archives (pup_<version>_<Os>_<arch>.tar.gz / .zip) and stamps the version into every package.json, including the root package's optionalDependencies. The npm binaries are byte-identical to the signed release binaries.
  • .github/workflows/npm-publish.yml: workflow_dispatch only, for an existing release tag. dry_run defaults to true; a real publish also requires an NPM_TOKEN secret and runs in an npm-publish environment (which can require reviewer approval). Before packaging, it verifies the cosign-signed checksums against the release.yml signing identity. Platform packages publish before the root package, with --provenance. Nothing has been published.
  • ci.yml: new npm Packaging job that runs the launcher and builder tests.
  • .gitignore: the pup binary pattern also matched the npm/pup directory, so it is re-included.

Testing

Unit tests (node --test 'npm/**/*.test.js'): 12 passed, 0 failed. They cover platform resolution for every supported platform, unsupported platforms, a missing optional dependency, argument and exit-code passthrough, SIGTERM forwarding (asserted with a marker file written by the child's trap), the version stamping, a missing release archive, and invalid CLI input.

Smoke test on macOS arm64, from a cargo build --release binary packed with npm pack and installed into a fresh project:

datadog-pup-1.23.7.tgz              8.0K
datadog-pup-darwin-arm64-1.23.7.tgz 25M   (74M unpacked)

$ npx --no-install pup --version
pup 1.23.7                                   exit=0
$ npx --no-install pup auth status
"authenticated": true, "site": "datadoghq.com"  exit=0
$ npx --no-install pup monitors list --limit 1  exit=0
$ npx --no-install pup definitely-not-a-command exit=2  (same as the binary)

# installed with --omit=optional
$ npx --no-install pup --version
The @datadog/pup-darwin-arm64 package is not installed. It is an optional dependency of @datadog/pup; reinstall without --omit=optional or --no-optional.
exit=1

Also ran the build script against the real v1.23.7 release archives (Darwin_arm64.tar.gz, Windows_x86_64.zip). Checksums verified, and the extracted binary reports pup 1.23.7. Release archive sizes are 24 MB to 28 MB, so the per-platform npm download is about the same as the GitHub release asset.

The publish workflow has not been run.

Open questions

  • npm org ownership: who owns the @datadog scope on npm, and who holds NPM_TOKEN? Trusted publishing (OIDC, no long-lived token) is preferable if the scope supports it.
  • Provenance and signing: --provenance links each package to this workflow run. Is that enough, or should the launcher also verify the binary against the release checksums at runtime?
  • Version sync: this POC publishes manually after a release. Should release.yml trigger it automatically, and should a failed npm publish block the release?
  • Windows arm64 and other platforms: not in the release matrix today, so not published.

🤖 Generated with Claude Code

Publish pup as @datadog/pup so it can run with `npx @datadog/pup` on any
machine with Node.js, without Homebrew or a manual download. The root
package is a small launcher; each release binary ships in its own
optionalDependencies package (@datadog/pup-<platform>) so npm installs
only the one matching the host.

- npm/pup: launcher that resolves the platform package, passes arguments
  and exit codes through, and forwards SIGINT/SIGTERM/SIGHUP
- npm/scripts/build-packages.js: builds the platform and root packages
  from GitHub release archives and stamps the version
- npm-publish.yml: manual-only publish of an existing release, dry run by
  default, verifies the cosign-signed checksums before packaging
- ci.yml: runs the launcher and builder tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

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

1 participant