Compare commits

..

46 Commits

Author SHA1 Message Date
a1c666d855 Merge pull request #97 from crazy-max/fix-get-buildkit-version
Fix `docker: invalid reference format`
2021-06-29 14:04:53 +02:00
d5b70f51d8 Fix docker: invalid reference format
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-29 14:02:48 +02:00
2e941f2def Merge pull request #95 from crazy-max/dev-deps
Update dev deps
2021-06-23 17:12:30 +02:00
eef74457f7 Update dev deps
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-23 17:03:04 +02:00
e168301d39 Merge pull request #94 from crazy-max/exec-output
Use built-in `getExecOutput`
2021-06-23 16:42:15 +02:00
29f1eeb9e5 Use built-in getExecOutput
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-23 16:11:57 +02:00
faca7837b0 Merge pull request #93 from crazy-max/bool-input
Use `core.getBooleanInput`
2021-06-23 15:49:45 +02:00
dffa64995b Use core.getBooleanInput
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-23 15:43:25 +02:00
c0e291b502 Merge pull request #86 from docker/dependabot/npm_and_yarn/actions/tool-cache-1.7.1
Bump @actions/tool-cache from 1.7.0 to 1.7.1
2021-06-23 15:01:18 +02:00
2323559062 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-23 14:59:36 +02:00
e80b8cc6d8 Bump @actions/tool-cache from 1.7.0 to 1.7.1
Bumps [@actions/tool-cache](https://github.com/actions/toolkit/tree/HEAD/packages/tool-cache) from 1.7.0 to 1.7.1.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/tool-cache/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/tool-cache)

---
updated-dependencies:
- dependency-name: "@actions/tool-cache"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-23 12:30:27 +00:00
31e7cc5f84 Merge pull request #85 from docker/dependabot/npm_and_yarn/actions/exec-1.1.0
Bump @actions/exec from 1.0.4 to 1.1.0
2021-06-23 14:28:46 +02:00
9db0a23fb3 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-23 14:26:04 +02:00
90e26af07a Bump @actions/exec from 1.0.4 to 1.1.0
Bumps [@actions/exec](https://github.com/actions/toolkit/tree/HEAD/packages/exec) from 1.0.4 to 1.1.0.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/exec/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/@actions/core@1.1.0/packages/exec)

---
updated-dependencies:
- dependency-name: "@actions/exec"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-23 12:17:11 +00:00
01ed3f7910 Merge pull request #87 from docker/dependabot/npm_and_yarn/actions/core-1.4.0
Bump @actions/core from 1.3.0 to 1.4.0
2021-06-23 14:11:09 +02:00
11ae4c31f6 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-23 13:56:24 +02:00
983bf3e000 Merge pull request #91 from docker/dependabot/npm_and_yarn/y18n-4.0.3
Bump y18n from 4.0.0 to 4.0.3
2021-06-23 12:10:31 +02:00
9a462131b5 Merge pull request #89 from docker/dependabot/npm_and_yarn/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9
2021-06-23 12:09:47 +02:00
1806a02fac Merge pull request #90 from docker/dependabot/npm_and_yarn/ws-7.5.0
Bump ws from 7.3.1 to 7.5.0
2021-06-23 12:09:30 +02:00
c1f17c078a Merge pull request #92 from docker/dependabot/npm_and_yarn/lodash-4.17.21
Bump lodash from 4.17.19 to 4.17.21
2021-06-23 12:01:51 +02:00
76bfd425d8 Bump lodash from 4.17.19 to 4.17.21
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.19 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.19...4.17.21)

---
updated-dependencies:
- dependency-name: lodash
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-23 09:58:26 +00:00
5a93241d03 Bump y18n from 4.0.0 to 4.0.3
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.3.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/y18n-v4.0.3/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/compare/v4.0.0...y18n-v4.0.3)

---
updated-dependencies:
- dependency-name: y18n
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-23 09:58:22 +00:00
2f13c4010e Bump hosted-git-info from 2.8.8 to 2.8.9
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

