Skip to content

chore: provision node and bun via nix instead of pnpm - #1271

Merged
ryoppippi merged 3 commits into
mainfrom
chore/provision-runtimes-via-nix
Jun 11, 2026
Merged

ryoppippi merged 3 commits into
mainfrom
chore/provision-runtimes-via-nix

Conversation

@ryoppippi

@ryoppippi ryoppippi commented Jun 11, 2026 •

Copy link
Copy Markdown
Member

Summary

Recreated from #1270 (which was auto-closed when its stacked base branch was
deleted on merge). Now targets main directly with #1268/#1269 already landed.

package.json declared engines.runtime for node and bun with
onFail: download, so pnpm fetched and managed those runtimes itself rather
than using the pinned Nix toolchain. This removes that and provisions both
runtimes via Nix.

What changed

  • package.json: drop engines.runtime; pnpm-lock.yaml resynced (managed runtimes removed).
  • flake dev shell: add nodejs (bun already present).
  • CI test: install nodejs for Vitest.
  • CI pkg-pr-new: add nodejs + bun for the tsdown / ensure-native-binary prepack scripts.
  • CI perf jobs: add nodejs alongside bun.
  • release.yaml: add bun; node still comes from setup-node (kept for npm registry auth / provenance).
  • Use the default pnpm / nodejs nixpkgs attributes (pnpm 11.1.1, node LTS 24.x).

Verification

With a clean pnpm state, after removing engines.runtime:

  • pnpm install --frozen-lockfile no longer manages/downloads node or bun.
  • pnpm exec vitest run runs on the PATH Nix node; 34 tests pass.

View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Provision Node and Bun via Nix instead of pnpm runtime downloads. Removes engines.runtime and updates dev shell and CI to use Nix-pinned nodejs and bun for reproducible builds.

  • Refactors

    • Dev shell: add nodejs; switch to nixpkgs defaults (pnpm, nodejs); keep bun.
    • CI test job: install pnpm/nodejs/just via Nix for Vitest.
    • CI pkg-pr-new: install pnpm/nodejs/bun for tsdown and ensure-native-binary prepack scripts.
    • CI perf jobs: add nodejs alongside bun.
    • Release: keep setup-node for npm auth/provenance; install pnpm and bun via Nix.
  • Dependencies

    • Remove engines.runtime from package.json to stop pnpm-managed runtime downloads.
    • Regenerate pnpm-lock.yaml to drop runtime: entries for Node and Bun.

Written for commit 52e7887. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Chores
    • Updated CI and release workflow configurations to adjust tooling dependencies and installation steps.
    • Updated development environment setup to use updated package manager versions.
    • Removed runtime version requirements from package configuration.

`package.json` declared `engines.runtime` for node and bun with
`onFail: download`, so pnpm fetched and managed those runtimes itself. That
made every environment depend on a pnpm-managed download at runtime instead of
the pinned Nix toolchain.

Drop `engines.runtime` and provide both runtimes explicitly:

- dev shell: add `nodejs_24` (bun was already present).
- test job: install `nodejs_24` for Vitest (dropping the unused bun).
- pkg-pr-new: add `nodejs_24` and `bun` for the tsdown / ensure-native-binary
  prepack scripts that previously relied on the managed runtimes.
- perf jobs: add `nodejs_24` alongside the existing bun.
- release: add `bun`; node still comes from `setup-node`, which is kept for the
  npm registry auth and provenance setup.

Verified locally with a clean pnpm state: `pnpm install --frozen-lockfile` no
longer manages runtimes and Vitest runs on the PATH node.
The lockfile recorded the `engines.runtime` node/bun entries as `runtime:`
dependencies. With `engines.runtime` removed, regenerate the lockfile so
`pnpm install --frozen-lockfile` stays in sync and no longer resolves the
pnpm-managed runtimes.
Pin to the unversioned `pnpm` and `nodejs` attributes rather than `pnpm_11` /
`nodejs_24`. `pnpm` currently resolves to 11.1.1 (same as the explicit alias,
matching the lockfile) and `nodejs` tracks the active LTS, so the dev shell and
CI follow the maintained defaults without hard-coding a major.
@ryoppippi
ryoppippi merged commit 42e5b16 into main Jun 11, 2026
5 of 6 checks passed
@ryoppippi
ryoppippi deleted the chore/provision-runtimes-via-nix branch June 11, 2026 15:19
@coderabbitai

coderabbitai Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0b1d6603-9f5e-492d-9bbd-c8d2ea9e6433

📥 Commits

Reviewing files that changed from the base of the PR and between d6d34c4 and 52e7887.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • .github/workflows/ci.yaml
  • .github/workflows/release.yaml
  • nix/dev-shell.nix
  • package.json

📝 Walkthrough

Walkthrough

