Files
orca/config/scripts/linux-package-fixture-cache.test.mjs
T

121 lines
4.6 KiB
JavaScript

import { chmodSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { delimiter, join } from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'
import { parse } from 'yaml'
import { runProcessSync } from '../../src/shared/child-process/run-process'
const action = parse(
readFileSync('.github/actions/prepare-linux-package-fixture/action.yml', 'utf8')
)
const load = action.runs.steps.find((step) => step.id === 'image')
const workflow = (name) => parse(readFileSync(`.github/workflows/${name}.yml`, 'utf8'))
let directory
afterEach(() => {
if (directory) {
rmSync(directory, { recursive: true, force: true })
}
})
function exercise({ hit = false, save = false, loadFails = false, inspectFails = false } = {}) {
directory = mkdtempSync(join(tmpdir(), 'orca-package-cache-'))
const bin = join(directory, 'bin')
mkdirSync(bin)
const commandLog = join(directory, 'commands')
const output = join(directory, 'output')
writeFileSync(commandLog, '')
writeFileSync(output, '')
const docker = join(bin, 'docker')
writeFileSync(
docker,
'#!/bin/bash\n' +
'echo "$*" >> "$COMMAND_LOG"\n' +
'if [[ "$1" == load && "$LOAD_FAILS" == true ]]; then exit 1; fi\n' +
'if [[ "$1 $2" == "image inspect" ]]; then\n' +
' if [[ "$INSPECT_FAILS" == true ]]; then exit 1; fi\n' +
' echo sha256:fixture-image\n' +
'fi\n'
)
chmodSync(docker, 0o755)
const result = runProcessSync({
program: 'bash',
args: ['-c', load.run],
env: {
...process.env,
ORCA_BACKGROUND_LAUNCH: '1',
PATH: `${bin}${delimiter}${process.env.PATH ?? ''}`,
RUNNER_TEMP: directory,
GITHUB_OUTPUT: output,
COMMAND_LOG: commandLog,
FIXTURE: 'cli-launch-contract',
CACHE_HIT: String(hit),
SAVE_CACHE: String(save),
LOAD_FAILS: String(loadFails),
INSPECT_FAILS: String(inspectFails)
},
timeoutMs: 10_000
})
expect(result.code, result.stderr).toBe(0)
return { commands: readFileSync(commandLog, 'utf8'), output: readFileSync(output, 'utf8') }
}
describe.runIf(process.platform !== 'win32')('fixture cache fallbacks', () => {
it('leaves a PR cache miss to the existing runner without building or exporting', () => {
expect(exercise()).toEqual({ commands: '', output: '' })
})
it.each([{ loadFails: true }, { inspectFails: true }])(
'discards an unusable restored cache: %j',
(failure) => {
const result = exercise({ hit: true, ...failure })
expect(result.output).toBe('')
expect(result.commands).toContain('load --input')
expect(result.commands).not.toMatch(/(?:build|save) /)
}
)
it('returns the local image tag after a successful load', () => {
const result = exercise({ hit: true })
expect(result.output).toBe('image=orca-package-fixture-cli-launch-contract:cache\n')
expect(result.commands).not.toMatch(/(?:build|save) /)
})
it('builds and exports inline cache only when the warmer has no usable image', () => {
const result = exercise({ save: true })
expect(result.commands).toContain(
'build --platform linux/amd64 --build-arg BUILDKIT_INLINE_CACHE=1'
)
expect(result.commands).toContain(
'--file config/docker/cli-launch-contract/Dockerfile config/docker/cli-launch-contract'
)
expect(result.commands).toContain('save --output')
expect(result.output).toBe('image=orca-package-fixture-cli-launch-contract:cache\nbuilt=true\n')
})
})
it('uses exact context/platform keys and the same restore-only action in package checks', () => {
const cache = action.runs.steps.find((step) => step.id === 'cache')
expect(cache.with.key).toContain('linux-amd64')
expect(cache.with.key).toContain("format('config/docker/{0}/**', inputs.fixture)")
expect(cache.with.key).toContain('.github/actions/prepare-linux-package-fixture/action.yml')
expect(cache.with['restore-keys']).toBeUndefined()
expect(action.inputs['save-cache'].default).toBe('false')
const prepared = workflow('pr').jobs.package.steps.filter((step) =>
step.uses?.endsWith('/prepare-linux-package-fixture')
)
expect(prepared.map((step) => step.with)).toEqual([
{ fixture: 'headless-serve-shutdown' },
{ fixture: 'cli-launch-contract' }
])
const warm = workflow('ci-cache-warmup').jobs['warm-linux-package-fixtures']
expect(warm.steps.slice(1).map((step) => step.with.fixture)).toEqual(
prepared.map((step) => step.with.fixture)
)
expect(
warm.steps
.slice(1)
.every((step) => step.with['save-cache'] === "${{ github.event_name != 'pull_request' }}")
).toBe(true)
})