cli: add aubr/aubx multicall shims for run and dlx#6
Conversation
Greptile SummaryThis PR adds Key changes:
Confidence Score: 4/5Safe to merge; the core dispatch logic is correct and well-tested, with one non-blocking style note in the test helper. The
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["Process starts\nstd::env::args_os()"] --> B["rewrite_multicall_argv(args)"]
B --> C{argv0 basename\nafter file_stem +\nto_ascii_lowercase}
C -- "aubr" --> D["Insert 'run' at args[1]\nargs[0] = 'aube'"]
C -- "aubx" --> E["Insert 'dlx' at args[1]\nargs[0] = 'aube'"]
C -- "aube / other" --> F["Pass args unchanged"]
D --> G["Cli::parse_from(args)\n→ Commands::Run(...)"]
E --> H["Cli::parse_from(args)\n→ Commands::Dlx(...)"]
F --> I["Cli::parse_from(args)\n→ normal dispatch"]
Reviews (2): Last reviewed commit: "cli: add aubr/aubx multicall shims for `..." | Re-trigger Greptile |
Dispatch happens in `main.rs` via `argv[0]` basename: invocations as `aubr …` rewrite to `aube run …`, `aubx …` to `aube dlx …`. Shims are hardlinks to the same `aube` executable (so size cost is zero and macOS codesign carries through) created by the `mise build` task and refreshed in BATS `common_setup` on every run. Follow-up: teach the release workflow and each install channel (Homebrew formula, install.sh, cargo-binstall, winget) to materialize the shims at distribution time — until then users enable them with a local `ln` as documented in the README. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…archives
Switch from the hardlink-at-install approach to real Cargo bin targets:
`aubr` and `aubx` get `[[bin]]` entries pointing at tiny `src/bin/*.rs`
stubs that `include!("../main.rs")`, so they share the argv[0] dispatch
with `aube` while keeping Cargo from warning about duplicate source
paths. `test = false` on the shim bins keeps `cargo test` from running
the shared suite three times.
Release workflow now calls `taiki-e/upload-rust-binary-action` in
multi-bin mode (`bin: aube,aubr,aubx`, `archive: aube-$tag-$target`),
so every target's single tarball carries all three binaries. macOS
codesign applies uniformly via `codesign_prefix: dev.jdx.`.
Drop the mise/BATS hardlink plumbing: since Cargo now produces the
shim binaries natively at `target/debug/{aubr,aubx}`, nothing needs to
be faked in either the `mise build` task or the BATS `common_setup`.
Document the shortcut in `docs/package-manager/scripts.md` alongside
the existing `run` / `exec` / `dlx` coverage.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5443aa1 to
45660c9
Compare
Local `cargo build` produces all three multicall binaries natively, but CI only uploads `target/debug/aube` as a Buildkite artifact — the bats shards then download just `aube` and call `aubr`/`aubx` through PATH, which fails with command-not-found (seen on https://buildkite.com/endev/aube/builds/17). Restore the idempotent `ln -f` fallback in common_setup.bash that I dropped in the previous commit. It's a no-op when the shims already exist (e.g. after a local `cargo build`) and reconstructs them from the downloaded `aube` artifact in CI. Cheaper than teaching every artifact-download step in `.buildkite/pipeline.sh` to fetch three identical 72 MB binaries. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
## Summary - Add a preinstall-based npm distribution alongside the existing mise/cargo/curl paths. Root package is `@endevco/aube`; six per-platform subs are `@endevco/aube-<os>-<arch>` (darwin-arm64, darwin-x64, linux-x64, linux-arm64, win32-x64, win32-arm64). - New standalone workflow [`publish-npm.yml`](.github/workflows/publish-npm.yml) triggers on `release: published` (and `workflow_dispatch` for reruns). Decoupled from `release-plz.yml` so an npm hiccup never blocks crates.io or the GitHub release. - Auth via npm **Trusted Publishing (OIDC)** — no `NPM_TOKEN` secret. ## How it works At install time, `@endevco/aube`'s [`preinstall` script](npm/installArchSpecificPackage.js) spawns `npm install --no-save @endevco/aube-<os>-<arch>@<version>` and hardlinks (falling back to copy) the three binaries (`aube`, `aubr`, `aubx`) from the sub-package's `bin/` into the root's `./bin/`. Shape mirrors [`@jdxcode/mise`](https://www.npmjs.com/package/@jdxcode/mise) — no runtime JS shim and no `optionalDependencies` sprawl in `package-lock.json`. Note this means `--ignore-scripts` and fully offline caches won't work; those users keep the mise/cargo paths. The multicall dispatch from [#6](#6) works through npm because the preinstall creates three named files, so `aubr` invoked via npm's bin wrapper sees `argv[0]` ending in `aubr` and routes to `run`. At release time, [`npm/scripts/publish.mjs`](npm/scripts/publish.mjs) downloads each `aube-<tag>-<target>.{tar.gz,zip}` from the just-published GitHub release, extracts the binaries, stages a platform-scoped `package.json` with correct `os`/`cpu`/`bin`, and `npm publish`es each sub-package. Root publishes last so its preinstall can resolve every sub. Auto-picks the `next` dist-tag for pre-releases (`1.0.0-beta.1` → `next`) and `latest` for stable. `DRY_RUN=1`, `SKIP_ROOT=1`, and `SKIP_PLATFORMS=1` env flags exist for manual recovery. ## Why OIDC npm's Trusted Publishing (GA mid-2025) exchanges a short-lived GitHub OIDC token for a one-shot npm publish token. No long-lived secret to rotate or leak, and the publish is provenance-signed. Requires npm ≥ 11.5.1 — the workflow upgrades to `npm@latest` before publishing to avoid drift with the version Node 24 ships. ## Pre-merge setup On [npmjs.com/org/endevco](https://www.npmjs.com/org/endevco) → Settings → Trusted Publishers, add an org-level trusted publisher: - Repo: `endevco/aube` - Workflow: `.github/workflows/publish-npm.yml` - Environment: (blank) Org-level config covers all new `@endevco/*` packages, so the first release auto-covers root + 6 subs. ## Limitations / follow-ups - `aube` (unscoped) is taken on npm by a year-old placeholder (`estjs/aube`, 1 version, never updated). If you want the unscoped name, file an [npm dispute](https://docs.npmjs.com/policies/disputes) — unrelated to this PR. - No Alpine / musl package yet. Linux users on glibc distros get `linux-<arch>`; muslc users will hit the glibc binary and fail. Adding `linux-x64-musl` / `linux-arm64-musl` needs corresponding Rust release targets first. - Retrying after partial publish failure: same-version republishes return 403. Recovery is running the workflow manually with `SKIP_PLATFORMS=1` (or vice versa) to publish only what hasn't shipped. ## Test plan - [x] Built `aube`, `aubr`, `aubx` locally; staged a fake `@endevco/aube-darwin-arm64` sub-package under `node_modules/`; ran the link logic and confirmed each bin dispatches to the right subcommand via `argv[0]` basename (`aubr --help` → `run`'s help, `aubx --help` → `dlx`'s help). - [x] `npm pack --dry-run` on the root package — tarball contains only `installArchSpecificPackage.js` + `package.json` (README copied in by publish script at release time). - [x] `npm pack --dry-run` on a hand-staged platform package — contains `bin/{aube,aubr,aubx}`, `package.json` with correct `os`/`cpu`, `README.md`. - [ ] End-to-end first publish under `1.0.0-beta.X` with `next` dist-tag, then `npm install -g @endevco/aube@next` from a clean machine. Runs for real on the next release. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Adds a new release-triggered GitHub Actions workflow and `preinstall`-driven npm packaging/publishing logic, which can impact release automation and end-user installation behavior if misconfigured. > > **Overview** > Adds npm distribution for `aube` by introducing a root `@endevco/aube` package that installs a platform-specific `@endevco/aube-<os>-<arch>` subpackage at `preinstall` time and links/copies the native `aube`/`aubr`/`aubx` binaries into `./bin`. > > Introduces a new `publish-npm` GitHub Actions workflow that runs on `release: published` (or manual tag input) and uses npm Trusted Publishing (OIDC) to download release artifacts, stage per-platform npm packages, and publish them before publishing the root package. Documentation is updated to mention `npm install -g @endevco/aube` as an install option. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit cf71251. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
aubr …dispatches toaube run …andaubx …toaube dlx …, purely viaargv[0]basename detection in crates/aube-cli/src/main.rs — no new clap subcommands or second compile pass.aubeexecutable: zero disk cost, macOS codesign carries through via the shared inode, and basename dispatch stays transparent for flags (aubr --helpshowsrun's help, etc.).mise buildtask now recreatestarget/debug/aubr/aubxaftercargo build, and BATScommon_setuprefreshes them at the start of every test so the suite exercises the real shim path..exesuffixes); a newtest/multicall_shims.batsfile drives end-to-end smoke tests against the live binary.Follow-up (not in this PR)
Release packaging and installer integration still need to ship the shims:
.github/workflows/release.ymlcurrently uploads onlyaube— needs a post-step that hardlinksaubr/aubxinto the archive (and copies on Windows, where hardlinks are impractical).install.sh,cargo-binstall, winget/scoop manifests each need a two-line update to create the shims at install time.Until those land, users enable the shims with a local
lnas documented in the new README section.Test plan
cargo test --workspace— 5 new multicall unit tests plus the existing suite green.cargo clippy --all-targets -- -D warningsclean.cargo fmt --checkclean../test/bats/bin/bats test/multicall_shims.bats— 4/4 pass../test/bats/bin/bats test/run.bats test/dlx.bats— 21/21 still green after the common_setup change.🤖 Generated with Claude Code
Note
Medium Risk
Introduces new entrypoints and rewrites CLI argv parsing based on
argv[0], which could affect command dispatch/help output and release packaging across platforms if edge cases slip through.Overview
Adds multicall CLI shims
aubrandaubxthat invoke the existing binary but auto-dispatch toaube run …andaube dlx …by rewriting argv based onargv[0].Updates build/release and tests to ship and validate the shims: Cargo now builds three bins (with
aubr/aubxstubs includingmain.rs), the release workflow uploads a single archive containing all three binaries per target, and the BATS harness creates hardlinked shims plus a new end-to-endmulticall_shims.batssuite; docs/README are updated to document the shortcuts.Reviewed by Cursor Bugbot for commit dc7a870. Bugbot is set up for automated code reviews on this repo. Configure here.