Skip to content

Commit c7a5baf

Browse files
committed
Memoize calls to yarn why for lockfile checking
1 parent 2b36efb commit c7a5baf

File tree

1 file changed

+43
-21
lines changed

1 file changed

+43
-21
lines changed

.github/actions/src/lockfiles.ts

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ async function getMasterLockFile() {
6868

6969
interface ResolutionSpec { pkgSpecifier: string, pkgName: string }
7070

71+
/**
72+
* Parsed output entry returned by `yarn why`
73+
*/
7174
interface YarnWhyOutput {
7275
value: string;
7376
children: {
@@ -78,6 +81,28 @@ interface YarnWhyOutput {
7881
};
7982
}
8083

84+
/**
85+
* Run `yarn why <package_name>` to see why a package is included
86+
* Don't use recursive (-R) since we want to build the graph ourselves
87+
* @function
88+
*/
89+
const runYarnWhy = memoize(async (pkgName: string) => {
90+
// Memoize the call so that we don't need to call yarn why multiple times for each package
91+
const { stdout: output, exitCode, stderr } = await getExecOutput('yarn', ['why', pkgName, '--json'], { silent: true });
92+
if (exitCode !== 0) {
93+
core.error(stderr);
94+
throw new Error(`yarn why for ${pkgName} failed!`);
95+
}
96+
97+
return output.split('\n').reduce<YarnWhyOutput[]>((res, each) => {
98+
each = each.trim();
99+
if (each === '') return res;
100+
101+
const pkg = JSON.parse(each) as YarnWhyOutput;
102+
return [...res, pkg];
103+
}, []);
104+
})
105+
81106
/**
82107
* Determines the names of the packages that have changed versions
83108
*/
@@ -92,45 +117,42 @@ export async function getPackagesWithResolutionChanges() {
92117
changes.delete(edge);
93118
}
94119

95-
const changedDeps: ResolutionSpec[] = [];
120+
const frontier: ResolutionSpec[] = [];
121+
const changedDeps = new Set<string>();
96122
for (const edge of changes) {
97123
const [pkgSpecifier] = edge.split(' -> ');
98-
changedDeps.push({ pkgSpecifier, pkgName: extractPackageName(pkgSpecifier) });
124+
changedDeps.add(pkgSpecifier);
125+
frontier.push({
126+
pkgSpecifier,
127+
pkgName: extractPackageName(pkgSpecifier)
128+
});
99129
}
100130

101-
const frontier = [...changedDeps];
102131
while (frontier.length > 0) {
103132
const { pkgName, pkgSpecifier } = frontier.shift()!;
104133

105-
// Run `yarn why <package_name>` to see why a package is included
106-
// Don't use recursive (-R) since we want to build the graph ourselves
107-
const { stdout: output, exitCode, stderr } = await getExecOutput('yarn', ['why', pkgName, '--json'], { silent: true });
108-
if (exitCode !== 0) {
109-
core.error(stderr);
110-
throw new Error(`yarn why for ${pkgName} failed!`);
111-
}
112-
113-
output.split('\n').forEach(each => {
114-
each = each.trim();
115-
if (each === '') return;
134+
const reasons = await runYarnWhy(pkgName);
135+
reasons.forEach(pkg => {
136+
if (changedDeps.has(pkg.value)) {
137+
// If we've already added this pkg specifier, don't need to explore it again
138+
return;
139+
}
116140

117-
const pkg = JSON.parse(each) as YarnWhyOutput;
118141
const childrenSpecifiers = Object.values(pkg.children).map(({ descriptor }) => descriptor);
119142
if (!childrenSpecifiers.includes(pkgSpecifier)) return;
120143

121-
const toAdd: ResolutionSpec = { pkgSpecifier: pkg.value, pkgName: extractPackageName(pkg.value) };
122-
frontier.push(toAdd);
123-
changedDeps.push(toAdd);
144+
frontier.push({ pkgSpecifier: pkg.value, pkgName: extractPackageName(pkg.value) });
145+
changedDeps.add(pkg.value);
124146
});
125147
}
126148

127149
core.info('=== Summary of dirty monorepo packages ===\n');
128-
const pkgsToRebuild = changedDeps.filter(({ pkgSpecifier }) => pkgSpecifier.includes('@workspace:'));
129-
for (const { pkgName } of pkgsToRebuild) {
150+
const pkgsToRebuild = [...changedDeps].filter(pkgSpecifier => pkgSpecifier.includes('@workspace:'));
151+
for (const pkgName of pkgsToRebuild) {
130152
core.info(`- ${pkgName}`);
131153
}
132154

133-
return pkgsToRebuild.map(({ pkgName }) => pkgName);
155+
return pkgsToRebuild.map(extractPackageName);
134156
}
135157

136158
/**

0 commit comments

Comments
 (0)