mirror of
https://github.com/stablyai/orca.git
synced 2026-10-02 08:02:02 +00:00
* Reuse serializer oracle cells and isolate native cache policy * Preserve native cache post-save paths and record hosted oracle gain * Record native cache reuse and separate cancel-test startup budget
144 lines
4.8 KiB
JavaScript
144 lines
4.8 KiB
JavaScript
import { build } from 'esbuild'
|
|
import { appendFileSync, globSync, readFileSync } from 'node:fs'
|
|
import { resolve } from 'node:path'
|
|
import { pathToFileURL } from 'node:url'
|
|
import {
|
|
externalNativeAddons,
|
|
ORCAD_CHILD_ENTRY_POINTS,
|
|
ORCAD_ENTRY_POINT
|
|
} from './orcad-entry-build.mjs'
|
|
import { nodeServerTestPaths } from './node-server-test-paths.mjs'
|
|
import { nodeServerQualification } from './node-server-qualification.mjs'
|
|
|
|
const ROOT = resolve(import.meta.dirname, '../..')
|
|
const BUILD_SCRIPTS = [
|
|
'config/scripts/build-orcad-node.mjs',
|
|
'config/scripts/server-build-target.mjs',
|
|
'config/scripts/pinned-node-downloads.mjs',
|
|
'config/scripts/build-orcad.mjs',
|
|
'config/scripts/build-orcad-prebuilds.mjs',
|
|
'config/scripts/orcad-prebuild-smoke-child.cjs',
|
|
'config/scripts/build-windows-process-tree-relay-addon.mjs',
|
|
'config/scripts/run-node-server-tests.mjs',
|
|
'config/vitest.config.ts',
|
|
'config/scripts/happy-dom-offscreen-canvas.ts',
|
|
'config/scripts/happy-dom-mutation-observer-retention.ts',
|
|
'config/scripts/vitest-host-ports-setup.ts',
|
|
'config/scripts/vitest-real-agent-home-write-guard.ts'
|
|
]
|
|
const ALWAYS_FILES = new Set([
|
|
'package.json',
|
|
'pnpm-lock.yaml',
|
|
'pnpm-workspace.yaml',
|
|
'.npmrc',
|
|
'.pnpmfile.cjs',
|
|
'tsconfig.json',
|
|
'.github/workflows/node-server-tests.yml',
|
|
'config/scripts/node-server-change-scope.mjs',
|
|
'config/scripts/node-server-change-scope.test.mjs',
|
|
'config/scripts/node-server-qualification.mjs',
|
|
'config/scripts/node-server-qualification.test.mjs'
|
|
])
|
|
const ALWAYS_PREFIXES = [
|
|
'.github/actions/install-node-dependencies/',
|
|
'.github/actions/prepare-native-runtime/',
|
|
// These areas also contain worker paths and fixtures opened without an import.
|
|
'src/main/persistence/',
|
|
'src/main/sqlite/',
|
|
'src/main/orcad/',
|
|
'src/main/daemon/pty-subprocess/',
|
|
'src/main/providers/',
|
|
'config/patches/',
|
|
'config/tsconfig',
|
|
'native/',
|
|
'resources/licenses/ripgrep/'
|
|
]
|
|
|
|
export function discoverNodeServerTests(root = ROOT) {
|
|
const selectors = nodeServerTestPaths({ artifact: true, crossRuntime: true })
|
|
return globSync(
|
|
['src/**/*.test.{ts,tsx}', 'config/scripts/**/*.test.{ts,mjs}', 'tests/e2e/**/*.unit.test.ts'],
|
|
{ cwd: root }
|
|
)
|
|
.map((file) => file.replaceAll('\\', '/'))
|
|
.filter((file) => selectors.some((selector) => file.includes(selector)))
|
|
.sort()
|
|
}
|
|
|
|
export async function collectNodeServerInputs({ root = ROOT, entryPoints } = {}) {
|
|
const entries = entryPoints ?? [
|
|
ORCAD_ENTRY_POINT,
|
|
...Object.values(ORCAD_CHILD_ENTRY_POINTS),
|
|
...BUILD_SCRIPTS,
|
|
...discoverNodeServerTests(root)
|
|
]
|
|
const result = await build({
|
|
absWorkingDir: root,
|
|
entryPoints: entries,
|
|
bundle: true,
|
|
write: false,
|
|
outdir: resolve(root, '.node-server-scope'),
|
|
platform: 'node',
|
|
format: 'esm',
|
|
splitting: true,
|
|
packages: 'external',
|
|
loader: { '.svg': 'empty', '.png': 'empty', '.webp': 'empty', '.css': 'empty' },
|
|
plugins: [externalNativeAddons],
|
|
metafile: true,
|
|
logLevel: 'silent'
|
|
})
|
|
if (result.warnings.length > 0) {
|
|
throw new Error(result.warnings.map((warning) => warning.text).join('\n'))
|
|
}
|
|
return new Set(
|
|
Object.keys(result.metafile.inputs).map((file) =>
|
|
file.replaceAll('\\', '/').replace(/\?.*$/, '')
|
|
)
|
|
)
|
|
}
|
|
|
|
export async function classifyNodeServerChanges(changedFiles, collect = collectNodeServerInputs) {
|
|
if (changedFiles.length === 0) {
|
|
return { shouldRun: true, reason: 'No complete changed-file evidence' }
|
|
}
|
|
const selectors = nodeServerTestPaths({ artifact: true, crossRuntime: true })
|
|
const forced = changedFiles.find(
|
|
(file) =>
|
|
ALWAYS_FILES.has(file) ||
|
|
ALWAYS_PREFIXES.some((prefix) => file.startsWith(prefix)) ||
|
|
selectors.some((selector) => file.includes(selector))
|
|
)
|
|
if (forced) {
|
|
return { shouldRun: true, reason: `Build or CI input changed: ${forced}` }
|
|
}
|
|
try {
|
|
const inputs = await collect()
|
|
const matched = changedFiles.find((file) => inputs.has(file))
|
|
return {
|
|
shouldRun: Boolean(matched),
|
|
reason: matched
|
|
? `Runtime or test dependency changed: ${matched}`
|
|
: 'No headless-server inputs changed'
|
|
}
|
|
} catch (error) {
|
|
return {
|
|
shouldRun: true,
|
|
graphUnavailable: true,
|
|
reason: `Dependency graph unavailable: ${String(error)}`
|
|
}
|
|
}
|
|
}
|
|
|
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
const changedFiles = readFileSync(process.argv[2], 'utf8').split('\0').filter(Boolean)
|
|
const result = await classifyNodeServerChanges(changedFiles)
|
|
console.log(result.reason)
|
|
const policy = nodeServerQualification(changedFiles, result)
|
|
const output = `should_run=${result.shouldRun}\nqualification=${policy.qualification}\nrunners=${JSON.stringify(policy.runners)}\n`
|
|
if (process.env.GITHUB_OUTPUT) {
|
|
appendFileSync(process.env.GITHUB_OUTPUT, output)
|
|
} else {
|
|
process.stdout.write(output)
|
|
}
|
|
}
|