Skip to content

chore: migrate from npm to pnpm 11 with 2-day release-age cooldown#274

Merged
esimkowitz merged 3 commits into
mainfrom
chore/pnpm-migration
May 16, 2026
Merged

chore: migrate from npm to pnpm 11 with 2-day release-age cooldown#274
esimkowitz merged 3 commits into
mainfrom
chore/pnpm-migration

Conversation

@esimkowitz
Copy link
Copy Markdown
Owner

@esimkowitz esimkowitz commented May 16, 2026

Summary

  • Migrates the project from npm to pnpm 11.1.2 (pinned via packageManager + Corepack).
  • Adds minimum-release-age=2880 (2 days, in minutes) to .npmrc so pnpm refuses to resolve dependency versions younger than 2 days — mitigates supply-chain attacks via quickly-yanked malicious releases.
  • Mirrors the cooldown in Dependabot with cooldown.default-days: 2 across all five ecosystems (cargo, devcontainers, github-actions, npm, rust-toolchain).
  • Dependabot keeps package-ecosystem: "npm" — it auto-detects pnpm from pnpm-lock.yaml.

Notable changes

  • GitHub Actions: corepack enable added before setup-node; cache: pnpm; npm install/npm cipnpm install --frozen-lockfile; CI path triggers updated to pnpm-lock.yaml. Release publish uses pnpm publish --no-git-checks (tag-based release runs from detached HEAD).
  • @eslint/js added as explicit devDependency (pinned to ^9.39.4 to match the version previously hoisted by npm). pnpm's strict node_modules layout no longer satisfies it transitively via eslint.
  • esbuild install script allowlisted in pnpm-workspace.yaml — pnpm 11 blocks dependency build scripts by default.
  • Dev tooling: Taskfile.yml uses pnpm exec instead of npx; devcontainer setup, bump-version.js, and CONTRIBUTING.md updated.
  • package-lock.json removed, pnpm-lock.yaml added.

Test plan

  • pnpm install --frozen-lockfile clean (no ignored-build warnings)
  • task fmt:prettier:check passes
  • task lint:eslint passes
  • task check:typescript passes
  • task compile passes
  • CI green on all matrix entries
  • Release workflow (will be exercised on next tagged release)

Note

Medium Risk
Medium risk because it changes the project’s dependency manager and updates CI/release workflows (including Node version bumps and publishing via pnpm), which can break installs, caching, or the release pipeline if any step differs from npm behavior.

Overview
Migrates the repo’s JavaScript tooling from npm to pnpm (via Corepack): devcontainer setup, Taskfile.yml commands (npxpnpm exec), and package.json (packageManager, prepublishOnly) are updated accordingly, and package-lock.json is removed.

GitHub Actions workflows are updated to enable Corepack, use Node 22 for most jobs, switch install steps to pnpm install --frozen-lockfile, and adjust caching/CI triggers to pnpm-lock.yaml; the release workflow also switches publishing to pnpm publish --no-git-checks.

Adds a 2-day dependency “cooldown” policy: minimum-release-age=2880 in .npmrc and matching cooldown.default-days: 2 across Dependabot ecosystems, plus minor repo hygiene updates (e.g., ignoring pnpm-lock.yaml in Prettier and adding @eslint/js explicitly).

Reviewed by Cursor Bugbot for commit bb9eb35. Bugbot is set up for automated code reviews on this repo. Configure here.

Pins pnpm@11.1.2 via packageManager (Corepack) and sets
minimum-release-age=2880 in .npmrc so dependency resolution skips
versions younger than 2 days, mitigating supply-chain attacks via
quickly-yanked malicious releases. Dependabot gets a matching
cooldown.default-days: 2 across all five ecosystems.

GitHub Actions enable Corepack before setup-node and use cache: pnpm
with pnpm install --frozen-lockfile. Release publish uses pnpm publish
--no-git-checks since tag-based release runs from detached HEAD.

@eslint/js is added as an explicit devDependency pinned to ^9.39.4 —
pnpm's strict node_modules layout no longer satisfies it via npm's
flat hoisting. esbuild's install script is allowlisted via
pnpm-workspace.yaml (pnpm 11 blocks dependency build scripts by
default).

Taskfile, devcontainer setup, bump-version script, and CONTRIBUTING.md
updated for pnpm. package-lock.json replaced by pnpm-lock.yaml.
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 16, 2026

🧪 CI Results

Formatting

Check Status
Rust fmt
Prettier

Linting

Check Status
Clippy
ESLint

Tests

JavaScript Runtimes

Runtime Status Tests Coverage
🦕 Deno 44/44 passed 67% (456/684)
🥟 Bun 44/44 passed 79% (517/653)
🟢 Node.js 44/44 passed 78% (2636/3379)

Rust Library

Component Status Tests Coverage
🦀 Core 14/14 passed 40% (508/1282)

Overall Status: ✅ All checks passing

Last updated: 2026-05-16 00:24:54 UTC | View CI Run 🤖

Comment thread .github/workflows/release.yml
pnpm 11.1.2 uses node:sqlite, a builtin added in Node 22. Workflows
were pinned to Node 20, causing Corepack to fail with
ERR_UNKNOWN_BUILTIN_MODULE when downloading pnpm.

Library engines stays at >= 20 — consumers are unaffected. NAPI
binaries are not Node-version-coupled, so building on Node 22 is safe.
The publish job stays on Node 24.
pnpm publish writes to stderr only — it does not produce log files at
~/.npm/_logs/ like npm does. The upload step would always find zero
files. Failure diagnostics remain available via the GitHub Actions
step log for 'Publish to npm'.
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit bb9eb35. Configure here.

Comment thread .npmrc
@@ -1 +1,2 @@
@jsr:registry=https://npm.jsr.io
minimum-release-age=2880
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Supply-chain cooldown setting silently ignored by pnpm 11

High Severity

pnpm 11 only reads authentication and registry settings from .npmrc; all other settings must be in pnpm-workspace.yaml. The minimum-release-age=2880 line in .npmrc is silently ignored, so the intended 2-day supply-chain cooldown never takes effect. The setting belongs in pnpm-workspace.yaml as minimumReleaseAge: 2880 (camelCase). pnpm 11's built-in default of 1440 minutes (1 day) still applies, but the explicit 2-day policy matching the Dependabot cooldown.default-days: 2 configuration is not enforced, creating a false sense of security.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit bb9eb35. Configure here.

@esimkowitz esimkowitz merged commit 796dc97 into main May 16, 2026
15 checks passed
@esimkowitz esimkowitz deleted the chore/pnpm-migration branch May 16, 2026 23:53
esimkowitz added a commit that referenced this pull request May 17, 2026
#287)

* ci(release): pin publish job to Node 24 for npm OIDC trusted publisher

Node 22 ships npm 10.9.x, which lacks OIDC trusted publisher support
(introduced in npm 11.5.1). #274 unintentionally regressed the publish
job from node-version: 24 to node-version-file: .node-version (= 22),
causing v2.0.0 publish to fail with 404 because no NPM_TOKEN exists
and the OIDC handshake never ran.

Restore node-version: 24 on the publish job only. Build/test jobs
continue to use .node-version so the minimum-supported-runtime
guarantee remains tested.

* style: fix oxfmt quote style
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