Skip to content

Commit ad57e78

Browse files
committed
ci
1 parent 47f7548 commit ad57e78

File tree

2 files changed

+197
-16
lines changed

2 files changed

+197
-16
lines changed

.github/workflows/registry.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ jobs:
4040
steps:
4141
- name: 📥 Checkout Repo
4242
uses: actions/checkout@v4
43+
with:
44+
fetch-depth: 0
4345

4446
- name: ♻️ Setup Node.js
4547
uses: actions/setup-node@v4
@@ -68,6 +70,8 @@ jobs:
6870
run: pnpm templates:update --local
6971

7072
- name: 📦 Override templates with local workspace packages
73+
env:
74+
TEMPLATE_LOCAL_PACKAGE_BASE_REF: origin/${{ github.base_ref }}
7175
run: |
7276
node tooling/scripts/prepare-local-template-packages.mjs \
7377
templates/plate-template \

tooling/scripts/prepare-local-template-packages.mjs

Lines changed: 193 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { fileURLToPath } from 'node:url';
77

88
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
99
const repoRoot = path.resolve(scriptDir, '..', '..');
10+
const baseRef = process.env.TEMPLATE_LOCAL_PACKAGE_BASE_REF?.trim();
1011
const templateDirArgs = process.argv.slice(2);
1112

1213
if (templateDirArgs.includes('-h') || templateDirArgs.includes('--help')) {
@@ -47,20 +48,28 @@ const templateConfigs = await Promise.all(
4748
};
4849
})
4950
);
50-
const packagesToPrepare = new Map();
5151

5252
for (const templateConfig of templateConfigs) {
53-
for (const dependencyName of templateConfig.localDependencies) {
54-
const workspacePackage = workspacePackages.get(dependencyName);
55-
56-
if (!workspacePackage) continue;
57-
58-
packagesToPrepare.set(dependencyName, workspacePackage);
59-
}
53+
templateConfig.relevantPackageNames = getReachableWorkspacePackageNames(
54+
templateConfig.localDependencies,
55+
workspacePackages
56+
);
6057
}
6158

59+
const packagesToPrepare = getPackagesToPrepare({
60+
baseRef,
61+
templateConfigs,
62+
workspacePackages,
63+
});
64+
6265
if (packagesToPrepare.size === 0) {
63-
console.log('No local workspace packages referenced by templates.');
66+
if (baseRef) {
67+
console.log(
68+
`No affected local workspace packages referenced by templates for ${baseRef}...HEAD.`
69+
);
70+
} else {
71+
console.log('No local workspace packages referenced by templates.');
72+
}
6473
process.exit(0);
6574
}
6675

@@ -103,13 +112,74 @@ function buildWorkspacePackages(workspacePackagesToBuild) {
103112
}
104113
}
105114

106-
function getLocalDependencies(packageJson) {
107-
const dependencyNames = new Set([
108-
...Object.keys(packageJson.dependencies ?? {}),
109-
...Object.keys(packageJson.devDependencies ?? {}),
110-
]);
115+
function getPackagesToPrepare({ baseRef, templateConfigs, workspacePackages }) {
116+
const packagesToPrepare = new Map();
117+
const dependencyNames = new Set(
118+
templateConfigs.flatMap(
119+
(templateConfig) => templateConfig.localDependencies
120+
)
121+
);
122+
123+
if (!baseRef) {
124+
for (const dependencyName of dependencyNames) {
125+
const workspacePackage = workspacePackages.get(dependencyName);
126+
127+
if (!workspacePackage) continue;
128+
129+
packagesToPrepare.set(dependencyName, workspacePackage);
130+
}
131+
132+
return packagesToPrepare;
133+
}
134+
135+
const changedPackageNames = getChangedWorkspacePackageNames(
136+
baseRef,
137+
workspacePackages
138+
);
139+
140+
if (changedPackageNames.size === 0) {
141+
return packagesToPrepare;
142+
}
143+
144+
const relevantPackageNames = new Set(
145+
templateConfigs.flatMap((templateConfig) => [
146+
...templateConfig.relevantPackageNames,
147+
])
148+
);
149+
const selectedPackageNames = [...changedPackageNames].filter((packageName) =>
150+
relevantPackageNames.has(packageName)
151+
);
152+
153+
if (selectedPackageNames.length === 0) {
154+
return packagesToPrepare;
155+
}
156+
157+
console.log(
158+
`Changed workspace packages for ${baseRef}...HEAD: ${[
159+
...changedPackageNames,
160+
]
161+
.sort()
162+
.join(', ')}`
163+
);
164+
console.log(
165+
`Selected workspace packages for templates: ${selectedPackageNames
166+
.toSorted()
167+
.join(', ')}`
168+
);
169+
170+
for (const packageName of selectedPackageNames) {
171+
const workspacePackage = workspacePackages.get(packageName);
172+
173+
if (!workspacePackage) continue;
111174

112-
return [...dependencyNames].filter((dependencyName) =>
175+
packagesToPrepare.set(packageName, workspacePackage);
176+
}
177+
178+
return packagesToPrepare;
179+
}
180+
181+
function getLocalDependencies(packageJson) {
182+
return getDependencyNames(packageJson).filter((dependencyName) =>
113183
workspacePackages.has(dependencyName)
114184
);
115185
}
@@ -130,10 +200,18 @@ async function getWorkspacePackages() {
130200

131201
workspacePackagesByName.set(packageJson.name, {
132202
directory: directoryEntry,
203+
packageJson,
204+
relativeDirectory: toPosixPath(path.relative(repoRoot, directoryEntry)),
133205
});
134206
}
135207
}
136208

209+
for (const workspacePackage of workspacePackagesByName.values()) {
210+
workspacePackage.localDependencyNames = getDependencyNames(
211+
workspacePackage.packageJson
212+
).filter((dependencyName) => workspacePackagesByName.has(dependencyName));
213+
}
214+
137215
return workspacePackagesByName;
138216
}
139217

