check BuildKit compatibility before setting default provenance opts
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									0149503e26
								
							
						
					
					
						commit
						74f883a069
					
				
							
								
								
									
										37
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@ -491,7 +491,39 @@ jobs:
 | 
			
		||||
          cache-from: type=gha,scope=nocachefilter
 | 
			
		||||
          cache-to: type=gha,scope=nocachefilter,mode=max
 | 
			
		||||
 | 
			
		||||
  attests:
 | 
			
		||||
  attests-compat:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
      matrix:
 | 
			
		||||
        include:
 | 
			
		||||
          - buildx: latest
 | 
			
		||||
            buildkit: moby/buildkit:buildx-stable-1
 | 
			
		||||
          - buildx: latest
 | 
			
		||||
            buildkit: moby/buildkit:v0.10.6
 | 
			
		||||
          - buildx: v0.9.1
 | 
			
		||||
            buildkit: moby/buildkit:buildx-stable-1
 | 
			
		||||
    steps:
 | 
			
		||||
      -
 | 
			
		||||
        name: Checkout
 | 
			
		||||
        uses: actions/checkout@v3
 | 
			
		||||
      -
 | 
			
		||||
        name: Set up Docker Buildx
 | 
			
		||||
        uses: docker/setup-buildx-action@v2
 | 
			
		||||
        with:
 | 
			
		||||
          version: ${{ matrix.buildx }}
 | 
			
		||||
          driver-opts: |
 | 
			
		||||
            network=host
 | 
			
		||||
            image=${{ matrix.buildkit }}
 | 
			
		||||
      -
 | 
			
		||||
        name: Build
 | 
			
		||||
        uses: ./
 | 
			
		||||
        with:
 | 
			
		||||
          context: ./test/go
 | 
			
		||||
          file: ./test/go/Dockerfile
 | 
			
		||||
          outputs: type=cacheonly
 | 
			
		||||
 | 
			
		||||
  sbom:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    strategy:
 | 
			
		||||
      fail-fast: false
 | 
			
		||||
@ -506,9 +538,6 @@ jobs:
 | 
			
		||||
        image: registry:2
 | 
			
		||||
        ports:
 | 
			
		||||
          - 5000:5000
 | 
			
		||||
    env:
 | 
			
		||||
      BUILDX_VERSION: v0.10.0-rc2  # TODO: remove when Buildx v0.10.0 is released
 | 
			
		||||
      BUILDKIT_IMAGE: moby/buildkit:v0.11.0-rc3  # TODO: remove when BuildKit v0.11.0 is released
 | 
			
		||||
    steps:
 | 
			
		||||
      -
 | 
			
		||||
        name: Checkout
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										123
									
								
								src/buildx.ts
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								src/buildx.ts
									
									
									
									
									
								
							@ -3,9 +3,24 @@ import fs from 'fs';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
import * as semver from 'semver';
 | 
			
		||||
import * as exec from '@actions/exec';
 | 
			
		||||
 | 
			
		||||
import * as context from './context';
 | 
			
		||||
 | 
			
		||||
