Merge pull request #759 from crazy-max/fix-provenance-input
Fix provenance input
This commit is contained in:
		
						commit
						d1b0eb0a29
					
				
							
								
								
									
										35
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @ -523,6 +523,41 @@ jobs: | |||||||
|           file: ./test/go/Dockerfile |           file: ./test/go/Dockerfile | ||||||
|           outputs: type=cacheonly |           outputs: type=cacheonly | ||||||
| 
 | 
 | ||||||
|  |   provenance: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     strategy: | ||||||
|  |       fail-fast: false | ||||||
|  |       matrix: | ||||||
|  |         attrs: | ||||||
|  |           - '' | ||||||
|  |           - mode=max | ||||||
|  |           - builder-id=foo | ||||||
|  |           - false | ||||||
|  |           - true | ||||||
|  |     steps: | ||||||
|  |       - | ||||||
|  |         name: Checkout | ||||||
|  |         uses: actions/checkout@v3 | ||||||
|  |       - | ||||||
|  |         name: Set up Docker Buildx | ||||||
|  |         uses: docker/setup-buildx-action@v2 | ||||||
|  |         with: | ||||||
|  |           version: ${{ inputs.buildx-version || env.BUILDX_VERSION }} | ||||||
|  |           driver-opts: | | ||||||
|  |             network=host | ||||||
|  |             image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }} | ||||||
|  |       - | ||||||
|  |         name: Build | ||||||
|  |         uses: ./ | ||||||
|  |         with: | ||||||
|  |           context: ./test/go | ||||||
|  |           file: ./test/go/Dockerfile | ||||||
|  |           target: binary | ||||||
|  |           outputs: type=oci,dest=/tmp/build.tar | ||||||
|  |           provenance: ${{ matrix.attrs }} | ||||||
|  |           cache-from: type=gha,scope=provenance | ||||||
|  |           cache-to: type=gha,scope=provenance,mode=max | ||||||
|  | 
 | ||||||
|   sbom: |   sbom: | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
|     strategy: |     strategy: | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ import {beforeEach, describe, expect, it, jest, test} from '@jest/globals'; | |||||||
| import * as fs from 'fs'; | import * as fs from 'fs'; | ||||||
| import * as path from 'path'; | import * as path from 'path'; | ||||||
| 
 | 
 | ||||||
|  | import * as buildx from '../src/buildx'; | ||||||
| import * as context from '../src/context'; | import * as context from '../src/context'; | ||||||
| 
 | 
 | ||||||
| const pgp = `-----BEGIN PGP PRIVATE KEY BLOCK-----
 | const pgp = `-----BEGIN PGP PRIVATE KEY BLOCK-----
 | ||||||
| @ -127,6 +128,8 @@ jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => { | |||||||
|   return path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep); |   return path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | jest.spyOn(buildx, 'satisfiesBuildKitVersion').mockResolvedValueOnce(true); | ||||||
|  | 
 | ||||||
