Local development on one Node major (e.g. 20) while CI runs another (e.g. 22) lets version-specific breakage slip through review — a syntax/API difference passes locally and only fails after merge, or worse, ships. For a prediction-market backend that means trades, resolutions, or admin actions silently failing in production.
This repo pins one Node major and one pnpm major, and enforces that pin everywhere.
| Where | File / setting | Value |
|---|---|---|
Version managers (nvm, ...) |
.nvmrc |
22 |
| Package manifest floor | package.json → engines.node |
>=22.0.0 |
| Package manifest floor | package.json → engines.pnpm |
>=10.0.0 |
| CI runner | .github/workflows/ci.yml → actions/setup-node node-version-file |
.nvmrc |
| Container image | Dockerfile → ARG NODE_VERSION |
22-* |
CI reads .nvmrc directly (node-version-file: ".nvmrc"), so bumping the
Node major is a one-line change to .nvmrc plus the engines.node floor.
pnpm installfail-fast —.npmrcsetsengine-strict=true, so pnpm refuses to install under a Node or pnpm version outsideengines.pnpm engines:check(scripts/check-engines.ts) — verifies the running Node/pnpm satisfyenginesand that.nvmrc, theengines.nodefloor, and the CI workflow all agree on the same Node major.engine-strictcannot see config files drifting apart from each other; this can.- CI (
CIset) orNODE_ENV=production: exits non-zero on any drift. - Local dev: warn-only (exit 0) — you get a nudge to run
nvm usewithout being blocked mid-task.
- CI (
- CI step —
Enforce engine parity (Node/pnpm)runspnpm engines:checkright afterpnpm install, so a drifted.nvmrc/workflow/manifest fails the build.
- Update
.nvmrc(Node) and/orpackage.jsonenginesfloors. - Update
DockerfileARG NODE_VERSIONto match the Node major. - Run
pnpm engines:checklocally, thennvm use. tests/config/engine-enforcement.test.tsfails if any of these drift apart.