Skip to content

Commit d1b0eb0

Browse files
authored
Merge pull request #759 from crazy-max/fix-provenance-input
Fix provenance input
2 parents 2a16835 + a0635fe commit d1b0eb0

File tree

6 files changed

+188
-13
lines changed

6 files changed

+188
-13
lines changed

.github/workflows/ci.yml

+35
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,41 @@ jobs:
523523
file: ./test/go/Dockerfile
524524
outputs: type=cacheonly
525525

526+
provenance:
527+
runs-on: ubuntu-latest
528+
strategy:
529+
fail-fast: false
530+
matrix:
531+
attrs:
532+
- ''
533+
- mode=max
534+
- builder-id=foo
535+
- false
536+
- true
537+
steps:
538+
-
539+
name: Checkout
540+
uses: actions/checkout@v3
541+
-
542+
name: Set up Docker Buildx
543+
uses: docker/setup-buildx-action@v2
544+
with:
545+
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
546+
driver-opts: |
547+
network=host
548+
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
549+
-
550+
name: Build
551+
uses: ./
552+
with:
553+
context: ./test/go
554+
file: ./test/go/Dockerfile
555+
target: binary
556+
outputs: type=oci,dest=/tmp/build.tar
557+
provenance: ${{ matrix.attrs }}
558+
cache-from: type=gha,scope=provenance
559+
cache-to: type=gha,scope=provenance,mode=max
560+
526561
sbom:
527562
runs-on: ubuntu-latest
528563
strategy:

__tests__/context.test.ts

+122-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {beforeEach, describe, expect, it, jest, test} from '@jest/globals';
22
import * as fs from 'fs';
33
import * as path from 'path';
44

5+
import * as buildx from '../src/buildx';
56
import * as context from '../src/context';
67

