Conversation
…cted command to avoid repeating lib builds
There was a problem hiding this comment.
Pull request overview
This PR implements comprehensive supply chain security improvements by upgrading to Yarn 4.12.0 and introducing package age gates, immutable lockfiles, and automated version validation. The changes modernize the development toolchain to protect against compromised npm packages while standardizing on Node 24 across all environments.
Key Changes:
- Added 7-day package age requirement (
npmMinimalAgeGate: 10080) to block newly published packages - Upgraded from Yarn 3.3.1 to 4.12.0 with Corepack-based version management
- Enabled immutable lockfile protection to prevent accidental mass upgrades
Reviewed changes
Copilot reviewed 18 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/scripts/check-package-manager.mjs | New preinstall hook that validates correct Yarn version via user agent parsing |
| package.json | Updated to Yarn 4.12.0, added preinstall/postinstall scripts, blocked npm usage, added prettier dependency |
| packages/*/package.json (9 files) | Removed individual volta version pins (now centralized in root package.json) |
| .yarnrc.yml | Configured npmMinimalAgeGate (7 days), enableImmutableInstalls, removed Yarn 3 plugins |
| .npmrc | Added engine-strict enforcement to block npm with clear error messages |
| .github/workflows/*.yml (3 files) | Standardized on Node 24.11.0, added corepack, improved caching, removed redundant build step |
| README.adoc | Comprehensive documentation of new setup requirements and security features |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| // Read expected version from package.json | ||
| const packageJson = JSON.parse(readFileSync(join(repoRoot, 'package.json'), 'utf-8')); | ||
| const expectedVersion = packageJson.packageManager?.replace('yarn@', ''); |
There was a problem hiding this comment.
The replace() method only replaces the first occurrence. If packageManager contains multiple '@' characters (e.g., 'yarn@4.12.0@something'), this could produce incorrect results. Use packageJson.packageManager?.split('@')[1] or add a regex with proper anchoring: replace(/^yarn@/, '') to ensure only the prefix is removed.
| const expectedVersion = packageJson.packageManager?.replace('yarn@', ''); | |
| const expectedVersion = packageJson.packageManager?.split('@')[1]; |
| "packages/sites/*" | ||
| ], | ||
| "scripts": { | ||
| "preinstall": "node tools/scripts/check-package-manager.mjs", |
There was a problem hiding this comment.
[nitpick] The preinstall script runs for every yarn install, including in CI. Consider whether this adds unnecessary overhead in trusted environments like GitHub Actions where the Yarn version is already guaranteed by corepack. You could make the check conditional (e.g., skip if CI=true environment variable is set) to reduce execution time in automated workflows.
| "preinstall": "node tools/scripts/check-package-manager.mjs", | |
| "preinstall": "if [ \"$CI\" != \"true\" ]; then node tools/scripts/check-package-manager.mjs; fi", |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
Note: we are not cherry-picking this into the legacy deployment branch It's not really needed there and there are yarn.lock file merge complications. |
* node 14 to 24 upgrade in github actions * remove broken condition in cache.yml workflow * start setting up for yarn 4.10.3 with corepack * more corepack/volta config * better docs for volta users * remove volta configs from sub-packages * minutes not nice time strings * indentation error fixed * enable corepack in github actions * rejig corepack and cache config * upgrade to latest action plugin versions * document sunsetting of cache.yml * pin Node version exactly in actions * try caching NX cache too * move comment, mainly to trigger new action * add built package lib dirs to cache * add --verbose to understand nx behaviour * abandon trying to cache nx between actions; only run one yarn nx affected command to avoid repeating lib builds * upgrade to yarn 4.12.0 for no urgent reason * more checks on yarn versions and attempts/documentation to prevent npm usage * added lockfile checks for devs too, improved documentation * Explain minutes value Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
What does this PR do?
This PR implements several security improvements and modernizes our development tooling to protect against supply chain attacks (when malicious code sneaks into our project through compromised npm packages).
Key Changes
1. Supply Chain Security: 7-Day Package Age Requirement 🛡️
What changed: Added
npmMinimalAgeGate: 10080to.yarnrc.ymlWhat this means: Yarn will now refuse to install any npm package that's less than 7 days old (10080 minutes = 7 days).
Why this helps: If a popular package gets compromised, it usually gets detected and fixed within a few days. By waiting 7 days before allowing new package versions, we avoid automatically pulling in malicious code that might have just been published.
Example: If someone publishes
react@19.0.0-malwaretoday (December 1), our project won't be able to install it until December 8, giving the security community time to catch and report it.2. Upgraded to Yarn 4.12.0 📦
What changed: Updated from Yarn 3.3.1 to Yarn 4.12.0 using Corepack
Why:
npmMinimalAgeGatesecurity feature (not available in Yarn 3)What you need to do:
3. Package Manager Validation ✅
What changed: Added
tools/scripts/check-package-manager.mjsthat runs before everyyarn installWhat this does:
What you'll see:
✓ Yarn version check passed4. Immutable Lockfile Protection 🔒
(See also VEuPathDB/install#42 which will be merged soon.)
What changed: Added
enableImmutableInstalls: trueto.yarnrc.ymlWhat this means: The
yarn.lockfile cannot be modified by runningyarn install. It must be properly committed to git.Why this helps:
yarn.lock, many packages would upgrade to newer versions)How it affects you:
yarn add date-fns- works normally, updates lockfile as expectedyarn remove lodash- works normally, updates lockfile as expectedyarn install- works if lockfile is up to dateyarn install- fails if lockfile is missing or out of sync (intentional protection!)Error you might see:
What to do: Make sure your
yarn.lockis committed and up to date. Don't try to regenerate it from scratch - dependency upgrades should be intentional.5. Blocked npm Usage 🚫
What changed:
.npmrcwithengine-strict=true"npm": "please-use-yarn"to package.json enginesWhy: This project uses Yarn-specific features that npm doesn't support. These changes are intended to give developers a clear error if they accidentally try
npm installinstead ofyarn install. However, this does not preventnpm installfrom doing initial dependency checks which will fail with a cryptic error message about dependency failures. This measure is just belt-and-braces.6. Standardized on Node 24 ⬆️
What changed: All GitHub Actions workflows now consistently use Node 24.11.0, and local development environment updated to match
Why:
7. Improved CI Caching ⚡
What changed:
.yarn/cacheand.yarn/install-state.gzImpact: Faster CI builds (~300MB cache, much faster yarn install)
8. Simplified CI Build Process 🎯
What changed: Removed separate
yarn nx affected --target=build-npm-modulesstep from PR checksWhy: The
compile:checktarget automatically builds dependencies (configured via NX'sdependsOn), so we were building things twice. Now we just runcompile:checkonce.9. Cleaned Up Configuration 🧹
What changed:
Why: Simplify configuration and remove obsolete/conflicting settings
What do I need to do?
First Time Setup (One-time per machine):
Regular Development:
Nothing changes! Just use
yarncommands as normal:yarn install- installs dependencies (with 7-day age check)yarn nx start @veupathdb/genomics-site- start dev serverSecurity Benefits Summary
Questions?
Q: What if I need a package that was just published?
A: You'll need to wait 7 days, or temporarily disable the check (not recommended). This is intentional - fresh packages are risky.
Q: Will this slow down my development?
A: No! The age check only affects new packages you're adding. Existing dependencies install normally.
Q: What if I see "Expected Yarn 4.12.0 but got 1.22.22"?
A: Run
corepack enable --install-directory ~/.volta/bin(see setup instructions in README.adoc)Q: Can I still use npm?
A: No, this project requires Yarn.
npm installwill fail.Q: What if I see "The lockfile would have been modified by this install"?
A: This means your
yarn.lockis out of sync withpackage.json. Make sure you've pulled the latest changes from git. If you're intentionally adding/removing packages, useyarn addoryarn remove(not plainyarn install).Technical Details
For more information about the security features:
Testing
You can force the wrong version of
yarnwith something like this:An npm publish action has been tested on this branch and it succeeded:
https://github.com/VEuPathDB/web-monorepo/actions/runs/19822162339