mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
* test: audit CLI environment, Jira and orchestration coverage * test: audit project setup routing and refusal coverage * test: audit hook delivery, config gates and mobile shell coverage * docs: retain a reachable audit tracker source commit --------- Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
135 lines
4.9 KiB
JavaScript
135 lines
4.9 KiB
JavaScript
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { join } from 'node:path'
|
|
import { describe, expect, it } from 'vitest'
|
|
import { runProcess } from '@orca/process-host'
|
|
import {
|
|
aggregateEnvironment,
|
|
aggregateNeeds,
|
|
aggregateRequiredJobs as requiredJobs,
|
|
aggregateSelectors,
|
|
aggregateShell as gate
|
|
} from './pr-aggregate-gate-context.mjs'
|
|
|
|
async function verifyCases(environments, script, env = {}) {
|
|
const quote = (value) => `'${value.replaceAll("'", "'\\''")}'`
|
|
const cases = environments.map((environment, index) => {
|
|
const exports = Object.entries(environment)
|
|
.map(([name, value]) => `export ${name}=${quote(value)}`)
|
|
.join('\n')
|
|
return `(\n${exports}\n${script}\n)\nprintf 'AGGREGATE_CASE_${index}=%s\\n' "$?"`
|
|
})
|
|
const directory = mkdtempSync(join(tmpdir(), 'orca-aggregate-cases-'))
|
|
const file = join(directory, 'cases.sh')
|
|
try {
|
|
writeFileSync(file, cases.join('\n'))
|
|
const result = await runProcess({
|
|
program: 'bash',
|
|
args: [file],
|
|
env: { ...process.env, ORCA_BACKGROUND_LAUNCH: '1', ...env },
|
|
timeoutMs: 10_000
|
|
})
|
|
expect(result.code, result.stderr).toBe(0)
|
|
return [...result.stdout.matchAll(/^AGGREGATE_CASE_\d+=(\d+)$/gm)].map((match) =>
|
|
Number(match[1])
|
|
)
|
|
} finally {
|
|
rmSync(directory, { recursive: true, force: true })
|
|
}
|
|
}
|
|
|
|
const malformedSelectors = [
|
|
'',
|
|
'TRUE',
|
|
'True',
|
|
'FALSE',
|
|
'0',
|
|
'1',
|
|
'null',
|
|
'unknown',
|
|
' true',
|
|
'true\n',
|
|
undefined,
|
|
null
|
|
]
|
|
const outcomes = ['success', 'skipped', 'failure', 'cancelled', '', 'unknown', undefined, null]
|
|
|
|
// The aggregate runs as Bash on Linux; Windows has no required Bash installation.
|
|
describe.skipIf(process.platform === 'win32')(
|
|
'required PR checks through the real aggregate shell',
|
|
() => {
|
|
it('accepts code, docs, reuse and mixed plans with their required outcomes', async () => {
|
|
const plans = [aggregateNeeds('true'), aggregateNeeds('false')]
|
|
for (const static_analysis of ['true', 'false']) {
|
|
for (const typecheck of ['true', 'false']) {
|
|
plans.push(aggregateNeeds('false', { static_analysis, typecheck }))
|
|
}
|
|
}
|
|
plans.push(aggregateNeeds('false', { test: 'true', package: 'true', typecheck: 'true' }))
|
|
for (const should_run of ['true', 'false', ...malformedSelectors]) {
|
|
plans.push(aggregateNeeds('true', { should_run }))
|
|
}
|
|
for (const needs of plans) {
|
|
const { static_analysis, typecheck } = needs.code_paths.outputs
|
|
expect(needs.preflight.result).toBe(
|
|
static_analysis === 'true' || typecheck === 'true' ? 'success' : 'skipped'
|
|
)
|
|
}
|
|
expect(await verifyCases(plans.map(aggregateEnvironment), gate.run)).toEqual(
|
|
plans.map(() => 0)
|
|
)
|
|
})
|
|
|
|
it('rejects missing, failed, cancelled or incorrectly skipped required results', async () => {
|
|
const cases = []
|
|
const expected = []
|
|
for (const selected of ['true', 'false']) {
|
|
for (const job of ['code_paths', ...requiredJobs]) {
|
|
for (const result of outcomes) {
|
|
const needs = aggregateNeeds(selected)
|
|
needs[job].result = result
|
|
cases.push(aggregateEnvironment(needs))
|
|
const correct = job === 'code_paths' || selected === 'true' ? 'success' : 'skipped'
|
|
expected.push(result === correct ? 0 : 1)
|
|
}
|
|
const missing = aggregateNeeds(selected)
|
|
delete missing[job]
|
|
cases.push(aggregateEnvironment(missing))
|
|
expected.push(1)
|
|
}
|
|
}
|
|
expect(await verifyCases(cases, gate.run)).toEqual(expected)
|
|
})
|
|
|
|
it('rejects every malformed or masked raw selector even when downstream jobs were skipped', async () => {
|
|
const cases = []
|
|
for (const job of aggregateSelectors) {
|
|
for (const selected of malformedSelectors) {
|
|
cases.push(aggregateEnvironment(aggregateNeeds('false', { [job]: selected })))
|
|
}
|
|
const missing = aggregateNeeds('false')
|
|
delete missing.code_paths.outputs[job]
|
|
cases.push(aggregateEnvironment(missing))
|
|
}
|
|
expect(await verifyCases(cases, gate.run)).toEqual(cases.map(() => 1))
|
|
})
|
|
|
|
it('rejects malformed preflight phases even when the other phase selects preflight', async () => {
|
|
const cases = []
|
|
for (const phase of ['static_analysis', 'typecheck']) {
|
|
const other = phase === 'static_analysis' ? 'typecheck' : 'static_analysis'
|
|
for (const selected of malformedSelectors) {
|
|
for (const otherSelected of ['true', 'false']) {
|
|
for (const result of ['success', 'skipped']) {
|
|
const needs = aggregateNeeds('false', { [phase]: selected, [other]: otherSelected })
|
|
needs.preflight.result = result
|
|
cases.push(aggregateEnvironment(needs))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
expect(await verifyCases(cases, gate.run)).toEqual(cases.map(() => 1))
|
|
})
|
|
}
|
|
)
|