feat(node): gracefully handle out of sync package-lock.json (#643)

* feat(node): add out-of-sync package-lock npm example

- Add new example demonstrating npm ci failure with an out-of-sync lockfile
- Include test configuration and documentation for the scenario

Generated-by: aiautocommit

* fix(node): fallback to npm install when lockfile is missing

- Always use `npm install` for npm projects to prevent build failures when `package-lock.json` is missing.
- Log a warning when the lockfile is absent to encourage generating one.
- Clean up outdated comments regarding package manifest parsing.

Generated-by: aiautocommit

* test(core): update test snapshots for npm install changes

Generated-by: aiautocommit

* feat(node): add npm ci recommendation and railpack example

- Document recommendations for preferring `npm ci` over `npm install` for Node.js projects using npm.
- Add a corresponding `railpack.json` example demonstrating how to configure deterministic installs with `npm ci`.

Generated-by: aiautocommit

* refactor(core): use npm ci in build plan for node npm examples

- Switch from `npm install` to `npm ci` for deterministic builds when package-lock.json is present.
- Remove redundant cache directory creation step.

Generated-by: aiautocommit

* feat(node): add suggestions for missing lockfiles

- Log suggestions when `package-lock.json` or `pnpm-lock.yaml` is missing to encourage deterministic installs.
- Update architecture documentation with guidance on committing `package-lock.json`.

Generated-by: aiautocommit

* test(core): update out-of-sync package-lock snapshot for builder changes

Generated-by: aiautocommit

* feat(node): allow overriding npm install command via config variable

Generated-by: aiautocommit

* docs(node): document RAILPACK_NODE_NPM_INSTALL environment variable

Generated-by: aiautocommit

* docs: recommend committing all package manager lockfiles

Generated-by: aiautocommit
This commit is contained in:
Michael Bianco
2026-07-27 06:50:07 -06:00
committed by GitHub
parent 5814dcc0e6
commit ac1fbbafa3
32 changed files with 357 additions and 32 deletions
+20
View File
@@ -0,0 +1,20 @@
{
"$schema": "https://schema.railpack.com",
"steps": {
"install": {
// Railpack defaults to `npm install` so out-of-sync lockfiles still succeed.
// Opt into `npm ci` when the lockfile is kept in sync for deterministic installs.
//
// Configuring a step auto-adds it to deploy with include: ["."]. Use an empty
// deployOutputs so install is not copied into the final image; node_modules
// still reach the image via the build step.
"deployOutputs": [],
"commands": [
{ "path": "/app/node_modules/.bin" },
{ "src": "package-lock.json", "dest": "package-lock.json" },
{ "src": "package.json", "dest": "package.json" },
"npm ci"
]
}
}
}
@@ -0,0 +1,9 @@
# Out-of-sync npm lockfile
This example intentionally keeps `package-lock.json` out of sync with
`package.json` to reproduce an `npm ci` failure. The lockfile was generated
with only `dayjs` installed; `is-number` was then added to `package.json`
without regenerating the lockfile.
Do not run `npm install` in this directory unless you are recreating the
out-of-sync fixture.
@@ -0,0 +1,4 @@
import dayjs from "dayjs";
import isNumber from "is-number";
console.log(`npm dependencies loaded: ${dayjs("2026-07-21").format("YYYY-MM-DD")} ${isNumber(42)}`);
+21
View File
@@ -0,0 +1,21 @@
{
"name": "npm-out-of-sync-package-lock",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "npm-out-of-sync-package-lock",
"version": "1.0.0",
"dependencies": {
"dayjs": "1.11.13"
}
},
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
"license": "MIT"
}
}
}
@@ -0,0 +1,13 @@
{
"name": "npm-out-of-sync-package-lock",
"private": true,
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"dayjs": "1.11.13",
"is-number": "7.0.0"
}
}
@@ -0,0 +1,7 @@
[
{
"expectedOutput": "npm dependencies loaded: 2026-07-21 true",
// NPM_CONFIG_PRODUCTION currently emits a deprecation warning during installation.
"stderrAllowed": true
}
]