mirror docker/build-push-action@v5
This commit is contained in:
+115
-65
@@ -1,28 +1,30 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as handlebars from 'handlebars';
|
||||
|
||||
import {Build} from '@docker/actions-toolkit/lib/buildx/build';
|
||||
import {Context} from '@docker/actions-toolkit/lib/context';
|
||||
import {GitHub} from '@docker/actions-toolkit/lib/github';
|
||||
import {Inputs as BuildxInputs} from '@docker/actions-toolkit/lib/buildx/inputs';
|
||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
|
||||
import {Util} from '@docker/actions-toolkit/lib/util';
|
||||
|
||||
export interface Inputs {
|
||||
addHosts: string[];
|
||||
'add-hosts': string[];
|
||||
allow: string[];
|
||||
annotations: string[];
|
||||
attests: string[];
|
||||
buildArgs: string[];
|
||||
buildContexts: string[];
|
||||
'build-args': string[];
|
||||
'build-contexts': string[];
|
||||
builder: string;
|
||||
cacheFrom: string[];
|
||||
cacheTo: string[];
|
||||
cgroupParent: string;
|
||||
'cache-from': string[];
|
||||
'cache-to': string[];
|
||||
'cgroup-parent': string;
|
||||
context: string;
|
||||
file: string;
|
||||
labels: string[];
|
||||
load: boolean;
|
||||
network: string;
|
||||
noCache: boolean;
|
||||
noCacheFilters: string[];
|
||||
'no-cache': boolean;
|
||||
'no-cache-filters': string[];
|
||||
outputs: string[];
|
||||
platforms: string[];
|
||||
provenance: string;
|
||||
@@ -30,47 +32,50 @@ export interface Inputs {
|
||||
push: boolean;
|
||||
sbom: string;
|
||||
secrets: string[];
|
||||
secretFiles: string[];
|
||||
shmSize: string;
|
||||
'secret-envs': string[];
|
||||
'secret-files': string[];
|
||||
'shm-size': string;
|
||||
ssh: string[];
|
||||
tags: string[];
|
||||
target: string;
|
||||
ulimit: string[];
|
||||
githubToken: string;
|
||||
'github-token': string;
|
||||
}
|
||||
|
||||
export async function getInputs(): Promise<Inputs> {
|
||||
return {
|
||||
addHosts: Util.getInputList('add-hosts'),
|
||||
'add-hosts': Util.getInputList('add-hosts'),
|
||||
allow: Util.getInputList('allow'),
|
||||
annotations: Util.getInputList('annotations', {ignoreComma: true}),
|
||||
attests: Util.getInputList('attests', {ignoreComma: true}),
|
||||
buildArgs: Util.getInputList('build-args', {ignoreComma: true}),
|
||||
buildContexts: Util.getInputList('build-contexts', {ignoreComma: true}),
|
||||
'build-args': Util.getInputList('build-args', {ignoreComma: true}),
|
||||
'build-contexts': Util.getInputList('build-contexts', {ignoreComma: true}),
|
||||
builder: core.getInput('builder'),
|
||||
cacheFrom: Util.getInputList('cache-from', {ignoreComma: true}),
|
||||
cacheTo: Util.getInputList('cache-to', {ignoreComma: true}),
|
||||
cgroupParent: core.getInput('cgroup-parent'),
|
||||
'cache-from': Util.getInputList('cache-from', {ignoreComma: true}),
|
||||
'cache-to': Util.getInputList('cache-to', {ignoreComma: true}),
|
||||
'cgroup-parent': core.getInput('cgroup-parent'),
|
||||
context: core.getInput('context') || Context.gitContext(),
|
||||
file: core.getInput('file'),
|
||||
labels: Util.getInputList('labels', {ignoreComma: true}),
|
||||
load: core.getBooleanInput('load'),
|
||||
network: core.getInput('network'),
|
||||
noCache: core.getBooleanInput('no-cache'),
|
||||
noCacheFilters: Util.getInputList('no-cache-filters'),
|
||||
outputs: Util.getInputList('outputs', {ignoreComma: true}),
|
||||
'no-cache': core.getBooleanInput('no-cache'),
|
||||
'no-cache-filters': Util.getInputList('no-cache-filters'),
|
||||
outputs: Util.getInputList('outputs', {ignoreComma: true, quote: false}),
|
||||
platforms: Util.getInputList('platforms'),
|
||||
provenance: BuildxInputs.getProvenanceInput('provenance'),
|
||||
provenance: Build.getProvenanceInput('provenance'),
|
||||
pull: core.getBooleanInput('pull'),
|
||||
push: core.getBooleanInput('push'),
|
||||
sbom: core.getInput('sbom'),
|
||||
secrets: Util.getInputList('secrets', {ignoreComma: true}),
|
||||
secretFiles: Util.getInputList('secret-files', {ignoreComma: true}),
|
||||
shmSize: core.getInput('shm-size'),
|
||||
'secret-envs': Util.getInputList('secret-envs'),
|
||||
'secret-files': Util.getInputList('secret-files', {ignoreComma: true}),
|
||||
'shm-size': core.getInput('shm-size'),
|
||||
ssh: Util.getInputList('ssh'),
|
||||
tags: Util.getInputList('tags'),
|
||||
target: core.getInput('target'),
|
||||
ulimit: Util.getInputList('ulimit', {ignoreComma: true}),
|
||||
githubToken: core.getInput('github-token')
|
||||
'github-token': core.getInput('github-token')
|
||||
};
|
||||
}
|
||||
|
||||
@@ -88,44 +93,55 @@ export async function getArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<s
|
||||
|
||||
async function getBuildArgs(inputs: Inputs, context: string, toolkit: Toolkit): Promise<Array<string>> {
|
||||
const args: Array<string> = ['build'];
|
||||
await Util.asyncForEach(inputs.addHosts, async addHost => {
|
||||
await Util.asyncForEach(inputs['add-hosts'], async addHost => {
|
||||
args.push('--add-host', addHost);
|
||||
});
|
||||
if (inputs.allow.length > 0) {
|
||||
args.push('--allow', inputs.allow.join(','));
|
||||
}
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.10.0')) {
|
||||
await Util.asyncForEach(inputs.attests, async attest => {
|
||||
args.push('--attest', attest);
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.12.0')) {
|
||||
await Util.asyncForEach(inputs.annotations, async annotation => {
|
||||
args.push('--annotation', annotation);
|
||||
});
|
||||
} else if (inputs.annotations.length > 0) {
|
||||
core.warning("Annotations are only supported by buildx >= 0.12.0; the input 'annotations' is ignored.");
|
||||
}
|
||||
await Util.asyncForEach(inputs.buildArgs, async buildArg => {
|
||||
await Util.asyncForEach(inputs['build-args'], async buildArg => {
|
||||
args.push('--build-arg', buildArg);
|
||||
});
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.8.0')) {
|
||||
await Util.asyncForEach(inputs.buildContexts, async buildContext => {
|
||||
await Util.asyncForEach(inputs['build-contexts'], async buildContext => {
|
||||
args.push('--build-context', buildContext);
|
||||
});
|
||||
} else if (inputs['build-contexts'].length > 0) {
|
||||
core.warning("Build contexts are only supported by buildx >= 0.8.0; the input 'build-contexts' is ignored.");
|
||||
}
|
||||
await Util.asyncForEach(inputs.cacheFrom, async cacheFrom => {
|
||||
await Util.asyncForEach(inputs['cache-from'], async cacheFrom => {
|
||||
args.push('--cache-from', cacheFrom);
|
||||
});
|
||||
await Util.asyncForEach(inputs.cacheTo, async cacheTo => {
|
||||
await Util.asyncForEach(inputs['cache-to'], async cacheTo => {
|
||||
args.push('--cache-to', cacheTo);
|
||||
});
|
||||
if (inputs.cgroupParent) {
|
||||
args.push('--cgroup-parent', inputs.cgroupParent);
|
||||
if (inputs['cgroup-parent']) {
|
||||
args.push('--cgroup-parent', inputs['cgroup-parent']);
|
||||
}
|
||||
await Util.asyncForEach(inputs['secret-envs'], async secretEnv => {
|
||||
try {
|
||||
args.push('--secret', Build.resolveSecretEnv(secretEnv));
|
||||
} catch (err) {
|
||||
core.warning(err.message);
|
||||
}
|
||||
});
|
||||
if (inputs.file) {
|
||||
args.push('--file', inputs.file);
|
||||
}
|
||||
if (!BuildxInputs.hasLocalExporter(inputs.outputs) && !BuildxInputs.hasTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || (await toolkit.buildx.versionSatisfies('>=0.4.2')))) {
|
||||
args.push('--iidfile', BuildxInputs.getBuildImageIDFilePath());
|
||||
if (!Build.hasLocalExporter(inputs.outputs) && !Build.hasTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || (await toolkit.buildx.versionSatisfies('>=0.4.2')))) {
|
||||
args.push('--iidfile', toolkit.buildxBuild.getImageIDFilePath());
|
||||
}
|
||||
await Util.asyncForEach(inputs.labels, async label => {
|
||||
args.push('--label', label);
|
||||
});
|
||||
await Util.asyncForEach(inputs.noCacheFilters, async noCacheFilter => {
|
||||
await Util.asyncForEach(inputs['no-cache-filters'], async noCacheFilter => {
|
||||
args.push('--no-cache-filter', noCacheFilter);
|
||||
});
|
||||
await Util.asyncForEach(inputs.outputs, async output => {
|
||||
@@ -135,44 +151,29 @@ async function getBuildArgs(inputs: Inputs, context: string, toolkit: Toolkit):
|
||||
args.push('--platform', inputs.platforms.join(','));
|
||||
}
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.10.0')) {
|
||||
if (inputs.provenance) {
|
||||
args.push('--provenance', inputs.provenance);
|
||||
} else if ((await toolkit.buildkit.versionSatisfies(inputs.builder, '>=0.11.0')) && !BuildxInputs.hasDockerExporter(inputs.outputs, inputs.load)) {
|
||||
// if provenance not specified and BuildKit version compatible for
|
||||
// attestation, set default provenance. Also needs to make sure user
|
||||
// doesn't want to explicitly load the image to docker.
|
||||
if (GitHub.context.payload.repository?.private ?? false) {
|
||||
// if this is a private repository, we set the default provenance
|
||||
// attributes being set in buildx: https://github.com/docker/buildx/blob/fb27e3f919dcbf614d7126b10c2bc2d0b1927eb6/build/build.go#L603
|
||||
args.push('--provenance', BuildxInputs.resolveProvenanceAttrs(`mode=min,inline-only=true`));
|
||||
} else {
|
||||
// for a public repository, we set max provenance mode.
|
||||
args.push('--provenance', BuildxInputs.resolveProvenanceAttrs(`mode=max`));
|
||||
}
|
||||
}
|
||||
if (inputs.sbom) {
|
||||
args.push('--sbom', inputs.sbom);
|
||||
}
|
||||
args.push(...(await getAttestArgs(inputs, toolkit)));
|
||||
} else {
|
||||
core.warning("Attestations are only supported by buildx >= 0.10.0; the inputs 'attests', 'provenance' and 'sbom' are ignored.");
|
||||
}
|
||||
await Util.asyncForEach(inputs.secrets, async secret => {
|
||||
try {
|
||||
args.push('--secret', BuildxInputs.resolveBuildSecretString(secret));
|
||||
args.push('--secret', Build.resolveSecretString(secret));
|
||||
} catch (err) {
|
||||
core.warning(err.message);
|
||||
}
|
||||
});
|
||||
await Util.asyncForEach(inputs.secretFiles, async secretFile => {
|
||||
await Util.asyncForEach(inputs['secret-files'], async secretFile => {
|
||||
try {
|
||||
args.push('--secret', BuildxInputs.resolveBuildSecretFile(secretFile));
|
||||
args.push('--secret', Build.resolveSecretFile(secretFile));
|
||||
} catch (err) {
|
||||
core.warning(err.message);
|
||||
}
|
||||
});
|
||||
if (inputs.githubToken && !BuildxInputs.hasGitAuthTokenSecret(inputs.secrets) && context.startsWith(Context.gitContext())) {
|
||||
args.push('--secret', BuildxInputs.resolveBuildSecretString(`GIT_AUTH_TOKEN=${inputs.githubToken}`));
|
||||
if (inputs['github-token'] && !Build.hasGitAuthTokenSecret(inputs.secrets) && context.startsWith(Context.gitContext())) {
|
||||
args.push('--secret', Build.resolveSecretString(`GIT_AUTH_TOKEN=${inputs['github-token']}`));
|
||||
}
|
||||
if (inputs.shmSize) {
|
||||
args.push('--shm-size', inputs.shmSize);
|
||||
if (inputs['shm-size']) {
|
||||
args.push('--shm-size', inputs['shm-size']);
|
||||
}
|
||||
await Util.asyncForEach(inputs.ssh, async ssh => {
|
||||
args.push('--ssh', ssh);
|
||||
@@ -198,12 +199,12 @@ async function getCommonArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<st
|
||||
args.push('--load');
|
||||
}
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.6.0')) {
|
||||
args.push('--metadata-file', BuildxInputs.getBuildMetadataFilePath());
|
||||
args.push('--metadata-file', toolkit.buildxBuild.getMetadataFilePath());
|
||||
}
|
||||
if (inputs.network) {
|
||||
args.push('--network', inputs.network);
|
||||
}
|
||||
if (inputs.noCache) {
|
||||
if (inputs['no-cache']) {
|
||||
args.push('--no-cache');
|
||||
}
|
||||
if (inputs.pull) {
|
||||
@@ -214,3 +215,52 @@ async function getCommonArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<st
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
async function getAttestArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> {
|
||||
const args: Array<string> = [];
|
||||
|
||||
// check if provenance attestation is set in attests input
|
||||
let hasAttestProvenance = false;
|
||||
await Util.asyncForEach(inputs.attests, async (attest: string) => {
|
||||
if (Build.hasAttestationType('provenance', attest)) {
|
||||
hasAttestProvenance = true;
|
||||
}
|
||||
});
|
||||
|
||||
let provenanceSet = false;
|
||||
let sbomSet = false;
|
||||
if (inputs.provenance) {
|
||||
args.push('--attest', Build.resolveAttestationAttrs(`type=provenance,${inputs.provenance}`));
|
||||
provenanceSet = true;
|
||||
} else if (!hasAttestProvenance && (await toolkit.buildkit.versionSatisfies(inputs.builder, '>=0.11.0')) && !Build.hasDockerExporter(inputs.outputs, inputs.load)) {
|
||||
// if provenance not specified in provenance or attests inputs and BuildKit
|
||||
// version compatible for attestation, set default provenance. Also needs
|
||||
// to make sure user doesn't want to explicitly load the image to docker.
|
||||
if (GitHub.context.payload.repository?.private ?? false) {
|
||||
// if this is a private repository, we set the default provenance
|
||||
// attributes being set in buildx: https://github.com/docker/buildx/blob/fb27e3f919dcbf614d7126b10c2bc2d0b1927eb6/build/build.go#L603
|
||||
args.push('--attest', `type=provenance,${Build.resolveProvenanceAttrs(`mode=min,inline-only=true`)}`);
|
||||
} else {
|
||||
// for a public repository, we set max provenance mode.
|
||||
args.push('--attest', `type=provenance,${Build.resolveProvenanceAttrs(`mode=max`)}`);
|
||||
}
|
||||
}
|
||||
if (inputs.sbom) {
|
||||
args.push('--attest', Build.resolveAttestationAttrs(`type=sbom,${inputs.sbom}`));
|
||||
sbomSet = true;
|
||||
}
|
||||
|
||||
// set attests but check if provenance or sbom types already set as
|
||||
// provenance and sbom inputs take precedence over attests input.
|
||||
await Util.asyncForEach(inputs.attests, async (attest: string) => {
|
||||
if (!Build.hasAttestationType('provenance', attest) && !Build.hasAttestationType('sbom', attest)) {
|
||||
args.push('--attest', Build.resolveAttestationAttrs(attest));
|
||||
} else if (!provenanceSet && Build.hasAttestationType('provenance', attest)) {
|
||||
args.push('--attest', Build.resolveProvenanceAttrs(attest));
|
||||
} else if (!sbomSet && Build.hasAttestationType('sbom', attest)) {
|
||||
args.push('--attest', attest);
|
||||
}
|
||||
});
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
+22
-8
@@ -3,13 +3,14 @@ import * as path from 'path';
|
||||
import * as stateHelper from './state-helper';
|
||||
import * as core from '@actions/core';
|
||||
import * as actionsToolkit from '@docker/actions-toolkit';
|
||||
|
||||
import {Context} from '@docker/actions-toolkit/lib/context';
|
||||
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
|
||||
import {Exec} from '@docker/actions-toolkit/lib/exec';
|
||||
import {GitHub} from '@docker/actions-toolkit/lib/github';
|
||||
import {Inputs as BuildxInputs} from '@docker/actions-toolkit/lib/buildx/inputs';
|
||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
|
||||
import {ConfigFile} from '@docker/actions-toolkit/lib/types/docker';
|
||||
|
||||
import {ConfigFile} from '@docker/actions-toolkit/lib/types/docker/docker';
|
||||
|
||||
import * as context from './context';
|
||||
|
||||
@@ -17,6 +18,8 @@ actionsToolkit.run(
|
||||
// main
|
||||
async () => {
|
||||
const inputs: context.Inputs = await context.getInputs();
|
||||
core.debug(`inputs: ${JSON.stringify(inputs)}`);
|
||||
|
||||
const toolkit = new Toolkit();
|
||||
|
||||
await core.group(`GitHub Actions runtime token ACs`, async () => {
|
||||
@@ -48,7 +51,7 @@ actionsToolkit.run(
|
||||
if (dockerConfig && dockerConfig.proxies) {
|
||||
for (const host in dockerConfig.proxies) {
|
||||
let prefix = '';
|
||||
if (dockerConfig.proxies.length > 1) {
|
||||
if (Object.keys(dockerConfig.proxies).length > 1) {
|
||||
prefix = ' ';
|
||||
core.info(host);
|
||||
}
|
||||
@@ -72,8 +75,18 @@ actionsToolkit.run(
|
||||
await toolkit.buildx.printVersion();
|
||||
});
|
||||
|
||||
await core.group(`Builder info`, async () => {
|
||||
const builder = await toolkit.builder.inspect(inputs.builder);
|
||||
core.info(JSON.stringify(builder, null, 2));
|
||||
});
|
||||
|
||||
const args: string[] = await context.getArgs(inputs, toolkit);
|
||||
core.debug(`context.getArgs: ${JSON.stringify(args)}`);
|
||||
|
||||
const buildCmd = await toolkit.buildx.getCommand(args);
|
||||
core.debug(`buildCmd.command: ${buildCmd.command}`);
|
||||
core.debug(`buildCmd.args: ${JSON.stringify(buildCmd.args)}`);
|
||||
|
||||
await Exec.getExecOutput(buildCmd.command, buildCmd.args, {
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
@@ -82,9 +95,9 @@ actionsToolkit.run(
|
||||
}
|
||||
});
|
||||
|
||||
const imageID = BuildxInputs.resolveBuildImageID();
|
||||
const metadata = BuildxInputs.resolveBuildMetadata();
|
||||
const digest = BuildxInputs.resolveDigest();
|
||||
const imageID = toolkit.buildxBuild.resolveImageID();
|
||||
const metadata = toolkit.buildxBuild.resolveMetadata();
|
||||
const digest = toolkit.buildxBuild.resolveDigest();
|
||||
|
||||
if (imageID) {
|
||||
await core.group(`ImageID`, async () => {
|
||||
@@ -100,8 +113,9 @@ actionsToolkit.run(
|
||||
}
|
||||
if (metadata) {
|
||||
await core.group(`Metadata`, async () => {
|
||||
core.info(metadata);
|
||||
core.setOutput('metadata', metadata);
|
||||
const metadatadt = JSON.stringify(metadata, null, 2);
|
||||
core.info(metadatadt);
|
||||
core.setOutput('metadata', metadatadt);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user