Files
orca/config/scripts/build-workspace-packages.mjs
T
Neil e4bbbe045f perf(test): faster local test loop and cold-worktree changed runs (#33421)
- test:changed exits before starting Vitest when Git reports no changed files.
- Unrecorded tests beyond 100 in scope use Vitest's static import graph instead
  of all running, so a fresh worktree's first changed run no longer runs the
  whole suite (patched RecordedModulesResolver; CI does not record, unchanged).
- Bun's slow config load was the SQLite import scan statting every unit test;
  filtered runs now classify only the tests their filters can select, and the
  scan walks directories instead of fs.globSync.
- Silence the native config loader notice on every run.
- Zod's test bundle is content-addressed and reused, so a killed run leaks
  nothing; leaked per-run directories older than 6h are swept.
- build:packages skips compiling when package inputs, compiler, and dist are
  unchanged; test scripts no longer nest pnpm invocations.
2026-10-24 23:15:51 -07:00

123 lines
3.8 KiB
JavaScript

import { spawnSync } from 'node:child_process'
import { createHash } from 'node:crypto'
import {
mkdirSync,
readdirSync,
readFileSync,
realpathSync,
renameSync,
statSync,
writeFileSync
} from 'node:fs'
import { createRequire } from 'node:module'
import { dirname, join, relative, resolve } from 'node:path'
const root = resolve(import.meta.dirname, '../..')
const PACKAGES = [{ name: '@orca/process-host', dir: 'src/packages/process-host' }]
// Outputs and build scratch space, not inputs.
const NON_INPUTS = new Set(['dist', 'node_modules', '.dist-build.lock'])
const COMPILER_PACKAGES = ['typescript', 'tsx', '@types/node']
function listFiles(directory, base = directory) {
return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
if (directory === base && (NON_INPUTS.has(entry.name) || entry.name.startsWith('.dist-'))) {
return []
}
const path = join(directory, entry.name)
return entry.isDirectory()
? listFiles(path, base)
: [relative(base, path).replaceAll('\\', '/')]
})
}
/** Sources, manifest, build script, and the exact installed compiler and Node types. */
export function hashPackageInputs(packageDir) {
const hash = createHash('sha256')
for (const file of listFiles(packageDir).sort()) {
hash
.update(`${file}\0`)
.update(readFileSync(join(packageDir, file)))
.update('\0')
}
const require = createRequire(join(packageDir, 'package.json'))
for (const name of COMPILER_PACKAGES) {
const manifest = realpathSync(require.resolve(`${name}/package.json`))
hash.update(`${manifest}\0`).update(readFileSync(manifest)).update('\0')
}
return hash.digest('hex')
}
/** Size and mtime of every output, so a deleted or edited dist file forces a rebuild. */
function describeOutputs(packageDir) {
const dist = join(packageDir, 'dist')
try {
return listFiles(dist)
.sort()
.map((file) => {
const { size, mtimeMs } = statSync(join(dist, file))
return `${file}:${size}:${mtimeMs}`
})
} catch {
return []
}
}
function stampPath(packageDir) {
return join(packageDir, 'node_modules', '.cache', 'orca-dist-stamp.json')
}
export function isPackageBuildCurrent(packageDir, inputs) {
try {
const stamp = JSON.parse(readFileSync(stampPath(packageDir), 'utf8'))
const outputs = describeOutputs(packageDir)
return (
stamp.inputs === inputs &&
outputs.length > 0 &&
JSON.stringify(stamp.outputs) === JSON.stringify(outputs)
)
} catch {
return false
}
}
function writeStamp(packageDir, inputs) {
const path = stampPath(packageDir)
mkdirSync(dirname(path), { recursive: true })
const temporary = `${path}.${process.pid}`
writeFileSync(temporary, JSON.stringify({ inputs, outputs: describeOutputs(packageDir) }))
renameSync(temporary, path)
}
function runPackageBuild(name) {
// Why not @orca/process-host: this builds it, so its dist may not exist yet.
const pnpmEntry = process.env.npm_execpath
const [program, args] = /\.[cm]?js$/.test(pnpmEntry ?? '')
? [process.execPath, [pnpmEntry, '--filter', name, 'build']]
: ['pnpm', ['--filter', name, 'build']]
const result = spawnSync(program, args, {
cwd: root,
stdio: 'inherit',
shell: program === 'pnpm' && process.platform === 'win32'
})
if (result.error) {
throw result.error
}
return result.status ?? 1
}
if (process.argv[1] && realpathSync(process.argv[1]) === import.meta.filename) {
for (const { name, dir } of PACKAGES) {
const packageDir = join(root, dir)
// Hashed before building: an edit during the build leaves a stale stamp, never a skipped build.
const inputs = hashPackageInputs(packageDir)
if (isPackageBuildCurrent(packageDir, inputs)) {
continue
}
const status = runPackageBuild(name)
if (status !== 0) {
process.exit(status)
}
writeStamp(packageDir, inputs)
}
}