@@ -157,6 +235,66 @@ async function listDirectories(parentDirectory) {
157235
return directories;
158236
}
159237

238+
function getChangedWorkspacePackageNames(baseRef, workspacePackages) {
239+
const result = spawnSync(
240+
'git',
241+
['diff', '--name-only', `${baseRef}...HEAD`],
242+
{
243+
cwd: repoRoot,
244+
encoding: 'utf8',
245+
}
246+
);
247+
248+
if (result.status !== 0) {
249+
console.error(
250+
`Failed to determine changed workspace packages for ${baseRef}...HEAD`
251+
);
252+
process.exit(result.status ?? 1);
253+
}
254+
255+
const changedFiles = result.stdout
256+
.split('\n')
257+
.map((filePath) => filePath.trim())
258+
.filter(Boolean);
259+
const changedPackageNames = new Set();
260+
261+
for (const changedFile of changedFiles) {
262+
for (const [packageName, workspacePackage] of workspacePackages) {
263+
const packagePrefix = `${workspacePackage.relativeDirectory}/`;
264+
265+
if (changedFile.startsWith(packagePrefix)) {
266+
changedPackageNames.add(packageName);
267+
}
268+
}
269+
}
270+
271+
return changedPackageNames;
272+
}
273+
274+
function getReachableWorkspacePackageNames(
275+
initialPackageNames,
276+
workspacePackages
277+
) {
278+
const relevantPackageNames = new Set();
279+
const pendingPackageNames = [...initialPackageNames];
280+
281+
while (pendingPackageNames.length > 0) {
282+
const packageName = pendingPackageNames.shift();
283+
284+
if (!packageName || relevantPackageNames.has(packageName)) continue;
285+
286+
relevantPackageNames.add(packageName);
287+
288+
const workspacePackage = workspacePackages.get(packageName);
289+
290+
if (!workspacePackage) continue;
291+
292+
pendingPackageNames.push(...workspacePackage.localDependencyNames);
293+
}
294+
295+
return relevantPackageNames;
296+
}
297+
160298
function packWorkspacePackage(packageDirectory) {
161299
const result = spawnSync(
162300
'pnpm',
@@ -182,9 +320,22 @@ function packWorkspacePackage(packageDirectory) {
182320
return tarballPath;
183321
}
184322

323+
function getDependencyNames(packageJson) {
324+
const dependencyNames = new Set([
325+
...Object.keys(packageJson.dependencies ?? {}),
326+
...Object.keys(packageJson.devDependencies ?? {}),
327+
...Object.keys(packageJson.optionalDependencies ?? {}),
328+
...Object.keys(packageJson.peerDependencies ?? {}),
329+
]);
330+
331+
return [...dependencyNames];
332+
}
333+
185334
function rewriteTemplatePackageJson(templateConfig, tarballsByPackageName) {
186-
const { packageJson, packageJsonPath, templateDir } = templateConfig;
335+
const { packageJson, packageJsonPath, relevantPackageNames, templateDir } =
336+
templateConfig;
187337
const dependencySections = ['dependencies', 'devDependencies'];
338+
const rewrittenPackageNames = new Set();
188339

189340
for (const section of dependencySections) {
190341
const dependencies = packageJson[section];
@@ -203,6 +354,32 @@ function rewriteTemplatePackageJson(templateConfig, tarballsByPackageName) {
203354
}
204355

205356
dependencies[dependencyName] = `file:${toPosixPath(relativeTarballPath)}`;
357+
rewrittenPackageNames.add(dependencyName);
358+
}
359+
}
360+
361+
const missingDependencyNames = [...tarballsByPackageName.keys()].filter(
362+
(dependencyName) =>
363+
relevantPackageNames.has(dependencyName) &&
364+
!rewrittenPackageNames.has(dependencyName)
365+
);
366+
367+
if (missingDependencyNames.length > 0) {
368+
packageJson.devDependencies ??= {};
369+
370+
for (const dependencyName of missingDependencyNames.toSorted()) {
371+
const tarballPath = tarballsByPackageName.get(dependencyName);
372+
373+
if (!tarballPath) continue;
374+
375+
let relativeTarballPath = path.relative(templateDir, tarballPath);
376+
377+
if (!relativeTarballPath.startsWith('.')) {
378+
relativeTarballPath = `./${relativeTarballPath}`;
379+
}
380+
381+
packageJson.devDependencies[dependencyName] =
382+
`file:${toPosixPath(relativeTarballPath)}`;
206383
}
207384
}
208385

0 commit comments

Comments
 (0)