Skip to content

Commit 41132fa

Browse files
authored
Improve logic for detecting what PR tests to run (#2615)
1 parent eb614f0 commit 41132fa

File tree

1 file changed

+67
-11
lines changed

1 file changed

+67
-11
lines changed

scripts/run_changed.js

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717

1818
const { resolve } = require('path');
19-
const { spawn } = require('child-process-promise');
19+
const { spawn, exec } = require('child-process-promise');
2020
const chalk = require('chalk');
2121
const simpleGit = require('simple-git/promise');
2222

@@ -52,35 +52,84 @@ const alwaysRunTestPaths = [
5252
'integration/webpack'
5353
];
5454

55+
/**
56+
* These files trigger tests in other dirs
57+
*/
58+
const specialPaths = {
59+
'scripts/emulator-testing/emulators/firestore-emulator.ts': ['packages/firestore'],
60+
'scripts/emulator-testing/emulators/database-emulator.ts': ['packages/database'],
61+
'scripts/emulator-testing/emulators/emulator.ts': ['packages/firestore', 'packages/database'],
62+
'scripts/emulator-testing/firestore-test-runner.ts': ['packages/firestore'],
63+
'scripts/emulator-testing/database-test-runner.ts': ['packages/database']
64+
};
65+
5566
/**
5667
* Identify modified packages that require tests.
5768
*/
5869
async function getChangedPackages() {
70+
const packageInfo = JSON.parse(
71+
(await exec('npx lerna ls --json', { cwd: root })).stdout
72+
);
73+
const depGraph = JSON.parse(
74+
(await exec('npx lerna ls --graph', { cwd: root })).stdout
75+
);
5976
const diff = await git.diff(['--name-only', 'origin/master...HEAD']);
6077
const changedFiles = diff.split('\n');
6178
const changedPackages = {};
6279
for (const filename of changedFiles) {
80+
// Files that trigger full test suite.
6381
if (fullTestTriggerFiles.includes(filename)) {
6482
console.log(
6583
chalk`{blue Running all tests because ${filename} was modified.}`
6684
);
6785
return { testAll: true };
6886
}
87+
// Files outside a package dir that should trigger its tests.
88+
if (specialPaths[filename]) {
89+
for (const targetPackage of specialPaths[filename]) {
90+
changedPackages[targetPackage] = 'dependency';
91+
}
92+
}
93+
// Check for changed files inside package dirs.
6994
const match = filename.match('^(packages/[a-zA-Z0-9-]+)/.*');
7095
if (match && match[1]) {
71-
const pkg = require(resolve(root, match[1], 'package.json'));
72-
if (pkg && pkg.scripts.test) {
73-
changedPackages[match[1]] = true;
96+
const changedPackage = require(resolve(root, match[1], 'package.json'));
97+
if (changedPackage) {
98+
if (changedPackage.scripts.test) {
99+
// Add the package itself.
100+
changedPackages[match[1]] = 'direct';
101+
}
102+
// Add packages that depend on it.
103+
for (const package in depGraph) {
104+
if (depGraph[package].includes(changedPackage.name)) {
105+
const depData = packageInfo.find(item => item.name === package);
106+
if (depData) {
107+
const depPkgJson = require(resolve(
108+
depData.location,
109+
'package.json'
110+
));
111+
if (depPkgJson && depPkgJson.scripts.test) {
112+
const depPath = depData.location.replace(`${root}/`, '');
113+
if (!changedPackages[depPath]) {
114+
changedPackages[depPath] = 'dependency';
115+
}
116+
}
117+
}
118+
}
119+
}
74120
}
75121
}
76122
}
77123
if (Object.keys(changedPackages).length > 0) {
78-
return { testAll: false, packageDirs: Object.keys(changedPackages) };
124+
return {
125+
testAll: false,
126+
changedPackages
127+
};
79128
} else {
80129
console.log(
81130
chalk`{green No changes detected in any package. Skipping all package-specific tests.}`
82131
);
83-
return { testAll: false, packageDirs: [] };
132+
return { testAll: false };
84133
}
85134
}
86135

@@ -103,21 +152,28 @@ async function runTests(pathList) {
103152

104153
async function main() {
105154
try {
106-
const { testAll, packageDirs = [] } = await getChangedPackages();
155+
const {
156+
testAll,
157+
changedPackages = {}
158+
} = await getChangedPackages();
107159
if (testAll) {
108160
await spawn('yarn', ['test'], {
109161
stdio: 'inherit'
110162
});
111163
} else {
112164
console.log(chalk`{blue Running tests in:}`);
113-
for (const filename of alwaysRunTestPaths) {
165+
for (const filename of alwaysRunTestPaths) { // array
114166
console.log(chalk`{green ${filename} (always runs)}`);
115167
}
116-
for (const filename of packageDirs) {
117-
console.log(chalk`{yellow ${filename} (contains modified files)}`);
168+
for (const filename in changedPackages) { // obj
169+
if (changedPackages[filename] === 'direct') {
170+
console.log(chalk`{yellow ${filename} (contains modified files)}`);
171+
} else {
172+
console.log(chalk`{yellow ${filename} (depends on modified files)}`);
173+
}
118174
}
119175
await runTests(alwaysRunTestPaths);
120-
await runTests(packageDirs);
176+
await runTests(Object.keys(changedPackages));
121177
}
122178
} catch (e) {
123179
console.error(e);

0 commit comments

Comments
 (0)