Files
orca/config/scripts/run-node-server-tests.mjs
T
Jinjing f7c542c7a3 Keep profile saving alive after a stalled main loop (#25318)
* Keep profile saving alive after a stalled main loop

After a long main-loop stall (overnight sleep, dark wakes), the profile
writer's overdue 30s timeout could run before an acknowledgement that was
already queued, permanently retiring the writer until restart. Terminal
creation then failed because pane bindings could not be saved.

- Writer deadlines measure lateness on the monotonic clock and grant a
  bounded fresh window when the callback is overdue or the system reports
  suspended; resume re-arms without spending grace. Applies to
  initialization, every command, and the close/exit wait.
- The "Saving stopped" alert is parented to a visible main window (never a
  parentless synchronous macOS alert), deferred until shown, deduplicated,
  and says whether the latest change is unconfirmed.
- Timeouts, grace, writer faults, and alert presentation leave sanitized
  durable breadcrumbs.

* Fix profile writer timeout and shutdown races

* Run profile writer stall regression on Linux and Windows

* Keep Electron probes out of headless runtime qualification
2026-10-06 14:13:39 -07:00

96 lines
3.3 KiB
JavaScript

// Runs the headless-server suites under the pinned Node (design D4/D4a), not the host's.
import { join, resolve } from 'node:path'
import { randomUUID } from 'node:crypto'
import { readFileSync } from 'node:fs'
import { ORCAD_VERSION_FILENAME } from '../../src/shared/orcad-artifacts.ts'
import { NODE_RUNTIME_PIN } from '../../src/shared/node-runtime-pin.ts'
import {
ORCAD_PROFILE_PREFLIGHT_FLAG,
parseOrcadProfilePreflight
} from '../../src/shared/orcad-profile-preflight.ts'
import { packagedNodeRuntimePath } from './build-orcad-node.mjs'
import { ensurePinnedNodeExecutable } from './pinned-node-downloads.mjs'
import { currentTarget } from './server-build-target.mjs'
import { describeProcessFailure, runProcessSync } from './script-child-process.mjs'
import {
CROSS_RUNTIME_TEST_PATHS,
nodeServerTestPaths,
REQUIRED_TEST_INPUTS_ENV
} from './node-server-test-paths.mjs'
const root = resolve(import.meta.dirname, '../..')
const target = currentTarget()
const artifact = process.argv.includes('--artifact')
// Lanes that provide Bun 1.4.2 and the last Bun orcad slot (design D7 upgrade and rollback).
const crossRuntime = process.argv.includes('--cross-runtime')
const testArgs = process.argv
.slice(2)
.filter((arg) => arg !== '--artifact' && arg !== '--cross-runtime')
const packageDir = join(root, 'out', 'orcad')
const runtimePath = artifact
? packagedNodeRuntimePath(packageDir, target)
: await ensurePinnedNodeExecutable({ target })
// Tests that launch the packaged runtime themselves find it here. A lane's named inputs are
// required: their tests fail on a missing input instead of passing as a skip.
const env = {
...process.env,
ORCA_BACKGROUND_LAUNCH: '1',
ORCA_PINNED_NODE: runtimePath,
[REQUIRED_TEST_INPUTS_ENV]: [artifact && 'artifact', crossRuntime && 'cross-runtime']
.filter(Boolean)
.join(',')
}
function run(program, args) {
const result = runProcessSync({
program,
args,
cwd: root,
env,
stdio: 'inherit',
timeoutMs: null
})
if (result.code !== 0) {
process.exit(result.code ?? 1)
}
}
if (artifact) {
const nonce = randomUUID()
const result = runProcessSync({
program: runtimePath,
args: [join(packageDir, 'orcad.js'), ORCAD_PROFILE_PREFLIGHT_FLAG, nonce],
cwd: root,
env,
timeoutMs: 90_000
})
if (result.code !== 0 || result.timedOut || result.outputTruncated) {
throw new Error(`Bundled runtime readiness failed: ${describeProcessFailure(result)}`)
}
const response = parseOrcadProfilePreflight(
result.stdout,
nonce,
{ runtime: 'node', runtimeVersion: NODE_RUNTIME_PIN.version },
readFileSync(join(packageDir, ORCAD_VERSION_FILENAME), 'utf8').trim()
)
process.stdout.write(`${JSON.stringify({ target, ...response })}\n`)
}
run(runtimePath, [
join(root, 'node_modules/vitest/vitest.mjs'),
'run',
'--config',
'config/vitest.config.ts',
...(testArgs.length > 0 ? testArgs : defaultTestArgs())
])
function defaultTestArgs() {
return [
...nodeServerTestPaths({ artifact, crossRuntime }),
// Electron probes run in desktop jobs; headless compatibility containers have no display.
'--exclude',
'**/*.electron.test.ts',
// A directory selector would otherwise pull them into lanes that lack their inputs.
...(crossRuntime ? [] : CROSS_RUNTIME_TEST_PATHS.flatMap((path) => ['--exclude', path]))
]
}