Skip to content

Commit dc56ebb

Browse files
feat(test_downstream_projects): Support yarn workspaces
1 parent 1cc57ef commit dc56ebb

File tree

3 files changed

+107
-76
lines changed

3 files changed

+107
-76
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"find-parent-dir": "^0.3.0",
3535
"git-semver-tags": "^1.2.1",
3636
"lodash": "^4.17.5",
37+
"node-cleanup": "^2.1.2",
3738
"npm-run-all": "^4.1.1",
3839
"open": "^0.0.5",
3940
"readline-sync": "^1.4.7",

test_downstream_projects.js

Lines changed: 98 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,22 @@ const path = require('path');
44
const tmp = require('tmp');
55
const shelljs = require('shelljs');
66

7+
const nodeCleanup = require('node-cleanup');
78
const publishYalcPackage = require('./publish_yalc_package');
9+
810
const util = require('./util');
911
util.packageDir();
1012
const PKG_DIR = process.cwd();
1113

1214
const config = JSON.parse(fs.readFileSync('downstream_projects.json'));
1315
const pkgjson = JSON.parse(fs.readFileSync('package.json'));
1416

15-
const DOWNSTREAM_CACHE = path.resolve(PKG_DIR, '.downstream_cache');
16-
const TEMP = tmp.dirSync();
17-
const TEMP_DIR = TEMP.name;
18-
19-
const UPSTREAM_PKGS = (process.env.UPSTREAM_PKGS || '').split(',').filter(x => x).concat(pkgjson.name);
2017
const DOWNSTREAM_PKGS = (process.env.DOWNSTREAM_PKGS || '').split(',').filter(x => x);
2118

22-
function forEachDownstream(callback) {
23-
Object.keys(config).forEach(key => {
24-
if (DOWNSTREAM_PKGS.length && DOWNSTREAM_PKGS.indexOf(key) === -1) {
25-
console.log(callback.constructor.name + ": " + key + ' not in DOWNSTREAM_PKGS, skipping...');
26-
return;
27-
}
28-
29-
process.chdir(path.resolve(DOWNSTREAM_CACHE, key));
30-
callback(key, config[key]);
31-
});
32-
}
19+
const TEMP = tmp.dirSync();
20+
const TEMP_DIR = TEMP.name;
21+
const TEMP_DOWNSTREAM_CACHE = path.resolve(TEMP_DIR, '.downstream_cache');
22+
const DOWNSTREAM_CACHE = path.resolve(PKG_DIR, '.downstream_cache');
3323

