mirror of
https://github.com/stablyai/orca.git
synced 2026-09-23 00:02:29 +00:00
* fix(linux): release orphaned processes when their owner exits * fix(linux): handle inhibitor errors until streams close --------- Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
158 lines
4.5 KiB
JavaScript
158 lines
4.5 KiB
JavaScript
import { execFileSync, spawnSync } from 'node:child_process'
|
|
import { copyFileSync, existsSync, mkdtempSync, rmSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { delimiter, dirname, join, resolve } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { build } from 'esbuild'
|
|
|
|
const repo = resolve(fileURLToPath(new URL('../..', import.meta.url)))
|
|
const fixture = join(repo, 'config/docker/linux-lid-sleep-assertion')
|
|
const sourcePath = join(repo, 'src/main/linux-lid-sleep-assertion.ts')
|
|
const args = process.argv.slice(2)
|
|
const options = new Map()
|
|
for (let index = 0; index < args.length; index += 2) {
|
|
const key = args[index]
|
|
const value = args[index + 1]
|
|
if (
|
|
!['--baseline', '--container'].includes(key) ||
|
|
!value ||
|
|
value.startsWith('-') ||
|
|
options.has(key)
|
|
) {
|
|
throw new Error(
|
|
'Usage: run-linux-lid-sleep-assertion-docker.mjs [--baseline <git-ref>] [--container <name>]'
|
|
)
|
|
}
|
|
options.set(key, value)
|
|
}
|
|
const baseline = options.get('--baseline')
|
|
const suffix = `${process.pid}-${Date.now()}`
|
|
const container = options.get('--container') ?? `orca-inhibitor-oracle-${suffix}`
|
|
const image = `orca-inhibitor-oracle:${suffix}`
|
|
const docker =
|
|
process.env.ORCA_DOCKER ??
|
|
(existsSync('/Applications/Docker.app/Contents/Resources/bin/docker')
|
|
? '/Applications/Docker.app/Contents/Resources/bin/docker'
|
|
: 'docker')
|
|
const dockerDir = dirname(docker)
|
|
const env = {
|
|
...process.env,
|
|
ORCA_BACKGROUND_LAUNCH: '1',
|
|
PATH: `${dockerDir}${delimiter}${process.env.PATH ?? ''}`
|
|
}
|
|
const platform =
|
|
process.env.ORCA_DOCKER_PLATFORM ?? (process.arch === 'arm64' ? 'linux/arm64' : 'linux/amd64')
|
|
const temp = mkdtempSync(join(tmpdir(), 'orca-inhibitor-oracle-'))
|
|
const remote = `/tmp/orca-inhibitor-oracle-${suffix}`
|
|
|
|
function runDocker(command, allowFailure = false) {
|
|
const result = spawnSync(docker, command, {
|
|
cwd: repo,
|
|
env,
|
|
encoding: 'utf8',
|
|
maxBuffer: 16 * 1024 * 1024
|
|
})
|
|
if (result.error) {
|
|
throw result.error
|
|
}
|
|
if (result.status !== 0 && !allowFailure) {
|
|
throw new Error(`docker ${command[0]} failed: ${result.stdout}\n${result.stderr}`)
|
|
}
|
|
return result
|
|
}
|
|
|
|
async function bundle(mode, ref) {
|
|
const oldSource = ref
|
|
? execFileSync('git', ['show', `${ref}:src/main/linux-lid-sleep-assertion.ts`], {
|
|
cwd: repo,
|
|
encoding: 'utf8'
|
|
})
|
|
: null
|
|
await build({
|
|
entryPoints: [sourcePath],
|
|
bundle: true,
|
|
platform: 'node',
|
|
format: 'cjs',
|
|
target: 'node18',
|
|
outfile: join(temp, `${mode}.cjs`),
|
|
logLevel: 'warning',
|
|
plugins:
|
|
oldSource === null
|
|
? []
|
|
: [
|
|
{
|
|
name: 'baseline-source',
|
|
setup(api) {
|
|
api.onLoad({ filter: /linux-lid-sleep-assertion\.ts$/ }, () => ({
|
|
contents: oldSource,
|
|
loader: 'ts',
|
|
resolveDir: dirname(sourcePath)
|
|
}))
|
|
}
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
try {
|
|
await bundle('candidate')
|
|
if (baseline) {
|
|
await bundle('baseline', baseline)
|
|
}
|
|
for (const file of ['owner.cjs', 'oracle.cjs']) {
|
|
copyFileSync(join(fixture, file), join(temp, file))
|
|
}
|
|
if (!options.has('--container')) {
|
|
runDocker(['build', '--platform', platform, '-t', image, fixture])
|
|
runDocker([
|
|
'run',
|
|
'-d',
|
|
'--name',
|
|
container,
|
|
'--platform',
|
|
platform,
|
|
'--privileged',
|
|
'--cgroupns=host',
|
|
'--tmpfs',
|
|
'/run',
|
|
'--tmpfs',
|
|
'/run/lock',
|
|
'-v',
|
|
'/sys/fs/cgroup:/sys/fs/cgroup:rw',
|
|
image
|
|
])
|
|
}
|
|
const deadline = Date.now() + 20000
|
|
while (
|
|
runDocker(['exec', container, 'systemctl', 'is-active', 'systemd-logind'], true).status !== 0
|
|
) {
|
|
if (Date.now() >= deadline) {
|
|
throw new Error('systemd-logind did not start')
|
|
}
|
|
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
}
|
|
runDocker(['exec', container, 'mkdir', remote])
|
|
runDocker(['cp', `${temp}/.`, `${container}:${remote}`])
|
|
for (const mode of baseline ? ['baseline', 'candidate'] : ['candidate']) {
|
|
const result = runDocker([
|
|
'exec',
|
|
'-e',
|
|
'ORCA_BACKGROUND_LAUNCH=1',
|
|
container,
|
|
'node',
|
|
`${remote}/oracle.cjs`,
|
|
mode,
|
|
`${remote}/${mode}.cjs`
|
|
])
|
|
process.stdout.write(result.stdout)
|
|
process.stderr.write(result.stderr)
|
|
}
|
|
} finally {
|
|
runDocker(['exec', container, 'rm', '-rf', remote], true)
|
|
if (!options.has('--container')) {
|
|
runDocker(['rm', '-f', container], true)
|
|
runDocker(['image', 'rm', image], true)
|
|
}
|
|
rmSync(temp, { recursive: true, force: true })
|
|
}
|