mirror of
				https://gitea.com/docker/build-push-action.git
				synced 2025-10-31 09:08:18 +07:00 
			
		
		
		
	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-from: type=gha,scope=nocachefilter | ||||||
|           cache-to: type=gha,scope=nocachefilter,mode=max |           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 |     runs-on: ubuntu-latest | ||||||
|     strategy: |     strategy: | ||||||
|       fail-fast: false |       fail-fast: false | ||||||
| @ -506,9 +538,6 @@ jobs: | |||||||
|         image: registry:2 |         image: registry:2 | ||||||
|         ports: |         ports: | ||||||
|           - 5000:5000 |           - 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: |     steps: | ||||||
|       - |       - | ||||||
|         name: Checkout |         name: Checkout | ||||||
|  | |||||||
							
								
								
									
										123
									
								
								src/buildx.ts
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								src/buildx.ts
									
									
									
									
									
								
							| @ -3,9 +3,24 @@ import fs from 'fs'; | |||||||
| import path from 'path'; | import path from 'path'; | ||||||
| import * as semver from 'semver'; | import * as semver from 'semver'; | ||||||
| import * as exec from '@actions/exec'; | import * as exec from '@actions/exec'; | ||||||
| 
 |  | ||||||
| import * as context from './context'; | 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> { | export async function getImageIDFile(): Promise<string> { | ||||||
|   return path.join(context.tmpDir(), 'iidfile').split(path.sep).join(path.posix.sep); |   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> { | export async function getVersion(standalone?: boolean): Promise<string> { | ||||||
|   const cmd = getCommand(['version'], standalone); |   const cmd = getCommand(['version'], standalone); | ||||||
|   return await exec |   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}); |   const context = handlebars.compile(inputs.context)({defaultContext}); | ||||||
|   // prettier-ignore
 |   // prettier-ignore
 | ||||||
|   return [ |   return [ | ||||||
|     ...await getBuildArgs(inputs, defaultContext, context, buildxVersion), |     ...await getBuildArgs(inputs, defaultContext, context, buildxVersion, standalone), | ||||||
|     ...await getCommonArgs(inputs, buildxVersion), |     ...await getCommonArgs(inputs, buildxVersion), | ||||||
|     context |     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']; |   const args: Array<string> = ['build']; | ||||||
|   await asyncForEach(inputs.addHosts, async addHost => { |   await asyncForEach(inputs.addHosts, async addHost => { | ||||||
|     args.push('--add-host', addHost); |     args.push('--add-host', addHost); | ||||||
| @ -164,11 +164,13 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, context: str | |||||||
|   if (buildx.satisfies(buildxVersion, '>=0.10.0')) { |   if (buildx.satisfies(buildxVersion, '>=0.10.0')) { | ||||||
|     if (inputs.provenance) { |     if (inputs.provenance) { | ||||||
|       args.push('--provenance', inputs.provenance); |       args.push('--provenance', inputs.provenance); | ||||||
|     } else if (fromPayload('repository.private') !== false) { |     } else if (await buildx.satisfiesBuildKitVersion(inputs.builder, '>=0.11.0', standalone)) { | ||||||
|  |       if (fromPayload('repository.private') !== false) { | ||||||
|         args.push('--provenance', `mode=min,inline-only=true`); |         args.push('--provenance', `mode=min,inline-only=true`); | ||||||
|       } else { |       } 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}`); |         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) { |     if (inputs.sbom) { | ||||||
|       args.push('--sbom', 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); |     const buildCmd = buildx.getCommand(args, standalone); | ||||||
|     await exec |     await exec | ||||||
|       .getExecOutput(buildCmd.command, buildCmd.args, { |       .getExecOutput(buildCmd.command, buildCmd.args, { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user