diff --git a/__tests__/buildx/history.test.itg.ts b/__tests__/buildx/history.test.itg.ts index 5b8af75f..71ef2e1d 100644 --- a/__tests__/buildx/history.test.itg.ts +++ b/__tests__/buildx/history.test.itg.ts @@ -187,40 +187,4 @@ maybe('export', () => { expect(fs.existsSync(exportRes?.dockerbuildFilename)).toBe(true); expect(exportRes?.summaries).toBeDefined(); }); - - it('export using container', async () => { - const buildx = new Buildx(); - const build = new Build({buildx: buildx}); - - fs.mkdirSync(tmpDir, {recursive: true}); - await expect( - (async () => { - // prettier-ignore - const buildCmd = await buildx.getCommand([ - '--builder', process.env.CTN_BUILDER_NAME ?? 'default', - 'build', '-f', path.join(fixturesDir, 'hello.Dockerfile'), - '--metadata-file', build.getMetadataFilePath(), - fixturesDir - ]); - await Exec.exec(buildCmd.command, buildCmd.args); - })() - ).resolves.not.toThrow(); - - const metadata = build.resolveMetadata(); - expect(metadata).toBeDefined(); - const buildRef = build.resolveRef(metadata); - expect(buildRef).toBeDefined(); - - const history = new History({buildx: buildx}); - const exportRes = await history.export({ - refs: [buildRef ?? ''], - useContainer: true - }); - - expect(exportRes).toBeDefined(); - expect(exportRes?.dockerbuildFilename).toBeDefined(); - expect(exportRes?.dockerbuildSize).toBeDefined(); - expect(fs.existsSync(exportRes?.dockerbuildFilename)).toBe(true); - expect(exportRes?.summaries).toBeDefined(); - }); }); diff --git a/src/buildx/history.ts b/src/buildx/history.ts index 02abde6d..636938da 100644 --- a/src/buildx/history.ts +++ b/src/buildx/history.ts @@ -14,16 +14,12 @@ * limitations under the License. */ -import {ChildProcessByStdio, spawn} from 'child_process'; import fs from 'fs'; -import os from 'os'; import path from 'path'; -import {Readable, Writable} from 'stream'; import * as core from '@actions/core'; import {Buildx} from './buildx'; import {Context} from '../context'; -import {Docker} from '../docker/docker'; import {Exec} from '../exec'; import {GitHub} from '../github'; import {Util} from '../util'; @@ -101,10 +97,6 @@ export class History { core.info(`exporting build record to ${outDir}`); fs.mkdirSync(outDir, {recursive: true}); - if (opts.useContainer || (await this.buildx.versionSatisfies('<0.23.0'))) { - return await this.exportLegacy(builderName, nodeName, refs, outDir, opts.image); - } - if (await this.buildx.versionSatisfies('<0.24.0')) { // wait 3 seconds to ensure build records are finalized: https://github.com/moby/buildkit/pull/5109 // not necessary since buildx 0.24.0: https://github.com/docker/buildx/pull/3152 @@ -162,143 +154,6 @@ export class History { }; } - private async exportLegacy(builderName: string, nodeName: string, refs: Array, outDir: string, image?: string): Promise { - if (os.platform() === 'win32') { - throw new Error('Exporting a build record is currently not supported on Windows'); - } - if (!(await Docker.isAvailable())) { - throw new Error('Docker is required to export a build record'); - } - if (!(await Docker.isDaemonRunning())) { - throw new Error('Docker daemon needs to be running to export a build record'); - } - if (!(await this.buildx.versionSatisfies('>=0.13.0'))) { - throw new Error('Buildx >= 0.13.0 is required to export a build record'); - } - - // wait 3 seconds to ensure build records are finalized: https://github.com/moby/buildkit/pull/5109 - await Util.sleep(3); - - const buildxInFifoPath = Context.tmpName({ - template: 'buildx-in-XXXXXX.fifo', - tmpdir: Context.tmpDir() - }); - await Exec.exec('mkfifo', [buildxInFifoPath]); - - const buildxOutFifoPath = Context.tmpName({ - template: 'buildx-out-XXXXXX.fifo', - tmpdir: Context.tmpDir() - }); - await Exec.exec('mkfifo', [buildxOutFifoPath]); - - const buildxDialStdioCmd = await this.buildx.getCommand(['--builder', builderName, 'dial-stdio']); - core.info(`[command]${buildxDialStdioCmd.command} ${buildxDialStdioCmd.args.join(' ')}`); - const buildxDialStdioProc = spawn(buildxDialStdioCmd.command, buildxDialStdioCmd.args, { - stdio: ['pipe', 'pipe', 'inherit'], - detached: true - }); - let buildxDialStdioKilled = false; - fs.createReadStream(buildxInFifoPath).pipe(buildxDialStdioProc.stdin); - buildxDialStdioProc.stdout.pipe(fs.createWriteStream(buildxOutFifoPath)); - buildxDialStdioProc.on('exit', (code, signal) => { - buildxDialStdioKilled = true; - if (signal) { - core.info(`Process "buildx dial-stdio" was killed with signal ${signal}`); - } else { - core.info(`Process "buildx dial-stdio" exited with code ${code}`); - } - }); - - const tmpDockerbuildFilename = path.join(outDir, 'rec.dockerbuild'); - const summaryFilename = path.join(outDir, 'summary.json'); - - let dockerRunProc: ChildProcessByStdio | undefined; - let dockerRunProcKilled = false; - await new Promise((resolve, reject) => { - const ebargs: Array = ['--ref-state-dir=/buildx-refs', `--node=${builderName}/${nodeName}`]; - for (const ref of refs) { - ebargs.push(`--ref=${ref}`); - } - if (typeof process.getuid === 'function') { - ebargs.push(`--uid=${process.getuid()}`); - } - if (typeof process.getgid === 'function') { - ebargs.push(`--gid=${process.getgid()}`); - } - // prettier-ignore - const dockerRunArgs = [ - 'run', '--rm', '-i', - '-v', `${Buildx.refsDir}:/buildx-refs`, - '-v', `${outDir}:/out`, - image || process.env['DOCKER_BUILD_EXPORT_BUILD_IMAGE'] || 'docker.io/dockereng/export-build:latest', - ...ebargs - ] - core.info(`[command]docker ${dockerRunArgs.join(' ')}`); - dockerRunProc = spawn('docker', dockerRunArgs, { - stdio: ['pipe', 'pipe', 'inherit'], - env: { - ...process.env, - DOCKER_CONTENT_TRUST: 'false' - } - }); - fs.createReadStream(buildxOutFifoPath).pipe(dockerRunProc.stdin); - dockerRunProc.stdout.pipe(fs.createWriteStream(buildxInFifoPath)); - dockerRunProc.on('close', code => { - if (code === 0) { - if (!fs.existsSync(tmpDockerbuildFilename)) { - reject(new Error(`Failed to export build record: ${tmpDockerbuildFilename} not found`)); - } else { - resolve(); - } - } else { - reject(new Error(`Process "docker run" closed with code ${code}`)); - } - }); - dockerRunProc.on('error', err => { - core.error(`Error executing "docker run": ${err}`); - reject(err); - }); - dockerRunProc.on('exit', (code, signal) => { - dockerRunProcKilled = true; - if (signal) { - core.info(`Process "docker run" was killed with signal ${signal}`); - } else { - core.info(`Process "docker run" exited with code ${code}`); - } - }); - }) - .catch(err => { - throw err; - }) - .finally(() => { - if (buildxDialStdioProc && !buildxDialStdioKilled) { - core.debug('Force terminating "buildx dial-stdio" process'); - buildxDialStdioProc.kill('SIGKILL'); - } - if (dockerRunProc && !dockerRunProcKilled) { - core.debug('Force terminating "docker run" process'); - dockerRunProc.kill('SIGKILL'); - } - }); - - const dockerbuildPath = path.join(outDir, `${History.exportFilename(refs)}.dockerbuild`); - fs.renameSync(tmpDockerbuildFilename, dockerbuildPath); - const dockerbuildStats = fs.statSync(dockerbuildPath); - - core.info(`Parsing ${summaryFilename}`); - fs.statSync(summaryFilename); - const summaries = JSON.parse(fs.readFileSync(summaryFilename, {encoding: 'utf-8'})); - - return { - dockerbuildFilename: dockerbuildPath, - dockerbuildSize: dockerbuildStats.size, - builderName: builderName, - nodeName: nodeName, - refs: refs, - summaries: summaries - }; - } - private static exportFilename(refs: Array): string { let name = `${GitHub.context.repo.owner}~${GitHub.context.repo.repo}~${refs[0].substring(0, 6).toUpperCase()}`; if (refs.length > 1) {