Skip to content

Commit c6b4d3f

Browse files
[LG-5635] chore: Fixes flaky icon builds (#3244)
* create new node externals instance * rm debug script * add postbuild * Delete tsconfig.json * rm extra console.logs * Update index.ts * Create icon-build-process.md * Update index.ts
1 parent 2d50b59 commit c6b4d3f

File tree

6 files changed

+104
-49
lines changed

6 files changed

+104
-49
lines changed

.changeset/icon-build-process.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@leafygreen-ui/icon': patch
3+
---
4+
5+
Updates build process to avoid race conditions in `rollup` plugins that intermittently caused `@emotion/server/create-instance` to be marked as a direct dependency of icon

packages/icon/package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"scripts": {
2727
"prebuild": "ts-node ./scripts/prebuild/index.ts",
2828
"build": "ts-node ./scripts/build/build.ts",
29+
"postbuild": "ts-node ./scripts/postbuild/index.ts",
2930
"tsc": "lg-build tsc",
3031
"docs": "lg-build docs"
3132
},
@@ -43,14 +44,16 @@
4344
"@lg-tools/build": "workspace:^",
4445
"@lg-tools/lint": "workspace:^",
4546
"@lg-tools/storybook-utils": "workspace:^",
47+
"@rollup/plugin-node-resolve": "15.1.0",
4648
"@svgr/core": "^5.3.1",
4749
"@types/xml2json": "^0.11.0",
4850
"commander": "^11.0.0",
51+
"fs-extra": "11.1.1",
52+
"p-queue": "^8.1.0",
4953
"rollup": "4.16.1",
54+
"rollup-plugin-node-externals": "7.1.1",
5055
"ts-node": "^10.9.2",
51-
"xml2json": "^0.12.0",
52-
"p-queue": "^8.1.0",
53-
"fs-extra": "11.1.1"
56+
"xml2json": "^0.12.0"
5457
},
5558
"gitHead": "dd71a2d404218ccec2e657df9c0263dc1c15b9e0",
5659
"homepage": "https://github.com/mongodb/leafygreen-ui/tree/main/packages/icon",

packages/icon/scripts/build/build-batch.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ async function getBatchBuildOptions(
1010
'@lg-tools/build/config/utils/constructUMDGlobalName.mjs'
1111
);
1212

13+
const { nodeExternals } = await import('rollup-plugin-node-externals');
14+
1315
const { esmConfig, umdConfig } = await import(
1416
'@lg-tools/build/config/rollup.config.mjs'
1517
);
@@ -20,6 +22,11 @@ async function getBatchBuildOptions(
2022
...esmConfig,
2123
input: batch.map(icon => `${GENERATED_DIR}/${icon}.tsx`),
2224
output: [esmConfig.output],
25+
plugins: [
26+
// Ensure @emotion packages are externalized (not bundled into icons)
27+
nodeExternals({ deps: true, include: [/@emotion/] }),
28+
...esmConfig.plugins,
29+
],
2330
},
2431
// UMD builds need a single input file
2532
...batch.map(iconName => {
@@ -33,6 +40,11 @@ async function getBatchBuildOptions(
3340
dir: `dist/umd`,
3441
},
3542
],
43+
plugins: [
44+
// Ensure @emotion packages are externalized (not bundled into icons)
45+
nodeExternals({ deps: true, include: [/@emotion/] }),
46+
...umdConfig.plugins,
47+
],
3648
};
3749
}),
3850
];
@@ -45,16 +57,13 @@ export async function buildBatch(
4557
batch: Array<string>,
4658
verbose = false,
4759
): Promise<void> {
60+
verbose && console.log('Building batch', batch);
4861
try {
4962
const rollupConfigs = await getBatchBuildOptions(batch);
5063

5164
for (const config of rollupConfigs) {
5265
const bundle = await rollup(config);
5366

54-
if (verbose) {
55-
console.log(bundle.watchFiles);
56-
}
57-
5867
await Promise.all(config.output.map(bundle.write));
5968
await bundle.close();
6069
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/* eslint-disable no-console */
2+
import fs from 'fs';
3+
import path from 'path';
4+
5+
/**
6+
* Validates that built icon files do not import @emotion packages directly.
7+
* Icons should only depend on @leafygreen-ui/emotion, not @emotion/* packages.
8+
*/
9+
function validateBuiltIcons(): void {
10+
const distDirs = ['dist/esm', 'dist/umd'];
11+
const emotionPattern = /@emotion\//g;
12+
let hasErrors = false;
13+
const errors: Array<{ file: string; matches: Array<string> }> = [];
14+
15+
console.log('Validating built icons...\n');
16+
17+
for (const distDir of distDirs) {
18+
const fullPath = path.join(process.cwd(), distDir);
19+
20+
if (!fs.existsSync(fullPath)) {
21+
console.warn(`Warning: ${distDir} directory does not exist. Skipping...`);
22+
continue;
23+
}
24+
25+
const files = fs.readdirSync(fullPath);
26+
const jsFiles = files.filter(file => file.endsWith('.js'));
27+
28+
for (const file of jsFiles) {
29+
// Skip the main index file and glyphCommon as they may have different rules
30+
if (file === 'index.js' || file === 'glyphCommon.js') {
31+
continue;
32+
}
33+
34+
const filePath = path.join(fullPath, file);
35+
const content = fs.readFileSync(filePath, 'utf-8');
36+
37+
// Check for @emotion imports/requires
38+
const matches = content.match(emotionPattern);
39+
40+
if (matches) {
41+
hasErrors = true;
42+
const uniqueMatches = Array.from(new Set(matches));
43+
errors.push({ file: `${distDir}/${file}`, matches: uniqueMatches });
44+
}
45+
}
46+
}
47+
48+
if (hasErrors) {
49+
console.error('❌ ERROR: Found @emotion imports in built icon files!\n');
50+
console.error(
51+
'Icons should only depend on @leafygreen-ui/emotion, not @emotion/* packages directly.\n',
52+
);
53+
console.error('Files with @emotion imports:');
54+
for (const error of errors) {
55+
console.error(` - ${error.file}`);
56+
for (const match of error.matches) {
57+
console.error(` → ${match}`);
58+
}
59+
}
60+
console.error('\nThis indicates a build configuration issue.');
61+
console.error(
62+
'Check packages/icon/scripts/build/build-batch.ts for proper externalization rules.',
63+
);
64+
process.exit(1);
65+
} else {
66+
console.log('Icon builds OK \n');
67+
process.exit(0);
68+
}
69+
}
70+
71+
validateBuiltIcons();

packages/icon/scripts/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
},
66
"include": [
77
"./prebuild/**/*",
8-
"./build/**/*"
8+
"./build/**/*",
9+
"./postbuild/**/*"
910
]
1011
}

pnpm-lock.yaml

Lines changed: 7 additions & 41 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)