---
updated-dependencies:
- dependency-name: hosted-git-info
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-23 09:58:22 +00:00
1dd5af0c3a Bump ws from 7.3.1 to 7.5.0
Bumps [ws](https://github.com/websockets/ws) from 7.3.1 to 7.5.0.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.3.1...7.5.0)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-23 09:58:22 +00:00
55dd79473c Bump @actions/core from 1.3.0 to 1.4.0
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-08 04:04:34 +00:00
b1f1f719c7 Merge pull request #82 from docker/dependabot/npm_and_yarn/actions/tool-cache-1.7.0
Bump @actions/tool-cache from 1.6.1 to 1.7.0
2021-05-30 16:43:16 +02:00
68810d1ede Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-05-30 16:41:24 +02:00
cd8b844a0a Bump @actions/tool-cache from 1.6.1 to 1.7.0
Bumps [@actions/tool-cache](https://github.com/actions/toolkit/tree/HEAD/packages/tool-cache) from 1.6.1 to 1.7.0.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/tool-cache/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/tool-cache)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-28 04:03:56 +00:00
894f000c27 Merge pull request #80 from docker/dependabot/npm_and_yarn/actions/core-1.3.0
Bump @actions/core from 1.2.7 to 1.3.0
2021-05-25 02:57:25 +02:00
f080c7125b Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-05-25 02:52:57 +02:00
49b8353604 Bump @actions/core from 1.2.7 to 1.3.0
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.7 to 1.3.0.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-24 04:10:09 +00:00
0d135e0c2f Merge pull request #72 from crazy-max/buildkit-version
Display BuildKit version
2021-04-28 22:06:10 +02:00
36d8e005ca Display BuildKit version
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-28 18:09:01 +02:00
012185ccbe Merge pull request #71 from crazy-max/remove-limitation
Remove os limitation
2021-04-23 23:12:37 +02:00
881cacd606 Remove os limitation
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-23 22:43:09 +02:00
076026291d Merge pull request #68 from crazy-max/config-test
Add test job for config input
2021-04-23 22:37:54 +02:00
f4b1b8d38d Add test job for config input
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-23 22:26:59 +02:00
316c3e4a7c Merge pull request #70 from crazy-max/debug-buildkitd
BuildKit container logs
2021-04-23 22:24:19 +02:00
5b1c96aee8 Display BuildKit container logs
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-23 22:08:45 +02:00
0f034385ce Merge pull request #69 from crazy-max/inspect
Enhance builder inspection
2021-04-23 19:34:42 +02:00
72750233ac Enhance builder inspection
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-23 18:14:58 +02:00
abdb186058 Merge pull request #67 from GMartinez-Sisti/config-input
Add config input
2021-04-22 15:24:39 +02:00
9b365965c1 Add config input
Signed-off-by: Gabriel Martinez <gabrielmartinez@sisti.pt>
2021-04-22 14:05:31 +01:00
583a3147f8 Merge pull request #65 from docker/dependabot/npm_and_yarn/actions/core-1.2.7
Bump @actions/core from 1.2.6 to 1.2.7
2021-04-16 15:23:02 +02:00
2913c18445 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-16 14:49:12 +02:00
26e1d017b6 Bump @actions/core from 1.2.6 to 1.2.7
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.6 to 1.2.7.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-14 04:08:35 +00:00
17 changed files with 7732 additions and 7246 deletions

BIN
.github/buildkit-container-logs.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -35,11 +35,13 @@ jobs:
with: with:
version: ${{ matrix.buildx-version }} version: ${{ matrix.buildx-version }}
- -
name: Builder instance name name: Inspect builder
run: echo ${{ steps.buildx.outputs.name }} run: |
- echo "Name: ${{ steps.buildx.outputs.name }}"
name: Available platforms echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}"
run: echo ${{ steps.buildx.outputs.platforms }} echo "Status: ${{ steps.buildx.outputs.status }}"
echo "Flags: ${{ steps.buildx.outputs.flags }}"
echo "Platforms: ${{ steps.buildx.outputs.platforms }}"
- -
name: Dump context name: Dump context
uses: crazy-max/ghaction-dump-context@v1 uses: crazy-max/ghaction-dump-context@v1
@ -55,15 +57,81 @@ jobs:
id: buildx1 id: buildx1
uses: ./ uses: ./
- -
name: Builder 1 instance name name: Inspect builder 1
run: echo ${{ steps.buildx1.outputs.name }} run: |
echo "Name: ${{ steps.buildx1.outputs.name }}"
echo "Endpoint: ${{ steps.buildx1.outputs.endpoint }}"
echo "Status: ${{ steps.buildx1.outputs.status }}"
echo "Flags: ${{ steps.buildx1.outputs.flags }}"
echo "Platforms: ${{ steps.buildx1.outputs.platforms }}"
- -
name: Set up Docker Buildx 2 name: Set up Docker Buildx 2
id: buildx2 id: buildx2
uses: ./ uses: ./
- -
name: Builder 2 instance name name: Inspect builder 2
run: echo ${{ steps.buildx2.outputs.name }} run: |
echo "Name: ${{ steps.buildx2.outputs.name }}"
echo "Endpoint: ${{ steps.buildx2.outputs.endpoint }}"
echo "Status: ${{ steps.buildx2.outputs.status }}"
echo "Flags: ${{ steps.buildx2.outputs.flags }}"
echo "Platforms: ${{ steps.buildx2.outputs.platforms }}"
error:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Stop docker
run: |
sudo systemctl stop docker
-
name: Set up Docker Buildx
id: buildx
continue-on-error: true
uses: ./
-
name: Check
run: |
echo "${{ toJson(steps.buildx) }}"
if [ "${{ steps.buildx.outcome }}" != "failure" ] || [ "${{ steps.buildx.conclusion }}" != "success" ]; then
echo "::error::Should have failed"
exit 1
fi
-
name: Dump context
if: always()
uses: crazy-max/ghaction-dump-context@v1
debug:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Create Dockerfile
run: |
cat > ./Dockerfile <<EOL
FROM alpine
RUN uname -a
EOL
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: ./
with:
buildkitd-flags: --debug
-
name: Build
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/amd64,linux/arm64,linux/ppc64le
install: install:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -175,6 +243,40 @@ jobs:
uses: ./ uses: ./
with: with:
endpoint: mycontext endpoint: mycontext
env:
DOCKER_CONTEXT: mycontext
config:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Create buildkitd conf
run: |
cat > /tmp/buildkitd.toml <<EOL
debug = true
[registry."docker.io"]
mirrors = ["mirror.gcr.io"]
EOL
-
name: Create Dockerfile
run: |
cat > ./Dockerfile <<EOL
FROM alpine
EOL
-
name: Set up Docker Buildx
uses: ./
with:
buildkitd-flags: --debug
config: /tmp/buildkitd.toml
-
name: Build
uses: docker/build-push-action@v2
with:
context: .
with-qemu: with-qemu:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -204,8 +306,10 @@ jobs:
with: with:
version: ${{ matrix.buildx-version }} version: ${{ matrix.buildx-version }}
- -
name: Available platforms name: Inspect builder
run: echo ${{ steps.buildx.outputs.platforms }} run: |
- echo "Name: ${{ steps.buildx.outputs.name }}"
name: Builder instance name echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}"
run: echo ${{ steps.buildx.outputs.name }} echo "Status: ${{ steps.buildx.outputs.status }}"
echo "Flags: ${{ steps.buildx.outputs.flags }}"
echo "Platforms: ${{ steps.buildx.outputs.platforms }}"

