From dd5dfb3e486f95b92edd0854df2a2896d3ddefd2 Mon Sep 17 00:00:00 2001 From: Nikola Jokic Date: Wed, 8 Jun 2022 13:20:54 +0200 Subject: [PATCH 1/4] refactored tests to be easier to follow --- .../docker/src/dockerCommands/container.ts | 9 +- packages/docker/tests/cleanup-job-test.ts | 41 ++----- packages/docker/tests/e2e-test.ts | 114 ++++++++---------- packages/docker/tests/prepare-job-test.ts | 72 +++++------ packages/docker/tests/run-script-step.ts | 47 ++++++++ packages/docker/tests/test-setup.ts | 40 +++--- 6 files changed, 166 insertions(+), 157 deletions(-) create mode 100644 packages/docker/tests/run-script-step.ts diff --git a/packages/docker/src/dockerCommands/container.ts b/packages/docker/src/dockerCommands/container.ts index e47fc84..74050d3 100644 --- a/packages/docker/src/dockerCommands/container.ts +++ b/packages/docker/src/dockerCommands/container.ts @@ -2,10 +2,8 @@ import * as core from '@actions/core' import * as fs from 'fs' import { ContainerInfo, - JobContainerInfo, RunContainerStepArgs, - ServiceContainerInfo, - StepContainerInfo + ServiceContainerInfo } from 'hooklib/lib' import path from 'path' import { env } from 'process' @@ -55,7 +53,7 @@ export async function createContainer( const mountVolumes = [ ...(args.userMountVolumes || []), - ...((args as JobContainerInfo | StepContainerInfo).systemMountVolumes || []) + ...(args.systemMountVolumes || []) ] for (const mountVolume of mountVolumes) { dockerArgs.push( @@ -328,8 +326,7 @@ export async function containerExecStep( } } - // Todo figure out prepend path and update it here - // (we need to pass path in as -e Path={fullpath}) where {fullpath is the prepend path added to the current containers path} + dockerArgs.push('-e', `"PATH=${args.prependPath.join(':')}:$PATH"`) dockerArgs.push(containerId) dockerArgs.push(args.entryPoint) diff --git a/packages/docker/tests/cleanup-job-test.ts b/packages/docker/tests/cleanup-job-test.ts index a9cf3fe..e02727d 100644 --- a/packages/docker/tests/cleanup-job-test.ts +++ b/packages/docker/tests/cleanup-job-test.ts @@ -1,51 +1,30 @@ import * as fs from 'fs' -import * as path from 'path' -import { v4 as uuidv4 } from 'uuid' import { cleanupJob, prepareJob } from '../src/hooks' import TestSetup from './test-setup' -const prepareJobInputPath = path.resolve( - `${__dirname}/../../../examples/prepare-job.json` -) - -const tmpOutputDir = `${__dirname}/${uuidv4()}` - -let prepareJobOutputPath: string -let prepareJobData: any - let testSetup: TestSetup jest.useRealTimers() describe('cleanup job', () => { - beforeAll(() => { - fs.mkdirSync(tmpOutputDir, { recursive: true }) - }) - - afterAll(() => { - fs.rmSync(tmpOutputDir, { recursive: true }) - }) - beforeEach(async () => { - const prepareJobRawData = fs.readFileSync(prepareJobInputPath, 'utf8') - prepareJobData = JSON.parse(prepareJobRawData.toString()) - - prepareJobOutputPath = `${tmpOutputDir}/prepare-job-output-${uuidv4()}.json` - fs.writeFileSync(prepareJobOutputPath, '') - testSetup = new TestSetup() testSetup.initialize() - prepareJobData.args.container.userMountVolumes = testSetup.userMountVolumes - prepareJobData.args.container.systemMountVolumes = - testSetup.systemMountVolumes - prepareJobData.args.container.workingDirectory = testSetup.workingDirectory + const prepareJobDefinition = JSON.parse( + fs.readFileSync( + `${__dirname}/../../../examples/prepare-job.json`, + 'utf-8' + ) + ) - await prepareJob(prepareJobData.args, prepareJobOutputPath) + const prepareJobOutput = testSetup.createOutputFile( + 'prepare-job-output.json' + ) + await prepareJob(prepareJobDefinition.args, prepareJobOutput) }) afterEach(() => { - fs.rmSync(prepareJobOutputPath, { force: true }) testSetup.teardown() }) diff --git a/packages/docker/tests/e2e-test.ts b/packages/docker/tests/e2e-test.ts index ea48f9f..b2e4ffc 100644 --- a/packages/docker/tests/e2e-test.ts +++ b/packages/docker/tests/e2e-test.ts @@ -1,6 +1,5 @@ import * as fs from 'fs' import * as path from 'path' -import { v4 as uuidv4 } from 'uuid' import { cleanupJob, prepareJob, @@ -9,94 +8,83 @@ import { } from '../src/hooks' import TestSetup from './test-setup' -const prepareJobJson = fs.readFileSync( - path.resolve(__dirname + '/../../../examples/prepare-job.json'), - 'utf8' -) +const definitions = { + prepareJob: JSON.parse( + fs.readFileSync( + path.resolve(__dirname + '/../../../examples/prepare-job.json'), + 'utf8' + ) + ), -const containerStepJson = fs.readFileSync( - path.resolve(__dirname + '/../../../examples/run-container-step.json'), - 'utf8' -) + runContainerStep: JSON.parse( + fs.readFileSync( + path.resolve(__dirname + '/../../../examples/run-container-step.json'), + 'utf8' + ) + ), -const tmpOutputDir = `${__dirname}/_temp/${uuidv4()}` - -let prepareJobData: any -let scriptStepJson: any -let scriptStepData: any -let containerStepData: any - -let prepareJobOutputFilePath: string + runScriptStep: JSON.parse( + fs.readFileSync( + path.resolve(__dirname + '/../../../examples/run-script-step.json'), + 'utf-8' + ) + ) +} let testSetup: TestSetup describe('e2e', () => { - beforeAll(() => { - fs.mkdirSync(tmpOutputDir, { recursive: true }) - }) - - afterAll(() => { - fs.rmSync(tmpOutputDir, { recursive: true }) - }) - beforeEach(() => { - // init dirs testSetup = new TestSetup() testSetup.initialize() - - prepareJobData = JSON.parse(prepareJobJson) - prepareJobData.args.container.userMountVolumes = testSetup.userMountVolumes - prepareJobData.args.container.systemMountVolumes = + definitions.prepareJob.args.container.systemMountVolumes = testSetup.systemMountVolumes - prepareJobData.args.container.workingDirectory = testSetup.workingDirectory - - scriptStepJson = fs.readFileSync( - path.resolve(__dirname + '/../../../examples/run-script-step.json'), - 'utf8' - ) - scriptStepData = JSON.parse(scriptStepJson) - scriptStepData.args.workingDirectory = testSetup.workingDirectory - - containerStepData = JSON.parse(containerStepJson) - containerStepData.args.workingDirectory = testSetup.workingDirectory - containerStepData.args.userMountVolumes = testSetup.userMountVolumes - containerStepData.args.systemMountVolumes = testSetup.systemMountVolumes - - prepareJobOutputFilePath = `${tmpOutputDir}/prepare-job-output-${uuidv4()}.json` - fs.writeFileSync(prepareJobOutputFilePath, '') }) afterEach(() => { - fs.rmSync(prepareJobOutputFilePath, { force: true }) testSetup.teardown() }) it('should prepare job, then run script step, then run container step then cleanup', async () => { + const prepareJobOutput = testSetup.createOutputFile( + 'prepare-job-output.json' + ) + await expect( - prepareJob(prepareJobData.args, prepareJobOutputFilePath) + prepareJob(definitions.prepareJob.args, prepareJobOutput) ).resolves.not.toThrow() - let rawState = fs.readFileSync(prepareJobOutputFilePath, 'utf-8') + + let rawState = fs.readFileSync(prepareJobOutput, 'utf-8') let resp = JSON.parse(rawState) + await expect( - runScriptStep(scriptStepData.args, resp.state) + runScriptStep(definitions.runScriptStep.args, resp.state) ).resolves.not.toThrow() + await expect( - runContainerStep(containerStepData.args, resp.state) + runContainerStep(definitions.runContainerStep.args, resp.state) ).resolves.not.toThrow() + await expect(cleanupJob()).resolves.not.toThrow() }) it('should prepare job, then run script step, then run container step with Dockerfile then cleanup', async () => { + const prepareJobOutput = testSetup.createOutputFile( + 'prepare-job-output.json' + ) + await expect( - prepareJob(prepareJobData.args, prepareJobOutputFilePath) - ).resolves.not.toThrow() - let rawState = fs.readFileSync(prepareJobOutputFilePath, 'utf-8') - let resp = JSON.parse(rawState) - await expect( - runScriptStep(scriptStepData.args, resp.state) + prepareJob(definitions.prepareJob.args, prepareJobOutput) ).resolves.not.toThrow() - const dockerfilePath = `${tmpOutputDir}/Dockerfile` + let rawState = fs.readFileSync(prepareJobOutput, 'utf-8') + let resp = JSON.parse(rawState) + + await expect( + runScriptStep(definitions.runScriptStep.args, resp.state) + ).resolves.not.toThrow() + + const dockerfilePath = `${testSetup.workingDirectory}/Dockerfile` fs.writeFileSync( dockerfilePath, `FROM ubuntu:latest @@ -104,13 +92,17 @@ ENV TEST=test ENTRYPOINT [ "tail", "-f", "/dev/null" ] ` ) - const containerStepDataCopy = JSON.parse(JSON.stringify(containerStepData)) - process.env.GITHUB_WORKSPACE = tmpOutputDir + + const containerStepDataCopy = JSON.parse( + JSON.stringify(definitions.runContainerStep) + ) + containerStepDataCopy.args.dockerfile = 'Dockerfile' - containerStepDataCopy.args.context = '.' + await expect( runContainerStep(containerStepDataCopy.args, resp.state) ).resolves.not.toThrow() + await expect(cleanupJob()).resolves.not.toThrow() }) }) diff --git a/packages/docker/tests/prepare-job-test.ts b/packages/docker/tests/prepare-job-test.ts index e94aa08..1494628 100644 --- a/packages/docker/tests/prepare-job-test.ts +++ b/packages/docker/tests/prepare-job-test.ts @@ -1,40 +1,24 @@ import * as fs from 'fs' -import { v4 as uuidv4 } from 'uuid' import { prepareJob } from '../src/hooks' import TestSetup from './test-setup' jest.useRealTimers() -let prepareJobOutputPath: string -let prepareJobData: any -const tmpOutputDir = `${__dirname}/_temp/${uuidv4()}` -const prepareJobInputPath = `${__dirname}/../../../examples/prepare-job.json` +const prepareJobDefinition = JSON.parse( + fs.readFileSync(`${__dirname}/../../../examples/prepare-job.json`, 'utf-8') +) let testSetup: TestSetup describe('prepare job', () => { - beforeAll(() => { - fs.mkdirSync(tmpOutputDir, { recursive: true }) - }) - - afterAll(() => { - fs.rmSync(tmpOutputDir, { recursive: true }) - }) - - beforeEach(async () => { + beforeEach(() => { testSetup = new TestSetup() testSetup.initialize() - let prepareJobRawData = fs.readFileSync(prepareJobInputPath, 'utf8') - prepareJobData = JSON.parse(prepareJobRawData.toString()) - - prepareJobData.args.container.userMountVolumes = testSetup.userMountVolumes - prepareJobData.args.container.systemMountVolumes = + prepareJobDefinition.args.container.systemMountVolumes = testSetup.systemMountVolumes - prepareJobData.args.container.workingDirectory = testSetup.workingDirectory - - prepareJobOutputPath = `${tmpOutputDir}/prepare-job-output-${uuidv4()}.json` - fs.writeFileSync(prepareJobOutputPath, '') + prepareJobDefinition.args.container.workingDirectory = + testSetup.workingDirectory }) afterEach(() => { @@ -42,38 +26,42 @@ describe('prepare job', () => { }) it('should not throw', async () => { + const prepareJobOutput = testSetup.createOutputFile( + 'prepare-job-output.json' + ) await expect( - prepareJob(prepareJobData.args, prepareJobOutputPath) + prepareJob(prepareJobDefinition.args, prepareJobOutput) ).resolves.not.toThrow() - expect(() => fs.readFileSync(prepareJobOutputPath, 'utf-8')).not.toThrow() + expect(() => fs.readFileSync(prepareJobOutput, 'utf-8')).not.toThrow() }) it('should have JSON output written to a file', async () => { - await prepareJob(prepareJobData.args, prepareJobOutputPath) - const prepareJobOutputContent = fs.readFileSync( - prepareJobOutputPath, - 'utf-8' + const prepareJobOutput = testSetup.createOutputFile( + 'prepare-job-output.json' ) + await prepareJob(prepareJobDefinition.args, prepareJobOutput) + const prepareJobOutputContent = fs.readFileSync(prepareJobOutput, 'utf-8') expect(() => JSON.parse(prepareJobOutputContent)).not.toThrow() }) it('should have context written to a file', async () => { - await prepareJob(prepareJobData.args, prepareJobOutputPath) - const prepareJobOutputContent = fs.readFileSync( - prepareJobOutputPath, - 'utf-8' + const prepareJobOutput = testSetup.createOutputFile( + 'prepare-job-output.json' + ) + await prepareJob(prepareJobDefinition.args, prepareJobOutput) + const parsedPrepareJobOutput = JSON.parse( + fs.readFileSync(prepareJobOutput, 'utf-8') ) - const parsedPrepareJobOutput = JSON.parse(prepareJobOutputContent) expect(parsedPrepareJobOutput.context).toBeDefined() }) it('should have container ids written to file', async () => { - await prepareJob(prepareJobData.args, prepareJobOutputPath) - const prepareJobOutputContent = fs.readFileSync( - prepareJobOutputPath, - 'utf-8' + const prepareJobOutput = testSetup.createOutputFile( + 'prepare-job-output.json' ) + await prepareJob(prepareJobDefinition.args, prepareJobOutput) + const prepareJobOutputContent = fs.readFileSync(prepareJobOutput, 'utf-8') const parsedPrepareJobOutput = JSON.parse(prepareJobOutputContent) expect(parsedPrepareJobOutput.context.container.id).toBeDefined() @@ -82,11 +70,11 @@ describe('prepare job', () => { }) it('should have ports for context written in form [containerPort]:[hostPort]', async () => { - await prepareJob(prepareJobData.args, prepareJobOutputPath) - const prepareJobOutputContent = fs.readFileSync( - prepareJobOutputPath, - 'utf-8' + const prepareJobOutput = testSetup.createOutputFile( + 'prepare-job-output.json' ) + await prepareJob(prepareJobDefinition.args, prepareJobOutput) + const prepareJobOutputContent = fs.readFileSync(prepareJobOutput, 'utf-8') const parsedPrepareJobOutput = JSON.parse(prepareJobOutputContent) const mainContainerPorts = parsedPrepareJobOutput.context.container.ports diff --git a/packages/docker/tests/run-script-step.ts b/packages/docker/tests/run-script-step.ts new file mode 100644 index 0000000..15fbc41 --- /dev/null +++ b/packages/docker/tests/run-script-step.ts @@ -0,0 +1,47 @@ +import * as fs from 'fs' +import { PrepareJobResponse } from 'hooklib/lib' +import * as path from 'path' +import { prepareJob, runScriptStep } from '../src/hooks' +import TestSetup from './test-setup' + +jest.useRealTimers() + +let testSetup: TestSetup + +const definitions = { + prepareJob: JSON.parse( + fs.readFileSync( + path.resolve(__dirname + '/../../../examples/prepare-job.json'), + 'utf8' + ) + ), + + runScriptStep: JSON.parse( + fs.readFileSync( + path.resolve(__dirname + '/../../../examples/run-script-step.json'), + 'utf-8' + ) + ) +} + +let prepareJobResponse: PrepareJobResponse + +describe('run-script-step', () => { + beforeEach(async () => { + testSetup = new TestSetup() + testSetup.initialize() + + const prepareJobOutput = testSetup.createOutputFile( + 'prepare-job-output.json' + ) + await prepareJob(definitions.prepareJob.args, prepareJobOutput) + + prepareJobResponse = JSON.parse(fs.readFileSync(prepareJobOutput, 'utf-8')) + }) + + it('Should run script step without exceptions', async () => { + await expect( + runScriptStep(definitions.runScriptStep.args, prepareJobResponse.state) + ).resolves.not.toThrow() + }) +}) diff --git a/packages/docker/tests/test-setup.ts b/packages/docker/tests/test-setup.ts index 58434b9..df19c77 100644 --- a/packages/docker/tests/test-setup.ts +++ b/packages/docker/tests/test-setup.ts @@ -1,11 +1,14 @@ import * as fs from 'fs' -import { v4 as uuidv4 } from 'uuid' -import { env } from 'process' import { Mount } from 'hooklib' +import * as path from 'path' +import { env } from 'process' +import { v4 as uuidv4 } from 'uuid' export default class TestSetup { private testdir: string private runnerMockDir: string + readonly runnerOutputDir: string + private runnerMockSubdirs = { work: '_work', externals: 'externals', @@ -16,15 +19,16 @@ export default class TestSetup { githubWorkflow: '_work/_temp/_github_workflow' } - private readonly projectName = 'example' + private readonly projectName = 'repo' constructor() { this.testdir = `${__dirname}/_temp/${uuidv4()}` this.runnerMockDir = `${this.testdir}/runner/_layout` + this.runnerOutputDir = `${this.testdir}/outputs` } private get allTestDirectories() { - const resp = [this.testdir, this.runnerMockDir] + const resp = [this.testdir, this.runnerMockDir, this.runnerOutputDir] for (const [key, value] of Object.entries(this.runnerMockSubdirs)) { resp.push(`${this.runnerMockDir}/${value}`) @@ -38,29 +42,21 @@ export default class TestSetup { } public initialize(): void { - for (const dir of this.allTestDirectories) { - fs.mkdirSync(dir, { recursive: true }) - } + env['GITHUB_WORKSPACE'] = this.workingDirectory env['RUNNER_NAME'] = 'test' env[ 'RUNNER_TEMP' ] = `${this.runnerMockDir}/${this.runnerMockSubdirs.workTemp}` + + for (const dir of this.allTestDirectories) { + fs.mkdirSync(dir, { recursive: true }) + } } public teardown(): void { fs.rmdirSync(this.testdir, { recursive: true }) } - public get userMountVolumes(): Mount[] { - return [ - { - sourceVolumePath: 'my_docker_volume', - targetVolumePath: '/volume_mount', - readOnly: false - } - ] - } - public get systemMountVolumes(): Mount[] { return [ { @@ -106,7 +102,17 @@ export default class TestSetup { ] } + public createOutputFile(name: string): string { + let filePath = path.join(this.runnerOutputDir, name || `${uuidv4()}.json`) + fs.writeFileSync(filePath, '') + return filePath + } + public get workingDirectory(): string { + return `${this.runnerMockDir}/_work/${this.projectName}/${this.projectName}` + } + + public get containerWorkingDirectory(): string { return `/__w/${this.projectName}/${this.projectName}` } } From 88b7b19db790f4e9cd8d05cedf698f22951b58ee Mon Sep 17 00:00:00 2001 From: Nikola Jokic Date: Wed, 8 Jun 2022 13:25:45 +0200 Subject: [PATCH 2/4] fixed interface for hooklib and example repos --- examples/prepare-job.json | 2 +- examples/run-container-step.json | 2 +- examples/run-script-step.json | 2 +- packages/hooklib/src/interfaces.ts | 1 + packages/k8s/tests/run-script-step-test.ts | 8 ++++---- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/prepare-job.json b/examples/prepare-job.json index abc9474..cf6f838 100644 --- a/examples/prepare-job.json +++ b/examples/prepare-job.json @@ -5,7 +5,7 @@ "args": { "container": { "image": "node:14.16", - "workingDirectory": "/__w/thboop-test2/thboop-test2", + "workingDirectory": "/__w/repo/repo", "createOptions": "--cpus 1", "environmentVariables": { "NODE_ENV": "development" diff --git a/examples/run-container-step.json b/examples/run-container-step.json index cf3cf97..7a7cfac 100644 --- a/examples/run-container-step.json +++ b/examples/run-container-step.json @@ -16,7 +16,7 @@ "echo \"hello world2\"" ], "entryPoint": "bash", - "workingDirectory": "/__w/thboop-test2/thboop-test2", + "workingDirectory": "/__w/repo/repo", "createOptions": "--cpus 1", "environmentVariables": { "NODE_ENV": "development" diff --git a/examples/run-script-step.json b/examples/run-script-step.json index 2b7aebf..1b57dc1 100644 --- a/examples/run-script-step.json +++ b/examples/run-script-step.json @@ -21,6 +21,6 @@ "/foo/bar", "bar/foo" ], - "workingDirectory": "/__w/thboop-test2/thboop-test2" + "workingDirectory": "/__w/repo/repo" } } \ No newline at end of file diff --git a/packages/hooklib/src/interfaces.ts b/packages/hooklib/src/interfaces.ts index f29dcbd..53e20c1 100644 --- a/packages/hooklib/src/interfaces.ts +++ b/packages/hooklib/src/interfaces.ts @@ -34,6 +34,7 @@ export interface ContainerInfo { createOptions?: string environmentVariables?: { [key: string]: string } userMountVolumes?: Mount[] + systemMountVolumes?: Mount[] registry?: Registry portMappings?: string[] } diff --git a/packages/k8s/tests/run-script-step-test.ts b/packages/k8s/tests/run-script-step-test.ts index 64c05b7..dfa6edb 100644 --- a/packages/k8s/tests/run-script-step-test.ts +++ b/packages/k8s/tests/run-script-step-test.ts @@ -1,7 +1,7 @@ -import { prepareJob, cleanupJob, runScriptStep } from '../src/hooks' -import { TestHelper } from './test-setup' -import * as path from 'path' import * as fs from 'fs' +import * as path from 'path' +import { cleanupJob, prepareJob, runScriptStep } from '../src/hooks' +import { TestHelper } from './test-setup' jest.useRealTimers() @@ -45,7 +45,7 @@ describe('Run script step', () => { NODE_ENV: 'development' }, prependPath: ['/foo/bar', 'bar/foo'], - workingDirectory: '/__w/thboop-test2/thboop-test2' + workingDirectory: '/__w/repo/repo' } const state = { jobPod: prepareJobOutputData.state.jobPod From bf3707d7e046a7bcaf40a4f6df111a7978f0d145 Mon Sep 17 00:00:00 2001 From: Nikola Jokic Date: Wed, 8 Jun 2022 13:28:46 +0200 Subject: [PATCH 3/4] added guard around prependPath --- packages/docker/src/dockerCommands/container.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/docker/src/dockerCommands/container.ts b/packages/docker/src/dockerCommands/container.ts index 74050d3..0345ee2 100644 --- a/packages/docker/src/dockerCommands/container.ts +++ b/packages/docker/src/dockerCommands/container.ts @@ -326,7 +326,9 @@ export async function containerExecStep( } } - dockerArgs.push('-e', `"PATH=${args.prependPath.join(':')}:$PATH"`) + if (args.prependPath?.length) { + dockerArgs.push('-e', `"PATH=${args.prependPath.join(':')}:$PATH"`) + } dockerArgs.push(containerId) dockerArgs.push(args.entryPoint) From 8351f842bd1f3bed8901bf5bcb7690730e430f0c Mon Sep 17 00:00:00 2001 From: Nikola Jokic Date: Wed, 8 Jun 2022 14:29:10 +0200 Subject: [PATCH 4/4] added isAlpine test to prepare job --- packages/docker/tests/prepare-job-test.ts | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/docker/tests/prepare-job-test.ts b/packages/docker/tests/prepare-job-test.ts index 1494628..21fae04 100644 --- a/packages/docker/tests/prepare-job-test.ts +++ b/packages/docker/tests/prepare-job-test.ts @@ -56,6 +56,32 @@ describe('prepare job', () => { expect(parsedPrepareJobOutput.context).toBeDefined() }) + it('should have isAlpine field set correctly', async () => { + let prepareJobOutput = testSetup.createOutputFile( + 'prepare-job-output-alpine.json' + ) + const prepareJobArgsClone = JSON.parse( + JSON.stringify(prepareJobDefinition.args) + ) + prepareJobArgsClone.container.image = 'alpine:latest' + await prepareJob(prepareJobArgsClone, prepareJobOutput) + + let parsedPrepareJobOutput = JSON.parse( + fs.readFileSync(prepareJobOutput, 'utf-8') + ) + expect(parsedPrepareJobOutput.isAlpine).toBe(true) + + prepareJobOutput = testSetup.createOutputFile( + 'prepare-job-output-ubuntu.json' + ) + prepareJobArgsClone.container.image = 'ubuntu:latest' + await prepareJob(prepareJobArgsClone, prepareJobOutput) + parsedPrepareJobOutput = JSON.parse( + fs.readFileSync(prepareJobOutput, 'utf-8') + ) + expect(parsedPrepareJobOutput.isAlpine).toBe(false) + }) + it('should have container ids written to file', async () => { const prepareJobOutput = testSetup.createOutputFile( 'prepare-job-output.json'