mirror of
				https://github.com/docker/setup-buildx-action.git
				synced 2025-10-31 01:20:09 +08:00 
			
		
		
		
	support standalone mode and display version
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									2a6fbda6d8
								
							
						
					
					
						commit
						3472856dd9
					
				
							
								
								
									
										34
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								README.md
									
									
									
									
									
								
							| @ -24,6 +24,7 @@ ___ | |||||||
|   * [BuildKit daemon configuration](#buildkit-daemon-configuration) |   * [BuildKit daemon configuration](#buildkit-daemon-configuration) | ||||||
|     * [Registry mirror](#registry-mirror) |     * [Registry mirror](#registry-mirror) | ||||||
|     * [Max parallelism](#max-parallelism) |     * [Max parallelism](#max-parallelism) | ||||||
|  |   * [Standalone mode](#standalone-mode) | ||||||
| * [Customizing](#customizing) | * [Customizing](#customizing) | ||||||
|   * [inputs](#inputs) |   * [inputs](#inputs) | ||||||
|   * [outputs](#outputs) |   * [outputs](#outputs) | ||||||
| @ -180,6 +181,33 @@ jobs: | |||||||
|           config: .github/buildkitd.toml |           config: .github/buildkitd.toml | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | ### Standalone mode | ||||||
|  | 
 | ||||||
|  | If you don't have the Docker CLI installed on the GitHub Runner, buildx binary | ||||||
|  | is invoked directly, instead of calling it as a docker plugin. This can be | ||||||
|  | useful if you want to use the `kubernetes` driver in your self-hosted runner: | ||||||
|  | 
 | ||||||
|  | ```yaml | ||||||
|  | name: ci | ||||||
|  | 
 | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   buildx: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - | ||||||
|  |         name: Set up Docker Buildx | ||||||
|  |         uses: docker/setup-buildx-action@v1 | ||||||
|  |         with: | ||||||
|  |           driver: kubernetes | ||||||
|  |       - | ||||||
|  |         name: Build | ||||||
|  |         run: | | ||||||
|  |           buildx build . | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ## Customizing | ## Customizing | ||||||
| 
 | 
 | ||||||
| ### inputs | ### inputs | ||||||
| @ -195,10 +223,10 @@ Following inputs can be used as `step.with` keys | |||||||
| | `install`          | Bool    | Sets up `docker build` command as an alias to `docker buildx` (default `false`) | | | `install`          | Bool    | Sets up `docker build` command as an alias to `docker buildx` (default `false`) | | ||||||
| | `use`              | Bool    | Switch to this builder instance (default `true`) | | | `use`              | Bool    | Switch to this builder instance (default `true`) | | ||||||
| | `endpoint`         | String  | [Optional address for docker socket](https://github.com/docker/buildx/blob/master/docs/reference/buildx_create.md#description) or context from `docker context ls` | | | `endpoint`         | String  | [Optional address for docker socket](https://github.com/docker/buildx/blob/master/docs/reference/buildx_create.md#description) or context from `docker context ls` | | ||||||
| | `config`           | String  | [BuildKit config file](https://github.com/docker/buildx/blob/master/docs/reference/buildx_create.md#config) | | | `config`¹          | String  | [BuildKit config file](https://github.com/docker/buildx/blob/master/docs/reference/buildx_create.md#config) | | ||||||
| | `config-inline`    | String  | Same as `config` but inline | | | `config-inline`¹   | String  | Same as `config` but inline | | ||||||
| 
 | 
 | ||||||
| > `config` and `config-inline` are mutually exclusive. | > * ¹ `config` and `config-inline` are mutually exclusive | ||||||
| 
 | 
 | ||||||
| > `CSV` type must be a newline-delimited string | > `CSV` type must be a newline-delimited string | ||||||
| > ```yaml | > ```yaml | ||||||
|  | |||||||
| @ -32,6 +32,17 @@ describe('isAvailable', () => { | |||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | describe('isAvailable standalone', () => { | ||||||
|  |   const execSpy = jest.spyOn(exec, 'getExecOutput'); | ||||||
|  |   buildx.isAvailable(true); | ||||||
|  | 
 | ||||||
|  |   // eslint-disable-next-line jest/no-standalone-expect
 | ||||||
|  |   expect(execSpy).toHaveBeenCalledWith(`buildx`, [], { | ||||||
|  |     silent: true, | ||||||
|  |     ignoreReturnCode: true | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| describe('getVersion', () => { | describe('getVersion', () => { | ||||||
|   it('valid', async () => { |   it('valid', async () => { | ||||||
|     const version = await buildx.getVersion(); |     const version = await buildx.getVersion(); | ||||||
| @ -75,29 +86,32 @@ describe('build', () => { | |||||||
| 
 | 
 | ||||||
|   // eslint-disable-next-line jest/no-disabled-tests
 |   // eslint-disable-next-line jest/no-disabled-tests
 | ||||||
|   it.skip('builds refs/pull/648/head', async () => { |   it.skip('builds refs/pull/648/head', async () => { | ||||||
|     const buildxBin = await buildx.build('https://github.com/docker/buildx.git#refs/pull/648/head', tmpDir); |     const buildxBin = await buildx.build('https://github.com/docker/buildx.git#refs/pull/648/head', tmpDir, false); | ||||||
|     expect(fs.existsSync(buildxBin)).toBe(true); |     expect(fs.existsSync(buildxBin)).toBe(true); | ||||||
|   }, 100000); |   }, 100000); | ||||||
| 
 | 
 | ||||||
|   // eslint-disable-next-line jest/no-disabled-tests
 |   // eslint-disable-next-line jest/no-disabled-tests
 | ||||||
|   it.skip('builds 67bd6f4dc82a9cd96f34133dab3f6f7af803bb14', async () => { |   it.skip('builds 67bd6f4dc82a9cd96f34133dab3f6f7af803bb14', async () => { | ||||||
|     const buildxBin = await buildx.build('https://github.com/docker/buildx.git#67bd6f4dc82a9cd96f34133dab3f6f7af803bb14', tmpDir); |     const buildxBin = await buildx.build('https://github.com/docker/buildx.git#67bd6f4dc82a9cd96f34133dab3f6f7af803bb14', tmpDir, false); | ||||||
|     expect(fs.existsSync(buildxBin)).toBe(true); |     expect(fs.existsSync(buildxBin)).toBe(true); | ||||||
|   }, 100000); |   }, 100000); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| describe('install', () => { | describe('install', () => { | ||||||
|   const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-buildx-')); |   const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-buildx-')); | ||||||
| 
 |   test.each([ | ||||||
|   it('acquires v0.4.1 version of buildx', async () => { |     ['v0.4.1', false], | ||||||
|     const buildxBin = await buildx.install('v0.4.1', tmpDir); |     ['latest', false], | ||||||
|  |     ['v0.4.1', true], | ||||||
|  |     ['latest', true] | ||||||
|  |   ])( | ||||||
|  |     'acquires %p of buildx (standalone: %p)', | ||||||
|  |     async (version, standalone) => { | ||||||
|  |       const buildxBin = await buildx.install(version, tmpDir, standalone); | ||||||
|       expect(fs.existsSync(buildxBin)).toBe(true); |       expect(fs.existsSync(buildxBin)).toBe(true); | ||||||
|   }, 100000); |     }, | ||||||
| 
 |     100000 | ||||||
|   it('acquires latest version of buildx', async () => { |   ); | ||||||
|     const buildxBin = await buildx.install('latest', tmpDir); |  | ||||||
|     expect(fs.existsSync(buildxBin)).toBe(true); |  | ||||||
|   }, 100000); |  | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| describe('getConfig', () => { | describe('getConfig', () => { | ||||||
|  | |||||||
							
								
								
									
										16
									
								
								__tests__/docker.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								__tests__/docker.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | import {describe, expect, it, jest} from '@jest/globals'; | ||||||
|  | import * as docker from '../src/docker'; | ||||||
|  | import * as exec from '@actions/exec'; | ||||||
|  | 
 | ||||||
|  | describe('isAvailable', () => { | ||||||
|  |   it('cli', () => { | ||||||
|  |     const execSpy = jest.spyOn(exec, 'getExecOutput'); | ||||||
|  |     docker.isAvailable(); | ||||||
|  | 
 | ||||||
|  |     // eslint-disable-next-line jest/no-standalone-expect
 | ||||||
|  |     expect(execSpy).toHaveBeenCalledWith(`docker`, undefined, { | ||||||
|  |       silent: true, | ||||||
|  |       ignoreReturnCode: true | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
							
								
								
									
										4
									
								
								dist/index.js
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								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
											
										
									
								
							| @ -41,9 +41,10 @@ export async function getConfig(s: string, file: boolean): Promise<string> { | |||||||
|   return configFile; |   return configFile; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function isAvailable(): Promise<boolean> { | export async function isAvailable(standalone?: boolean): Promise<boolean> { | ||||||
|  |   const cmd = getCommand([], standalone); | ||||||
|   return await exec |   return await exec | ||||||
|     .getExecOutput('docker', ['buildx'], { |     .getExecOutput(cmd.commandLine, cmd.args, { | ||||||
|       ignoreReturnCode: true, |       ignoreReturnCode: true, | ||||||
|       silent: true |       silent: true | ||||||
|     }) |     }) | ||||||
| @ -52,12 +53,17 @@ export async function isAvailable(): Promise<boolean> { | |||||||
|         return false; |         return false; | ||||||
|       } |       } | ||||||
|       return res.exitCode == 0; |       return res.exitCode == 0; | ||||||
|  |     }) | ||||||
|  |     // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | ||||||
|  |     .catch(error => { | ||||||
|  |       return false; | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function getVersion(): Promise<string> { | export async function getVersion(standalone?: boolean): Promise<string> { | ||||||
|  |   const cmd = getCommand(['version'], standalone); | ||||||
|   return await exec |   return await exec | ||||||
|     .getExecOutput('docker', ['buildx', 'version'], { |     .getExecOutput(cmd.commandLine, cmd.args, { | ||||||
|       ignoreReturnCode: true, |       ignoreReturnCode: true, | ||||||
|       silent: true |       silent: true | ||||||
|     }) |     }) | ||||||
| @ -81,9 +87,10 @@ export function satisfies(version: string, range: string): boolean { | |||||||
|   return semver.satisfies(version, range) || /^[0-9a-f]{7}$/.exec(version) !== null; |   return semver.satisfies(version, range) || /^[0-9a-f]{7}$/.exec(version) !== null; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function inspect(name: string): Promise<Builder> { | export async function inspect(name: string, standalone?: boolean): Promise<Builder> { | ||||||
|  |   const cmd = getCommand(['inspect', name], standalone); | ||||||
|   return await exec |   return await exec | ||||||
|     .getExecOutput(`docker`, ['buildx', 'inspect', name], { |     .getExecOutput(cmd.commandLine, cmd.args, { | ||||||
|       ignoreReturnCode: true, |       ignoreReturnCode: true, | ||||||
|       silent: true |       silent: true | ||||||
|     }) |     }) | ||||||
| @ -133,7 +140,7 @@ export async function inspect(name: string): Promise<Builder> { | |||||||
|     }); |     }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function build(inputBuildRef: string, dockerConfigHome: string): Promise<string> { | export async function build(inputBuildRef: string, dest: string, standalone: boolean): Promise<string> { | ||||||
|   // eslint-disable-next-line prefer-const
 |   // eslint-disable-next-line prefer-const
 | ||||||
|   let [repo, ref] = inputBuildRef.split('#'); |   let [repo, ref] = inputBuildRef.split('#'); | ||||||
|   if (ref.length == 0) { |   if (ref.length == 0) { | ||||||
| @ -152,8 +159,27 @@ export async function build(inputBuildRef: string, dockerConfigHome: string): Pr | |||||||
|   toolPath = tc.find('buildx', vspec); |   toolPath = tc.find('buildx', vspec); | ||||||
|   if (!toolPath) { |   if (!toolPath) { | ||||||
|     const outFolder = path.join(context.tmpDir(), 'out').split(path.sep).join(path.posix.sep); |     const outFolder = path.join(context.tmpDir(), 'out').split(path.sep).join(path.posix.sep); | ||||||
|  |     let buildWithStandalone = false; | ||||||
|  |     const standaloneFound = await isAvailable(true); | ||||||
|  |     const pluginFound = await isAvailable(false); | ||||||
|  |     if (standalone && standaloneFound) { | ||||||
|  |       core.debug(`Buildx standalone found, build with it`); | ||||||
|  |       buildWithStandalone = true; | ||||||
|  |     } else if (!standalone && pluginFound) { | ||||||
|  |       core.debug(`Buildx plugin found, build with it`); | ||||||
|  |       buildWithStandalone = false; | ||||||
|  |     } else if (standaloneFound) { | ||||||
|  |       core.debug(`Buildx plugin not found, but standalone found so trying to build with it`); | ||||||
|  |       buildWithStandalone = true; | ||||||
|  |     } else if (pluginFound) { | ||||||
|  |       core.debug(`Buildx standalone not found, but plugin found so trying to build with it`); | ||||||
|  |       buildWithStandalone = false; | ||||||
|  |     } else { | ||||||
|  |       throw new Error(`Neither buildx standalone or plugin have been found to build from ref`); | ||||||
|  |     } | ||||||
|  |     const buildCmd = getCommand(['build', '--target', 'binaries', '--build-arg', 'BUILDKIT_CONTEXT_KEEP_GIT_DIR=1', '--output', `type=local,dest=${outFolder}`, inputBuildRef], buildWithStandalone); | ||||||
|     toolPath = await exec |     toolPath = await exec | ||||||
|       .getExecOutput('docker', ['buildx', 'build', '--target', 'binaries', '--build-arg', 'BUILDKIT_CONTEXT_KEEP_GIT_DIR=1', '--output', `type=local,dest=${outFolder}`, inputBuildRef], { |       .getExecOutput(buildCmd.commandLine, buildCmd.args, { | ||||||
|         ignoreReturnCode: true |         ignoreReturnCode: true | ||||||
|       }) |       }) | ||||||
|       .then(res => { |       .then(res => { | ||||||
| @ -164,10 +190,13 @@ export async function build(inputBuildRef: string, dockerConfigHome: string): Pr | |||||||
|       }); |       }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return setPlugin(toolPath, dockerConfigHome); |   if (standalone) { | ||||||
|  |     return setStandalone(toolPath, dest); | ||||||
|  |   } | ||||||
|  |   return setPlugin(toolPath, dest); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function install(inputVersion: string, dockerConfigHome: string): Promise<string> { | export async function install(inputVersion: string, dest: string, standalone: boolean): Promise<string> { | ||||||
|   const release: github.GitHubRelease | null = await github.getRelease(inputVersion); |   const release: github.GitHubRelease | null = await github.getRelease(inputVersion); | ||||||
|   if (!release) { |   if (!release) { | ||||||
|     throw new Error(`Cannot find buildx ${inputVersion} release`); |     throw new Error(`Cannot find buildx ${inputVersion} release`); | ||||||
| @ -185,10 +214,40 @@ export async function install(inputVersion: string, dockerConfigHome: string): P | |||||||
|     toolPath = await download(version); |     toolPath = await download(version); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return setPlugin(toolPath, dockerConfigHome); |   if (standalone) { | ||||||
|  |     return setStandalone(toolPath, dest); | ||||||
|  |   } | ||||||
|  |   return setPlugin(toolPath, dest); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | async function setStandalone(toolPath: string, dest: string): Promise<string> { | ||||||
|  |   core.info('Standalone mode'); | ||||||
|  |   const toolBinPath = path.join(toolPath, context.osPlat == 'win32' ? 'docker-buildx.exe' : 'docker-buildx'); | ||||||
|  | 
 | ||||||
|  |   const binDir = path.join(dest, 'bin'); | ||||||
|  |   core.debug(`Bin dir is ${binDir}`); | ||||||
|  |   if (!fs.existsSync(binDir)) { | ||||||
|  |     fs.mkdirSync(binDir, {recursive: true}); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const filename: string = context.osPlat == 'win32' ? 'buildx.exe' : 'buildx'; | ||||||
|  |   const buildxPath: string = path.join(binDir, filename); | ||||||
|  |   core.debug(`Bin path is ${buildxPath}`); | ||||||
|  |   fs.copyFileSync(toolBinPath, buildxPath); | ||||||
|  | 
 | ||||||
|  |   core.info('Fixing perms'); | ||||||
|  |   fs.chmodSync(buildxPath, '0755'); | ||||||
|  | 
 | ||||||
|  |   core.addPath(binDir); | ||||||
|  |   core.info('Added buildx to the path'); | ||||||
|  | 
 | ||||||
|  |   return buildxPath; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function setPlugin(toolPath: string, dockerConfigHome: string): Promise<string> { | async function setPlugin(toolPath: string, dockerConfigHome: string): Promise<string> { | ||||||
|  |   core.info('Docker plugin mode'); | ||||||
|  |   const toolBinPath = path.join(toolPath, context.osPlat == 'win32' ? 'docker-buildx.exe' : 'docker-buildx'); | ||||||
|  | 
 | ||||||
|   const pluginsDir: string = path.join(dockerConfigHome, 'cli-plugins'); |   const pluginsDir: string = path.join(dockerConfigHome, 'cli-plugins'); | ||||||
|   core.debug(`Plugins dir is ${pluginsDir}`); |   core.debug(`Plugins dir is ${pluginsDir}`); | ||||||
|   if (!fs.existsSync(pluginsDir)) { |   if (!fs.existsSync(pluginsDir)) { | ||||||
| @ -198,7 +257,7 @@ async function setPlugin(toolPath: string, dockerConfigHome: string): Promise<st | |||||||
|   const filename: string = context.osPlat == 'win32' ? 'docker-buildx.exe' : 'docker-buildx'; |   const filename: string = context.osPlat == 'win32' ? 'docker-buildx.exe' : 'docker-buildx'; | ||||||
|   const pluginPath: string = path.join(pluginsDir, filename); |   const pluginPath: string = path.join(pluginsDir, filename); | ||||||
|   core.debug(`Plugin path is ${pluginPath}`); |   core.debug(`Plugin path is ${pluginPath}`); | ||||||
|   fs.copyFileSync(path.join(toolPath, filename), pluginPath); |   fs.copyFileSync(toolBinPath, pluginPath); | ||||||
| 
 | 
 | ||||||
|   core.info('Fixing perms'); |   core.info('Fixing perms'); | ||||||
|   fs.chmodSync(pluginPath, '0755'); |   fs.chmodSync(pluginPath, '0755'); | ||||||
| @ -269,3 +328,10 @@ export async function getBuildKitVersion(containerID: string): Promise<string> { | |||||||
|       return bkitimage.stdout.trim(); |       return bkitimage.stdout.trim(); | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | export function getCommand(args: Array<string>, standalone?: boolean) { | ||||||
|  |   return { | ||||||
|  |     commandLine: standalone ? 'buildx' : 'docker', | ||||||
|  |     args: standalone ? args : ['buildx', ...args] | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								src/docker.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/docker.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | import * as exec from '@actions/exec'; | ||||||
|  | 
 | ||||||
|  | export async function isAvailable(): Promise<boolean> { | ||||||
|  |   return await exec | ||||||
|  |     .getExecOutput('docker', undefined, { | ||||||
|  |       ignoreReturnCode: true, | ||||||
|  |       silent: true | ||||||
|  |     }) | ||||||
|  |     .then(res => { | ||||||
|  |       if (res.stderr.length > 0 && res.exitCode != 0) { | ||||||
|  |         return false; | ||||||
|  |       } | ||||||
|  |       return res.exitCode == 0; | ||||||
|  |     }) | ||||||
|  |     // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | ||||||
|  |     .catch(error => { | ||||||
|  |       return false; | ||||||
|  |     }); | ||||||
|  | } | ||||||
							
								
								
									
										65
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								src/main.ts
									
									
									
									
									
								
							| @ -3,6 +3,7 @@ import * as path from 'path'; | |||||||
| import * as uuid from 'uuid'; | import * as uuid from 'uuid'; | ||||||
| import * as buildx from './buildx'; | import * as buildx from './buildx'; | ||||||
| import * as context from './context'; | import * as context from './context'; | ||||||
|  | import * as docker from './docker'; | ||||||
| import * as stateHelper from './state-helper'; | import * as stateHelper from './state-helper'; | ||||||
| import * as util from './util'; | import * as util from './util'; | ||||||
| import * as core from '@actions/core'; | import * as core from '@actions/core'; | ||||||
| @ -10,32 +11,54 @@ import * as exec from '@actions/exec'; | |||||||
| 
 | 
 | ||||||
| async function run(): Promise<void> { | async function run(): Promise<void> { | ||||||
|   try { |   try { | ||||||
|     core.startGroup(`Docker info`); |  | ||||||
|     await exec.exec('docker', ['version']); |  | ||||||
|     await exec.exec('docker', ['info']); |  | ||||||
|     core.endGroup(); |  | ||||||
| 
 |  | ||||||
|     const inputs: context.Inputs = await context.getInputs(); |     const inputs: context.Inputs = await context.getInputs(); | ||||||
|     const dockerConfigHome: string = process.env.DOCKER_CONFIG || path.join(os.homedir(), '.docker'); |     const dockerConfigHome: string = process.env.DOCKER_CONFIG || path.join(os.homedir(), '.docker'); | ||||||
| 
 | 
 | ||||||
|     if (util.isValidUrl(inputs.version)) { |     // standalone if docker cli not available
 | ||||||
|       core.startGroup(`Build and install buildx`); |     const standalone = !(await docker.isAvailable()); | ||||||
|       await buildx.build(inputs.version, dockerConfigHome); |     stateHelper.setStandalone(standalone); | ||||||
|  | 
 | ||||||
|  |     core.startGroup(`Docker info`); | ||||||
|  |     if (standalone) { | ||||||
|  |       core.info(`Docker info skipped in standalone mode`); | ||||||
|  |     } else { | ||||||
|  |       await exec.exec('docker', ['version'], { | ||||||
|  |         failOnStdErr: false | ||||||
|  |       }); | ||||||
|  |       await exec.exec('docker', ['info'], { | ||||||
|  |         failOnStdErr: false | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|     core.endGroup(); |     core.endGroup(); | ||||||
|     } else if (!(await buildx.isAvailable()) || inputs.version) { | 
 | ||||||
|  |     if (util.isValidUrl(inputs.version)) { | ||||||
|  |       if (standalone) { | ||||||
|  |         throw new Error(`Cannot build from source without the Docker CLI`); | ||||||
|  |       } | ||||||
|  |       core.startGroup(`Build and install buildx`); | ||||||
|  |       await buildx.build(inputs.version, dockerConfigHome, standalone); | ||||||
|  |       core.endGroup(); | ||||||
|  |     } else if (!(await buildx.isAvailable(standalone)) || inputs.version) { | ||||||
|       core.startGroup(`Download and install buildx`); |       core.startGroup(`Download and install buildx`); | ||||||
|       await buildx.install(inputs.version || 'latest', dockerConfigHome); |       await buildx.install(inputs.version || 'latest', standalone ? context.tmpDir() : dockerConfigHome, standalone); | ||||||
|       core.endGroup(); |       core.endGroup(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const buildxVersion = await buildx.getVersion(); |     const buildxVersion = await buildx.getVersion(standalone); | ||||||
|  |     await core.group(`Buildx version`, async () => { | ||||||
|  |       const versionCmd = buildx.getCommand(['version'], standalone); | ||||||
|  |       await exec.exec(versionCmd.commandLine, versionCmd.args, { | ||||||
|  |         failOnStdErr: false | ||||||
|  |       }); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|     const builderName: string = inputs.driver == 'docker' ? 'default' : `builder-${uuid.v4()}`; |     const builderName: string = inputs.driver == 'docker' ? 'default' : `builder-${uuid.v4()}`; | ||||||
|     context.setOutput('name', builderName); |     context.setOutput('name', builderName); | ||||||
|     stateHelper.setBuilderName(builderName); |     stateHelper.setBuilderName(builderName); | ||||||
| 
 | 
 | ||||||
|     if (inputs.driver !== 'docker') { |     if (inputs.driver !== 'docker') { | ||||||
|       core.startGroup(`Creating a new builder instance`); |       core.startGroup(`Creating a new builder instance`); | ||||||
|       const createArgs: Array<string> = ['buildx', 'create', '--name', builderName, '--driver', inputs.driver]; |       const createArgs: Array<string> = ['create', '--name', builderName, '--driver', inputs.driver]; | ||||||
|       if (buildx.satisfies(buildxVersion, '>=0.3.0')) { |       if (buildx.satisfies(buildxVersion, '>=0.3.0')) { | ||||||
|         await context.asyncForEach(inputs.driverOpts, async driverOpt => { |         await context.asyncForEach(inputs.driverOpts, async driverOpt => { | ||||||
|           createArgs.push('--driver-opt', driverOpt); |           createArgs.push('--driver-opt', driverOpt); | ||||||
| @ -55,26 +78,31 @@ async function run(): Promise<void> { | |||||||
|       } else if (inputs.configInline) { |       } else if (inputs.configInline) { | ||||||
|         createArgs.push('--config', await buildx.getConfigInline(inputs.configInline)); |         createArgs.push('--config', await buildx.getConfigInline(inputs.configInline)); | ||||||
|       } |       } | ||||||
|       await exec.exec('docker', createArgs); |       const createCmd = buildx.getCommand(createArgs, standalone); | ||||||
|  |       await exec.exec(createCmd.commandLine, createCmd.args); | ||||||
|       core.endGroup(); |       core.endGroup(); | ||||||
| 
 | 
 | ||||||
|       core.startGroup(`Booting builder`); |       core.startGroup(`Booting builder`); | ||||||
|       const bootstrapArgs: Array<string> = ['buildx', 'inspect', '--bootstrap']; |       const bootstrapArgs: Array<string> = ['inspect', '--bootstrap']; | ||||||
|       if (buildx.satisfies(buildxVersion, '>=0.4.0')) { |       if (buildx.satisfies(buildxVersion, '>=0.4.0')) { | ||||||
|         bootstrapArgs.push('--builder', builderName); |         bootstrapArgs.push('--builder', builderName); | ||||||
|       } |       } | ||||||
|       await exec.exec('docker', bootstrapArgs); |       const bootstrapCmd = buildx.getCommand(bootstrapArgs, standalone); | ||||||
|  |       await exec.exec(bootstrapCmd.commandLine, bootstrapCmd.args); | ||||||
|       core.endGroup(); |       core.endGroup(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (inputs.install) { |     if (inputs.install) { | ||||||
|  |       if (standalone) { | ||||||
|  |         throw new Error(`Cannot set buildx as default builder without the Docker CLI`); | ||||||
|  |       } | ||||||
|       core.startGroup(`Setting buildx as default builder`); |       core.startGroup(`Setting buildx as default builder`); | ||||||
|       await exec.exec('docker', ['buildx', 'install']); |       await exec.exec('docker', ['buildx', 'install']); | ||||||
|       core.endGroup(); |       core.endGroup(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     core.startGroup(`Inspect builder`); |     core.startGroup(`Inspect builder`); | ||||||
|     const builder = await buildx.inspect(builderName); |     const builder = await buildx.inspect(builderName, standalone); | ||||||
|     core.info(JSON.stringify(builder, undefined, 2)); |     core.info(JSON.stringify(builder, undefined, 2)); | ||||||
|     context.setOutput('driver', builder.driver); |     context.setOutput('driver', builder.driver); | ||||||
|     context.setOutput('endpoint', builder.node_endpoint); |     context.setOutput('endpoint', builder.node_endpoint); | ||||||
| @ -83,7 +111,7 @@ async function run(): Promise<void> { | |||||||
|     context.setOutput('platforms', builder.node_platforms); |     context.setOutput('platforms', builder.node_platforms); | ||||||
|     core.endGroup(); |     core.endGroup(); | ||||||
| 
 | 
 | ||||||
|     if (inputs.driver == 'docker-container') { |     if (!standalone && inputs.driver == 'docker-container') { | ||||||
|       stateHelper.setContainerName(`buildx_buildkit_${builder.node_name}`); |       stateHelper.setContainerName(`buildx_buildkit_${builder.node_name}`); | ||||||
|       core.startGroup(`BuildKit version`); |       core.startGroup(`BuildKit version`); | ||||||
|       core.info(await buildx.getBuildKitVersion(`buildx_buildkit_${builder.node_name}`)); |       core.info(await buildx.getBuildKitVersion(`buildx_buildkit_${builder.node_name}`)); | ||||||
| @ -114,8 +142,9 @@ async function cleanup(): Promise<void> { | |||||||
| 
 | 
 | ||||||
|   if (stateHelper.builderName.length > 0) { |   if (stateHelper.builderName.length > 0) { | ||||||
|     core.startGroup(`Removing builder`); |     core.startGroup(`Removing builder`); | ||||||
|  |     const rmCmd = buildx.getCommand(['rm', stateHelper.builderName], /true/i.test(stateHelper.standalone)); | ||||||
|     await exec |     await exec | ||||||
|       .getExecOutput('docker', ['buildx', 'rm', `${stateHelper.builderName}`], { |       .getExecOutput(rmCmd.commandLine, rmCmd.args, { | ||||||
|         ignoreReturnCode: true |         ignoreReturnCode: true | ||||||
|       }) |       }) | ||||||
|       .then(res => { |       .then(res => { | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ import * as core from '@actions/core'; | |||||||
| 
 | 
 | ||||||
| export const IsPost = !!process.env['STATE_isPost']; | export const IsPost = !!process.env['STATE_isPost']; | ||||||
| export const IsDebug = !!process.env['STATE_isDebug']; | export const IsDebug = !!process.env['STATE_isDebug']; | ||||||
|  | export const standalone = process.env['STATE_standalone'] || ''; | ||||||
| export const builderName = process.env['STATE_builderName'] || ''; | export const builderName = process.env['STATE_builderName'] || ''; | ||||||
| export const containerName = process.env['STATE_containerName'] || ''; | export const containerName = process.env['STATE_containerName'] || ''; | ||||||
| 
 | 
 | ||||||
| @ -9,6 +10,10 @@ export function setDebug(debug: string) { | |||||||
|   core.saveState('isDebug', debug); |   core.saveState('isDebug', debug); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export function setStandalone(standalone: boolean) { | ||||||
|  |   core.saveState('standalone', standalone); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export function setBuilderName(builderName: string) { | export function setBuilderName(builderName: string) { | ||||||
|   core.saveState('builderName', builderName); |   core.saveState('builderName', builderName); | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 CrazyMax
						CrazyMax