Summary
Every workflow that installs dependencies runs npm install. It should run npm ci, so that CI and the deploy servers install exactly the tree recorded in package-lock.json.
Why this matters
npm install is allowed to resolve newer versions inside the declared semver ranges and to rewrite package-lock.json in place. Two consequences:
- The CI test job can pass against a dependency tree that is not the one reviewed and approved in the PR.
- The deploy servers can install a tree that was never tested anywhere.
npm ci installs the lockfile exactly, never writes to it, and fails loudly if package.json and package-lock.json have drifted apart.
This surfaced while reviewing #293, which curates the dependency set so that npm-check and npm audit are both clean. That work only holds if the lockfile is what actually gets installed.
Affected lines
| File |
Line |
Current |
.github/workflows/cd_dev.yaml |
29 |
run: npm install (test job) |
.github/workflows/cd_dev.yaml |
59 |
npm install (deploy step) |
.github/workflows/cd_prod.yaml |
31 |
run: npm install (test job) |
.github/workflows/cd_prod.yaml |
58 |
npm install (deploy step) |
Proposed change
Test jobs:
- name: Install dependencies
run: npm ci
- name: Generate coverage report
run: npm run coverage:ci
Deploy steps: npm ci. Worth considering npm ci --omit=dev on the deploy steps as well, since a bare install currently puts c8, supertest, yargs, glob, and the rest of the test tooling into production node_modules. That is a related but separable concern — happy to split it into its own issue if preferred.
Notes
- The lockfile is already
ci-ready. Verified on the 8-24-26-packages branch: npm ci in a clean directory installs 169 packages and reports 0 vulnerabilities.
npm ci requires package-lock.json to exist and to agree with package.json. Both hold today.
npm ci deletes node_modules before installing. On the self-hosted deploy runners (vlcdhp02, vlcdhprdp02) this makes installs slower but reproducible. The actions/cache@v4 step already in both workflows should absorb most of that cost on the GitHub-hosted test jobs.
Acceptance criteria
Summary
Every workflow that installs dependencies runs
npm install. It should runnpm ci, so that CI and the deploy servers install exactly the tree recorded inpackage-lock.json.Why this matters
npm installis allowed to resolve newer versions inside the declared semver ranges and to rewritepackage-lock.jsonin place. Two consequences:npm ciinstalls the lockfile exactly, never writes to it, and fails loudly ifpackage.jsonandpackage-lock.jsonhave drifted apart.This surfaced while reviewing #293, which curates the dependency set so that
npm-checkandnpm auditare both clean. That work only holds if the lockfile is what actually gets installed.Affected lines
.github/workflows/cd_dev.yamlrun: npm install(test job).github/workflows/cd_dev.yamlnpm install(deploy step).github/workflows/cd_prod.yamlrun: npm install(test job).github/workflows/cd_prod.yamlnpm install(deploy step)Proposed change
Test jobs:
Deploy steps:
npm ci. Worth consideringnpm ci --omit=devon the deploy steps as well, since a bare install currently putsc8,supertest,yargs,glob, and the rest of the test tooling into productionnode_modules. That is a related but separable concern — happy to split it into its own issue if preferred.Notes
ci-ready. Verified on the8-24-26-packagesbranch:npm ciin a clean directory installs 169 packages and reports 0 vulnerabilities.npm cirequirespackage-lock.jsonto exist and to agree withpackage.json. Both hold today.npm cideletesnode_modulesbefore installing. On the self-hosted deploy runners (vlcdhp02,vlcdhprdp02) this makes installs slower but reproducible. Theactions/cache@v4step already in both workflows should absorb most of that cost on the GitHub-hosted test jobs.Acceptance criteria
cd_dev.yamlandcd_prod.yamlusenpm ciin the test jobscd_dev.yamlandcd_prod.yamlusenpm ciin the deploy stepspackage-lock.jsonunmodified afterward