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