3424
function makeDownstreamCache() {
3525
if (!fs.existsSync(DOWNSTREAM_CACHE)) {
@@ -38,27 +28,19 @@ function makeDownstreamCache() {
3828
}
3929
}
4030

41-
function localPublish() {
42-
process.chdir(PKG_DIR);
31+
function localPublish(packageDir) {
32+
packageDir = packageDir || PKG_DIR;
33+
process.chdir(packageDir);
4334
console.log('Publishing using yalc...');
4435
util._exec('yalc publish');
4536
}
4637

47-
function installUpstreamDeps() {
48-
UPSTREAM_PKGS.forEach(upstream => util._exec('yalc add ' + upstream));
38+
function installUpstreamDeps(upstreamPackages) {
39+
upstreamPackages.forEach(upstream => util._exec('yalc add ' + upstream));
4940
}
5041

5142
function runTests() {
52-
util._exec(`UPSTREAM_PKGS="${UPSTREAM_PKGS.join(',')}" npm test`);
53-
}
54-
55-
function runDownstreamTests() {
56-
const downstreamPkgJson = JSON.parse(fs.readFileSync('package.json'));
57-
const hasDownstreamTests = downstreamPkgJson.scripts && !!downstreamPkgJson.scripts['test:downstream'];
58-
59-
if (hasDownstreamTests) {
60-
util._exec(`UPSTREAM_PKGS="${UPSTREAM_PKGS.join(',')}" npm run test:downstream`);
61-
}
43+
util._exec(`npm test`);
6244
}
6345

6446
function revertLocalChanges(source) {
@@ -68,53 +50,97 @@ function revertLocalChanges(source) {
6850
util._exec('git clean --force -d');
6951
}
7052

71-
try {
72-
console.log(` ===> Making .downstream_cache working directory <===`);
73-
makeDownstreamCache();
53+
function fetchDownstreamProjects(downstreamConfig, prefix, downstreamTreeNode) {
54+
prefix = prefix || "";
55+
56+
Object.keys(downstreamConfig).forEach(key => {
57+
const installDir = prefix ? `${prefix}.${key}` : key;
7458

75-
console.log(` ===> Publishing ${pkgjson.name} to yalc registry <===`);
76-
localPublish();
59+
console.log(` ===> Fetching downstream project to '${installDir}' <===`);
60+
const installSource = downstreamConfig[key];
61+
const isFile = /^\./.exec(installSource);
62+
const installSourcePath = prefix ? path.resolve(DOWNSTREAM_CACHE, prefix, installSource) : path.resolve(PKG_DIR, installSource);
63+
const installSourceForYalc = isFile ? './' + path.relative(process.cwd(), installSourcePath) : installSource;
64+
const flags = { noBuild: true, noPublish: true, noInstall: true };
65+
publishYalcPackage(path.resolve(DOWNSTREAM_CACHE, installDir), installSourceForYalc, flags);
7766

78-
Object.keys(config).forEach(key => {
79-
if (DOWNSTREAM_PKGS.length && DOWNSTREAM_PKGS.indexOf(key) === -1) {
80-
console.log(`${key} not in DOWNSTREAM_PKGS, skipping...`);
81-
return;
67+
const children = {};
68+
downstreamTreeNode[key] = { installDir, installSource, children };
69+
70+
const nestedDownstreamConfigPath = path.resolve(DOWNSTREAM_CACHE, installDir, 'downstream_projects.json');
71+
if (fs.existsSync(nestedDownstreamConfigPath)) {
72+
const nestedDownstreamConfig = JSON.parse(fs.readFileSync(nestedDownstreamConfigPath));
73+
fetchDownstreamProjects(nestedDownstreamConfig, installDir, children);
8274
}
75+
});
76+
}
77+
78+
function getDownstreamInstallDirs(downstreamTreeNode) {
79+
const children = Object.keys(downstreamTreeNode.children);
80+
const childrenInstallDirs = children.map(key => getDownstreamInstallDirs(downstreamTreeNode.children[key]));
81+
return [downstreamTreeNode.installDir]
82+
.concat(childrenInstallDirs)
83+
.reduce((acc, arr) => acc.concat(arr), [])
84+
.filter(x => !!x);
85+
}
8386

84-
const DOWNSTREAM_PACKAGE_DIR = path.resolve(DOWNSTREAM_CACHE, key);
85-
process.chdir(PKG_DIR);
86-
87-
console.log(` ===> Fetching downstream project '${key}' and its dependencies <===`);
88-
const installTargetDir = DOWNSTREAM_PACKAGE_DIR;
89-
const installSource = config[key];
90-
const flags = { noBuild: true, noPublish: true };
91-
publishYalcPackage(installTargetDir, installSource, flags);
92-
93-
console.log(` ===> Installing freshly built upstream packages <===`);
94-
process.chdir(DOWNSTREAM_PACKAGE_DIR);
95-
installUpstreamDeps();
96-
97-
const DOWNSTREAM_PACKAGE_TEMP_DIR = path.resolve(TEMP_DIR, path.basename(DOWNSTREAM_PACKAGE_DIR));
98-
try {
99-
console.log(` ===> Moving downstream project '${key}' to temp dir '${TEMP_DIR}' <===`);
100-
shelljs.mv(DOWNSTREAM_PACKAGE_DIR, TEMP_DIR);
101-
102-
console.log(` ===> Running '${key}' tests <===`);
103-
process.chdir(DOWNSTREAM_PACKAGE_TEMP_DIR);
104-
runTests();
105-
} finally {
106-
console.log(` ===> Moving downstream project '${key}' back from temp dir <===`);
107-
shelljs.mv(DOWNSTREAM_PACKAGE_TEMP_DIR, DOWNSTREAM_CACHE);
87+
function installDependencies(downstreamInstallDirs) {
88+
const yarnWorkspacePackageJsonPath = path.resolve(DOWNSTREAM_CACHE, "package.json");
89+
const yarnWorkspacePackageJson = {
90+
private: true,
91+
"workspaces": {
92+
"packages": downstreamInstallDirs,
93+
"nohoist": [
94+
"**/webpack",
95+
"**/karma-webpack",
96+
]
10897
}
98+
};
10999

110-
console.log(` ===> Running '${key}' downstream tests <===`);
111-
process.chdir(DOWNSTREAM_PACKAGE_DIR);
112-
runDownstreamTests();
100+
fs.writeFileSync(yarnWorkspacePackageJsonPath, JSON.stringify(yarnWorkspacePackageJson, null, 2));
101+
process.chdir(DOWNSTREAM_CACHE);
102+
util._exec('yarn && yarn upgrade');
103+
}
113104

114-
console.log(` ===> Cleaning downstream project '${key}' <===`);
115-
process.chdir(DOWNSTREAM_PACKAGE_DIR);
116-
revertLocalChanges(installSource);
117-
});
118-
} finally {
119-
shelljs.rm('-rf', TEMP_DIR)
105+
function runDownstreamTests(key, upstreamPackages, downstreamTreeNode) {
106+
if (DOWNSTREAM_PKGS.length && DOWNSTREAM_PKGS.indexOf(key) === -1) {
107+
console.log(`${key} not in DOWNSTREAM_PKGS, skipping...`);
108+
return;
109+
}
110+
111+
process.chdir(TEMP_DOWNSTREAM_CACHE);
112+
113+
console.log(` ===> Running '${key}' tests <===`);
114+
console.log(` ===> Installing freshly built upstream packages <===`);
115+
process.chdir(downstreamTreeNode.installDir);
116+
installUpstreamDeps(upstreamPackages);
117+
runTests();
118+
revertLocalChanges(downstreamTreeNode.installSource);
120119
}
120+
121+
console.log(` ===> Creating .downstream_cache working directory <===`);
122+
makeDownstreamCache();
123+
124+
console.log(` ===> Publishing ${pkgjson.name} to yalc registry <===`);
125+
localPublish();
126+
127+
console.log(` ===> Fetching downstream projects <===`);
128+
const tree = { children: {} };
129+
fetchDownstreamProjects(config, "", tree.children);
130+
131+
console.log(` ===> Installing downstream dependencies <===`);
132+
const downstreamDirs = getDownstreamInstallDirs(tree);
133+
installDependencies(downstreamDirs);
134+
135+
console.log(` ===> Moving working directory to temp dir ${TEMP_DIR} <===`);
136+
shelljs.mv(DOWNSTREAM_CACHE, TEMP_DIR);
137+
138+
nodeCleanup(() => {
139+
shelljs.mv(TEMP_DOWNSTREAM_CACHE, PKG_DIR);
140+
});
141+
142+
console.log(` ===> Running downstream tests <===`);
143+
Object.keys(tree.children).forEach(key => {
144+
console.log(` ===> Running tests for '${key}' <===`);
145+
runDownstreamTests(key, [pkgjson.name], tree.children[key]);
146+
});

yarn.lock

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,10 @@ modify-values@^1.0.0:
868868
version "1.0.0"
869869
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.0.tgz#e2b6cdeb9ce19f99317a53722f3dbf5df5eaaab2"
870870

871+
node-cleanup@^2.1.2:
872+
version "2.1.2"
873+
resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c"
874+
871875
normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5:
872876
version "2.4.0"
873877
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
@@ -1348,15 +1352,15 @@ typedoc-default-themes@^0.5.0:
13481352
version "0.5.0"
13491353
resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.5.0.tgz#6dc2433e78ed8bea8e887a3acde2f31785bd6227"
13501354

1351-
typedoc-plugin-external-module-name@^1.1.1:
1355+
typedoc-plugin-external-module-name@1.1.1:
13521356
version "1.1.1"
13531357
resolved "https://registry.yarnpkg.com/typedoc-plugin-external-module-name/-/typedoc-plugin-external-module-name-1.1.1.tgz#0ef2d6a760b42c703519c474258b6f062983aa83"
13541358

1355-
typedoc-plugin-internal-external@^1.0.10:
1359+
typedoc-plugin-internal-external@1.0.10:
13561360
version "1.0.10"
13571361
resolved "https://registry.yarnpkg.com/typedoc-plugin-internal-external/-/typedoc-plugin-internal-external-1.0.10.tgz#df9fd6ee1743f009c39b8746a3c26edc36ce8bcd"
13581362

1359-
typedoc-plugin-ui-router@^1.0.6:
1363+
typedoc-plugin-ui-router@1.0.6:
13601364
version "1.0.6"
13611365
resolved "https://registry.yarnpkg.com/typedoc-plugin-ui-router/-/typedoc-plugin-ui-router-1.0.6.tgz#6d452d499d1bd35701ebfdeb2beee670d8530e8b"
13621366

@@ -1399,7 +1403,7 @@ uglify-to-browserify@~1.0.0:
13991403
version "1.0.2"
14001404
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
14011405

1402-
ui-router-typedoc-themes@^1.0.2:
1406+
ui-router-typedoc-themes@1.0.2:
14031407
version "1.0.2"
14041408
resolved "https://registry.yarnpkg.com/ui-router-typedoc-themes/-/ui-router-typedoc-themes-1.0.2.tgz#3274960b8ee61e026b405ce3afcd9a2925992861"
14051409

0 commit comments

Comments
 (0)