This PR updates toolchain provisioning across CI workflows, release workflow, and dev shell by migrating from pnpm_11 to plain pnpm, explicitly adding nodejs to Nix profile installs, adding bun to the release publish job, and removing Node/Bun version constraints from package.json.

Changes

Toolchain Provisioning Updates

Layer / File(s) Summary
CI test and packing jobs toolchain updates
.github/workflows/ci.yaml
test job replaces pnpm_11/bun/just with pnpm/nodejs/just. npm-publish-dry-run-and-upload-pkg-pr-now job explicitly installs pnpm, nodejs, and bun for packaging. Both ccusage-perf-comment and ccusage-rust-perf-comment jobs add nodejs to their Nix profile installs.
Release workflow publish preparation
.github/workflows/release.yaml
npm job now installs both nixpkgs#pnpm and nixpkgs#bun via nix profile install, with comments indicating node provision source and bun necessity for prepack script.
Dev shell toolchain defaults
nix/dev-shell.nix
devShells.default.buildInputs migrates from pnpm_11 to pnpm and explicitly adds nodejs alongside it.
Package.json engine constraints removal
package.json
engines field block specifying Node and Bun version requirements is removed.

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • ccusage/ccusage#1258: Updates Nix nix profile install inputs for the same perf-comment and npm-publish jobs with overlapping tooling changes.
  • ccusage/ccusage#1257: Also modifies release workflow npm publish tooling setup in .github/workflows/release.yaml for Nix profile JS toolchain provisioning.

Suggested reviewers

  • pullfrog

Poem

🐰 A rabbit hops through workflows spry,
Unpinning pnpm, adding node nearby,
Bun joins the publish feast,
Engines removed (constraints decreased),
Dev shells shine—our toolchain's fly! ✨

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/provision-runtimes-via-nix

Comment @coderabbitai help to get the list of available commands and usage tips.

@pullfrog pullfrog Bot 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.

✅ No new issues found.

Reviewed changes — Removes pnpm-managed runtime downloads (engines.runtime) for node and bun, provisioning both via Nix instead across the dev shell and all CI jobs.

  • Drop engines.runtime — Remove managed node/bun from package.json; regenerate pnpm-lock.yaml to drop runtime: entries
  • Update dev shell — pnpm_11 → pnpm, add nodejs (bun already present)
  • Update CI test job — Replace pnpm_11/bun with pnpm/nodejs (Vitest needs Node, not Bun)
  • Update CI pkg-pr-new — Explicitly provision nodejs + bun since pnpm no longer auto-downloads them
  • Update CI perf jobs — Add nodejs alongside existing bun
  • Update release — Add explicit bun for ensure-native-binary prepack script

Pullfrog  | View workflow run | Using Big Pickle (free via Pullfrog for OSS) | 𝕏

@cubic-dev-ai cubic-dev-ai Bot 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.

No issues found across 5 files

Re-trigger cubic

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: 52e788746518
Base SHA: d6d34c414941

This compares the Rust PR release binary against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new d6d34c414941 1.220s 815.9ms 70.0ms 3
PR pkg.pr.new 52e7887 1.047s 958.0ms 63.5ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: d6d34c414941; PR package: 52e7887. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 900.5ms 992.9ms 0.91x 738.25 MiB 723.75 MiB 0.98x 1.12 GiB/s 1.01 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 206.1ms 203.5ms 1.01x 91.75 MiB 91.50 MiB 1.00x 4.88 GiB/s 4.95 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 902.1ms 1.12 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 926.7ms 1.09 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 182.7ms 5.51 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 132.4ms 7.60 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 49.2ms 6.1ms 8.12x 43.00 MiB 3.00 MiB 0.07x 0.03 MiB/s 0.26 MiB/s
claude session --offline --json 0.00 MiB 40.2ms 5.9ms 6.80x 43.00 MiB 2.75 MiB 0.06x 0.04 MiB/s 0.26 MiB/s
codex daily --offline --json 0.00 MiB 43.9ms 5.9ms 7.48x 43.00 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.15 MiB/s
codex session --offline --json 0.00 MiB 43.2ms 5.6ms 7.76x 43.00 MiB 2.75 MiB 0.06x 0.02 MiB/s 0.15 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs rust/target/release/ccusage directly. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 943.2ms 891.5ms 1.06x 739.25 MiB 743.00 MiB 1.01x 1.07 GiB/s 1.13 GiB/s
codex --offline --json 1.01 GiB 182.8ms 145.5ms 1.26x 89.75 MiB 93.25 MiB 1.04x 5.51 GiB/s 6.92 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 17.32 KiB 17.33 KiB +0.00 KiB 1.00x
installed native package binary 3324.84 KiB 3324.84 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

@github-actions

Copy link
Copy Markdown
Contributor

ccusage performance comparison

PR SHA: 52e788746518
Base SHA: d6d34c414941

This compares the PR package against the configured base package on the same CI runner.