| describe('getArgs', () => { | describe('getArgs', () => { | ||||||
|   beforeEach(() => { |   beforeEach(() => { | ||||||
|     process.env = Object.keys(process.env).reduce((object, key) => { |     process.env = Object.keys(process.env).reduce((object, key) => { | ||||||
| @ -159,7 +162,11 @@ describe('getArgs', () => { | |||||||
|       1, |       1, | ||||||
|       '0.4.2', |       '0.4.2', | ||||||
|       new Map<string, string>([ |       new Map<string, string>([ | ||||||
|         ['build-args', 'MY_ARG=val1,val2,val3\nARG=val'], |         ['build-args', `MY_ARG=val1,val2,val3
 | ||||||
|  | ARG=val | ||||||
|  | "MULTILINE=aaaa | ||||||
|  | bbbb | ||||||
|  | ccc"`],
 | ||||||
|         ['load', 'false'], |         ['load', 'false'], | ||||||
|         ['no-cache', 'false'], |         ['no-cache', 'false'], | ||||||
|         ['push', 'false'], |         ['push', 'false'], | ||||||
| @ -169,6 +176,7 @@ describe('getArgs', () => { | |||||||
|         'build', |         'build', | ||||||
|         '--build-arg', 'MY_ARG=val1,val2,val3', |         '--build-arg', 'MY_ARG=val1,val2,val3', | ||||||
|         '--build-arg', 'ARG=val', |         '--build-arg', 'ARG=val', | ||||||
|  |         '--build-arg', `MULTILINE=aaaa\nbbbb\nccc`, | ||||||
|         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', |         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||||
|         'https://github.com/docker/build-push-action.git#refs/heads/test-jest' |         'https://github.com/docker/build-push-action.git#refs/heads/test-jest' | ||||||
|       ] |       ] | ||||||
| @ -517,7 +525,119 @@ nproc=3`], | |||||||
|         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', |         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||||
|         'https://github.com/docker/build-push-action.git#refs/heads/test-jest:subdir' |         'https://github.com/docker/build-push-action.git#refs/heads/test-jest:subdir' | ||||||
|       ] |       ] | ||||||
|     ] |     ], | ||||||
|  |     [ | ||||||
|  |       17, | ||||||
|  |       '0.8.2', | ||||||
|  |       new Map<string, string>([ | ||||||
|  |         ['context', '.'], | ||||||
|  |         ['load', 'false'], | ||||||
|  |         ['no-cache', 'false'], | ||||||
|  |         ['push', 'false'], | ||||||
|  |         ['pull', 'false'], | ||||||
|  |         ['provenance', 'true'], | ||||||
|  |       ]), | ||||||
|  |       [ | ||||||
|  |         'build', | ||||||
|  |         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||||
|  |         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||||
|  |         '.' | ||||||
|  |       ] | ||||||
|  |     ], | ||||||
|  |     [ | ||||||
|  |       18, | ||||||
|  |       '0.10.0', | ||||||
|  |       new Map<string, string>([ | ||||||
|  |         ['context', '.'], | ||||||
|  |         ['load', 'false'], | ||||||
|  |         ['no-cache', 'false'], | ||||||
|  |         ['push', 'false'], | ||||||
|  |         ['pull', 'false'], | ||||||
|  |       ]), | ||||||
|  |       [ | ||||||
|  |         'build', | ||||||
|  |         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||||
|  |         "--provenance", `mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|  |         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||||
|  |         '.' | ||||||
|  |       ] | ||||||
|  |     ], | ||||||
|  |     [ | ||||||
|  |       19, | ||||||
|  |       '0.10.0', | ||||||
|  |       new Map<string, string>([ | ||||||
|  |         ['context', '.'], | ||||||
|  |         ['load', 'false'], | ||||||
|  |         ['no-cache', 'false'], | ||||||
|  |         ['push', 'false'], | ||||||
|  |         ['pull', 'false'], | ||||||
|  |         ['provenance', 'true'], | ||||||
|  |       ]), | ||||||
|  |       [ | ||||||
|  |         'build', | ||||||
|  |         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||||
|  |         "--provenance", `builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|  |         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||||
|  |         '.' | ||||||
|  |       ] | ||||||
|  |     ], | ||||||
|  |     [ | ||||||
|  |       20, | ||||||
|  |       '0.10.0', | ||||||
|  |       new Map<string, string>([ | ||||||
|  |         ['context', '.'], | ||||||
|  |         ['load', 'false'], | ||||||
|  |         ['no-cache', 'false'], | ||||||
|  |         ['push', 'false'], | ||||||
|  |         ['pull', 'false'], | ||||||
|  |         ['provenance', 'mode=max'], | ||||||
|  |       ]), | ||||||
|  |       [ | ||||||
|  |         'build', | ||||||
|  |         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||||
|  |         "--provenance", `mode=max,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`, | ||||||
|  |         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||||
|  |         '.' | ||||||
|  |       ] | ||||||
|  |     ], | ||||||
|  |     [ | ||||||
|  |       21, | ||||||
|  |       '0.10.0', | ||||||
|  |       new Map<string, string>([ | ||||||
|  |         ['context', '.'], | ||||||
|  |         ['load', 'false'], | ||||||
|  |         ['no-cache', 'false'], | ||||||
|  |         ['push', 'false'], | ||||||
|  |         ['pull', 'false'], | ||||||
|  |         ['provenance', 'false'], | ||||||
|  |       ]), | ||||||
|  |       [ | ||||||
|  |         'build', | ||||||
|  |         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||||
|  |         "--provenance", 'false', | ||||||
|  |         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||||
|  |         '.' | ||||||
|  |       ] | ||||||
|  |     ], | ||||||
|  |     [ | ||||||
|  |       22, | ||||||
|  |       '0.10.0', | ||||||
|  |       new Map<string, string>([ | ||||||
|  |         ['context', '.'], | ||||||
|  |         ['load', 'false'], | ||||||
|  |         ['no-cache', 'false'], | ||||||
|  |         ['push', 'false'], | ||||||
|  |         ['pull', 'false'], | ||||||
|  |         ['provenance', 'builder-id=foo'], | ||||||
|  |       ]), | ||||||
|  |       [ | ||||||
|  |         'build', | ||||||
|  |         '--iidfile', '/tmp/.docker-build-push-jest/iidfile', | ||||||
|  |         "--provenance", 'builder-id=foo', | ||||||
|  |         '--metadata-file', '/tmp/.docker-build-push-jest/metadata-file', | ||||||
|  |         '.' | ||||||
|  |       ] | ||||||
|  |     ], | ||||||
|   ])( |   ])( | ||||||
|     '[%d] given %p with %p as inputs, returns %p', |     '[%d] given %p with %p as inputs, returns %p', | ||||||
|     async (num: number, buildxVersion: string, inputs: Map<string, string>, expected: Array<string>) => { |     async (num: number, buildxVersion: string, inputs: Map<string, string>, expected: Array<string>) => { | ||||||
|  | |||||||
| @ -68,6 +68,8 @@ FROM docker/buildx-bin:${BUILDX_VERSION} as buildx | |||||||
| FROM deps AS test | FROM deps AS test | ||||||
| ENV RUNNER_TEMP=/tmp/github_runner | ENV RUNNER_TEMP=/tmp/github_runner | ||||||
| ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache | ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache | ||||||
|  | ENV GITHUB_REPOSITORY=docker/build-push-action | ||||||
|  | ENV GITHUB_RUN_ID=123456789 | ||||||
| RUN --mount=type=bind,target=.,rw \ | RUN --mount=type=bind,target=.,rw \ | ||||||
|   --mount=type=cache,target=/src/node_modules \ |   --mount=type=cache,target=/src/node_modules \ | ||||||
|   --mount=type=bind,from=docker,source=/usr/local/bin/docker,target=/usr/bin/docker \ |   --mount=type=bind,from=docker,source=/usr/local/bin/docker,target=/usr/bin/docker \ | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										2
									
								
								dist/index.js.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								dist/index.js.map
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -68,6 +68,10 @@ export function tmpNameSync(options?: tmp.TmpNameOptions): string { | |||||||
|   return tmp.tmpNameSync(options); |   return tmp.tmpNameSync(options); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export function provenanceBuilderID(): string { | ||||||
|  |   return `${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${github.context.repo.repo}/actions/runs/${github.context.runId}`; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export async function getInputs(defaultContext: string): Promise<Inputs> { | export async function getInputs(defaultContext: string): Promise<Inputs> { | ||||||
|   return { |   return { | ||||||
|     addHosts: await getInputList('add-hosts'), |     addHosts: await getInputList('add-hosts'), | ||||||
| @ -88,7 +92,7 @@ export async function getInputs(defaultContext: string): Promise<Inputs> { | |||||||
|     noCacheFilters: await getInputList('no-cache-filters'), |     noCacheFilters: await getInputList('no-cache-filters'), | ||||||
|     outputs: await getInputList('outputs', true), |     outputs: await getInputList('outputs', true), | ||||||
|     platforms: await getInputList('platforms'), |     platforms: await getInputList('platforms'), | ||||||
|     provenance: core.getInput('provenance'), |     provenance: getProvenanceInput('provenance'), | ||||||
|     pull: core.getBooleanInput('pull'), |     pull: core.getBooleanInput('pull'), | ||||||
|     push: core.getBooleanInput('push'), |     push: core.getBooleanInput('push'), | ||||||
|     sbom: core.getInput('sbom'), |     sbom: core.getInput('sbom'), | ||||||
| @ -162,9 +166,8 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, context: str | |||||||
|     args.push('--platform', inputs.platforms.join(',')); |     args.push('--platform', inputs.platforms.join(',')); | ||||||
|   } |   } | ||||||
|   if (buildx.satisfies(buildxVersion, '>=0.10.0')) { |   if (buildx.satisfies(buildxVersion, '>=0.10.0')) { | ||||||
|     const prvBuilderID = `${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${github.context.repo.repo}/actions/runs/${github.context.runId}`; |  | ||||||
|     if (inputs.provenance) { |     if (inputs.provenance) { | ||||||
|       args.push('--provenance', getProvenanceAttrs(inputs.provenance, prvBuilderID)); |       args.push('--provenance', inputs.provenance); | ||||||
|     } else if ((await buildx.satisfiesBuildKitVersion(inputs.builder, '>=0.11.0', standalone)) && !hasDockerExport(inputs)) { |     } else if ((await buildx.satisfiesBuildKitVersion(inputs.builder, '>=0.11.0', standalone)) && !hasDockerExport(inputs)) { | ||||||
|       // if provenance not specified and BuildKit version compatible for
 |       // if provenance not specified and BuildKit version compatible for
 | ||||||
|       // attestation, set default provenance. Also needs to make sure user
 |       // attestation, set default provenance. Also needs to make sure user
 | ||||||
| @ -172,12 +175,10 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, context: str | |||||||
|       if (fromPayload('repository.private') !== false) { |       if (fromPayload('repository.private') !== false) { | ||||||
|         // if this is a private repository, we set the default provenance
 |         // 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
 |         // attributes being set in buildx: https://github.com/docker/buildx/blob/fb27e3f919dcbf614d7126b10c2bc2d0b1927eb6/build/build.go#L603
 | ||||||
|         // along the builder-id attribute.
 |         args.push('--provenance', getProvenanceAttrs(`mode=min,inline-only=true`)); | ||||||
|         args.push('--provenance', `mode=min,inline-only=true,builder-id=${prvBuilderID}`); |  | ||||||
|       } else { |       } else { | ||||||
|         // for a public repository, we set max provenance mode and the
 |         // for a public repository, we set max provenance mode.
 | ||||||
|         // builder-id attribute.
 |         args.push('--provenance', getProvenanceAttrs(`mode=max`)); | ||||||
|         args.push('--provenance', `mode=max,builder-id=${prvBuilderID}`); |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     if (inputs.sbom) { |     if (inputs.sbom) { | ||||||
| @ -298,7 +299,24 @@ function select(obj: any, path: string): any { | |||||||
|   return select(obj[key], path.slice(i + 1)); |   return select(obj[key], path.slice(i + 1)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function getProvenanceAttrs(input: string, builderID: string): string { | function getProvenanceInput(name: string): string { | ||||||
|  |   const input = core.getInput(name); | ||||||
|  |   if (!input) { | ||||||
|  |     // if input is not set, default values will be set later.
 | ||||||
|  |     return input; | ||||||
|  |   } | ||||||
|  |   const builderID = provenanceBuilderID(); | ||||||
|  |   try { | ||||||
|  |     return core.getBooleanInput(name) ? `builder-id=${builderID}` : 'false'; | ||||||
|  |   } catch (err) { | ||||||
|  |     // not a valid boolean, so we assume it's a string
 | ||||||
|  |     return getProvenanceAttrs(input); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function getProvenanceAttrs(input: string): string { | ||||||
|  |   const builderID = provenanceBuilderID(); | ||||||
|  |   // parse attributes from input
 | ||||||
|   const fields = parse(input, { |   const fields = parse(input, { | ||||||
|     relaxColumnCount: true, |     relaxColumnCount: true, | ||||||
|     skipEmptyLines: true |     skipEmptyLines: true | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user