diff --git a/.changeset/node-24-22-1.md b/.changeset/node-24-22-1.md new file mode 100644 index 000000000..59d651ccf --- /dev/null +++ b/.changeset/node-24-22-1.md @@ -0,0 +1,5 @@ +--- + +--- + +Pin the development toolchain to Node.js 24.22.1, the latest 24.x release. diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 6786e9b55..4796bc0c5 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -27,7 +27,7 @@ RUN curl https://get.volta.sh | bash WORKDIR /workspaces/macs-configurator # and install node and pnpm -RUN volta install node@24 +RUN volta install node@24.22.1 RUN npm i -g pnpm RUN echo diff --git a/.github/npm-trusted-publishing.md b/.github/npm-trusted-publishing.md index 1d8ef5874..0eaf53c68 100644 --- a/.github/npm-trusted-publishing.md +++ b/.github/npm-trusted-publishing.md @@ -15,13 +15,13 @@ Official docs: https://docs.npmjs.com/trusted-publishers/ Configure **each** publishable package (one trusted publisher per package): -| Package | npm settings URL | -| --- | --- | -| `effect-app` | https://www.npmjs.com/package/effect-app/access | -| `@effect-app/infra` | https://www.npmjs.com/package/@effect-app/infra/access | -| `@effect-app/vue` | https://www.npmjs.com/package/@effect-app/vue/access | -| `@effect-app/vue-components` | https://www.npmjs.com/package/@effect-app/vue-components/access | -| `@effect-app/cli` | https://www.npmjs.com/package/@effect-app/cli/access | +| Package | npm settings URL | +| ---------------------------------- | --------------------------------------------------------------------- | +| `effect-app` | https://www.npmjs.com/package/effect-app/access | +| `@effect-app/infra` | https://www.npmjs.com/package/@effect-app/infra/access | +| `@effect-app/vue` | https://www.npmjs.com/package/@effect-app/vue/access | +| `@effect-app/vue-components` | https://www.npmjs.com/package/@effect-app/vue-components/access | +| `@effect-app/cli` | https://www.npmjs.com/package/@effect-app/cli/access | | `@effect-app/eslint-codegen-model` | https://www.npmjs.com/package/@effect-app/eslint-codegen-model/access | | `@effect-app/eslint-shared-config` | https://www.npmjs.com/package/@effect-app/eslint-shared-config/access | @@ -37,7 +37,7 @@ Repeat for every package in the table: 4. Fill in exactly: - **Organization or user:** `effect-app` - **Repository:** `libs` - - **Workflow filename:** `release.yaml` + - **Workflow filename:** `release.yaml`\ (filename only, including `.yaml` — not `.yml`, not a path) - **Environment name:** leave **empty** (unless you later add a GitHub Environment to the job) - **Allowed actions:** select **`npm publish`** (required) @@ -50,7 +50,7 @@ npm does **not** validate the config on save — mismatches only show up at publ 1. **Configure trusted publishers** for all packages above (npm side). 2. **Merge** the PR that enables OIDC in `.github/workflows/release.yaml` (`id-token: write`, no `NPM_TOKEN` on publish). 3. On push to `main`, the Changesets workflow publishes any unpublished versions. -4. Confirm success in the Actions log: look for +4. Confirm success in the Actions log: look for\ `No NPM_TOKEN found, but OIDC is available - using npm trusted publishing`. 5. After a successful OIDC publish, optionally harden each package: - **Publishing access** → **Require two-factor authentication and disallow tokens** @@ -65,19 +65,19 @@ Live workflow: **`.github/workflows/release.yaml`**. It includes: - `permissions.id-token: write` -- Node `24` (latest 24.x; npm 12 needs Node ≥ `24.15` — pin the major, not a stale patch like `24.14`) +- Node `24.22.1` (latest 24.x; npm 12 needs Node ≥ `24.15`) - Workflow upgrades to `npm@latest` after setup-node (OIDC needs npm ≥ `11.5.1`) - **No** `NPM_TOKEN` on the publish step - Package `repository.url` points at `https://github.com/effect-app/libs.git` (set in package.json) ## Troubleshooting -| Symptom | Likely cause | -| --- | --- | +| Symptom | Likely cause | +| ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | `E404` / “could not be found or you do not have permission” | Trusted publisher mismatch (org/repo/workflow filename), or OIDC not used because `NPM_TOKEN` is still set | -| `ENEEDAUTH` / unable to authenticate | Missing `id-token: write`, old npm CLI, or self-hosted runner (not supported) | -| Only some packages publish | Trusted publisher missing on those packages | -| `EBADENGINE` installing `npm@latest` | Node pin too old (e.g. `24.14`); use major `24` so runners are ≥ `24.15` | +| `ENEEDAUTH` / unable to authenticate | Missing `id-token: write`, old npm CLI, or self-hosted runner (not supported) | +| Only some packages publish | Trusted publisher missing on those packages | +| `EBADENGINE` installing `npm@latest` | Node pin too old (npm 12 needs ≥ `24.15`); use `24.22.1` or newer 24.x | ## Optional hardening diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 387d897ee..53432c967 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v4 with: - node-version: 24 + node-version: 24.22.1 - name: Install pnpm uses: pnpm/action-setup@v6.1.0 @@ -79,7 +79,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v4 with: - node-version: 24 + node-version: 24.22.1 - name: Install pnpm uses: pnpm/action-setup@v6.1.0 @@ -130,7 +130,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v4 with: - node-version: 24 + node-version: 24.22.1 - name: Install pnpm uses: pnpm/action-setup@v6.1.0 diff --git a/.github/workflows/publish-snapshot.yml b/.github/workflows/publish-snapshot.yml index 5822d4138..50e8c17f2 100644 --- a/.github/workflows/publish-snapshot.yml +++ b/.github/workflows/publish-snapshot.yml @@ -22,7 +22,7 @@ jobs: - name: Install Node.js uses: actions/setup-node@v4 with: - node-version: 24 + node-version: 24.22.1 - name: Install pnpm uses: pnpm/action-setup@v6.1.0 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6b659168d..470d02444 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -43,8 +43,8 @@ jobs: - name: Install Node.js uses: actions/setup-node@v4 with: - # Major pin = latest 24.x (CI uses `latest`). npm@12 needs Node >= 24.15. - node-version: 24 + # Latest 24.x. npm@12 needs Node >= 24.15. + node-version: 24.22.1 registry-url: https://registry.npmjs.org # Trusted publishing requires npm CLI >= 11.5.1; keep CLI current on this Node line. diff --git a/.nvmrc b/.nvmrc index b6f5ce1e9..474d750b5 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v22.23 +v24.22.1 diff --git a/flake.nix b/flake.nix index ebdfabae1..0bb19098a 100644 --- a/flake.nix +++ b/flake.nix @@ -1,5 +1,5 @@ { - description = "Node 24 + pnpm 12 dev shell"; + description = "Node 24.22.1 + pnpm 12 dev shell"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; @@ -10,7 +10,50 @@ flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; }; - nodejs = pkgs.nodejs_24; + # nixpkgs nodejs_24 lags the latest 24.x patch (this lock still has + # 24.14.1). Fetch the official binary instead. + nodejsVersion = "24.22.1"; + nodejsSources = { + x86_64-linux = { + url = "https://nodejs.org/dist/v${nodejsVersion}/node-v${nodejsVersion}-linux-x64.tar.xz"; + hash = "sha256-bBcqmrZxj3uAH7WnvUhq8u5eMnWAhqBLhPzOKqdwleY="; + }; + aarch64-linux = { + url = "https://nodejs.org/dist/v${nodejsVersion}/node-v${nodejsVersion}-linux-arm64.tar.xz"; + hash = "sha256-26v3ocv5R+YFn/rSwnuABB25feoeVTtir97n8T/KM24="; + }; + x86_64-darwin = { + url = "https://nodejs.org/dist/v${nodejsVersion}/node-v${nodejsVersion}-darwin-x64.tar.xz"; + hash = "sha256-ZeRQ+Qpuqs1QAPYRhhxM5l+tyH+BN5XcTtDA5fL8otQ="; + }; + aarch64-darwin = { + url = "https://nodejs.org/dist/v${nodejsVersion}/node-v${nodejsVersion}-darwin-arm64.tar.xz"; + hash = "sha256-ZUunneYVVkfiIyGTK0Xyocy3BZdswzfJuOJ4vrCFpig="; + }; + }; + nodejsSrc = nodejsSources.${system} or (throw "no nodejs ${nodejsVersion} binary for ${system}"); + nodejs = pkgs.stdenv.mkDerivation { + pname = "nodejs"; + version = nodejsVersion; + src = pkgs.fetchurl nodejsSrc; + sourceRoot = "node-v${nodejsVersion}-${ + if pkgs.stdenv.isDarwin then "darwin" else "linux" + }-${ + if pkgs.stdenv.isAarch64 then "arm64" else "x64" + }"; + nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.autoPatchelfHook ]; + buildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.stdenv.cc.cc.lib ]; + dontConfigure = true; + dontBuild = true; + # The official binary embeds a V8 snapshot. Stripping breaks it. + dontStrip = true; + installPhase = '' + runHook preInstall + mkdir -p $out + cp -a * $out/ + runHook postInstall + ''; + }; # pnpm 12 is a native binary. The JavaScript tarball only installs that # binary, and nixpkgs generic.nix still links bin/pnpm.cjs, so fetch the # platform package. Hardlinks, not symlinks: the binary reads its own diff --git a/package.json b/package.json index 48ead372c..fede8160b 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "private": true, "packageManager": "pnpm@12.14.0", "engines": { - "node": ">=24", + "node": ">=24.22.1", "pnpm": ">= 12.0.0" }, "scripts": {