Package runner startup

Execution setup measures any pre-benchmark package materialization used by the execution benchmark. Bunx temp cache measures one bunx -p <url> ccusage --version run with an empty Bun install cache. Warm reuses that cache and reports the median of repeated runs.

Package SHA Execution setup Bunx temp cache Bunx warm median Warm samples
Base pkg.pr.new d6d34c414941 1.090s 1.318s 65.3ms 3
PR pkg.pr.new 52e7887 1.197s 1.190s 66.2ms 3

Cached bunx execution performance

Runs the same large fixture through bunx -p <pkg.pr.new URL> ccusage after the Bun install cache has already been populated by the startup measurement. This separates cached package-runner execution from first-fetch package materialization.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base package: d6d34c414941; PR package: 52e7887. Both run through bunx -p <pkg.pr.new URL> ccusage using the warmed Bun install cache from package runner startup, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
bunx -p <pkg> ccusage claude --offline --json 1.01 GiB 946.9ms 918.1ms 1.03x 731.25 MiB 732.25 MiB 1.00x 1.06 GiB/s 1.10 GiB/s
bunx -p <pkg> ccusage codex --offline --json 1.01 GiB 209.9ms 214.9ms 0.98x 90.25 MiB 86.75 MiB 0.96x 4.80 GiB/s 4.68 GiB/s

Package runtime diagnostics

Compares the PR package wrapper, the installed native optional dependency binary, and the workspace release binary on the same large fixture. This identifies whether slow package results come from JavaScript wrapper overhead, the published native binary build, or the Rust core itself.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
All rows run --offline --json, measured by hyperfine with 0 warmups and 1 runs. This isolates wrapper overhead from the installed native optional dependency and the workspace release binary built on the runner.

Command Runtime Input Median Throughput Samples
claude --offline --json Package wrapper 1.01 GiB 914.4ms 1.10 GiB/s 1
claude --offline --json Installed native binary 1.01 GiB 946.9ms 1.06 GiB/s 1
codex --offline --json Package wrapper 1.01 GiB 187.0ms 5.38 GiB/s 1
codex --offline --json Installed native binary 1.01 GiB 134.8ms 7.47 GiB/s 1

Committed fixture performance

Committed small fixtures for stable PR-to-PR feedback and explicit Claude/Codex command coverage.

Fixtures: Claude apps/ccusage/test/fixtures/claude (0.00 MiB, 2 files), Codex apps/ccusage/test/fixtures/codex (0.00 MiB, 1 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 2 warmups and 7 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude daily --offline --json 0.00 MiB 50.5ms 51.1ms 0.99x 43.00 MiB 43.00 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
claude session --offline --json 0.00 MiB 48.0ms 54.2ms 0.89x 43.00 MiB 43.00 MiB 1.00x 0.03 MiB/s 0.03 MiB/s
codex daily --offline --json 0.00 MiB 51.4ms 52.8ms 0.97x 43.25 MiB 43.00 MiB 0.99x 0.02 MiB/s 0.02 MiB/s
codex session --offline --json 0.00 MiB 43.9ms 43.0ms 1.02x 43.25 MiB 43.00 MiB 0.99x 0.02 MiB/s 0.02 MiB/s

Large real-world-shaped fixture performance

Generated fixtures shaped from aggregate local log statistics: thousands of JSONL files, many small sessions, and a long tail of larger sessions. No real prompts, paths, or outputs are stored in the fixtures.

Fixtures: Claude /home/runner/_work/_temp/ccusage-large-fixture (1.01 GiB, 2,597 files), Codex /home/runner/_work/_temp/ccusage-large-codex-fixture (1.01 GiB, 2,597 files)
Base runs the published ccusage package from pkg.pr.new, installed before measurement; PR runs the published ccusage package from pkg.pr.new, installed before measurement. Both run --offline --json, measured by hyperfine with 0 warmups and 1 runs.
Peak RSS is measured separately with /usr/bin/time using 1 runs. Lower RSS ratios are better.

Command Input Base median PR median PR vs base Base peak RSS PR peak RSS PR/base RSS Base throughput PR throughput
claude --offline --json 1.01 GiB 927.6ms 964.3ms 0.96x 732.50 MiB 722.25 MiB 0.99x 1.09 GiB/s 1.04 GiB/s
codex --offline --json 1.01 GiB 178.5ms 173.2ms 1.03x 94.00 MiB 91.25 MiB 0.97x 5.64 GiB/s 5.81 GiB/s

Artifact size

Artifact Base PR Delta Ratio
packed ccusage-*.tgz 17.32 KiB 17.33 KiB +0.00 KiB 1.00x
installed native package binary 3324.84 KiB 3324.84 KiB +0.00 KiB 1.00x

Lower medians and smaller artifacts are better. CI runner noise still applies; use same-run ratios as directional PR feedback, not release guarantees.

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