View File

@ -22,6 +22,9 @@ jobs:
uses: docker/bake-action@v1 uses: docker/bake-action@v1
with: with:
targets: validate targets: validate
-
name: Set up Docker Buildx
uses: ./
- -
name: Test name: Test
uses: docker/bake-action@v1 uses: docker/bake-action@v1

View File

@ -25,8 +25,9 @@ ___
* [inputs](#inputs) * [inputs](#inputs)
* [outputs](#outputs) * [outputs](#outputs)
* [environment variables](#environment-variables) * [environment variables](#environment-variables)
* [Notes](#notes)
* [BuildKit container logs](#buildkit-container-logs)
* [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot) * [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot)
* [Limitation](#limitation)
## Usage ## Usage
@ -50,11 +51,13 @@ jobs:
id: buildx id: buildx
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
- -
name: Builder instance name name: Inspect builder
run: echo ${{ steps.buildx.outputs.name }} run: |
- echo "Name: ${{ steps.buildx.outputs.name }}"
name: Available platforms echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}"
run: echo ${{ steps.buildx.outputs.platforms }} echo "Status: ${{ steps.buildx.outputs.status }}"
echo "Flags: ${{ steps.buildx.outputs.flags }}"
echo "Platforms: ${{ steps.buildx.outputs.platforms }}"
``` ```
### With QEMU ### With QEMU
@ -129,6 +132,7 @@ 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) |
> `CSV` type must be a newline-delimited string > `CSV` type must be a newline-delimited string
> ```yaml > ```yaml
@ -146,8 +150,12 @@ Following outputs are available
| Name | Type | Description | | Name | Type | Description |
|---------------|---------|---------------------------------------| |---------------|---------|---------------------------------------|
| `name` | String | Builder instance name | | `name` | String | Builder name |
| `platforms` | String | Available platforms (comma separated) | | `driver` | String | Builder driver |
| `endpoint` | String | Builder node endpoint |
| `status` | String | Builder node status |
| `flags` | String | Builder node flags (if applicable) |
| `platforms` | String | Builder node platforms available (comma separated) |
### environment variables ### environment variables
@ -157,6 +165,25 @@ The following [official docker environment variables](https://docs.docker.com/en
|-----------------|---------|-------------|-------------------------------------------------| |-----------------|---------|-------------|-------------------------------------------------|
| `DOCKER_CONFIG` | String | `~/.docker` | The location of your client configuration files | | `DOCKER_CONFIG` | String | `~/.docker` | The location of your client configuration files |
## Notes
### BuildKit container logs
To display BuildKit container logs (when `docker-container` driver is used) you have to [enable step debug logging](https://docs.github.com/en/actions/managing-workflow-runs/enabling-debug-logging#enabling-step-debug-logging)
or you can also enable debugging in the [setup-buildx action step](https://github.com/docker/setup-buildx-action):
```yaml
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
buildkitd-flags: --debug
```
Logs will be available at the end of a job:
![BuildKit container logs](.github/buildkit-container-logs.png)
## Keep up-to-date with GitHub Dependabot ## Keep up-to-date with GitHub Dependabot
Since [Dependabot](https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-github-dependabot) Since [Dependabot](https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-github-dependabot)
@ -172,7 +199,3 @@ updates:
schedule: schedule:
interval: "daily" interval: "daily"
``` ```
## Limitation
This action is only available for Linux [virtual environments](https://docs.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners#supported-virtual-environments-and-hardware-resources).

View File

@ -1,18 +1,40 @@
import fs = require('fs'); import fs = require('fs');
import * as docker from '../src/docker';
import * as buildx from '../src/buildx'; import * as buildx from '../src/buildx';
import * as path from 'path'; import * as path from 'path';
import * as os from 'os'; import * as os from 'os';
import * as semver from 'semver'; import * as semver from 'semver';
import * as exec from '@actions/exec'; import * as exec from '@actions/exec';
describe('isAvailable', () => {
const execSpy: jest.SpyInstance = jest.spyOn(exec, 'getExecOutput');
buildx.isAvailable();
expect(execSpy).toHaveBeenCalledWith(`docker`, ['buildx'], {
silent: true,
ignoreReturnCode: true
});
});
describe('getVersion', () => { describe('getVersion', () => {
it('valid', async () => { async function isDaemonRunning() {
await exec.exec('docker', ['buildx', 'version']); return await exec
const version = await buildx.getVersion(); .getExecOutput(`docker`, ['version', '--format', '{{.Server.Os}}'], {
console.log(`version: ${version}`); ignoreReturnCode: true,
expect(semver.valid(version)).not.toBeNull(); silent: true
}, 100000); })
.then(res => {
return !res.stdout.trim().includes(' ') && res.exitCode == 0;
});
}
(isDaemonRunning() ? it : it.skip)(
'valid',
async () => {
const version = await buildx.getVersion();
console.log(`version: ${version}`);
expect(semver.valid(version)).not.toBeNull();
},
100000
);
}); });
describe('parseVersion', () => { describe('parseVersion', () => {
@ -25,17 +47,26 @@ describe('parseVersion', () => {
}); });
}); });
describe('platforms', () => { describe('inspect', () => {
async function isDaemonRunning() { async function isDaemonRunning() {
return await docker.isDaemonRunning(); return await exec
.getExecOutput(`docker`, ['version', '--format', '{{.Server.Os}}'], {
ignoreReturnCode: true,
silent: true
})
.then(res => {
return !res.stdout.trim().includes(' ') && res.exitCode == 0;
});
} }
(isDaemonRunning() ? it : it.skip)( (isDaemonRunning() ? it : it.skip)(
'valid', 'valid',
async () => { async () => {
const platforms = buildx.platforms(); const builder = await buildx.inspect('');
console.log(`platforms: ${platforms}`); console.log('builder', builder);
expect(platforms).not.toBeUndefined(); expect(builder).not.toBeUndefined();
expect(platforms).not.toEqual(''); expect(builder.name).not.toEqual('');
expect(builder.driver).not.toEqual('');
expect(builder.node_platforms).not.toEqual('');
}, },
100000 100000
); );

View File

@ -1,3 +1,4 @@
import * as os from 'os';
import * as context from '../src/context'; import * as context from '../src/context';
describe('getInputList', () => { describe('getInputList', () => {
@ -78,6 +79,27 @@ describe('asyncForEach', () => {
}); });
}); });
describe('setOutput', () => {
beforeEach(() => {
process.stdout.write = jest.fn();
});
it('setOutput produces the correct command', () => {
context.setOutput('some output', 'some value');
assertWriteCalls([`::set-output name=some output::some value${os.EOL}`]);
});
it('setOutput handles bools', () => {
context.setOutput('some output', false);
assertWriteCalls([`::set-output name=some output::false${os.EOL}`]);
});
it('setOutput handles numbers', () => {
context.setOutput('some output', 1.01);
assertWriteCalls([`::set-output name=some output::1.01${os.EOL}`]);
});
});
// See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67 // See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67
function getInputName(name: string): string { function getInputName(name: string): string {
return `INPUT_${name.replace(/ /g, '_').toUpperCase()}`; return `INPUT_${name.replace(/ /g, '_').toUpperCase()}`;
@ -86,3 +108,11 @@ function getInputName(name: string): string {
function setInput(name: string, value: string): void { function setInput(name: string, value: string): void {
process.env[getInputName(name)] = value; process.env[getInputName(name)] = value;
} }
// Assert that process.stdout.write calls called only with the given arguments.
function assertWriteCalls(calls: string[]): void {
expect(process.stdout.write).toHaveBeenCalledTimes(calls.length);
for (let i = 0; i < calls.length; i++) {
expect(process.stdout.write).toHaveBeenNthCalledWith(i + 1, calls[i]);
}
}

View File

@ -32,12 +32,23 @@ inputs:
endpoint: endpoint:
description: 'Optional address for docker socket or context from `docker context ls`' description: 'Optional address for docker socket or context from `docker context ls`'
required: false required: false
config:
description: 'BuildKit config file'
required: false
outputs: outputs:
name: name:
description: 'Builder instance name' description: 'Builder name'
driver:
description: 'Builder driver'
endpoint:
description: 'Builder node endpoint'
status:
description: 'Builder node status'
flags:
description: 'Builder node flags (if applicable)'
platforms: platforms:
description: 'Available platforms (comma separated)' description: 'Builder node platforms available (comma separated)'
runs: runs:
using: 'node12' using: 'node12'

12247
dist/index.js generated vendored

File diff suppressed because it is too large Load Diff

View File

@ -27,24 +27,24 @@
], ],
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@actions/core": "^1.2.6", "@actions/core": "^1.4.0",
"@actions/exec": "^1.0.4", "@actions/exec": "^1.1.0",
"@actions/http-client": "^1.0.11", "@actions/http-client": "^1.0.11",
"@actions/tool-cache": "^1.6.1", "@actions/tool-cache": "^1.7.1",
"semver": "^7.3.5", "semver": "^7.3.5",
"uuid": "^8.3.2" "uuid": "^8.3.2"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^26.0.3", "@types/jest": "^26.0.23",
"@types/node": "^14.0.14", "@types/node": "^14.17.4",
"@vercel/ncc": "^0.23.0", "@vercel/ncc": "^0.28.6",
"dotenv": "^8.2.0", "dotenv": "^8.6.0",
"jest": "^26.1.0", "jest": "^26.6.3",
"jest-circus": "^26.1.0", "jest-circus": "^26.6.3",
"jest-runtime": "^26.1.0", "jest-runtime": "^26.6.3",
"prettier": "^2.0.5", "prettier": "^2.3.1",
"ts-jest": "^26.1.1", "ts-jest": "^26.5.6",
"typescript": "^3.9.5", "typescript": "^4.3.4",
"typescript-formatter": "^7.2.2" "typescript-formatter": "^7.2.2"
} }
} }

View File

@ -3,48 +3,107 @@ import * as path from 'path';
import * as semver from 'semver'; import * as semver from 'semver';
import * as util from 'util'; import * as util from 'util';
import * as context from './context'; import * as context from './context';
import * as exec from './exec';
import * as github from './github'; import * as github from './github';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as tc from '@actions/tool-cache'; import * as tc from '@actions/tool-cache';
export type Builder = {
name?: string;
driver?: string;
node_name?: string;
node_endpoint?: string;
node_status?: string;
node_flags?: string;
node_platforms?: string;
};
export async function isAvailable(): Promise<Boolean> {
return await exec
.getExecOutput('docker', ['buildx'], {
ignoreReturnCode: true,
silent: true
})
.then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
return false;
}
return res.exitCode == 0;
});
}
export async function getVersion(): Promise<string> { export async function getVersion(): Promise<string> {
return await exec.exec(`docker`, ['buildx', 'version'], true).then(res => { return await exec
if (res.stderr != '' && !res.success) { .getExecOutput('docker', ['buildx', 'version'], {
throw new Error(res.stderr); ignoreReturnCode: true,
} silent: true
return parseVersion(res.stdout); })
}); .then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
throw new Error(res.stderr.trim());
}
return parseVersion(res.stdout.trim());
});
} }
export async function parseVersion(stdout: string): Promise<string> { export async function parseVersion(stdout: string): Promise<string> {
const matches = /\sv?([0-9.]+)/.exec(stdout); const matches = /\sv?([0-9.]+)/.exec(stdout);
if (!matches) { if (!matches) {
throw new Error(`Cannot parse Buildx version`); throw new Error(`Cannot parse buildx version`);
} }
return semver.clean(matches[1]); return semver.clean(matches[1]);
} }
export async function isAvailable(): Promise<Boolean> { export async function inspect(name: string): Promise<Builder> {
return await exec.exec(`docker`, ['buildx'], true).then(res => { return await exec
if (res.stderr != '' && !res.success) { .getExecOutput(`docker`, ['buildx', 'inspect', name], {
return false; ignoreReturnCode: true,
} silent: true
return res.success; })
}); .then(res => {
} if (res.stderr.length > 0 && res.exitCode != 0) {
throw new Error(res.stderr.trim());
export async function platforms(): Promise<String | undefined> {
return await exec.exec(`docker`, ['buildx', 'inspect'], true).then(res => {
if (res.stderr != '' && !res.success) {
throw new Error(res.stderr);
}
for (const line of res.stdout.trim().split(`\n`)) {
if (line.startsWith('Platforms')) {
return line.replace('Platforms: ', '').replace(/\s/g, '').trim();
} }
} const builder: Builder = {};
}); itlines: for (const line of res.stdout.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) {
case 'Name': {
if (builder.name == undefined) {
builder.name = value;
} else {
builder.node_name = value;
}
break;
}
case 'Driver': {
builder.driver = value;
break;
}
case 'Endpoint': {
builder.node_endpoint = value;
break;
}
case 'Status': {
builder.node_status = value;
break;
}
case 'Flags': {
builder.node_flags = value;
break;
}
case 'Platforms': {
builder.node_platforms = value.replace(/\s/g, '');
break itlines;
}
}
}
return builder;
});
} }
export async function install(inputVersion: string, dockerConfigHome: string): Promise<string> { export async function install(inputVersion: string, dockerConfigHome: string): Promise<string> {
@ -127,3 +186,31 @@ async function filename(version: string): Promise<string> {
const ext: string = context.osPlat == 'win32' ? '.exe' : ''; const ext: string = context.osPlat == 'win32' ? '.exe' : '';
return util.format('buildx-v%s.%s-%s%s', version, platform, arch, ext); return util.format('buildx-v%s.%s-%s%s', version, platform, arch, ext);
} }
export async function getBuildKitVersion(containerID: string): Promise<string> {
return exec
.getExecOutput(`docker`, ['inspect', '--format', '{{.Config.Image}}', containerID], {
ignoreReturnCode: true,
silent: true
})
.then(bkitimage => {
if (bkitimage.exitCode == 0 && bkitimage.stdout.length > 0) {
return exec
.getExecOutput(`docker`, ['run', '--rm', bkitimage.stdout.trim(), '--version'], {
ignoreReturnCode: true,
silent: true
})
.then(bkitversion => {
if (bkitversion.exitCode == 0 && bkitversion.stdout.length > 0) {
return `${bkitimage.stdout.trim()} => ${bkitversion.stdout.trim()}`;
} else if (bkitversion.stderr.length > 0) {
core.warning(bkitversion.stderr.trim());
}
return bkitversion.stdout.trim();
});
} else if (bkitimage.stderr.length > 0) {
core.warning(bkitimage.stderr.trim());
}
return bkitimage.stdout.trim();
});
}

View File

@ -1,5 +1,6 @@
import * as os from 'os'; import * as os from 'os';
import * as core from '@actions/core'; import * as core from '@actions/core';
import {issueCommand} from '@actions/core/lib/command';
export const osPlat: string = os.platform(); export const osPlat: string = os.platform();
export const osArch: string = os.arch(); export const osArch: string = os.arch();
@ -12,6 +13,7 @@ export interface Inputs {
install: boolean; install: boolean;
use: boolean; use: boolean;
endpoint: string; endpoint: string;
config: string;
} }
export async function getInputs(): Promise<Inputs> { export async function getInputs(): Promise<Inputs> {
@ -22,9 +24,10 @@ export async function getInputs(): Promise<Inputs> {
buildkitdFlags: buildkitdFlags:
core.getInput('buildkitd-flags') || core.getInput('buildkitd-flags') ||
'--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host', '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
install: /true/i.test(core.getInput('install')), install: core.getBooleanInput('install'),
use: /true/i.test(core.getInput('use')), use: core.getBooleanInput('use'),
endpoint: core.getInput('endpoint') endpoint: core.getInput('endpoint'),
config: core.getInput('config')
}; };
} }
@ -47,3 +50,8 @@ export const asyncForEach = async (array, callback) => {
await callback(array[index], index, array); await callback(array[index], index, array);
} }
}; };
// FIXME: Temp fix https://github.com/actions/toolkit/issues/777
export function setOutput(name: string, value: any): void {
issueCommand('set-output', {name}, value);
}

