33 lines
2.8 KiB
JavaScript
33 lines
2.8 KiB
JavaScript
import { createHash } from 'node:crypto'
|
|
import { execFileSync, spawnSync } from 'node:child_process'
|
|
import { readFile, stat } from 'node:fs/promises'
|
|
import { resolve } from 'node:path'
|
|
|
|
const root = resolve(new URL('..', import.meta.url).pathname)
|
|
const evidence = JSON.parse(await readFile(resolve(root, 'config/camotics-native-artifact.json'), 'utf8'))
|
|
const sha256 = (bytes) => createHash('sha256').update(bytes).digest('hex')
|
|
|
|
if (evidence.schemaVersion !== 2 || evidence.status !== 'pass' || evidence.build.withGui !== true || evidence.build.withTpl !== true) throw new Error('CAMotics GUI/TPL evidence is not passing.')
|
|
const revision = execFileSync('git', ['-C', resolve(root, evidence.source.path), 'rev-parse', 'HEAD'], { encoding: 'utf8' }).trim()
|
|
if (revision !== evidence.source.revision) throw new Error(`CAMotics GUI/TPL source revision drift: ${revision}`)
|
|
for (const [path, expected] of Object.entries(evidence.artifacts)) {
|
|
const absolute = resolve(root, path)
|
|
const bytes = await readFile(absolute)
|
|
const metadata = await stat(absolute)
|
|
const digest = sha256(bytes)
|
|
if (!metadata.isFile() || (metadata.mode & 0o111) === 0 || bytes.byteLength !== expected.bytes || digest !== expected.sha256) throw new Error(`CAMotics GUI/TPL artifact drift: ${path}`)
|
|
}
|
|
|
|
const runHelp = (binary, env = {}) => {
|
|
const result = spawnSync(resolve(root, binary), ['--help'], { encoding: 'utf8', env: { ...process.env, ...env } })
|
|
const output = `${result.stdout}${result.stderr}`
|
|
return { status: result.status, output }
|
|
}
|
|
const camotics = runHelp('CAMotics/camotics', { QT_QPA_PLATFORM: 'offscreen' })
|
|
const tplang = runHelp('CAMotics/tplang')
|
|
if (camotics.status !== 0 || tplang.status !== 0 || !camotics.output.includes('Usage:') || !tplang.output.includes('Usage:')) throw new Error('CAMotics GUI/TPL help smoke failed.')
|
|
if (evidence.guiSmoke.status !== 'pass' || evidence.guiSmoke.window.mapState !== 'IsViewable' || evidence.guiSmoke.window.width !== 1200 || evidence.guiSmoke.window.height !== 800 || evidence.guiSmoke.browserRuntime !== false) throw new Error('CAMotics GUI Xvfb smoke boundary is invalid.')
|
|
if (evidence.pipelineBoundary.workspaceNativeGuiAvailable !== true || evidence.pipelineBoundary.workspaceNativeTplAvailable !== true || evidence.pipelineBoundary.browserNativeGuiAvailable !== false || evidence.pipelineBoundary.browserNativeTplAvailable !== false || evidence.pipelineBoundary.canonicalGcodeParser !== 'linuxcnc-wasm') throw new Error('CAMotics GUI/TPL browser boundary is invalid.')
|
|
|
|
console.log(JSON.stringify({ status: 'camotics-gui-tpl-pass', sourceRevision: revision, version: evidence.source.version, artifacts: evidence.artifacts, smoke: { camotics: { exitCode: camotics.status }, tplang: { exitCode: tplang.status }, gui: evidence.guiSmoke }, browserBoundary: evidence.pipelineBoundary }, null, 2))
|