mirror of
https://github.com/Heretek-AI/IUMBTEMS.git
synced 2026-10-12 02:03:00 +00:00
Merge pull request #313 from Heretek-AI/phase/6-clean-room
fix(tooling): scope test, lint and typecheck to packages/ (Refs #159)
This commit is contained in:
+13
-1
@@ -1,6 +1,18 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/2.5.15/schema.json",
|
||||
"files": { "includes": ["packages/**", "!**/node_modules", "!**/dist", "!**/fixtures"] },
|
||||
"files": {
|
||||
"includes": [
|
||||
"packages/**",
|
||||
"!**/node_modules",
|
||||
"!**/dist",
|
||||
"!**/fixtures",
|
||||
"!!review",
|
||||
"!!evals/results",
|
||||
"!!.worktrees",
|
||||
"!!.fleet",
|
||||
"!!.factory/worktrees"
|
||||
]
|
||||
},
|
||||
"formatter": { "indentStyle": "space", "indentWidth": 2, "lineWidth": 120 },
|
||||
"javascript": { "formatter": { "semicolons": "asNeeded", "quoteStyle": "double" } },
|
||||
"linter": {
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
[test]
|
||||
timeout = 30000
|
||||
# Discovery starts at packages/: a bare `bun test` or path filter never walks
|
||||
# review/ or evals/ (#159). Paths outside it still run when given as ./path.
|
||||
root = "packages"
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
"packages/*"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "bun --conditions=browser test $(bun scripts/packages.ts --browser | sed 's|^|packages/|') && bun test $(bun scripts/packages.ts --no-browser | sed 's|^|packages/|')",
|
||||
"test": "bun --conditions=browser test $(bun scripts/packages.ts --browser | sed 's|^|./packages/|') && bun test $(bun scripts/packages.ts --no-browser | sed 's|^|./packages/|')",
|
||||
"typecheck": "for p in $(bun scripts/packages.ts --tsconfig); do tsc -p packages/$p/tsconfig.json --noEmit --composite false || exit 1; done",
|
||||
"lint": "biome check .",
|
||||
"deps:check": "bun scripts/deps.ts",
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
// Clean-room isolation (#159): the workspace test, lint and typecheck entry
|
||||
// points stay inside packages/. Local-only reference checkouts (review/,
|
||||
// evals/results/) and nested worktrees carry third-party suites that hang and
|
||||
// biome.json files that are nested roots, so nothing may walk them. Each test
|
||||
// runs the real root config against a throwaway tree with planted intruders.
|
||||
import { afterEach, describe, expect, test } from "bun:test"
|
||||
import { cp, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises"
|
||||
import { tmpdir } from "node:os"
|
||||
import path from "node:path"
|
||||
|
||||
const repo = path.resolve(import.meta.dir, "../../..")
|
||||
// Every gitignored place a foreign checkout can sit beside packages/.
|
||||
const OUTSIDE = ["review/ext", "evals/results/run", ".worktrees/ticket", ".fleet/task", ".factory/worktrees/seat"]
|
||||
|
||||
// Each fixture suite logs its own label when loaded, so the assertions do not
|
||||
// depend on the reporter format; intruders also fail, like the real ones.
|
||||
const suite = (label: string, intruder: boolean) =>
|
||||
[
|
||||
'import { expect, test } from "bun:test"',
|
||||
'import { appendFileSync } from "node:fs"',
|
||||
"",
|
||||
`appendFileSync(process.env.CLEAN_ROOM_LOG!, "${label}\\n")`,
|
||||
"",
|
||||
`test("${label}", () => expect(${intruder}).toBe(false))`,
|
||||
"",
|
||||
].join("\n")
|
||||
|
||||
const dirs: string[] = []
|
||||
afterEach(async () => {
|
||||
for (const dir of dirs.splice(0)) await rm(dir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
async function fixture(options: { bunfig: boolean }) {
|
||||
const root = await mkdtemp(path.join(tmpdir(), "es-clean-room-"))
|
||||
dirs.push(root)
|
||||
const rootManifest = JSON.parse(await readFile(path.join(repo, "package.json"), "utf8")) as {
|
||||
scripts: { test: string }
|
||||
}
|
||||
await writeFile(
|
||||
path.join(root, "package.json"),
|
||||
JSON.stringify({ name: "fixture", private: true, scripts: { test: rootManifest.scripts.test } }),
|
||||
)
|
||||
await cp(path.join(repo, "biome.json"), path.join(root, "biome.json"))
|
||||
if (options.bunfig) await cp(path.join(repo, "bunfig.toml"), path.join(root, "bunfig.toml"))
|
||||
await mkdir(path.join(root, "scripts"))
|
||||
await cp(path.join(repo, "scripts/packages.ts"), path.join(root, "scripts/packages.ts"))
|
||||
|
||||
// beta takes the `--conditions=browser` leg of the test script, alpha the other.
|
||||
const manifests = {
|
||||
alpha: { name: "@fixture/alpha", version: "0.0.0", private: true },
|
||||
beta: { name: "@fixture/beta", version: "0.0.0", private: true, esTest: { conditions: ["browser"] } },
|
||||
}
|
||||
for (const [pkg, manifest] of Object.entries(manifests)) {
|
||||
await mkdir(path.join(root, "packages", pkg, "test"), { recursive: true })
|
||||
await writeFile(path.join(root, "packages", pkg, "package.json"), `${JSON.stringify(manifest, null, 2)}\n`)
|
||||
await writeFile(path.join(root, "packages", pkg, "test", "own.test.ts"), suite(`own:${pkg}`, false))
|
||||
for (const outside of OUTSIDE) {
|
||||
const dir = path.join(root, outside, "packages", pkg, "test")
|
||||
await mkdir(dir, { recursive: true })
|
||||
await writeFile(path.join(dir, "intruder.test.ts"), suite(`intruder:${outside}:${pkg}`, true))
|
||||
}
|
||||
}
|
||||
for (const outside of OUTSIDE) await writeFile(path.join(root, outside, "biome.json"), '{ "root": true }\n')
|
||||
return root
|
||||
}
|
||||
|
||||
async function run(root: string, cmd: string[]) {
|
||||
const log = path.join(root, "loaded.log")
|
||||
await writeFile(log, "")
|
||||
const proc = Bun.spawn(cmd, {
|
||||
cwd: root,
|
||||
env: { ...process.env, CLEAN_ROOM_LOG: log },
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
})
|
||||
const [stdout, stderr, exit] = await Promise.all([
|
||||
new Response(proc.stdout).text(),
|
||||
new Response(proc.stderr).text(),
|
||||
proc.exited,
|
||||
])
|
||||
const loaded = (await readFile(log, "utf8")).split("\n").filter(Boolean).sort()
|
||||
return { exit, loaded, output: stdout + stderr }
|
||||
}
|
||||
|
||||
describe("test runner isolation", () => {
|
||||
test("`bun run test` scopes itself to workspace packages without any runner config", async () => {
|
||||
const root = await fixture({ bunfig: false })
|
||||
const result = await run(root, ["bun", "run", "test"])
|
||||
expect(result.loaded).toEqual(["own:alpha", "own:beta"])
|
||||
expect(result.exit).toBe(0)
|
||||
})
|
||||
|
||||
test("a bare `bun test` discovers suites under packages/ only", async () => {
|
||||
const root = await fixture({ bunfig: true })
|
||||
const result = await run(root, ["bun", "test"])
|
||||
expect(result.loaded).toEqual(["own:alpha", "own:beta"])
|
||||
expect(result.exit).toBe(0)
|
||||
})
|
||||
|
||||
test("a bare path filter cannot reach a reference checkout", async () => {
|
||||
const root = await fixture({ bunfig: true })
|
||||
const result = await run(root, ["bun", "test", "packages/alpha"])
|
||||
expect(result.loaded).toEqual(["own:alpha"])
|
||||
expect(result.exit).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("lint and typecheck isolation", () => {
|
||||
test("`biome check .` ignores nested root configs outside packages/", async () => {
|
||||
const root = await fixture({ bunfig: true })
|
||||
const result = await run(root, [path.join(repo, "node_modules/.bin/biome"), "check", "."])
|
||||
expect(result.output).not.toContain("nested root configuration")
|
||||
expect(result.exit).toBe(0)
|
||||
})
|
||||
|
||||
test("tsconfig.base.json excludes the reference checkouts for every package", async () => {
|
||||
const base = JSON.parse(await readFile(path.join(repo, "tsconfig.base.json"), "utf8")) as { exclude?: string[] }
|
||||
expect(base.exclude).toEqual(expect.arrayContaining(["review", "evals/results"]))
|
||||
})
|
||||
})
|
||||
+2
-1
@@ -18,5 +18,6 @@
|
||||
"skipLibCheck": true,
|
||||
"composite": true,
|
||||
"types": ["bun", "node"]
|
||||
}
|
||||
},
|
||||
"exclude": ["review", "evals/results", "**/node_modules", "**/dist"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user