diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e72422..48e0ffe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,12 +15,12 @@ jobs: uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: 'pnpm' - name: Install dependencies @@ -43,12 +43,12 @@ jobs: uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: 'pnpm' - name: Install dependencies @@ -67,12 +67,12 @@ jobs: uses: actions/checkout@v4 - name: Setup pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: 'pnpm' - name: Install dependencies diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3ca27bd..ab4799c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -132,18 +132,19 @@ jobs: fetch-depth: 0 - name: Setup pnpm - uses: pnpm/action-setup@v2 + uses: pnpm/action-setup@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: 'pnpm' registry-url: 'https://registry.npmjs.org' - name: Upgrade npm - # Trusted publishing (OIDC) requires npm >= 11.5.1, newer than the - # version bundled with Node 20. Without this, publish fails with a + # Trusted publishing (OIDC) requires npm >= 11.5.1. Node 24 already + # bundles a new enough npm, but pinning to latest keeps this working if + # the runner's Node ever moves back. Without it, publish fails with a # misleading 404 on the PUT to the registry. run: npm install -g npm@latest diff --git a/.gitignore b/.gitignore index 7aaaea8..7a219e8 100644 --- a/.gitignore +++ b/.gitignore @@ -14,11 +14,10 @@ coverage/ .env .env.local .env.*.local -.envrc -.direnv -flake.nix -flake.lock +# Nix: flake.nix and flake.lock are tracked; direnv setup is per-developer +.envrc +.direnv/ # IDE .vscode/ diff --git a/README.md b/README.md index aaf5979..12fc7b5 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,12 @@ Monorepo for @parallel-web npm packages. ## Development -This is a pnpm monorepo. Make sure you have pnpm installed: +This is a pnpm monorepo requiring Node >= 22.13. The pnpm version is pinned by +the `packageManager` field in `package.json`, so use corepack rather than a +globally installed pnpm: ```bash -npm install -g pnpm +corepack enable ``` ### Setup @@ -25,6 +27,18 @@ Install dependencies: pnpm install ``` +#### With Nix (optional) + +A flake provides Node and a corepack-backed `pnpm` matching CI: + +```bash +nix develop +pnpm install +``` + +With [direnv](https://direnv.net), `echo "use flake" > .envrc && direnv allow` +enters the shell automatically. `.envrc` is gitignored, so this stays per-developer. + ### Commands ```bash diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..e2bc577 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1786348146, + "narHash": "sha256-we5zDEFfn8TgzeWKjKDMIjeQZ59omEPl23NIF+13/ys=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d482ef84049d9b7276b83a06e4e4d76983830097", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..8bfbbf1 --- /dev/null +++ b/flake.nix @@ -0,0 +1,55 @@ +{ + description = "Nix flake for the @parallel-web npm packages monorepo"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { + self, + nixpkgs, + flake-utils, + ... + }: + flake-utils.lib.eachDefaultSystem (system: let + pkgs = import nixpkgs { + inherit system; + }; + + # pnpm comes from corepack rather than nixpkgs, so the version always + # matches package.json's "packageManager" field (and therefore CI and the + # lockfile) instead of drifting with nixpkgs. + pnpm = pkgs.writeShellScriptBin "pnpm" '' + exec corepack pnpm "$@" + ''; + in { + devShells.default = pkgs.mkShell { + # nodejs_24 ships corepack, which is what resolves and runs the exact + # pnpm pinned by package.json's "packageManager" field. + packages = with pkgs; [ + nodejs_24 + pnpm + git + ]; + + env = { + # corepack shims must never block on a y/n prompt when they download + # the pinned package manager (CI, first shell entry, etc). + COREPACK_ENABLE_DOWNLOAD_PROMPT = "0"; + }; + + shellHook = '' + echo "parallel-npm-packages dev shell" + echo "node: $(node --version 2>/dev/null)" + echo "corepack: $(corepack --version 2>/dev/null)" + echo "pnpm: $(pnpm --version 2>/dev/null)" + echo + echo "Suggested setup:" + echo " pnpm install" + echo " pnpm build" + echo " pnpm test" + ''; + }; + }); +} diff --git a/package.json b/package.json index 4f6d600..2d6407e 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,8 @@ "vitest": "^1.0.4" }, "engines": { - "node": ">=18.0.0", - "pnpm": ">=9.0.0" + "node": ">=22.13.0", + "pnpm": ">=11.0.0" }, - "packageManager": "pnpm@9.15.2" + "packageManager": "pnpm@11.21.0" } diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 18ec407..0492a27 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,12 @@ packages: - 'packages/*' + +# pnpm >= 11 refuses to install unless every dependency lifecycle script is +# explicitly allowed or denied. esbuild's postinstall fetches its platform +# binary; nothing else here needs to run code at install time. +allowBuilds: + '@google/genai': false + esbuild: true + koffi: false + msgpackr-extract: false + protobufjs: false