export type Builder = {
 | 
			
		||||
  name?: string;
 | 
			
		||||
  driver?: string;
 | 
			
		||||
  nodes: Node[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export type Node = {
 | 
			
		||||
  name?: string;
 | 
			
		||||
  endpoint?: string;
 | 
			
		||||
  'driver-opts'?: Array<string>;
 | 
			
		||||
  status?: string;
 | 
			
		||||
  'buildkitd-flags'?: string;
 | 
			
		||||
  buildkit?: string;
 | 
			
		||||
  platforms?: string;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export async function getImageIDFile(): Promise<string> {
 | 
			
		||||
  return path.join(context.tmpDir(), 'iidfile').split(path.sep).join(path.posix.sep);
 | 
			
		||||
}
 | 
			
		||||
@ -126,6 +141,112 @@ export async function isAvailable(standalone?: boolean): Promise<boolean> {
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function satisfiesBuildKitVersion(builderName: string, range: string, standalone?: boolean): Promise<boolean> {
 | 
			
		||||
  const builderInspect = await inspect(builderName, standalone);
 | 
			
		||||
  for (const node of builderInspect.nodes) {
 | 
			
		||||
    if (!node.buildkit) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    // BuildKit version reported by moby is in the format of `v0.11.0-moby`
 | 
			
		||||
    if (builderInspect.driver == 'docker' && !node.buildkit.endsWith('-moby')) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    const version = node.buildkit.replace(/-moby$/, '');
 | 
			
		||||
    if (!semver.satisfies(version, range)) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function inspect(name: string, standalone?: boolean): Promise<Builder> {
 | 
			
		||||
  const cmd = getCommand(['inspect', name], standalone);
 | 
			
		||||
  return await exec
 | 
			
		||||
    .getExecOutput(cmd.command, cmd.args, {
 | 
			
		||||
      ignoreReturnCode: true,
 | 
			
		||||
      silent: true
 | 
			
		||||
    })
 | 
			
		||||
    .then(res => {
 | 
			
		||||
      if (res.stderr.length > 0 && res.exitCode != 0) {
 | 
			
		||||
        throw new Error(res.stderr.trim());
 | 
			
		||||
      }
 | 
			
		||||
      return parseInspect(res.stdout);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function parseInspect(data: string): Promise<Builder> {
 | 
			
		||||
  const builder: Builder = {
 | 
			
		||||
    nodes: []
 | 
			
		||||
  };
 | 
			
		||||
  let node: Node = {};
 | 
			
		||||
  for (const line of data.trim().split(`\n`)) {
 | 
			
		||||
    const [key, ...rest] = line.split(':');
 | 
			
		||||
    const value = rest.map(v => v.trim()).join(':');
 | 
			
		||||
    if (key.length == 0 || value.length == 0) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    switch (key.toLowerCase()) {
 | 
			
		||||
      case 'name': {
 | 
			
		||||
        if (builder.name == undefined) {
 | 
			
		||||
          builder.name = value;
 | 
			
		||||
        } else {
 | 
			
		||||
          if (Object.keys(node).length > 0) {
 | 
			
		||||
            builder.nodes.push(node);
 | 
			
		||||
            node = {};
 | 
			
		||||
          }
 | 
			
		||||
          node.name = value;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'driver': {
 | 
			
		||||
        builder.driver = value;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'endpoint': {
 | 
			
		||||
        node.endpoint = value;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'driver options': {
 | 
			
		||||
        node['driver-opts'] = (value.match(/(\w+)="([^"]*)"/g) || []).map(v => v.replace(/^(.*)="(.*)"$/g, '$1=$2'));
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'status': {
 | 
			
		||||
        node.status = value;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'flags': {
 | 
			
		||||
        node['buildkitd-flags'] = value;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'buildkit': {
 | 
			
		||||
        node.buildkit = value;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      case 'platforms': {
 | 
			
		||||
        let platforms: Array<string> = [];
 | 
			
		||||
        // if a preferred platform is being set then use only these
 | 
			
		||||
        // https://docs.docker.com/engine/reference/commandline/buildx_inspect/#get-information-about-a-builder-instance
 | 
			
		||||
        if (value.includes('*')) {
 | 
			
		||||
          for (const platform of value.split(', ')) {
 | 
			
		||||
            if (platform.includes('*')) {
 | 
			
		||||
              platforms.push(platform.replace('*', ''));
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        } else {
 | 
			
		||||
          // otherwise set all platforms available
 | 
			
		||||
          platforms = value.split(', ');
 | 
			
		||||
        }
 | 
			
		||||
        node.platforms = platforms.join(',');
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (Object.keys(node).length > 0) {
 | 
			
		||||
    builder.nodes.push(node);
 | 
			
		||||
  }
 | 
			
		||||
  return builder;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function getVersion(standalone?: boolean): Promise<string> {
 | 
			
		||||
  const cmd = getCommand(['version'], standalone);
 | 
			
		||||
  return await exec
 | 
			
		||||
 | 
			
		||||
@ -103,17 +103,17 @@ export async function getInputs(defaultContext: string): Promise<Inputs> {
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export async function getArgs(inputs: Inputs, defaultContext: string, buildxVersion: string): Promise<Array<string>> {
 | 
			
		||||
export async function getArgs(inputs: Inputs, defaultContext: string, buildxVersion: string, standalone?: boolean): Promise<Array<string>> {
 | 
			
		||||
  const context = handlebars.compile(inputs.context)({defaultContext});
 | 
			
		||||
  // prettier-ignore
 | 
			
		||||
  return [
 | 
			
		||||
    ...await getBuildArgs(inputs, defaultContext, context, buildxVersion),
 | 
			
		||||
    ...await getBuildArgs(inputs, defaultContext, context, buildxVersion, standalone),
 | 
			
		||||
    ...await getCommonArgs(inputs, buildxVersion),
 | 
			
		||||
    context
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getBuildArgs(inputs: Inputs, defaultContext: string, context: string, buildxVersion: string): Promise<Array<string>> {
 | 
			
		||||
async function getBuildArgs(inputs: Inputs, defaultContext: string, context: string, buildxVersion: string, standalone?: boolean): Promise<Array<string>> {
 | 
			
		||||
  const args: Array<string> = ['build'];
 | 
			
		||||
  await asyncForEach(inputs.addHosts, async addHost => {
 | 
			
		||||
    args.push('--add-host', addHost);
 | 
			
		||||
@ -164,10 +164,12 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, context: str
 | 
			
		||||
  if (buildx.satisfies(buildxVersion, '>=0.10.0')) {
 | 
			
		||||
    if (inputs.provenance) {
 | 
			
		||||
      args.push('--provenance', inputs.provenance);
 | 
			
		||||
    } else if (fromPayload('repository.private') !== false) {
 | 
			
		||||
      args.push('--provenance', `mode=min,inline-only=true`);
 | 
			
		||||
    } else {
 | 
			
		||||
      args.push('--provenance', `mode=max,builder-id=${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${github.context.repo.repo}/actions/runs/${github.context.runId}`);
 | 
			
		||||
    } else if (await buildx.satisfiesBuildKitVersion(inputs.builder, '>=0.11.0', standalone)) {
 | 
			
		||||
      if (fromPayload('repository.private') !== false) {
 | 
			
		||||
        args.push('--provenance', `mode=min,inline-only=true`);
 | 
			
		||||
      } else {
 | 
			
		||||
        args.push('--provenance', `mode=max,builder-id=${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${github.context.repo.repo}/actions/runs/${github.context.runId}`);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (inputs.sbom) {
 | 
			
		||||
      args.push('--sbom', inputs.sbom);
 | 
			
		||||
 | 
			
		||||
@ -41,7 +41,7 @@ async function run(): Promise<void> {
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const args: string[] = await context.getArgs(inputs, defContext, buildxVersion);
 | 
			
		||||
    const args: string[] = await context.getArgs(inputs, defContext, buildxVersion, standalone);
 | 
			
		||||
    const buildCmd = buildx.getCommand(args, standalone);
 | 
			
		||||
    await exec
 | 
			
		||||
      .getExecOutput(buildCmd.command, buildCmd.args, {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user