mirror of
https://github.com/hanzoai/extension.git
synced 2026-10-31 21:57:06 +00:00
ci.yml has failed on every push since 2026-08-05 — twenty runs — and the cause was two test files each running src/build.js into the same dist/, gated on DIFFERENT sentinels: output-root.test.ts checked for the directory, webextension-polyfill.test.ts checked for a file inside it. vitest runs files in parallel, the directory appears the instant the slower build starts, so the faster suite skipped its own build and asserted against a tree still being written. It failed 'chrome: expected false to be true' in 12ms — too fast to have built anything, which is the tell. The build is a fixture the suite needs, not something a test conjures, so it now happens once in globalSetup before parallelism starts and the assertions go back to being assertions. Requiring EVERY artifact, not just one, means an interrupted run rebuilds instead of being mistaken for a finished one — the same confusion between started and done that caused the race. Verified from a deleted dist/: 24 files, 302/302. Locally this suite had been reporting 22 files/292 tests off a stale dist — the two build-driving files never ran — which is why it looked green here while CI was red. Co-authored-by: Hanzo Dev <[email protected]>
51 lines
2.1 KiB
TypeScript
51 lines
2.1 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { execFileSync } from 'child_process';
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
|
|
/**
|
|
* src/build.js has ONE output root: the extension repo root's dist/, one
|
|
* directory per engine. It used to sit under packages/browser, and when it
|
|
* moved, six consumers were left pointing at the old path — every one of them
|
|
* failing silently:
|
|
*
|
|
* scripts/check-bundle-budgets.mjs measured a build four days stale
|
|
* .hanzo/workflows/ci.yml ran that check under continue-on-error
|
|
* e2e/playwright.config.ts loaded a stale extension
|
|
* e2e/fixtures.ts same
|
|
* e2e/cross-platform.config.ts same
|
|
* .hanzo/workflows/publish.yml packaged the stores from a missing dir
|
|
* tests/webextension-polyfill.test.ts `return`ed when the path was absent
|
|
*
|
|
* Nothing said a word. This is the thing that says it.
|
|
*/
|
|
|
|
const REPO = path.resolve(__dirname, '..', '..', '..');
|
|
const DIST = path.join(REPO, 'dist');
|
|
|
|
describe('the build output root is the one every consumer names', () => {
|
|
it('is written by src/build.js, one directory per engine', () => {
|
|
// The build is a fixture (tests/built-dist.ts), not something this test
|
|
// runs. It used to run it here, gated on the DIRECTORY existing, while
|
|
// another suite ran the same build gated on a FILE — so this one saw the
|
|
// directory appear under the other's build and asserted against a tree
|
|
// still being written.
|
|
for (const engine of ['chrome', 'firefox', 'safari']) {
|
|
expect(fs.existsSync(path.join(DIST, engine, 'manifest.json')) ||
|
|
fs.existsSync(path.join(DIST, engine, 'Info.plist')), engine).toBe(true);
|
|
}
|
|
});
|
|
|
|
it('leaves no tracked file naming the abandoned root', () => {
|
|
// Assembled, never spelled — otherwise this file is its own violation.
|
|
const abandoned = ['dist', 'browser-extension'].join('/');
|
|
let hits = '';
|
|
try {
|
|
hits = execFileSync('git', ['grep', '-l', abandoned], { cwd: REPO, encoding: 'utf8' }).trim();
|
|
} catch {
|
|
// git grep exits 1 when nothing matches — the passing case.
|
|
}
|
|
expect(hits).toBe('');
|
|
});
|
|
});
|