View File

@ -1,7 +0,0 @@
import * as exec from './exec';
export async function isDaemonRunning(): Promise<boolean> {
return await exec.exec(`docker`, ['version', '--format', '{{.Server.Os}}'], true).then(res => {
return !res.stdout.includes(' ') && res.success;
});
}

View File

@ -1,34 +0,0 @@
import * as aexec from '@actions/exec';
import {ExecOptions} from '@actions/exec';
export interface ExecResult {
success: boolean;
stdout: string;
stderr: string;
}
export const exec = async (command: string, args: string[] = [], silent: boolean): Promise<ExecResult> => {
let stdout: string = '';
let stderr: string = '';
const options: ExecOptions = {
silent: silent,
ignoreReturnCode: true
};
options.listeners = {
stdout: (data: Buffer) => {
stdout += data.toString();
},
stderr: (data: Buffer) => {
stderr += data.toString();
}
};
const returnCode: number = await aexec.exec(command, args, options);
return {
success: returnCode === 0,
stdout: stdout.trim(),
stderr: stderr.trim()
};
};

View File

@ -1,19 +1,18 @@
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as os from 'os'; import * as os from 'os';
import * as path from 'path'; import * as path from 'path';
import * as semver from 'semver'; import * as semver from 'semver';
import * as buildx from './buildx'; import * as buildx from './buildx';
import * as context from './context'; import * as context from './context';
import * as mexec from './exec';
import * as stateHelper from './state-helper'; import * as stateHelper from './state-helper';
import * as core from '@actions/core';
import * as exec from '@actions/exec';
async function run(): Promise<void> { async function run(): Promise<void> {
try { try {
if (os.platform() !== 'linux') { core.startGroup(`Docker info`);
core.setFailed('Only supported on linux platform'); await exec.exec('docker', ['version']);
return; 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');
@ -25,10 +24,8 @@ async function run(): Promise<void> {
} }
const buildxVersion = await buildx.getVersion(); const buildxVersion = await buildx.getVersion();
core.info(`Using buildx ${buildxVersion}`);
const builderName: string = inputs.driver == 'docker' ? 'default' : `builder-${require('uuid').v4()}`; const builderName: string = inputs.driver == 'docker' ? 'default' : `builder-${require('uuid').v4()}`;
core.setOutput('name', builderName); context.setOutput('name', builderName);
stateHelper.setBuilderName(builderName); stateHelper.setBuilderName(builderName);
if (inputs.driver !== 'docker') { if (inputs.driver !== 'docker') {
@ -48,6 +45,9 @@ async function run(): Promise<void> {
if (inputs.endpoint) { if (inputs.endpoint) {
createArgs.push(inputs.endpoint); createArgs.push(inputs.endpoint);
} }
if (inputs.config) {
createArgs.push('--config', inputs.config);
}
await exec.exec('docker', createArgs); await exec.exec('docker', createArgs);
core.endGroup(); core.endGroup();
@ -66,25 +66,58 @@ async function run(): Promise<void> {
core.endGroup(); core.endGroup();
} }
core.startGroup(`Extracting available platforms`); core.startGroup(`Inspect builder`);
const platforms = await buildx.platforms(); const builder = await buildx.inspect(builderName);
core.info(`${platforms}`); core.info(JSON.stringify(builder, undefined, 2));
core.setOutput('platforms', platforms); context.setOutput('driver', builder.driver);
context.setOutput('endpoint', builder.node_endpoint);
context.setOutput('status', builder.node_status);
context.setOutput('flags', builder.node_flags);
context.setOutput('platforms', builder.node_platforms);
core.endGroup(); core.endGroup();
if (inputs.driver == 'docker-container') {
stateHelper.setContainerName(`buildx_buildkit_${builder.node_name}`);
core.startGroup(`BuildKit version`);
core.info(await buildx.getBuildKitVersion(`buildx_buildkit_${builder.node_name}`));
core.endGroup();
}
if (core.isDebug() || builder.node_flags?.includes('--debug')) {
stateHelper.setDebug('true');
}
} catch (error) { } catch (error) {
core.setFailed(error.message); core.setFailed(error.message);
} }
} }
async function cleanup(): Promise<void> { async function cleanup(): Promise<void> {
if (stateHelper.builderName.length == 0) { if (stateHelper.IsDebug && stateHelper.containerName.length > 0) {
return; core.startGroup(`BuildKit container logs`);
await exec
.getExecOutput('docker', ['logs', `${stateHelper.containerName}`], {
ignoreReturnCode: true
})
.then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
core.warning(res.stderr.trim());
}
});
core.endGroup();
}
if (stateHelper.builderName.length > 0) {
core.startGroup(`Removing builder`);
await exec
.getExecOutput('docker', ['buildx', 'rm', `${stateHelper.builderName}`], {
ignoreReturnCode: true
})
.then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
core.warning(res.stderr.trim());
}
});
core.endGroup();
} }
await mexec.exec('docker', ['buildx', 'rm', `${stateHelper.builderName}`], false).then(res => {
if (res.stderr != '' && !res.success) {
core.warning(res.stderr);
}
});
} }
if (!stateHelper.IsPost) { if (!stateHelper.IsPost) {

View File

@ -1,12 +1,22 @@
import * as core from '@actions/core'; 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 builderName = process.env['STATE_builderName'] || ''; export const builderName = process.env['STATE_builderName'] || '';
export const containerName = process.env['STATE_containerName'] || '';
export function setDebug(debug: string) {
core.saveState('isDebug', debug);
}
export function setBuilderName(builderName: string) { export function setBuilderName(builderName: string) {
core.saveState('builderName', builderName); core.saveState('builderName', builderName);
} }
export function setContainerName(containerName: string) {
core.saveState('containerName', containerName);
}
if (!IsPost) { if (!IsPost) {
core.saveState('isPost', 'true'); core.saveState('isPost', 'true');
} }

2140
yarn.lock

File diff suppressed because it is too large Load Diff