mirror of
https://github.com/stablyai/orca.git
synced 2026-10-22 00:03:47 +00:00
ci: finalize Linux relay artifacts for aggregation
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
import { mkdtemp, mkdir, readFile, realpath, rm, writeFile } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
|
||||
import { parse } from 'yaml'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import { createSshRelayArtifactTestManifest } from '../../src/main/ssh/ssh-relay-artifact-test-manifest.ts'
|
||||
import {
|
||||
finalizeSshRelayRuntimeLinuxArtifact,
|
||||
parseSshRelayRuntimeLinuxFinalizationArguments
|
||||
} from './ssh-relay-runtime-linux-finalization.mjs'
|
||||
|
||||
const temporaryDirectories = []
|
||||
const VERIFIED_AT = '2026-07-15T13:30:00.000Z'
|
||||
const artifactWorkflowUrl = new URL(
|
||||
'../../.github/workflows/ssh-relay-runtime-artifacts.yml',
|
||||
import.meta.url
|
||||
)
|
||||
|
||||
function linuxIdentity() {
|
||||
const tuple = createSshRelayArtifactTestManifest().tuples[0]
|
||||
const {
|
||||
archive,
|
||||
metadataAssets: _metadataAssets,
|
||||
nativeVerification: _native,
|
||||
...identity
|
||||
} = tuple
|
||||
return { identity: { ...identity, archive }, finalIdentity: identity }
|
||||
}
|
||||
|
||||
function linuxPlan(identity) {
|
||||
return {
|
||||
platform: 'linux',
|
||||
verificationFiles: identity.entries
|
||||
.filter(
|
||||
(entry) =>
|
||||
entry.type === 'file' &&
|
||||
['node', 'node-pty-native', 'parcel-watcher-native', 'native-runtime'].includes(
|
||||
entry.role
|
||||
)
|
||||
)
|
||||
.map((entry) => ({ path: entry.path, role: entry.role, sourceSha256: entry.sha256 }))
|
||||
}
|
||||
}
|
||||
|
||||
async function fixture() {
|
||||
const root = await mkdtemp(join(tmpdir(), 'orca-runtime-linux-finalization-'))
|
||||
temporaryDirectories.push(root)
|
||||
const source = join(root, 'source')
|
||||
const runtime = join(source, 'runtime')
|
||||
const output = join(root, 'final')
|
||||
await mkdir(runtime, { recursive: true })
|
||||
const { identity, finalIdentity } = linuxIdentity()
|
||||
const identityPath = join(source, `orca-ssh-relay-runtime-${identity.tupleId}.identity.json`)
|
||||
const archivePath = join(source, identity.archive.name)
|
||||
const sbomPath = join(source, `orca-ssh-relay-runtime-${identity.tupleId}.spdx.json`)
|
||||
const provenancePath = join(source, `orca-ssh-relay-runtime-${identity.tupleId}.provenance.json`)
|
||||
await Promise.all([
|
||||
writeFile(identityPath, `${JSON.stringify(identity)}\n`),
|
||||
writeFile(archivePath, 'archive'),
|
||||
writeFile(sbomPath, 'sbom'),
|
||||
writeFile(provenancePath, 'provenance')
|
||||
])
|
||||
return { source, runtime, output, identity, finalIdentity, identityPath }
|
||||
}
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
temporaryDirectories
|
||||
.splice(0)
|
||||
.map((directory) => rm(directory, { recursive: true, force: true }))
|
||||
)
|
||||
})
|
||||
|
||||
describe('SSH relay runtime Linux hash-only finalization', () => {
|
||||
it('verifies before emitting an exact aggregate-ready descriptor and receipt', async () => {
|
||||
const input = await fixture()
|
||||
const order = []
|
||||
const plan = linuxPlan(input.finalIdentity)
|
||||
const physicalIdentityPath = await realpath(input.identityPath)
|
||||
const physicalRuntime = await realpath(input.runtime)
|
||||
const physicalSource = await realpath(input.source)
|
||||
const verifyRuntimeImpl = vi.fn(async ({ runtimeDirectory, identityPath, archivePath }) => {
|
||||
order.push('verify')
|
||||
expect(runtimeDirectory).toBe(physicalRuntime)
|
||||
expect(identityPath).toBe(physicalIdentityPath)
|
||||
expect(archivePath).toBe(join(physicalSource, input.identity.archive.name))
|
||||
return { smoke: { nodeVersion: 'v24.18.0' } }
|
||||
})
|
||||
const writeDescriptorImpl = vi.fn(async (options) => {
|
||||
order.push('descriptor')
|
||||
expect(options.finalIdentity).toEqual(input.finalIdentity)
|
||||
expect(options.verificationReport).toEqual({
|
||||
tupleId: input.identity.tupleId,
|
||||
sourceContentId: input.identity.contentId,
|
||||
finalContentId: input.identity.contentId,
|
||||
verifiedFiles: plan.verificationFiles.map((file) => ({
|
||||
path: file.path,
|
||||
role: file.role,
|
||||
sha256: file.sourceSha256
|
||||
}))
|
||||
})
|
||||
expect(options.nativeVerificationTool).toEqual({ name: 'node', version: '24.18.0' })
|
||||
expect(options.verifiedAt).toBe(VERIFIED_AT)
|
||||
return {
|
||||
tupleId: input.identity.tupleId,
|
||||
input: {
|
||||
tupleId: input.identity.tupleId,
|
||||
descriptor: { name: 'descriptor.json', size: 1, sha256: `sha256:${'a'.repeat(64)}` },
|
||||
archive: {
|
||||
name: input.identity.archive.name,
|
||||
size: 7,
|
||||
sha256: `sha256:${'b'.repeat(64)}`
|
||||
},
|
||||
sbom: { name: 'sbom.json', size: 4, sha256: `sha256:${'c'.repeat(64)}` },
|
||||
provenance: { name: 'provenance.json', size: 10, sha256: `sha256:${'d'.repeat(64)}` }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const result = await finalizeSshRelayRuntimeLinuxArtifact({
|
||||
sourceOutputDirectory: input.source,
|
||||
identityPath: input.identityPath,
|
||||
outputDirectory: input.output,
|
||||
verifiedAt: VERIFIED_AT,
|
||||
nativeVerificationTool: { name: 'node', version: '24.18.0' },
|
||||
readIdentityImpl: async () => input.identity,
|
||||
buildPlanImpl: () => plan,
|
||||
verifyRuntimeImpl,
|
||||
writeDescriptorImpl
|
||||
})
|
||||
|
||||
expect(order).toEqual(['verify', 'descriptor'])
|
||||
expect(result).toMatchObject({
|
||||
tupleId: input.identity.tupleId,
|
||||
contentId: input.identity.contentId,
|
||||
aggregateInput: { tupleId: input.identity.tupleId }
|
||||
})
|
||||
expect(JSON.parse(await readFile(result.receiptPath, 'utf8'))).toEqual({
|
||||
tupleId: input.identity.tupleId,
|
||||
contentId: input.identity.contentId,
|
||||
verification: { smoke: { nodeVersion: 'v24.18.0' } },
|
||||
aggregateInput: result.aggregateInput
|
||||
})
|
||||
await expect(
|
||||
readFile(join(result.assetsRoot, input.identity.archive.name), 'utf8')
|
||||
).resolves.toBe('archive')
|
||||
})
|
||||
|
||||
it('rejects non-Linux input and removes partial output on failure', async () => {
|
||||
const input = await fixture()
|
||||
const nonLinux = { ...input.identity, os: 'darwin', tupleId: 'darwin-x64' }
|
||||
await expect(
|
||||
finalizeSshRelayRuntimeLinuxArtifact({
|
||||
sourceOutputDirectory: input.source,
|
||||
identityPath: input.identityPath,
|
||||
outputDirectory: input.output,
|
||||
verifiedAt: VERIFIED_AT,
|
||||
nativeVerificationTool: { name: 'node', version: '24.18.0' },
|
||||
readIdentityImpl: async () => nonLinux,
|
||||
verifyRuntimeImpl: vi.fn(),
|
||||
writeDescriptorImpl: vi.fn()
|
||||
})
|
||||
).rejects.toThrow(/linux/i)
|
||||
|
||||
await expect(
|
||||
finalizeSshRelayRuntimeLinuxArtifact({
|
||||
sourceOutputDirectory: input.source,
|
||||
identityPath: input.identityPath,
|
||||
outputDirectory: input.output,
|
||||
verifiedAt: VERIFIED_AT,
|
||||
nativeVerificationTool: { name: 'node', version: '24.18.0' },
|
||||
readIdentityImpl: async () => input.identity,
|
||||
buildPlanImpl: () => linuxPlan(input.finalIdentity),
|
||||
verifyRuntimeImpl: async () => ({ smoke: true }),
|
||||
writeDescriptorImpl: async () => {
|
||||
throw new Error('descriptor failed')
|
||||
}
|
||||
})
|
||||
).rejects.toThrow(/descriptor failed/i)
|
||||
await expect(
|
||||
readFile(join(input.output, 'assets', input.identity.archive.name))
|
||||
).rejects.toMatchObject({ code: 'ENOENT' })
|
||||
})
|
||||
|
||||
it('parses only the exact bounded CLI arguments', () => {
|
||||
expect(
|
||||
parseSshRelayRuntimeLinuxFinalizationArguments([
|
||||
'--source-output-directory',
|
||||
'source',
|
||||
'--identity',
|
||||
'identity.json',
|
||||
'--output-directory',
|
||||
'output',
|
||||
'--verified-at',
|
||||
VERIFIED_AT,
|
||||
'--native-verification-tool-version',
|
||||
'24.18.0'
|
||||
])
|
||||
).toMatchObject({
|
||||
verifiedAt: VERIFIED_AT,
|
||||
nativeVerificationToolVersion: '24.18.0'
|
||||
})
|
||||
expect(() =>
|
||||
parseSshRelayRuntimeLinuxFinalizationArguments(['--output-directory', 'output'])
|
||||
).toThrow(/missing/i)
|
||||
expect(() =>
|
||||
parseSshRelayRuntimeLinuxFinalizationArguments([
|
||||
'--source-output-directory',
|
||||
'source',
|
||||
'--identity',
|
||||
'identity.json',
|
||||
'--output-directory',
|
||||
'output',
|
||||
'--verified-at',
|
||||
VERIFIED_AT,
|
||||
'--native-verification-tool-version',
|
||||
'24.18.0',
|
||||
'--extra',
|
||||
'value'
|
||||
])
|
||||
).toThrow(/invalid/i)
|
||||
})
|
||||
|
||||
it('emits Linux descriptors before upload and runs the contract on both native families', async () => {
|
||||
const source = await readFile(artifactWorkflowUrl, 'utf8')
|
||||
const workflow = parse(source)
|
||||
const posix = workflow.jobs['build-posix-runtime']
|
||||
const windows = workflow.jobs['build-windows-runtime']
|
||||
const build = posix.steps.find(
|
||||
(step) => step.name === 'Build twice, inspect, smoke, and compare exact runtime'
|
||||
).run
|
||||
const finalization = build.indexOf('ssh-relay-runtime-linux-finalization.mjs')
|
||||
const descriptorCopy = build.indexOf('.manifest-tuple.json', finalization)
|
||||
const linuxExit = build.indexOf('exit 0', descriptorCopy)
|
||||
expect(finalization).toBeGreaterThan(-1)
|
||||
expect(descriptorCopy).toBeGreaterThan(finalization)
|
||||
expect(linuxExit).toBeGreaterThan(descriptorCopy)
|
||||
for (const job of [posix, windows]) {
|
||||
const contract = job.steps.find(
|
||||
(step) => step.name === 'Run runtime artifact contract tests'
|
||||
).run
|
||||
expect(contract).toContain(
|
||||
'node --check config/scripts/ssh-relay-runtime-linux-finalization.mjs'
|
||||
)
|
||||
expect(contract).toContain('config/scripts/ssh-relay-runtime-linux-finalization.test.mjs')
|
||||
}
|
||||
expect(posix.steps.at(-1).with.path).toBe('runtime-evidence/${{ matrix.tuple }}/')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user