mirror of
				https://github.com/docker/build-push-action.git
				synced 2025-10-31 06:20:54 +00:00 
			
		
		
		
	plumb through the dockerfile path when creating a build_task
This commit is contained in:
		
					parent
					
						
							
								fca077e64d
							
						
					
				
			
			
				commit
				
					
						cb250fea79
					
				
			
		
					 4 changed files with 74 additions and 63 deletions
				
			
		
							
								
								
									
										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
											
										
									
								
							|  | @ -1,11 +1,11 @@ | ||||||
| import * as core from '@actions/core'; | import * as core from '@actions/core'; | ||||||
| import * as handlebars from 'handlebars'; | import * as handlebars from 'handlebars'; | ||||||
| 
 | 
 | ||||||
| import { Build } from '@docker/actions-toolkit/lib/buildx/build'; | import {Build} from '@docker/actions-toolkit/lib/buildx/build'; | ||||||
| import { Context } from '@docker/actions-toolkit/lib/context'; | import {Context} from '@docker/actions-toolkit/lib/context'; | ||||||
| import { GitHub } from '@docker/actions-toolkit/lib/github'; | import {GitHub} from '@docker/actions-toolkit/lib/github'; | ||||||
| import { Toolkit } from '@docker/actions-toolkit/lib/toolkit'; | import {Toolkit} from '@docker/actions-toolkit/lib/toolkit'; | ||||||
| import { Util } from '@docker/actions-toolkit/lib/util'; | import {Util} from '@docker/actions-toolkit/lib/util'; | ||||||
| 
 | 
 | ||||||
