@samitouri / QOS-React-2 / commits / 06f403481f

Add CI job to check npm dependencies (#22881)

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.

Andrew Clark committed Dec 8, 2021 at 02:09 UTC 06f403481fe1f30d6952ad60ecd759b410962926
3 files changed +78 -2
.circleci/config.yml
+17 -1
@@ -205,11 +205,24 @@ jobs:
205 environment: *environment
206 steps:
207 - checkout
208 - - attach_workspace: *attach_workspace
208 + - attach_workspace:
209 + at: .
210 - run: yarn workspaces info | head -n -1 > workspace_info.txt
211 - *restore_node_modules
212 - run: yarn lint-build
213
214 + yarn_check_release_dependencies:
215 + docker: *docker
216 + environment: *environment
217 + steps:
218 + - checkout
219 + - attach_workspace:
220 + at: .
221 + - run: yarn workspaces info | head -n -1 > workspace_info.txt
222 + - *restore_node_modules
223 + - run: yarn check-release-dependencies
224 +
225 +
226 check_error_codes:
227 docker: *docker
228 environment: *environment
@@ -427,6 +440,9 @@ workflows:
440 - yarn_lint_build:
441 requires:
442 - yarn_build_combined
443 + - yarn_check_release_dependencies:
444 + requires:
445 + - yarn_build_combined
446 - check_error_codes:
447 requires:
448 - yarn_build_combined
package.json
+2 -1
@@ -145,7 +145,8 @@
145 "publish-prereleases": "node ./scripts/release/publish-using-ci-workflow.js",
146 "download-build": "node ./scripts/release/download-experimental-build.js",
147 "download-build-for-head": "node ./scripts/release/download-experimental-build.js --commit=$(git rev-parse HEAD)",
148 - "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"
148 + "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",
149 + "check-release-dependencies": "node ./scripts/release/check-release-dependencies"
150 },
151 "resolutions": {
152 "react-is": "npm:react-is"
scripts/release/check-release-dependencies.js new
+59
@@ -0,0 +1,59 @@
1 +'use strict';
2 +
3 +/* eslint-disable no-for-of-loops/no-for-of-loops */
4 +
5 +const fs = require('fs');
6 +const semver = require('semver');
7 +
8 +const {stablePackages} = require('../../ReactVersions');
9 +
10 +function main() {
11 + if (!fs.existsSync('./build/oss-stable-semver')) {
12 + throw new Error('No build artifacts found');
13 + }
14 +
15 + const packages = new Map();
16 + for (const packageName in stablePackages) {
17 + if (!fs.existsSync(`build/oss-stable-semver/${packageName}/package.json`)) {
18 + throw new Error(`${packageName}`);
19 + } else {
20 + const info = JSON.parse(
21 + fs.readFileSync(`build/oss-stable-semver/${packageName}/package.json`)
22 + );
23 + packages.set(info.name, info);
24 + }
25 + }
26 +
27 + for (const [packageName, info] of packages) {
28 + if (info.dependencies) {
29 + for (const [depName, depRange] of Object.entries(info.dependencies)) {
30 + if (packages.has(depName)) {
31 + const releaseVersion = packages.get(depName).version;
32 + checkDependency(packageName, depName, releaseVersion, depRange);
33 + }
34 + }
35 + }
36 +
37 + if (info.peerDependencies) {
38 + for (const [depName, depRange] of Object.entries(info.peerDependencies)) {
39 + if (packages.has(depName)) {
40 + const releaseVersion = packages.get(depName).version;
41 + checkDependency(packageName, depName, releaseVersion, depRange);
42 + }
43 + }
44 + }
45 + }
46 +}
47 +
48 +function checkDependency(packageName, depName, version, range) {
49 + if (!semver.satisfies(version, range)) {
50 + throw new Error(
51 + `${packageName} has an invalid dependency on ${depName}: ${range}` +
52 + '\n\n' +
53 + 'Actual version is: ' +
54 + version
55 + );
56 + }
57 +}
58 +
59 +main();