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
 | 
			
		||||
          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:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    strategy:
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@ import {beforeEach, describe, expect, it, jest, test} from '@jest/globals';
 | 
			
		||||
import * as fs from 'fs';
 | 
			
		||||
import * as path from 'path';
 | 
			
		||||
 | 
			
		||||
import * as buildx from '../src/buildx';
 | 
			
		||||
import * as context from '../src/context';
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
jest.spyOn(buildx, 'satisfiesBuildKitVersion').mockResolvedValueOnce(true);
 | 
			
		||||
 | 
			
		||||
describe('getArgs', () => {
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    process.env = Object.keys(process.env).reduce((object, key) => {
 | 
			
		||||
@ -159,7 +162,11 @@ describe('getArgs', () => {
 | 
			
		||||
      1,
 | 
			
		||||
      '0.4.2',
 | 
			
		||||
      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'],
 | 
			
		||||
        ['no-cache', 'false'],
 | 
			
		||||
        ['push', 'false'],
 | 
			
		||||
@ -169,6 +176,7 @@ describe('getArgs', () => {
 | 
			
		||||
        'build',
 | 
			
		||||
        '--build-arg', 'MY_ARG=val1,val2,val3',
 | 
			
		||||
        '--build-arg', 'ARG=val',
 | 
			
		||||
        '--build-arg', `MULTILINE=aaaa\nbbbb\nccc`,
 | 
			
		||||
        '--iidfile', '/tmp/.docker-build-push-jest/iidfile',
 | 
			
		||||
        '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',
 | 
			
		||||
        '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',
 | 
			
		||||
    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
 | 
			
		||||
ENV RUNNER_TEMP=/tmp/github_runner
 | 
			
		||||
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 \
 | 
			
		||||
  --mount=type=cache,target=/src/node_modules \
 | 
			
		||||
  --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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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> {
 | 
			
		||||
  return {
 | 
			
		||||
    addHosts: await getInputList('add-hosts'),
 | 
			
		||||
@ -88,7 +92,7 @@ export async function getInputs(defaultContext: string): Promise<Inputs> {
 | 
			
		||||
    noCacheFilters: await getInputList('no-cache-filters'),
 | 
			
		||||
    outputs: await getInputList('outputs', true),
 | 
			
		||||
    platforms: await getInputList('platforms'),
 | 
			
		||||
    provenance: core.getInput('provenance'),
 | 
			
		||||
    provenance: getProvenanceInput('provenance'),
 | 
			
		||||
    pull: core.getBooleanInput('pull'),
 | 
			
		||||
    push: core.getBooleanInput('push'),
 | 
			
		||||
    sbom: core.getInput('sbom'),
 | 
			
		||||
@ -162,9 +166,8 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, context: str
 | 
			
		||||
    args.push('--platform', inputs.platforms.join(','));
 | 
			
		||||
  }
 | 
			
		||||
  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) {
 | 
			
		||||
      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)) {
 | 
			
		||||
      // if provenance not specified and BuildKit version compatible for
 | 
			
		||||
      // 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 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
 | 
			
		||||
        // along the builder-id attribute.
 | 
			
		||||
        args.push('--provenance', `mode=min,inline-only=true,builder-id=${prvBuilderID}`);
 | 
			
		||||
        args.push('--provenance', getProvenanceAttrs(`mode=min,inline-only=true`));
 | 
			
		||||
      } else {
 | 
			
		||||
        // for a public repository, we set max provenance mode and the
 | 
			
		||||
        // builder-id attribute.
 | 
			
		||||
        args.push('--provenance', `mode=max,builder-id=${prvBuilderID}`);
 | 
			
		||||
        // for a public repository, we set max provenance mode.
 | 
			
		||||
        args.push('--provenance', getProvenanceAttrs(`mode=max`));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (inputs.sbom) {
 | 
			
		||||
@ -298,7 +299,24 @@ function select(obj: any, path: string): any {
 | 
			
		||||
  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, {
 | 
			
		||||
    relaxColumnCount: true,
 | 
			
		||||
    skipEmptyLines: true
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user