| export interface Inputs { | export interface Inputs { | ||||||
|   'add-hosts': string[]; |   'add-hosts': string[]; | ||||||
|  | @ -46,39 +46,52 @@ export async function getInputs(): Promise<Inputs> { | ||||||
|   return { |   return { | ||||||
|     'add-hosts': Util.getInputList('add-hosts'), |     'add-hosts': Util.getInputList('add-hosts'), | ||||||
|     allow: Util.getInputList('allow'), |     allow: Util.getInputList('allow'), | ||||||
|     annotations: Util.getInputList('annotations', { ignoreComma: true }), |     annotations: Util.getInputList('annotations', {ignoreComma: true}), | ||||||
|     attests: Util.getInputList('attests', { ignoreComma: true }), |     attests: Util.getInputList('attests', {ignoreComma: true}), | ||||||
|     'build-args': Util.getInputList('build-args', { ignoreComma: true }), |     'build-args': Util.getInputList('build-args', {ignoreComma: true}), | ||||||
|     'build-contexts': Util.getInputList('build-contexts', { ignoreComma: true }), |     'build-contexts': Util.getInputList('build-contexts', {ignoreComma: true}), | ||||||
|     builder: core.getInput('builder'), |     builder: core.getInput('builder'), | ||||||
|     'cache-from': Util.getInputList('cache-from', { ignoreComma: true }), |     'cache-from': Util.getInputList('cache-from', {ignoreComma: true}), | ||||||
|     'cache-to': Util.getInputList('cache-to', { ignoreComma: true }), |     'cache-to': Util.getInputList('cache-to', {ignoreComma: true}), | ||||||
|     'cgroup-parent': core.getInput('cgroup-parent'), |     'cgroup-parent': core.getInput('cgroup-parent'), | ||||||
|     context: core.getInput('context') || Context.gitContext(), |     context: core.getInput('context') || Context.gitContext(), | ||||||
|     file: core.getInput('file'), |     file: core.getInput('file'), | ||||||
|     labels: Util.getInputList('labels', { ignoreComma: true }), |     labels: Util.getInputList('labels', {ignoreComma: true}), | ||||||
|     load: core.getBooleanInput('load'), |     load: core.getBooleanInput('load'), | ||||||
|     network: core.getInput('network'), |     network: core.getInput('network'), | ||||||
|     'no-cache': core.getBooleanInput('no-cache'), |     'no-cache': core.getBooleanInput('no-cache'), | ||||||
|     'no-cache-filters': Util.getInputList('no-cache-filters'), |     'no-cache-filters': Util.getInputList('no-cache-filters'), | ||||||
|     outputs: Util.getInputList('outputs', { ignoreComma: true, quote: false }), |     outputs: Util.getInputList('outputs', {ignoreComma: true, quote: false}), | ||||||
|     platforms: Util.getInputList('platforms'), |     platforms: Util.getInputList('platforms'), | ||||||
|     provenance: Build.getProvenanceInput('provenance'), |     provenance: Build.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'), | ||||||
|     secrets: Util.getInputList('secrets', { ignoreComma: true }), |     secrets: Util.getInputList('secrets', {ignoreComma: true}), | ||||||
|     'secret-envs': Util.getInputList('secret-envs'), |     'secret-envs': Util.getInputList('secret-envs'), | ||||||
|     'secret-files': Util.getInputList('secret-files', { ignoreComma: true }), |     'secret-files': Util.getInputList('secret-files', {ignoreComma: true}), | ||||||
|     'shm-size': core.getInput('shm-size'), |     'shm-size': core.getInput('shm-size'), | ||||||
|     ssh: Util.getInputList('ssh'), |     ssh: Util.getInputList('ssh'), | ||||||
|     tags: Util.getInputList('tags'), |     tags: Util.getInputList('tags'), | ||||||
|     target: core.getInput('target'), |     target: core.getInput('target'), | ||||||
|     ulimit: Util.getInputList('ulimit', { ignoreComma: true }), |     ulimit: Util.getInputList('ulimit', {ignoreComma: true}), | ||||||
|     'github-token': core.getInput('github-token') |     'github-token': core.getInput('github-token') | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // getDockerfilePath resolves the path to the build entity. This is basically
 | ||||||
|  | // {context}/{file} or {context}/{dockerfile} depending on the inputs.
 | ||||||
|  | export function getDockerfilePath(inputs: Inputs): string { | ||||||
|  |   const context = inputs.context || Context.gitContext(); | ||||||
|  |   if (inputs.file) { | ||||||
|  |     return context + '/' + inputs.file; | ||||||
|  |   } else if (inputs['dockerfile']) { | ||||||
|  |     return context + '/' + inputs['dockerfile']; | ||||||
|  |   } else { | ||||||
|  |     return context; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export function sanitizeInputs(inputs: Inputs) { | export function sanitizeInputs(inputs: Inputs) { | ||||||
|   const res = {}; |   const res = {}; | ||||||
|   for (const key of Object.keys(inputs)) { |   for (const key of Object.keys(inputs)) { | ||||||
|  | @ -284,12 +297,12 @@ async function getAttestArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<st | ||||||
|   return args; |   return args; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getRemoteBuilderArgs(name: string, inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> { | export async function getRemoteBuilderArgs(name: string, builderUrl: string): Promise<Array<string>> { | ||||||
|   const args: Array<string> = ['create', '--name', name, '--driver', 'remote']; |   const args: Array<string> = ['create', '--name', name, '--driver', 'remote']; | ||||||
|   if (inputs.platforms.length > 0) { |   args.push('--platform', 'linux/amd64'); | ||||||
|     args.push('--platform', inputs.platforms.join(',')); |  | ||||||
|   } |  | ||||||
|   // Always use the remote builder, overriding whatever has been configured so far.
 |   // Always use the remote builder, overriding whatever has been configured so far.
 | ||||||
|   args.push('--use'); |   args.push('--use'); | ||||||
|  |   // Use the provided builder URL
 | ||||||
|  |   args.push(builderUrl); | ||||||
|   return args; |   return args; | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										78
									
								
								src/main.ts
									
										
									
									
									
								
							
							
						
						
									
										78
									
								
								src/main.ts
									
										
									
									
									
								
							|  | @ -4,23 +4,23 @@ import * as stateHelper from './state-helper'; | ||||||
| import * as core from '@actions/core'; | import * as core from '@actions/core'; | ||||||
| import * as actionsToolkit from '@docker/actions-toolkit'; | import * as actionsToolkit from '@docker/actions-toolkit'; | ||||||
| 
 | 
 | ||||||
| import { Buildx } from '@docker/actions-toolkit/lib/buildx/buildx'; | import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx'; | ||||||
| import { History as BuildxHistory } from '@docker/actions-toolkit/lib/buildx/history'; | import {History as BuildxHistory} from '@docker/actions-toolkit/lib/buildx/history'; | ||||||
| import { Context } from '@docker/actions-toolkit/lib/context'; | import {Context} from '@docker/actions-toolkit/lib/context'; | ||||||
| import { Docker } from '@docker/actions-toolkit/lib/docker/docker'; | import {Docker} from '@docker/actions-toolkit/lib/docker/docker'; | ||||||
| import { Exec } from '@docker/actions-toolkit/lib/exec'; | import {Exec} from '@docker/actions-toolkit/lib/exec'; | ||||||
| import { GitHub } from '@docker/actions-toolkit/lib/github'; | import {GitHub} from '@docker/actions-toolkit/lib/github'; | ||||||
| import { Toolkit } from '@docker/actions-toolkit/lib/toolkit'; | import {Toolkit} from '@docker/actions-toolkit/lib/toolkit'; | ||||||
| import { Util } from '@docker/actions-toolkit/lib/util'; | import {Util} from '@docker/actions-toolkit/lib/util'; | ||||||
| 
 | 
 | ||||||
| import { BuilderInfo } from '@docker/actions-toolkit/lib/types/buildx/builder'; | import {BuilderInfo} from '@docker/actions-toolkit/lib/types/buildx/builder'; | ||||||
| import { ConfigFile } from '@docker/actions-toolkit/lib/types/docker/docker'; | import {ConfigFile} from '@docker/actions-toolkit/lib/types/docker/docker'; | ||||||
| import { UploadArtifactResponse } from '@docker/actions-toolkit/lib/types/github'; | import {UploadArtifactResponse} from '@docker/actions-toolkit/lib/types/github'; | ||||||
| import axios, { AxiosInstance } from 'axios'; | import axios, {AxiosInstance} from 'axios'; | ||||||
| 
 | 
 | ||||||
| import * as context from './context'; | import * as context from './context'; | ||||||
| 
 | 
 | ||||||
| const buildxVersion = "v0.17.0" | const buildxVersion = 'v0.17.0'; | ||||||
| 
 | 
 | ||||||
| async function getBlacksmithHttpClient(): Promise<AxiosInstance> { | async function getBlacksmithHttpClient(): Promise<AxiosInstance> { | ||||||
|   return axios.create({ |   return axios.create({ | ||||||
|  | @ -45,8 +45,7 @@ async function reportBuildCompleted() { | ||||||
| async function reportBuildFailed() { | async function reportBuildFailed() { | ||||||
|   try { |   try { | ||||||
|     const client = await getBlacksmithHttpClient(); |     const client = await getBlacksmithHttpClient(); | ||||||
|     // TODO(adityamaru): This endpoint doesn't exist yet.
 |     const response = await client.post(`/${stateHelper.blacksmithBuildTaskId}/fail`); | ||||||
|     const response = await client.post(`/${stateHelper.blacksmithBuildTaskId}/failed`); |  | ||||||
|     core.info(`Docker build failed, tearing down Blacksmith builder for ${stateHelper.blacksmithBuildTaskId}: ${JSON.stringify(response.data)}`); |     core.info(`Docker build failed, tearing down Blacksmith builder for ${stateHelper.blacksmithBuildTaskId}: ${JSON.stringify(response.data)}`); | ||||||
|   } catch (error) { |   } catch (error) { | ||||||
|     core.warning('Error completing Blacksmith build:', error); |     core.warning('Error completing Blacksmith build:', error); | ||||||
|  | @ -56,12 +55,19 @@ async function reportBuildFailed() { | ||||||
| 
 | 
 | ||||||
| // getRemoteBuilderAddr resolves the address to a remote Docker builder.
 | // getRemoteBuilderAddr resolves the address to a remote Docker builder.
 | ||||||
| // If it is unable to do so because of a timeout or an error it returns null.
 | // If it is unable to do so because of a timeout or an error it returns null.
 | ||||||
| async function getRemoteBuilderAddr(): Promise<string | null> { | async function getRemoteBuilderAddr(inputs: context.Inputs): Promise<string | null> { | ||||||
|   const controller = new AbortController(); |   const controller = new AbortController(); | ||||||
|   const timeoutId = setTimeout(() => controller.abort(), 30000); |   const timeoutId = setTimeout(() => controller.abort(), 30000); | ||||||
|   try { |   try { | ||||||
|     const client = await getBlacksmithHttpClient(); |     const client = await getBlacksmithHttpClient(); | ||||||
|     const response = await client.post(''); |     const dockerfilePath = context.getDockerfilePath(inputs); | ||||||
|  |     let payload = {}; | ||||||
|  |     if (dockerfilePath && dockerfilePath.length > 0) { | ||||||
|  |       payload = {dockerfile_path: dockerfilePath}; | ||||||
|  |       core.info(`Using dockerfile path: ${dockerfilePath}`); | ||||||
|  |     } | ||||||
|  |     core.info(`Waiting for Blacksmith builder agent to be ready...`); | ||||||
|  |     const response = await client.post('', payload); | ||||||
| 
 | 
 | ||||||
|     const data = response.data; |     const data = response.data; | ||||||
|     const taskId = data['id'] as string; |     const taskId = data['id'] as string; | ||||||
|  | @ -77,11 +83,10 @@ async function getRemoteBuilderAddr(): Promise<string | null> { | ||||||
|     while (Date.now() - startTime < 60000) { |     while (Date.now() - startTime < 60000) { | ||||||
|       const response = await client.get(`/${taskId}`); |       const response = await client.get(`/${taskId}`); | ||||||
|       const data = response.data; |       const data = response.data; | ||||||
|       core.info(`Got response from Blacksmith builder ${taskId}: ${JSON.stringify(data, null, 2)}`); |  | ||||||
|       const ec2Instance = data['ec2_instance'] ?? null; |       const ec2Instance = data['ec2_instance'] ?? null; | ||||||
|       if (ec2Instance) { |       if (ec2Instance) { | ||||||
|         const elapsedTime = Date.now() - startTime; |         const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(2); | ||||||
|         core.info(`Got EC2 instance IP after ${elapsedTime} ms`); |         core.info(`Blacksmith builder agent ready after ${elapsedTime} seconds`); | ||||||
|         return `tcp://${ec2Instance['instance_ip']}:4242` as string; |         return `tcp://${ec2Instance['instance_ip']}:4242` as string; | ||||||
|       } |       } | ||||||
|       await new Promise(resolve => setTimeout(resolve, 200)); |       await new Promise(resolve => setTimeout(resolve, 200)); | ||||||
|  | @ -122,13 +127,11 @@ async function setupBuildx(version: string, toolkit: Toolkit): Promise<void> { | ||||||
|   }); |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| actionsToolkit.run( | actionsToolkit.run( | ||||||
|   // main
 |   // main
 | ||||||
|   async () => { |   async () => { | ||||||
|     const startedTime = new Date(); |     const startedTime = new Date(); | ||||||
|     const inputs: context.Inputs = await context.getInputs(); |     const inputs: context.Inputs = await context.getInputs(); | ||||||
|     core.debug(`inputs: ${JSON.stringify(inputs)}`); |  | ||||||
|     stateHelper.setInputs(inputs); |     stateHelper.setInputs(inputs); | ||||||
| 
 | 
 | ||||||
|     const toolkit = new Toolkit(); |     const toolkit = new Toolkit(); | ||||||
|  | @ -159,23 +162,18 @@ actionsToolkit.run( | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     let remoteBuilderAddr: string | null = null; |     let remoteBuilderAddr: string | null = null; | ||||||
|     await core.group(`Starting Blacksmith remote builder`, async () => { |     await core.group(`Starting Blacksmith remote builder`, async () => { | ||||||
|       // TODO(adityamaru): Plumb the dockerfile path as the entity name.
 |       remoteBuilderAddr = await getRemoteBuilderAddr(inputs); | ||||||
|       remoteBuilderAddr = await getRemoteBuilderAddr(); |       if (!remoteBuilderAddr) { | ||||||
|       if (remoteBuilderAddr) { |  | ||||||
|         core.info(`Successfully obtained Blacksmith remote builder address: ${remoteBuilderAddr}`); |  | ||||||
|       } else { |  | ||||||
|         core.warning('Failed to obtain Blacksmith remote builder address. Falling back to a local build.'); |         core.warning('Failed to obtain Blacksmith remote builder address. Falling back to a local build.'); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     if (remoteBuilderAddr) { |     if (remoteBuilderAddr) { | ||||||
|       await core.group(`Creating a remote builder instance`, async () => { |       await core.group(`Creating a remote builder instance`, async () => { | ||||||
|         // TODO(during review): do we want this to be something useful?
 |         const name = `blacksmith`; | ||||||
|         const name = `test-name` |         const createCmd = await toolkit.buildx.getCommand(await context.getRemoteBuilderArgs(name, remoteBuilderAddr!)); | ||||||
|         const createCmd = await toolkit.buildx.getCommand(await context.getRemoteBuilderArgs(name, inputs, toolkit)); |  | ||||||
|         core.info(`Creating builder with command: ${createCmd.command}`); |         core.info(`Creating builder with command: ${createCmd.command}`); | ||||||
|         await Exec.getExecOutput(createCmd.command, createCmd.args, { |         await Exec.getExecOutput(createCmd.command, createCmd.args, { | ||||||
|           ignoreReturnCode: true |           ignoreReturnCode: true | ||||||
|  | @ -194,7 +192,7 @@ actionsToolkit.run( | ||||||
|             core.debug(`Found configured builder: ${builder.name}`); |             core.debug(`Found configured builder: ${builder.name}`); | ||||||
|           } else { |           } else { | ||||||
|             // TODO(adityamaru): Setup a "default" builder that will build locally.
 |             // TODO(adityamaru): Setup a "default" builder that will build locally.
 | ||||||
|             core.setFailed("No builder found. Please configure a builder before running this action."); |             core.setFailed('No builder found. Please configure a builder before running this action.'); | ||||||
|           } |           } | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|           core.setFailed(`Error configuring builder: ${error.message}`); |           core.setFailed(`Error configuring builder: ${error.message}`); | ||||||
|  | @ -334,13 +332,6 @@ actionsToolkit.run( | ||||||
|   }, |   }, | ||||||
|   // post
 |   // post
 | ||||||
|   async () => { |   async () => { | ||||||
|     if (stateHelper.remoteDockerBuildStatus != '') { |  | ||||||
|       if (stateHelper.remoteDockerBuildStatus == 'success') { |  | ||||||
|         await reportBuildCompleted(); |  | ||||||
|       } else { |  | ||||||
|         await reportBuildFailed(); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|     if (stateHelper.isSummarySupported) { |     if (stateHelper.isSummarySupported) { | ||||||
|       await core.group(`Generating build summary`, async () => { |       await core.group(`Generating build summary`, async () => { | ||||||
|         try { |         try { | ||||||
|  | @ -375,9 +366,16 @@ actionsToolkit.run( | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|  |     if (stateHelper.remoteDockerBuildStatus != '') { | ||||||
|  |       if (stateHelper.remoteDockerBuildStatus == 'success') { | ||||||
|  |         await reportBuildCompleted(); | ||||||
|  |       } else { | ||||||
|  |         await reportBuildFailed(); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|     if (stateHelper.tmpDir.length > 0) { |     if (stateHelper.tmpDir.length > 0) { | ||||||
|       await core.group(`Removing temp folder ${stateHelper.tmpDir}`, async () => { |       await core.group(`Removing temp folder ${stateHelper.tmpDir}`, async () => { | ||||||
|         fs.rmSync(stateHelper.tmpDir, { recursive: true }); |         fs.rmSync(stateHelper.tmpDir, {recursive: true}); | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue