Skip to content

Commit

Permalink
Add CI job to check npm dependencies (facebook#22881)
Browse files Browse the repository at this point in the history
Checks that if one React package depends on another, the current
version satisfies the given dependency range.

That way we don't forget to bump dependencies when we release a
new version.
  • Loading branch information
acdlite authored and zhengjitf committed Apr 15, 2022
1 parent 7c2eefe commit bc7f921
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
18 changes: 17 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,24 @@ jobs:
environment: *environment
steps:
- checkout
- attach_workspace: *attach_workspace
- attach_workspace:
at: .
- run: yarn workspaces info | head -n -1 > workspace_info.txt
- *restore_node_modules
- run: yarn lint-build

yarn_check_release_dependencies:
docker: *docker
environment: *environment
steps:
- checkout
- attach_workspace:
at: .
- run: yarn workspaces info | head -n -1 > workspace_info.txt
- *restore_node_modules
- run: yarn check-release-dependencies


check_error_codes:
docker: *docker
environment: *environment
Expand Down Expand Up @@ -427,6 +440,9 @@ workflows:
- yarn_lint_build:
requires:
- yarn_build_combined
- yarn_check_release_dependencies:
requires:
- yarn_build_combined
- check_error_codes:
requires:
- yarn_build_combined
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@
"publish-prereleases": "node ./scripts/release/publish-using-ci-workflow.js",
"download-build": "node ./scripts/release/download-experimental-build.js",
"download-build-for-head": "node ./scripts/release/download-experimental-build.js --commit=$(git rev-parse HEAD)",
"download-build-in-codesandbox-ci": "cd scripts/release && yarn install && cd ../../ && yarn download-build-for-head || yarn build-combined --type=node react/index react-dom scheduler"
"download-build-in-codesandbox-ci": "cd scripts/release && yarn install && cd ../../ && yarn download-build-for-head || yarn build-combined --type=node react/index react-dom scheduler",
"check-release-dependencies": "node ./scripts/release/check-release-dependencies"
},
"resolutions": {
"react-is": "npm:react-is"
Expand Down
59 changes: 59 additions & 0 deletions scripts/release/check-release-dependencies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use strict';

/* eslint-disable no-for-of-loops/no-for-of-loops */

const fs = require('fs');
const semver = require('semver');

const {stablePackages} = require('../../ReactVersions');

function main() {
if (!fs.existsSync('./build/oss-stable-semver')) {
throw new Error('No build artifacts found');
}

const packages = new Map();
for (const packageName in stablePackages) {
if (!fs.existsSync(`build/oss-stable-semver/${packageName}/package.json`)) {
throw new Error(`${packageName}`);
} else {
const info = JSON.parse(
fs.readFileSync(`build/oss-stable-semver/${packageName}/package.json`)
);
packages.set(info.name, info);
}
}

for (const [packageName, info] of packages) {
if (info.dependencies) {
for (const [depName, depRange] of Object.entries(info.dependencies)) {
if (packages.has(depName)) {
const releaseVersion = packages.get(depName).version;
checkDependency(packageName, depName, releaseVersion, depRange);
}
}
}

if (info.peerDependencies) {
for (const [depName, depRange] of Object.entries(info.peerDependencies)) {
if (packages.has(depName)) {
const releaseVersion = packages.get(depName).version;
checkDependency(packageName, depName, releaseVersion, depRange);
}
}
}
}
}

function checkDependency(packageName, depName, version, range) {
if (!semver.satisfies(version, range)) {
throw new Error(
`${packageName} has an invalid dependency on ${depName}: ${range}` +
'\n\n' +
'Actual version is: ' +
version
);
}
}

main();

0 comments on commit bc7f921

Please sign in to comment.