Pin All NPM Dependencies to Exact Versions
INFO
This document represents an architecture decision record (ADR) and has been mirrored from the ADR section in our Shopware 6 repository. You can find the original version here
Context
NPM dependencies with range specifiers (e.g., ^1.2.3 or ~1.2.3) allow automatic updates to newer compatible versions during installation. While convenient for library development, this creates several risks for application development:
- Non-Deterministic Builds: Different developers or CI runs may install different versions, leading to "works on my machine" issues
- Security Risk Window: Malicious packages can be introduced through automatic version updates without explicit review
- Breaking Changes: Even minor/patch updates can introduce bugs or breaking changes despite semantic versioning
- Difficult Debugging: Inconsistent dependency versions across environments make issues harder to reproduce and diagnose
Decision
All NPM dependencies in Shopware 6 must be pinned to exact versions without range specifiers:
- ❌
"package": "^1.2.3"or"package": "~1.2.3" - ✅
"package": "1.2.3"
This applies to both dependencies and devDependencies in all package.json files throughout the repository.
Automated CI checks have been implemented to:
- Discover all
package.jsonfiles in the repository - Validate that no unpinned dependencies exist
- Block merges if unpinned dependencies are found
These checks run via the npm-audit-check.yml workflow. Pull requests and pushes to trunk run audits only for tracked packages whose package.json, package-lock.json, or scripts/runNpmAudit.ts changed. Scheduled and manual runs still execute the full audit matrix for all tracked packages, and scheduled audit failures create or update one GitHub issue with the latest affected packages.
Consequences
Positive
- Reproducible Builds: Identical dependency versions across all environments (local, CI, production)
- Explicit Updates: Dependency updates require intentional changes and code review
- Enhanced Security: Prevents automatic installation of compromised package versions
- Easier Debugging: Consistent versions make issues reproducible and easier to diagnose
- Automated Enforcement: CI pipeline ensures compliance without manual review
Negative
- Manual Dependency Updates: Developers must explicitly update dependencies using
npm updateornpm install package@version - Increased Maintenance: Regular dependency updates require more conscious effort
- More Frequent PRs: Security patches and updates must be applied through explicit pull requests
For Developers
When adding or updating dependencies:
- Always specify exact versions in
package.json - Run
npm installto updatepackage-lock.json - The CI pipeline will reject PRs with unpinned dependencies
- Use tools like
npm outdatedto check for available updates
Updates
- 2025-11-15: PR audit run with pinned dependencies only, not on all npm packages in repository