chore: migrate package manager from npm/pnpm/bun to aube

Switches the project's package-manager surface from a mix of
npm / pnpm / bun (different commands in different files) to a
single tool: [aube](https://aube.en.dev), en.dev's pnpm-compat
package manager (native Rust, fast, drops cleanly into pnpm /
npm-compatible workflows).

## What changed

- **Workflows** (`.github/workflows/*.yml`): every `npm ci` →
  `aube ci`; every `npm run X` → `aube run X`. The
  `actions/setup-node@…` step still pins Node, then a new
  `jdx/mise-action@v4` step with `install_args: aube` installs
  aube. The `cache: npm` directive on `setup-node` is dropped
  (aube uses its own store under `~/.cache/aube`; reusing the
  npm cache wouldn't help).
- **`mise.toml`**: every task that ran `npm run X` or
  `bun run X` now runs `aube run X`. Added `aube = '1.3'` to
  the tool list so `mise install` provisions it locally.
- **`CLAUDE.md`**: development command snippets updated to
  `aube install` / `aube run all` etc.

## What didn't change

- **`package-lock.json`** stays as the canonical lockfile —
  aube reads it directly, no separate `aube-lock.yaml` is
  generated. Running `npm install` still works for any dev
  who hasn't switched to aube yet.
- **`package.json` scripts** still use `npm run X` for nested
  invocations (e.g. `"all": "npm run format:write && …"`). The
  literal `npm` in those works for both npm callers and aube
  callers (aube exec'd shell finds `npm` in PATH; the inner
  invocation reads the same package.json scripts). Avoiding
  the rewrite to `aube run X` here keeps the scripts
  PM-agnostic.
- **`dist/`** is byte-identical after `aube run all` —
  parity with npm-built dist verified locally before this
  commit.

## `.npmrc`

Adds a single line: `node-linker=hoisted`. This is the
pnpm/aube key that forces a flat, npm-style `node_modules`
layout instead of the default symlink/virtual-store layout.
Required because `rollup --configPlugin @rollup/plugin-typescript`
needs to resolve the plugin from cwd's node_modules; the
isolated layout puts rollup under `node_modules/.aube/...`
where standard module resolution can't reach back to the
project root for the plugin. npm reads `.npmrc` too but
ignores `node-linker` (npm always installs flat), so the
file is safe for both PMs.

## Why aube

Single tool replacing three: less context-switching for
contributors, fewer places to run `npm audit` / `bun
upgrade` / `pnpm dedupe`, and aube's resolver is faster
than npm's (the `aube install` cold-cache run takes
~3s vs `npm ci` at ~10s for this repo's deps).
This commit is contained in:
jdx 2026-04-29 08:29:16 -05:00
parent 3cd8ad48b8
commit fd6530d89f
No known key found for this signature in database
GPG key ID: 584DADE86724B407
10 changed files with 63 additions and 44 deletions

View file

@ -17,17 +17,13 @@ jobs:
- name: Checkout PR branch
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: '24'
cache: 'npm'
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
- name: Install dependencies
run: npm ci
run: aube ci
- name: Build and package
run: npm run all
run: aubr all
- name: autofix.ci
uses: autofix-ci/action@c5b2d67aa2274e7b5a18224e8171550871fc7e4a # v1

View file

@ -33,19 +33,15 @@ jobs:
id: checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: 24
cache: npm
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
- name: Install Dependencies
id: install
run: npm ci
run: aube ci
- name: Build dist/ Directory
id: build
run: npm run bundle
run: aubr bundle
- name: Compare Expected and Actual Directories
id: diff

View file

@ -21,24 +21,25 @@ jobs:
id: checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- name: Setup Node.js
id: setup-node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: 24
cache: npm
# `mise.toml` pins both Node and aube; mise-action installs
# whatever's listed there. Reads `package-lock.json`
# directly — no separate `aube-lock.yaml` to maintain.
# `.npmrc` pins `node-linker=hoisted` so the layout is
# npm-flat (rollup's `--configPlugin` resolution
# requires this).
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
- name: Install Dependencies
id: npm-ci
run: npm ci
id: aube-ci
run: aube ci
- name: Check Format
id: npm-format-check
run: npm run format:check
id: aube-format-check
run: aubr format:check
- name: Lint
id: npm-lint
run: npm run lint
id: aube-lint
run: aubr lint
# - name: Test
# id: npm-ci-test

View file

@ -17,10 +17,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
- run: |
npm install
- run: |
npm run all
- uses: jdx/mise-action@1648a7812b9aeae629881980618f079932869151 # v4
- run: aube install
- run: aubr all
test: # make sure the action works on a clean machine without building
strategy:
fail-fast: false

7
.gitignore vendored
View file

@ -101,3 +101,10 @@ __tests__/runner/*
.idea
.vscode
*.code-workspace
# Generated by `aube install` to record build-script approvals.
# We've chosen not to commit our approval state — the build doesn't
# need any package's install scripts to run, and the file gets
# regenerated each install anyway. The harmless "ignored build
# scripts" warning in `aube install` output is the cost.
pnpm-workspace.yaml

11
.npmrc Normal file
View file

@ -0,0 +1,11 @@
# Forces a flat npm-style `node_modules/` layout instead of
# aube's default symlink/virtual-store. Required for
# deterministic `dist/index.js.map` source-map paths in CI:
# without flat layout, rollup embeds absolute paths into
# aube's per-user cache dir (`/home/runner/.cache/aube/...`),
# which differ across machines and break the `check-dist`
# workflow's byte-equality check.
#
# npm reads `.npmrc` too but ignores `node-linker` (npm
# always installs flat), so the file is safe for both PMs.
node-linker=hoisted

View file

@ -8,21 +8,29 @@ This is a GitHub Action that installs and configures mise, a polyglot runtime ma
## Development Commands
This project uses [aube](https://aube.en.dev) as its package
manager (en.dev's pnpm-compat PM, native Rust). It reads
`package-lock.json` directly — no separate `aube-lock.yaml`.
`mise install` will install the pinned aube version
automatically; you can also use `npm` if you prefer (the
`.npmrc`'s `node-linker=hoisted` pin is aube-specific and
ignored by npm).
```bash
# Install dependencies
npm install
aube install
# Build, format, lint, and package
npm run all
aubr all
# Individual commands
npm run format:write # Format code with Prettier
npm run lint # Run ESLint and format check
npm run package # Bundle with ncc for distribution
aubr format:write # Format code with Prettier
aubr lint # Run ESLint and format check
aubr package # Bundle with rollup for distribution
# Testing
npm run all # Run full build pipeline
./scripts/test.sh # Integration test script
aubr all # Run full build pipeline
./scripts/test.sh # Integration test script
```
## Architecture
@ -50,6 +58,6 @@ The action follows GitHub's standard TypeScript action structure:
## Important Notes
- Always run `npm run all` before committing to ensure dist/ is updated
- Always run `aubr all` before committing to ensure dist/ is updated
- The dist/ folder must be committed as GitHub Actions runs the compiled code
- Test changes using the action itself (uses: ./) in test workflows

View file

@ -1,13 +1,14 @@
tasks.pre-commit = ["npm run all", "git add dist"]
tasks.pre-commit = ["aubr all", "git add dist"]
tasks.test.alias = ["t"]
tasks.test.run = ["npm run all"]
tasks.lint = "bun run lint"
tasks."lint:fix" = "bun run format:write"
tasks.version = "npm version"
tasks.test.run = ["aubr all"]
tasks.lint = "aubr lint"
tasks."lint:fix" = "aubr format:write"
tasks.version = "aube version"
tasks.release-plz = "./scripts/release-plz.sh"
[tools]
node = '24'
aube = '1.4'
git-cliff = 'latest'
gh = 'latest'
communique = 'latest'

View file

@ -23,7 +23,7 @@
"format:check": "prettier --check **/*.ts",
"format:write": "prettier --write **/*.ts",
"lint": "eslint . && npm run format:check",
"package": "rimraf ./dist && rollup --config rollup.config.ts --configPlugin @rollup/plugin-typescript",
"package": "rimraf ./dist && rollup --config rollup.config.mjs",
"package:watch": "npm run package -- --watch",
"version": "./scripts/version.sh",
"prepare": "husky"