diff --git a/__tests__/docker/docker.test.ts b/__tests__/docker/docker.test.ts index c36b2f3..ea4f78f 100644 --- a/__tests__/docker/docker.test.ts +++ b/__tests__/docker/docker.test.ts @@ -22,7 +22,6 @@ import osm = require('os'); import * as rimraf from 'rimraf'; import {Docker} from '../../src/docker/docker'; -import {Exec} from '../../src/exec'; import {ConfigFile} from '../../src/types/docker/docker'; @@ -105,48 +104,132 @@ describe('isAvailable', () => { }); }); -describe('context', () => { - it('call docker context show', async () => { - const execSpy = jest.spyOn(Exec, 'getExecOutput'); - await Docker.context().catch(() => { - // noop - }); - expect(execSpy).toHaveBeenCalledWith(`docker`, ['context', 'inspect', '--format', '{{.Name}}'], { +describe('exec', () => { + it('returns docker version', async () => { + const execSpy = jest.spyOn(Docker, 'exec'); + await Docker.exec(['version'], { ignoreReturnCode: true, silent: true }); + expect(execSpy).toHaveBeenCalledTimes(1); + const callfunc = execSpy.mock.calls[0]; + expect(Object.keys(callfunc[1]?.env || {}).length).toBeGreaterThan(0); + const env = callfunc[1]?.env; + expect(env).toHaveProperty('DOCKER_CONTENT_TRUST'); + expect(env?.DOCKER_CONTENT_TRUST).toBe('false'); + if (callfunc[1]?.env) { + // already checked env + callfunc[1].env = undefined; + } + expect(callfunc).toEqual([ + ['version'], + { + ignoreReturnCode: true, + silent: true + } + ]); + }); +}); + +describe('getExecOutput', () => { + it('returns docker version', async () => { + const execSpy = jest.spyOn(Docker, 'getExecOutput'); + await Docker.getExecOutput(['version'], { + ignoreReturnCode: true, + silent: true + }); + expect(execSpy).toHaveBeenCalledTimes(1); + const callfunc = execSpy.mock.calls[0]; + expect(Object.keys(callfunc[1]?.env || {}).length).toBeGreaterThan(0); + const env = callfunc[1]?.env; + expect(env).toHaveProperty('DOCKER_CONTENT_TRUST'); + expect(env?.DOCKER_CONTENT_TRUST).toBe('false'); + if (callfunc[1]?.env) { + // already checked env + callfunc[1].env = undefined; + } + expect(callfunc).toEqual([ + ['version'], + { + ignoreReturnCode: true, + silent: true + } + ]); + }); +}); + +describe('context', () => { + it('call docker context show', async () => { + const execSpy = jest.spyOn(Docker, 'getExecOutput'); + await Docker.context().catch(() => { + // noop + }); + expect(execSpy).toHaveBeenCalledTimes(1); + const callfunc = execSpy.mock.calls[0]; + if (callfunc && callfunc[1]) { + // we don't want to check env opt + callfunc[1].env = undefined; + } + expect(callfunc).toEqual([ + ['context', 'inspect', '--format', '{{.Name}}'], + { + ignoreReturnCode: true, + silent: true + } + ]); }); }); describe('contextInspect', () => { it('call docker context inspect', async () => { - const execSpy = jest.spyOn(Exec, 'getExecOutput'); + const execSpy = jest.spyOn(Docker, 'getExecOutput'); await Docker.contextInspect('foo').catch(() => { // noop }); - expect(execSpy).toHaveBeenCalledWith(`docker`, ['context', 'inspect', '--format=json', 'foo'], { - ignoreReturnCode: true, - silent: true - }); + expect(execSpy).toHaveBeenCalledTimes(1); + const callfunc = execSpy.mock.calls[0]; + if (callfunc && callfunc[1]) { + // we don't want to check env opt + callfunc[1].env = undefined; + } + expect(callfunc).toEqual([ + ['context', 'inspect', '--format=json', 'foo'], + { + ignoreReturnCode: true, + silent: true + } + ]); }); }); describe('printVersion', () => { it('call docker version', async () => { - const execSpy = jest.spyOn(Exec, 'exec'); + const execSpy = jest.spyOn(Docker, 'exec'); await Docker.printVersion().catch(() => { // noop }); - expect(execSpy).toHaveBeenCalledWith(`docker`, ['version']); + expect(execSpy).toHaveBeenCalledTimes(1); + const callfunc = execSpy.mock.calls[0]; + if (callfunc && callfunc[1]) { + // we don't want to check env opt + callfunc[1].env = undefined; + } + expect(callfunc).toEqual([['version']]); }); }); describe('printInfo', () => { it('call docker info', async () => { - const execSpy = jest.spyOn(Exec, 'exec'); + const execSpy = jest.spyOn(Docker, 'exec'); await Docker.printInfo().catch(() => { // noop }); - expect(execSpy).toHaveBeenCalledWith(`docker`, ['info']); + expect(execSpy).toHaveBeenCalledTimes(1); + const callfunc = execSpy.mock.calls[0]; + if (callfunc && callfunc[1]) { + // we don't want to check env opt + callfunc[1].env = undefined; + } + expect(callfunc).toEqual([['info']]); }); }); diff --git a/src/buildkit/buildkit.ts b/src/buildkit/buildkit.ts index af6b0d9..aa604be 100644 --- a/src/buildkit/buildkit.ts +++ b/src/buildkit/buildkit.ts @@ -19,8 +19,8 @@ import * as semver from 'semver'; import {Buildx} from '../buildx/buildx'; import {Builder} from '../buildx/builder'; +import {Docker} from '../docker/docker'; import {Config} from './config'; -import {Exec} from '../exec'; import {BuilderInfo, NodeInfo} from '../types/buildx/builder'; @@ -51,13 +51,13 @@ export class BuildKit { private async getVersionWithinImage(nodeName: string): Promise { core.debug(`BuildKit.getVersionWithinImage nodeName: ${nodeName}`); - return Exec.getExecOutput(`docker`, ['inspect', '--format', '{{.Config.Image}}', `${Buildx.containerNamePrefix}${nodeName}`], { + return Docker.getExecOutput(['inspect', '--format', '{{.Config.Image}}', `${Buildx.containerNamePrefix}${nodeName}`], { ignoreReturnCode: true, silent: true }).then(bkitimage => { if (bkitimage.exitCode == 0 && bkitimage.stdout.length > 0) { core.debug(`BuildKit.getVersionWithinImage image: ${bkitimage.stdout.trim()}`); - return Exec.getExecOutput(`docker`, ['run', '--rm', bkitimage.stdout.trim(), '--version'], { + return Docker.getExecOutput(['run', '--rm', bkitimage.stdout.trim(), '--version'], { ignoreReturnCode: true, silent: true }).then(bkitversion => { diff --git a/src/buildx/history.ts b/src/buildx/history.ts index abaca49..c28b12e 100644 --- a/src/buildx/history.ts +++ b/src/buildx/history.ts @@ -137,7 +137,11 @@ export class History { ] core.info(`[command]docker ${dockerRunArgs.join(' ')}`); dockerRunProc = spawn('docker', dockerRunArgs, { - stdio: ['pipe', 'pipe', 'inherit'] + stdio: ['pipe', 'pipe', 'inherit'], + env: { + ...process.env, + DOCKER_CONTENT_TRUST: 'false' + } }); fs.createReadStream(buildxOutFifoPath).pipe(dockerRunProc.stdin); dockerRunProc.stdout.pipe(fs.createWriteStream(buildxInFifoPath)); diff --git a/src/docker/docker.ts b/src/docker/docker.ts index e3b55c8..2584b06 100644 --- a/src/docker/docker.ts +++ b/src/docker/docker.ts @@ -18,6 +18,7 @@ import fs from 'fs'; import os from 'os'; import path from 'path'; import * as core from '@actions/core'; +import {ExecOptions, ExecOutput} from '@actions/exec'; import * as io from '@actions/io'; import {Context} from '../context'; @@ -53,12 +54,36 @@ export class Docker { }); } + public static async exec(args?: string[], options?: ExecOptions): Promise { + return Exec.exec('docker', args, Docker.execOptions(options)); + } + + public static async getExecOutput(args?: string[], options?: ExecOptions): Promise { + return Exec.getExecOutput('docker', args, Docker.execOptions(options)); + } + + private static execOptions(options?: ExecOptions): ExecOptions { + if (!options) { + options = {}; + } + if (!options.env) { + options.env = Object.assign({}, process.env, { + DOCKER_CONTENT_TRUST: 'false' + }) as { + [key: string]: string; + }; + } else { + options.env.DOCKER_CONTENT_TRUST = 'false'; + } + return options; + } + public static async context(name?: string): Promise { const args = ['context', 'inspect', '--format', '{{.Name}}']; if (name) { args.push(name); } - return await Exec.getExecOutput(`docker`, args, { + return await Docker.getExecOutput(args, { ignoreReturnCode: true, silent: true }).then(res => { @@ -74,7 +99,7 @@ export class Docker { if (name) { args.push(name); } - return await Exec.getExecOutput(`docker`, args, { + return await Docker.getExecOutput(args, { ignoreReturnCode: true, silent: true }).then(res => { @@ -86,11 +111,11 @@ export class Docker { } public static async printVersion(): Promise { - await Exec.exec('docker', ['version']); + await Docker.exec(['version']); } public static async printInfo(): Promise { - await Exec.exec('docker', ['info']); + await Docker.exec(['info']); } public static parseRepoTag(image: string): {repository: string; tag: string} { @@ -138,7 +163,7 @@ export class Docker { cacheFoundPath = await imageCache.find(); if (cacheFoundPath) { core.info(`Image found from cache in ${cacheFoundPath}`); - await Exec.getExecOutput(`docker`, ['load', '-i', cacheFoundPath], { + await Docker.getExecOutput(['load', '-i', cacheFoundPath], { ignoreReturnCode: true }).then(res => { if (res.stderr.length > 0 && res.exitCode != 0) { @@ -149,7 +174,7 @@ export class Docker { } let pulled = true; - await Exec.getExecOutput(`docker`, ['pull', image], { + await Docker.getExecOutput(['pull', image], { ignoreReturnCode: true }).then(res => { if (res.stderr.length > 0 && res.exitCode != 0) { @@ -165,7 +190,7 @@ export class Docker { if (cache && pulled) { const imageTarPath = path.join(Context.tmpDir(), `${Util.hash(image)}.tar`); - await Exec.getExecOutput(`docker`, ['save', '-o', imageTarPath, image], { + await Docker.getExecOutput(['save', '-o', imageTarPath, image], { ignoreReturnCode: true }).then(async res => { if (res.stderr.length > 0 && res.exitCode != 0) { diff --git a/src/docker/install.ts b/src/docker/install.ts index 46af76c..2153395 100644 --- a/src/docker/install.ts +++ b/src/docker/install.ts @@ -28,6 +28,7 @@ import * as io from '@actions/io'; import * as tc from '@actions/tool-cache'; import {Context} from '../context'; +import {Docker} from './docker'; import {Exec} from '../exec'; import {Util} from '../util'; import {limaYamlData, dockerServiceLogsPs1, setupDockerWinPs1} from './assets'; @@ -219,8 +220,8 @@ export class Install { }); await core.group('Create Docker context', async () => { - await Exec.exec('docker', ['context', 'create', this.contextName, '--docker', `host=${dockerHost}`]); - await Exec.exec('docker', ['context', 'use', this.contextName]); + await Docker.exec(['context', 'create', this.contextName, '--docker', `host=${dockerHost}`]); + await Docker.exec(['context', 'use', this.contextName]); }); return dockerHost; @@ -309,8 +310,8 @@ EOF`, }); await core.group('Create Docker context', async () => { - await Exec.exec('docker', ['context', 'create', this.contextName, '--docker', `host=${dockerHost}`]); - await Exec.exec('docker', ['context', 'use', this.contextName]); + await Docker.exec(['context', 'create', this.contextName, '--docker', `host=${dockerHost}`]); + await Docker.exec(['context', 'use', this.contextName]); }); return dockerHost; @@ -352,8 +353,8 @@ EOF`, }); await core.group('Create Docker context', async () => { - await Exec.exec('docker', ['context', 'create', this.contextName, '--docker', `host=${dockerHost}`]); - await Exec.exec('docker', ['context', 'use', this.contextName]); + await Docker.exec(['context', 'create', this.contextName, '--docker', `host=${dockerHost}`]); + await Docker.exec(['context', 'use', this.contextName]); }); return dockerHost; @@ -395,7 +396,7 @@ EOF`, await Exec.exec('limactl', ['delete', '--tty=false', this.limaInstanceName, '--force']); }); await core.group('Removing Docker context', async () => { - await Exec.exec('docker', ['context', 'rm', '-f', this.contextName]); + await Docker.exec(['context', 'rm', '-f', this.contextName]); }); await core.group(`Cleaning up runDir`, async () => { await Exec.exec('sudo', ['rm', '-rf', this.runDir]); @@ -411,7 +412,7 @@ EOF`, await Util.sleep(5); }); await core.group('Removing Docker context', async () => { - await Exec.exec('docker', ['context', 'rm', '-f', this.contextName]); + await Docker.exec(['context', 'rm', '-f', this.contextName]); }); await core.group(`Cleaning up runDir`, async () => { await Exec.exec('sudo', ['rm', '-rf', this.runDir], { @@ -427,7 +428,7 @@ EOF`, await Exec.exec(logCmd.command, logCmd.args); }); await core.group('Removing Docker context', async () => { - await Exec.exec('docker', ['context', 'rm', '-f', this.contextName]); + await Docker.exec(['context', 'rm', '-f', this.contextName]); }); }