78
const pgp = `-----BEGIN PGP PRIVATE KEY BLOCK-----
@@ -127,6 +128,8 @@ jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => {
127128
return path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
128129
});
129130

131+
jest.spyOn(buildx, 'satisfiesBuildKitVersion').mockResolvedValueOnce(true);
132+
130133
describe('getArgs', () => {
131134
beforeEach(() => {
132135
process.env = Object.keys(process.env).reduce((object, key) => {
@@ -159,7 +162,11 @@ describe('getArgs', () => {
159162
1,
160163
'0.4.2',
161164
new Map<string, string>([
162-
['build-args', 'MY_ARG=val1,val2,val3\nARG=val'],
165+
['build-args', `MY_ARG=val1,val2,val3
166+
ARG=val
167+
"MULTILINE=aaaa
168+
bbbb
169+
ccc"`],
163170
['load', 'false'],
164171
['no-cache', 'false'],
165172
['push', 'false'],
@@ -169,6 +176,7 @@ describe('getArgs', () => {
169176
'build',
170177
'--build-arg', 'MY_ARG=val1,val2,val3',
171178
'--build-arg', 'ARG=val',
179+
'--build-arg', `MULTILINE=aaaa\nbbbb\nccc`,
172180
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
173181
'https://github.com/docker/build-push-action.git#refs/heads/test-jest'
174182
]
@@ -517,7 +525,119 @@ nproc=3`],
517525
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
518526
'https://github.com/docker/build-push-action.git#refs/heads/test-jest:subdir'
519527
]
520-
]
528+
],
529+
[
530+
17,
531+
'0.8.2',
532+
new Map<string, string>([
533+
['context', '.'],
534+
['load', 'false'],
535+
['no-cache', 'false'],
536+
['push', 'false'],
537+
['pull', 'false'],
538+
['provenance', 'true'],
539+
]),
540+
[
541+
'build',
542+
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
543+
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
544+
'.'
545+
]
546+
],
547+
[
548+
18,
549+
'0.10.0',
550+
new Map<string, string>([
551+
['context', '.'],
552+
['load', 'false'],
553+
['no-cache', 'false'],
554+
['push', 'false'],
555+
['pull', 'false'],
556+
]),
557+
[
558+
'build',
559+
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
560+
"--provenance", `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`,
561+
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
562+
'.'
563+
]
564+
],
565+
[
566+
19,
567+
'0.10.0',
568+
new Map<string, string>([
569+
['context', '.'],
570+
['load', 'false'],
571+
['no-cache', 'false'],
572+
['push', 'false'],
573+
['pull', 'false'],
574+
['provenance', 'true'],
575+
]),
576+
[
577+
'build',
578+
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
579+
"--provenance", `builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`,
580+
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
581+
'.'
582+
]
583+
],
584+
[
585+
20,
586+
'0.10.0',
587+
new Map<string, string>([
588+
['context', '.'],
589+
['load', 'false'],
590+
['no-cache', 'false'],
591+
['push', 'false'],
592+
['pull', 'false'],
593+
['provenance', 'mode=max'],
594+
]),
595+
[
596+
'build',
597+
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
598+
"--provenance", `mode=max,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`,
599+
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
600+
'.'
601+
]
602+
],
603+
[
604+
21,
605+
'0.10.0',
606+
new Map<string, string>([
607+
['context', '.'],
608+
['load', 'false'],
609+
['no-cache', 'false'],
610+
['push', 'false'],
611+
['pull', 'false'],
612+
['provenance', 'false'],
613+
]),
614+
[
615+
'build',
616+
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
617+
"--provenance", 'false',
618+
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
619+
'.'
620+
]
621+
],
622+
[
623+
22,
624+
'0.10.0',
625+
new Map<string, string>([
626+
['context', '.'],
627+
['load', 'false'],
628+
['no-cache', 'false'],
629+
['push', 'false'],
630+
['pull', 'false'],
631+
['provenance', 'builder-id=foo'],
632+
]),
633+
[
634+
'build',
635+
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
636+
"--provenance", 'builder-id=foo',
637+
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
638+
'.'
639+
]
640+
],
521641
])(
522642
'[%d] given %p with %p as inputs, returns %p',
523643
async (num: number, buildxVersion: string, inputs: Map<string, string>, expected: Array<string>) => {

dev.Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ FROM docker/buildx-bin:${BUILDX_VERSION} as buildx
6868
FROM deps AS test
6969
ENV RUNNER_TEMP=/tmp/github_runner
7070
ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache
71+
ENV GITHUB_REPOSITORY=docker/build-push-action
72+
ENV GITHUB_RUN_ID=123456789
7173
RUN --mount=type=bind,target=.,rw \
7274
--mount=type=cache,target=/src/node_modules \
7375
--mount=type=bind,from=docker,source=/usr/local/bin/docker,target=/usr/bin/docker \

dist/index.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/context.ts

+27-9
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ export function tmpNameSync(options?: tmp.TmpNameOptions): string {
6868
return tmp.tmpNameSync(options);
6969
}
7070

71+
export function provenanceBuilderID(): string {
72+
return `${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${github.context.repo.repo}/actions/runs/${github.context.runId}`;
73+
}
74+
7175
export async function getInputs(defaultContext: string): Promise<Inputs> {
7276
return {
7377
addHosts: await getInputList('add-hosts'),
@@ -88,7 +92,7 @@ export async function getInputs(defaultContext: string): Promise<Inputs> {
8892
noCacheFilters: await getInputList('no-cache-filters'),
8993
outputs: await getInputList('outputs', true),
9094
platforms: await getInputList('platforms'),
91-
provenance: core.getInput('provenance'),
95+
provenance: getProvenanceInput('provenance'),
9296
pull: core.getBooleanInput('pull'),
9397
push: core.getBooleanInput('push'),
9498
sbom: core.getInput('sbom'),
@@ -162,22 +166,19 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, context: str
162166
args.push('--platform', inputs.platforms.join(','));
163167
}
164168
if (buildx.satisfies(buildxVersion, '>=0.10.0')) {
165-
const prvBuilderID = `${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${github.context.repo.repo}/actions/runs/${github.context.runId}`;
166169
if (inputs.provenance) {
167-
args.push('--provenance', getProvenanceAttrs(inputs.provenance, prvBuilderID));
170+
args.push('--provenance', inputs.provenance);
168171
} else if ((await buildx.satisfiesBuildKitVersion(inputs.builder, '>=0.11.0', standalone)) && !hasDockerExport(inputs)) {
169172
// if provenance not specified and BuildKit version compatible for
170173
// attestation, set default provenance. Also needs to make sure user
171174
// doesn't want to explicitly load the image to docker.
172175
if (fromPayload('repository.private') !== false) {
173176
// if this is a private repository, we set the default provenance
174177
// attributes being set in buildx: https://github.com/docker/buildx/blob/fb27e3f919dcbf614d7126b10c2bc2d0b1927eb6/build/build.go#L603
175-
// along the builder-id attribute.
176-
args.push('--provenance', `mode=min,inline-only=true,builder-id=${prvBuilderID}`);
178+
args.push('--provenance', getProvenanceAttrs(`mode=min,inline-only=true`));
177179
} else {
178-
// for a public repository, we set max provenance mode and the
179-
// builder-id attribute.
180-
args.push('--provenance', `mode=max,builder-id=${prvBuilderID}`);
180+
// for a public repository, we set max provenance mode.
181+
args.push('--provenance', getProvenanceAttrs(`mode=max`));
181182
}
182183
}
183184
if (inputs.sbom) {
@@ -298,7 +299,24 @@ function select(obj: any, path: string): any {
298299
return select(obj[key], path.slice(i + 1));
299300
}
300301

301-
function getProvenanceAttrs(input: string, builderID: string): string {
302+
function getProvenanceInput(name: string): string {
303+
const input = core.getInput(name);
304+
if (!input) {
305+
// if input is not set, default values will be set later.
306+
return input;
307+
}
308+
const builderID = provenanceBuilderID();
309+
try {
310+
return core.getBooleanInput(name) ? `builder-id=${builderID}` : 'false';
311+
} catch (err) {
312+
// not a valid boolean, so we assume it's a string
313+
return getProvenanceAttrs(input);
314+
}
315+
}
316+
317+
function getProvenanceAttrs(input: string): string {
318+
const builderID = provenanceBuilderID();
319+
// parse attributes from input
302320
const fields = parse(input, {
303321
relaxColumnCount: true,
304322
skipEmptyLines: true

0 commit comments

Comments
 (0)