Fix: fail CI when the vendored HTML parser bundle is stale.

Greptile caught that editing the bundle entry did not refresh the committed vendor file, and neither build nor the detector suite would notice. --check compares a fresh rebuild, bun run build runs that check, and the detector suite now triggers on the entry.

AI-assisted.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Abdul Wahab
2026-09-01 15:17:45 +05:00
co-authored by Cursor
parent 6d973cdea6
commit 3fcd656aaf
4 changed files with 70 additions and 22 deletions
+40 -19
View File
@@ -5,9 +5,11 @@
* by bundling htmlparser2, css-select, css-tree, and domutils for skill/plugin installs.
*
* Run: node scripts/build-static-html-parsers.js
* Check: node scripts/build-static-html-parsers.js --check
*/
import fs from 'fs';
import os from 'node:os';
import path from 'path';
import { fileURLToPath } from 'url';
import { spawnSync } from 'node:child_process';
@@ -18,29 +20,48 @@ const ROOT = path.resolve(__dirname, '..');
const ENTRY = path.join(__dirname, 'lib/static-html-parsers.entry.mjs');
const OUT_DIR = path.join(ROOT, 'cli/engine/vendor');
const OUTPUT = path.join(OUT_DIR, 'static-html-parsers.mjs');
fs.mkdirSync(OUT_DIR, { recursive: true });
const result = spawnSync(
'bun',
['build', ENTRY, '--outfile', OUTPUT, '--target', 'node', '--format', 'esm'],
{ cwd: ROOT, encoding: 'utf8' },
);
if (result.status !== 0) {
process.stderr.write(result.stderr || result.stdout || 'bun build failed\n');
process.exit(result.status ?? 1);
}
const bundled = fs.readFileSync(OUTPUT, 'utf8');
const output = `/**
const HEADER = `/**
* GENERATED -- do not edit. Source: scripts/lib/static-html-parsers.entry.mjs
* Rebuild: node scripts/build-static-html-parsers.js
*
* Bundles htmlparser2, css-select, css-tree, and domutils for skill/plugin installs.
* Third-party licenses: see NOTICE.md.
*/
${bundled}`;
`;
fs.writeFileSync(OUTPUT, output);
console.log(`Generated ${path.relative(ROOT, OUTPUT)} (${(output.length / 1024).toFixed(1)} KB)`);
function generate(outfile) {
fs.mkdirSync(path.dirname(outfile), { recursive: true });
const result = spawnSync(
'bun',
['build', ENTRY, '--outfile', outfile, '--target', 'node', '--format', 'esm'],
{ cwd: ROOT, encoding: 'utf8' },
);
if (result.status !== 0) {
process.stderr.write(result.stderr || result.stdout || 'bun build failed\n');
process.exit(result.status ?? 1);
}
const output = HEADER + fs.readFileSync(outfile, 'utf8');
fs.writeFileSync(outfile, output);
return output;
}
if (process.argv.includes('--check')) {
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'impeccable-static-html-parsers-'));
const tmpFile = path.join(tmpDir, 'static-html-parsers.mjs');
try {
const fresh = generate(tmpFile);
const committed = fs.readFileSync(OUTPUT, 'utf8');
if (fresh !== committed) {
process.stderr.write(
'cli/engine/vendor/static-html-parsers.mjs is stale. Run: node scripts/build-static-html-parsers.js\n',
);
process.exit(1);
}
} finally {
fs.rmSync(tmpDir, { recursive: true, force: true });
}
process.exit(0);
}
generate(OUTPUT);
console.log(`Generated ${path.relative(ROOT, OUTPUT)} (${(fs.statSync(OUTPUT).size / 1024).toFixed(1)} KB)`);
+2 -1
View File
@@ -25,7 +25,7 @@ export const SUITES = {
description: 'Build, provider transforms, CLI helpers, context, and storage unit tests.',
triggers: [
...COMMON_INFRA_PATTERNS,
/^scripts\/(?!benchmark-detector|build-browser-detector|build-static-html-parsers|build-extension)/,
/^scripts\/(?!benchmark-detector|build-browser-detector|build-static-html-parsers|build-extension|lib\/static-html-parsers\.entry)/,
/^skill\/(SKILL\.src\.md|agents\/|reference\/|scripts\/(cleanup-deprecated|comp-diff|comp-spec|build-phase|font-match|data\/font-index|concept-seed|generate-image|context|context-signals|critique-storage|design-parser|doctor|hook|impeccable-paths|is-generated|lib\/(artifact-schema|png|raster|image-metrics|font-fingerprint|font-index|hero-checks|composition-catalog|concept-catalog|provider|staleness|staleness-deep|staleness-notice|surface-briefs|target-slug|template-extensions)|pin|surface-brief))/,
/^README(\.npm)?\.md$/,
/^cli\/bin\//,
@@ -93,6 +93,7 @@ export const SUITES = {
/^cli\/engine\//,
/^extension\/(background|content|detector|devtools|popup|manifest\.json)/,
/^scripts\/(benchmark-detector|build-browser-detector|build-static-html-parsers|build-extension)\.js$/,
/^scripts\/lib\/static-html-parsers\.entry\.mjs$/,
/^site\/(pages\/detector|public\/antipattern|data\/anti-patterns-catalog\.js)/,
/^tests\/fixtures\/antipatterns/,
],