Compare commits

..

49 Commits

Author SHA1 Message Date
a66e35b9cb Merge pull request #439 from docker/dependabot/npm_and_yarn/actions/core-1.5.0
Bump @actions/core from 1.4.0 to 1.5.0
2021-08-20 11:07:21 +02:00
6a98f97e24 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-08-20 11:05:00 +02:00
26f24d6851 Bump @actions/core from 1.4.0 to 1.5.0
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.4.0 to 1.5.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-08-20 09:02:21 +00:00
b0b7751850 Merge pull request #412 from crazy-max/metadata-file
Add `metadata` output
2021-08-20 10:28:45 +02:00
c0b121fe44 Add metadata output
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-08-16 23:44:35 +02:00
09d66c261a Merge pull request #427 from crazy-max/doc-typo
Fix doc typo
2021-08-05 16:36:31 +02:00
24d162ecb4 Fix doc typo
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-08-05 16:36:12 +02:00
6484a61448 Merge pull request #426 from crazy-max/doc-sanitize-ref
Add note to sanitize tags
2021-08-05 08:12:32 +02:00
c40e0ee07a Add note to sanitize tags
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-08-05 08:09:56 +02:00
e06a3af40d Merge pull request #421 from crazy-max/doc-typo
Fix typo in cache doc
2021-07-29 17:03:20 +02:00
2e10e1984b Fix typo in cache doc
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-07-29 17:01:12 +02:00
1a60e0d706 Merge pull request #406 from crazy-max/cache-exporter-doc
Cache backend API example
2021-07-29 16:59:14 +02:00
3530a97c47 Cache backend API example
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-07-29 16:57:27 +02:00
3c507bedc4 Merge pull request #420 from crazy-max/upgrade-notes
Update upgrade notes
2021-07-29 09:51:45 +02:00
7c64fd5e10 Update upgrade notes
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-07-29 09:49:25 +02:00
c65ff7ffb1 Merge pull request #407 from crazy-max/git-subdir
Remove note about Git context not supporting subdir
2021-07-25 23:03:46 +02:00
2a8d638779 Merge pull request #415 from docker/dependabot/github_actions/codecov/codecov-action-2.0.1
Bump codecov/codecov-action from 1 to 2.0.1
2021-07-23 09:50:49 +02:00
900c06250b Use major
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-07-23 08:18:38 +02:00
b5e5b85e1b Bump codecov/codecov-action from 1 to 2.0.1
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 1 to 2.0.1.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v1...v2.0.1)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-07-20 11:01:50 +00:00
cf25934f0f Merge pull request #411 from crazy-max/test-dockerfile
Update test Dockerfile
2021-07-18 22:46:27 +02:00
37831a7a20 Update test Dockerfile
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-07-18 22:44:25 +02:00
ad1d2e93be Merge pull request #408 from dvalentiate/detail_ignore_of_dockerignore
Detail `.dockerignore` is ignored in git context
2021-07-16 13:36:05 +02:00
e80adc3299 Detail .dockerignore is ignored in git context
Add a note to README.md that .dockerignore is not processed by default
by build-push-action@v2.

Signed-off-by: David Valentiate <david@bluedrop.com>

Co-authored-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
Signed-off-by: David Valentiate <david@bluedrop.com>
2021-07-13 18:17:22 -04:00
7594ecce5b Remove note about Git context not supporting subdir
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-07-13 20:33:04 +02:00
1bc1040cae Merge pull request #400 from crazy-max/typo
Small typo and ensure trimmed output
2021-07-01 16:59:39 +02:00
fcaaa5e487 Small typo and ensure trimmed output
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-07-01 16:55:34 +02:00
0987321e12 Merge pull request #399 from crazy-max/sha-version
Handle git sha version of buildx
2021-07-01 15:34:01 +02:00
94827201d1 Handle git sha version of buildx
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-07-01 15:29:36 +02:00
128f05c85a Merge pull request #398 from crazy-max/fix-dependabot
Fix dependabot labels
2021-07-01 11:08:53 +02:00
a15ef4dd9f Fix dependabot labels
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-07-01 10:59:12 +02:00
c7dab97e55 Merge pull request #394 from cpswan/master
Fix ISSUE_TEMPLATE typo s/sumbitting/submitting/
2021-06-25 16:50:39 +02:00
a1d2218d38 Fix ISSUE_TEMPLATE typo s/sumbitting/submitting/
Signed-off-by: Chris Swan <478926+cpswan@users.noreply.github.com>
2021-06-25 15:46:56 +01:00
0b56a3c3b3 Merge pull request #393 from crazy-max/dev-deps
Update dev deps
2021-06-23 19:30:32 +02:00
ae29b67b96 Update dev deps
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-23 19:21:28 +02:00
b44cfd9087 Merge pull request #392 from crazy-max/exec-output
Use built-in `getExecOutput`
2021-06-22 19:54:47 +02:00
a437a4518f Use built-in getExecOutput
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-22 19:52:26 +02:00
a7071c9d9a Merge pull request #391 from crazy-max/bool-input
Use `core.getBooleanInput`
2021-06-22 17:32:35 +02:00
9199c83f6e Use core.getBooleanInput
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-22 17:25:57 +02:00
93a9859764 Merge pull request #385 from docker/dependabot/npm_and_yarn/csv-parse-4.16.0
Bump csv-parse from 4.15.4 to 4.16.0
2021-06-22 15:46:38 +02:00
9cbc67d577 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-22 15:44:18 +02:00
07bca60c0f Bump csv-parse from 4.15.4 to 4.16.0
Bumps [csv-parse](https://github.com/wdavidw/node-csv-parse) from 4.15.4 to 4.16.0.
- [Release notes](https://github.com/wdavidw/node-csv-parse/releases)
- [Changelog](https://github.com/adaltas/node-csv-parse/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wdavidw/node-csv-parse/compare/v4.15.4...v4.16.0)

---
updated-dependencies:
- dependency-name: csv-parse
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-22 13:34:01 +00:00
cc01c17e75 Merge pull request #382 from docker/dependabot/npm_and_yarn/actions/exec-1.1.0
Bump @actions/exec from 1.0.4 to 1.1.0
2021-06-22 15:32:21 +02:00
90850ba046 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-22 15:30:39 +02:00
915370c72f 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-22 12:53:49 +00:00
f87b75314d Merge pull request #383 from docker/dependabot/npm_and_yarn/actions/core-1.4.0
Bump @actions/core from 1.3.0 to 1.4.0
2021-06-22 14:51:44 +02:00
ecbc0634e4 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-22 14:46:28 +02:00
06b9aae8bc 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 05:24:02 +00:00
779802e2ee Merge pull request #375 from docker/dependabot/npm_and_yarn/ws-7.4.6
Bump ws from 7.3.1 to 7.4.6
2021-05-30 21:58:54 +02:00
dd8c19ed49 Bump ws from 7.3.1 to 7.4.6
Bumps [ws](https://github.com/websockets/ws) from 7.3.1 to 7.4.6.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.3.1...7.4.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-30 19:56:33 +00:00
22 changed files with 13591 additions and 13418 deletions

View File

@ -5,7 +5,7 @@ about: Create a report to help us improve
### Troubleshooting ### Troubleshooting
Before sumbitting a bug report please read the [Troubleshooting doc](https://github.com/docker/build-push-action/blob/master/TROUBLESHOOTING.md). Before submitting a bug report please read the [Troubleshooting doc](https://github.com/docker/build-push-action/blob/master/TROUBLESHOOTING.md).
### Behaviour ### Behaviour

View File

@ -5,8 +5,8 @@ updates:
schedule: schedule:
interval: "daily" interval: "daily"
labels: labels:
- ":game_die: dependencies" - "dependencies"
- ":robot: bot" - "bot"
- package-ecosystem: "npm" - package-ecosystem: "npm"
directory: "/" directory: "/"
schedule: schedule:
@ -14,5 +14,5 @@ updates:
allow: allow:
- dependency-type: "production" - dependency-type: "production"
labels: labels:
- ":game_die: dependencies" - "dependencies"
- ":robot: bot" - "bot"

View File

@ -70,9 +70,6 @@ jobs:
name: Inspect name: Inspect
run: | run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0 docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
- -
name: Check digest name: Check digest
run: | run: |
@ -133,9 +130,6 @@ jobs:
name: Inspect name: Inspect
run: | run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0 docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
- -
name: Check digest name: Check digest
run: | run: |
@ -191,9 +185,6 @@ jobs:
name: Inspect name: Inspect
run: | run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0 docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
- -
name: Check digest name: Check digest
run: | run: |
@ -392,9 +383,6 @@ jobs:
name: Inspect name: Inspect
run: | run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0 docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
- -
name: Check digest name: Check digest
run: | run: |
@ -447,9 +435,6 @@ jobs:
name: Inspect (1) name: Inspect (1)
run: | run: |
docker buildx imagetools inspect localhost:5000/name/app:latest docker buildx imagetools inspect localhost:5000/name/app:latest
-
name: Image digest (1)
run: echo ${{ steps.docker_build.outputs.digest }}
- -
name: Check digest (1) name: Check digest (1)
run: | run: |
@ -480,9 +465,6 @@ jobs:
name: Inspect (2) name: Inspect (2)
run: | run: |
docker buildx imagetools inspect localhost:5000/name/app:latest docker buildx imagetools inspect localhost:5000/name/app:latest
-
name: Image digest (2)
run: echo ${{ steps.docker_build2.outputs.digest }}
- -
name: Check digest (2) name: Check digest (2)
run: | run: |
@ -503,7 +485,7 @@ jobs:
if: always() if: always()
uses: crazy-max/ghaction-dump-context@v1 uses: crazy-max/ghaction-dump-context@v1
github-cache-first: local-cache-first:
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:
digest: ${{ steps.docker_build.outputs.digest }} digest: ${{ steps.docker_build.outputs.digest }}
@ -531,7 +513,7 @@ jobs:
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: /tmp/.buildx-cache path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-ghcache-${{ github.sha }} key: ${{ runner.os }}-buildx-local-${{ github.sha }}
restore-keys: | restore-keys: |
${{ runner.os }}-buildx-ghcache- ${{ runner.os }}-buildx-ghcache-
- -
@ -557,9 +539,6 @@ jobs:
name: Inspect name: Inspect
run: | run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0 docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
- -
name: Check digest name: Check digest
run: | run: |
@ -572,9 +551,9 @@ jobs:
if: always() if: always()
uses: crazy-max/ghaction-dump-context@v1 uses: crazy-max/ghaction-dump-context@v1
github-cache-hit: local-cache-hit:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: github-cache-first needs: local-cache-first
services: services:
registry: registry:
image: registry:2 image: registry:2
@ -600,7 +579,7 @@ jobs:
id: cache id: cache
with: with:
path: /tmp/.buildx-cache path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-ghcache-${{ github.sha }} key: ${{ runner.os }}-buildx-local-${{ github.sha }}
restore-keys: | restore-keys: |
${{ runner.os }}-buildx-ghcache- ${{ runner.os }}-buildx-ghcache-
- -
@ -622,9 +601,6 @@ jobs:
name: Inspect name: Inspect
run: | run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0 docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
- -
name: Check digest name: Check digest
run: | run: |
@ -635,8 +611,8 @@ jobs:
- -
name: Compare digests name: Compare digests
run: | run: |
echo Compare "${{ needs.github-cache-first.outputs.digest }}" with "${{ steps.docker_build.outputs.digest }}" echo Compare "${{ needs.local-cache-first.outputs.digest }}" with "${{ steps.docker_build.outputs.digest }}"
if [ "${{ needs.github-cache-first.outputs.digest }}" != "${{ steps.docker_build.outputs.digest }}" ]; then if [ "${{ needs.local-cache-first.outputs.digest }}" != "${{ steps.docker_build.outputs.digest }}" ]; then
echo "::error::Digests should be identical" echo "::error::Digests should be identical"
exit 1 exit 1
fi fi
@ -647,3 +623,53 @@ jobs:
name: Dump context name: Dump context
if: always() if: always()
uses: crazy-max/ghaction-dump-context@v1 uses: crazy-max/ghaction-dump-context@v1
github-cache:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
buildx_version:
- ""
- latest
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
version: ${{ matrix.buildx_version }}
driver-opts: |
network=host
buildkitd-flags: --debug
-
name: Build and push
uses: ./
with:
context: ./test
file: ./test/multi.Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: |
localhost:5000/name/app:latest
localhost:5000/name/app:1.0.0
cache-from: type=gha,scope=ci-${{ matrix.buildx_version }}
cache-to: type=gha,scope=ci-${{ matrix.buildx_version }}
-
name: Inspect
run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
name: Dump context
if: always()
uses: crazy-max/ghaction-dump-context@v1

View File

@ -27,6 +27,6 @@ jobs:
targets: test targets: test
- -
name: Upload coverage name: Upload coverage
uses: codecov/codecov-action@v1 uses: codecov/codecov-action@v2
with: with:
file: ./coverage/clover.xml file: ./coverage/clover.xml

View File

@ -1,5 +1,5 @@
{ {
"printWidth": 120, "printWidth": 240,
"tabWidth": 2, "tabWidth": 2,
"useTabs": false, "useTabs": false,
"semi": true, "semi": true,

View File

@ -33,8 +33,6 @@ ___
* [Push to multi-registries](docs/advanced/push-multi-registries.md) * [Push to multi-registries](docs/advanced/push-multi-registries.md)
* [Copy between registries](docs/advanced/copy-between-registries.md) * [Copy between registries](docs/advanced/copy-between-registries.md)
* [Cache](docs/advanced/cache.md) * [Cache](docs/advanced/cache.md)
* [Registry cache](docs/advanced/cache.md#registry-cache)
* [GitHub cache](docs/advanced/cache.md#github-cache)
* [Local registry](docs/advanced/local-registry.md) * [Local registry](docs/advanced/local-registry.md)
* [Export image to Docker](docs/advanced/export-docker.md) * [Export image to Docker](docs/advanced/export-docker.md)
* [Share built image between jobs](docs/advanced/share-image-jobs.md) * [Share built image between jobs](docs/advanced/share-image-jobs.md)
@ -53,7 +51,7 @@ By default, this action uses the [Git context](#git-context) so you don't need t
done directly by buildkit. The git reference will be based on the [event that triggered your workflow](https://docs.github.com/en/actions/reference/events-that-trigger-workflows) done directly by buildkit. The git reference will be based on the [event that triggered your workflow](https://docs.github.com/en/actions/reference/events-that-trigger-workflows)
and will result in the following context: `https://github.com/<owner>/<repo>.git#<ref>`. and will result in the following context: `https://github.com/<owner>/<repo>.git#<ref>`.
Be careful because **any file mutation in the steps that precede the build step will be ignored** since Be careful because **any file mutation in the steps that precede the build step will be ignored, including processing of the `.dockerignore` file** since
the context is based on the git reference. However, you can use the [Path context](#path-context) using the the context is based on the git reference. However, you can use the [Path context](#path-context) using the
[`context` input](#inputs) alongside the [`actions/checkout`](https://github.com/actions/checkout/) action to remove [`context` input](#inputs) alongside the [`actions/checkout`](https://github.com/actions/checkout/) action to remove
this restriction. this restriction.
@ -100,9 +98,6 @@ jobs:
with: with:
push: true push: true
tags: user/app:latest tags: user/app:latest
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
``` ```
Building from the current repository automatically uses the [GitHub Token](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token) Building from the current repository automatically uses the [GitHub Token](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token)
@ -121,9 +116,6 @@ a [secret](docs/advanced/secrets.md) named `GIT_AUTH_TOKEN` to be able to authen
GIT_AUTH_TOKEN=${{ secrets.MYTOKEN }} GIT_AUTH_TOKEN=${{ secrets.MYTOKEN }}
``` ```
> :warning: Subdir for Git context is not yet supported ([moby/buildkit#1684](https://github.com/moby/buildkit/issues/1684))
> but you can use the [path context](#path-context) in the meantime. More info on [Docker docs website](https://docs.docker.com/engine/reference/commandline/build/#git-repositories).
### Path context ### Path context
```yaml ```yaml
@ -170,8 +162,6 @@ jobs:
* [Push to multi-registries](docs/advanced/push-multi-registries.md) * [Push to multi-registries](docs/advanced/push-multi-registries.md)
* [Copy between registries](docs/advanced/copy-between-registries.md) * [Copy between registries](docs/advanced/copy-between-registries.md)
* [Cache](docs/advanced/cache.md) * [Cache](docs/advanced/cache.md)
* [Registry cache](docs/advanced/cache.md#registry-cache)
* [GitHub cache](docs/advanced/cache.md#github-cache)
* [Local registry](docs/advanced/local-registry.md) * [Local registry](docs/advanced/local-registry.md)
* [Export image to Docker](docs/advanced/export-docker.md) * [Export image to Docker](docs/advanced/export-docker.md)
* [Share built image between jobs](docs/advanced/share-image-jobs.md) * [Share built image between jobs](docs/advanced/share-image-jobs.md)
@ -223,9 +213,10 @@ Following inputs can be used as `step.with` keys
Following outputs are available Following outputs are available
| Name | Type | Description | | Name | Type | Description |
|---------------|---------|---------------------------------------| |-------------------|---------|---------------------------------------|
| `digest` | String | Image content-addressable identifier also called a digest | | `digest` | String | Image content-addressable identifier also called a digest |
| `metadata` | JSON | Build result metadata |
## Troubleshooting ## Troubleshooting

View File

@ -3,6 +3,7 @@
* [Cannot push to a registry](#cannot-push-to-a-registry) * [Cannot push to a registry](#cannot-push-to-a-registry)
* [BuildKit container logs](#buildkit-container-logs) * [BuildKit container logs](#buildkit-container-logs)
* [With containerd](#with-containerd) * [With containerd](#with-containerd)
* [`repository name must be lowercase`](#repository-name-must-be-lowercase)
## Cannot push to a registry ## Cannot push to a registry
@ -14,9 +15,11 @@ While pushing to a registry, you may encounter these kinds of issues:
* `failed commit on ref "manifest-sha256:...": unexpected status: 401 Unauthorized` * `failed commit on ref "manifest-sha256:...": unexpected status: 401 Unauthorized`
* `unexpected response: 401 Unauthorized` * `unexpected response: 401 Unauthorized`
These issues are not directly related to this action but are rather linked to [buildx](https://github.com/docker/buildx), These issues are not directly related to this action but are rather linked to
[buildkit](https://github.com/moby/buildkit), [containerd](https://github.com/containerd/containerd) or the registry [buildx](https://github.com/docker/buildx), [buildkit](https://github.com/moby/buildkit),
on which you're pushing your image. The quality of error message depends on the registry and are usually not very informative. [containerd](https://github.com/containerd/containerd) or the registry on which
you're pushing your image. The quality of error message depends on the registry
and are usually not very informative.
### BuildKit container logs ### BuildKit container logs
@ -25,8 +28,9 @@ action step and attach BuildKit container logs to your issue.
### With containerd ### With containerd
Next you can test pushing with [containerd action](https://github.com/crazy-max/ghaction-setup-containerd) using the Next you can test pushing with [containerd action](https://github.com/crazy-max/ghaction-setup-containerd)
following workflow. If it works then open an issue on [buildkit](https://github.com/moby/buildkit) repository. using the following workflow. If it works then open an issue on [buildkit](https://github.com/moby/buildkit)
repository.
```yaml ```yaml
name: containerd name: containerd
@ -69,3 +73,47 @@ jobs:
run: | run: |
sudo ctr --debug i push --user "${{ secrets.DOCKER_USERNAME }}:${{ secrets.DOCKER_PASSWORD }}" docker.io/user/app:latest sudo ctr --debug i push --user "${{ secrets.DOCKER_USERNAME }}:${{ secrets.DOCKER_PASSWORD }}" docker.io/user/app:latest
``` ```
## `repository name must be lowercase`
You may encounter this issue if you're using `github.repository` as a repo slug
in your tag:
```
#6 exporting to image
#6 exporting layers
#6 exporting layers 1.2s done
#6 exporting manifest sha256:b47f7dfb97b89ccd5de553af3c8cd94c4795884cbe5693e93946b1d95a7b1d12 0.0s done
#6 exporting config sha256:995e93fab8196893192f08a38deea6769dc4d98f86cf705eccc24ec96a3e271c 0.0s done
#6 ERROR: invalid reference format: repository name must be lowercase
------
> exporting to image:
------
error: failed to solve: invalid reference format: repository name must be lowercase
```
or a cache reference:
```
#10 importing cache manifest from ghcr.io/My-Org/repo:main
#10 ERROR: invalid reference format: repository name must be lowercase
```
To fix this issue you can use our [metadata action](https://github.com/docker/metadata-action)
to generate sanitized tags, or a dedicated step to sanitize the slug:
```yaml
- name: Sanitize repo slug
uses: actions/github-script@v4
id: repo_slug
with:
result-encoding: string
script: return `ghcr.io/${github.repository.toLowerCase()}`
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: ${{ steps.repo_slug.outputs.result }}:latest
```

View File

@ -101,25 +101,17 @@ steps:
name: Checkout name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- -
name: Prepare name: Docker meta
id: prep id: meta
run: | uses: docker/metadata-action@v3
DOCKER_IMAGE=myorg/myrepository with:
VERSION=edge images: |
if [[ $GITHUB_REF == refs/tags/* ]]; then myorg/myrepository
VERSION=${GITHUB_REF#refs/tags/} tags: |
elif [[ $GITHUB_REF == refs/heads/* ]]; then type=ref,event=branch
VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g') type=ref,event=pr
elif [[ $GITHUB_REF == refs/pull/* ]]; then type=semver,pattern={{version}}
VERSION=pr-${{ github.event.number }} type=sha
fi
TAGS="${DOCKER_IMAGE}:${VERSION}"
if [ "${{ github.event_name }}" = "push" ]; then
TAGS="$TAGS,${DOCKER_IMAGE}:sha-${GITHUB_SHA::8}"
fi
echo ::set-output name=version::${VERSION}
echo ::set-output name=tags::${TAGS}
echo ::set-output name=created::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
- -
name: Set up Docker Buildx name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1 uses: docker/setup-buildx-action@v1
@ -136,12 +128,6 @@ steps:
with: with:
context: . context: .
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.prep.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: | labels: ${{ steps.meta.outputs.labels }}
org.opencontainers.image.source=${{ github.event.repository.html_url }}
org.opencontainers.image.created=${{ steps.prep.outputs.created }}
org.opencontainers.image.revision=${{ github.sha }}
``` ```
> You can also use the [Docker meta action to handle tags and labels](docs/advanced/tags-labels.md) based on GitHub
> actions events and Git metadata.

View File

@ -1,13 +1,17 @@
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import * as semver from 'semver'; import * as semver from 'semver';
import * as exec from '@actions/exec';
import * as buildx from '../src/buildx'; import * as buildx from '../src/buildx';
import * as context from '../src/context'; import * as context from '../src/context';
import * as docker from '../src/docker';
const tmpNameSync = path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep); const tmpNameSync = path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
const digest = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9'; const digest = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9';
const metadata = `{
"containerimage.config.digest": "sha256:059b68a595b22564a1cbc167af369349fdc2ecc1f7bc092c2235cbf601a795fd",
"containerimage.digest": "sha256:b09b9482c72371486bb2c1d2c2a2633ed1d0b8389e12c8d52b9e052725c0c83c"
}`;
jest.spyOn(context, 'tmpDir').mockImplementation((): string => { jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
const tmpDir = path.join('/tmp/.docker-build-push-jest').split(path.sep).join(path.posix.sep); const tmpDir = path.join('/tmp/.docker-build-push-jest').split(path.sep).join(path.posix.sep);
@ -32,6 +36,17 @@ describe('getImageID', () => {
}); });
}); });
describe('getMetadata', () => {
it('matches', async () => {
const metadataFile = await buildx.getMetadataFile();
console.log(`metadataFile: ${metadataFile}`);
await fs.writeFileSync(metadataFile, metadata);
const expected = await buildx.getMetadata();
console.log(`metadata: ${expected}`);
expect(expected).toEqual(metadata);
});
});
describe('isLocalOrTarExporter', () => { describe('isLocalOrTarExporter', () => {
// prettier-ignore // prettier-ignore
test.each([ test.each([
@ -92,9 +107,26 @@ describe('isLocalOrTarExporter', () => {
); );
}); });
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', () => {
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.includes(' ') && res.exitCode == 0;
});
} }
(isDaemonRunning() ? it : it.skip)( (isDaemonRunning() ? it : it.skip)(
'valid', 'valid',
@ -111,9 +143,20 @@ describe('parseVersion', () => {
test.each([ test.each([
['github.com/docker/buildx 0.4.1+azure bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'], ['github.com/docker/buildx 0.4.1+azure bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'],
['github.com/docker/buildx v0.4.1 bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'], ['github.com/docker/buildx v0.4.1 bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'],
['github.com/docker/buildx v0.4.2 fb7b670b764764dc4716df3eba07ffdae4cc47b2', '0.4.2'] ['github.com/docker/buildx v0.4.2 fb7b670b764764dc4716df3eba07ffdae4cc47b2', '0.4.2'],
['github.com/docker/buildx f117971 f11797113e5a9b86bd976329c5dbb8a8bfdfadfa', 'f117971']
])('given %p', async (stdout, expected) => { ])('given %p', async (stdout, expected) => {
expect(await buildx.parseVersion(stdout)).toEqual(expected); expect(buildx.parseVersion(stdout)).toEqual(expected);
});
});
describe('satisfies', () => {
test.each([
['0.4.1', '>=0.3.2', true],
['bda4882a65349ca359216b135896bddc1d92461c', '>0.1.0', false],
['f117971', '>0.6.0', true]
])('given %p', async (version, range, expected) => {
expect(buildx.satisfies(version, range)).toBe(expected);
}); });
}); });
@ -125,13 +168,7 @@ describe('getSecret', () => {
['aaaaaaaa', false, '', '', true], ['aaaaaaaa', false, '', '', true],
['aaaaaaaa=', false, '', '', true], ['aaaaaaaa=', false, '', '', true],
['=bbbbbbb', false, '', '', true], ['=bbbbbbb', false, '', '', true],
[ [`foo=${path.join(__dirname, 'fixtures', 'secret.txt').split(path.sep).join(path.posix.sep)}`, true, 'foo', 'bar', false],
`foo=${path.join(__dirname, 'fixtures', 'secret.txt').split(path.sep).join(path.posix.sep)}`,
true,
'foo',
'bar',
false
],
[`notfound=secret`, true, '', '', true] [`notfound=secret`, true, '', '', true]
])('given %p key and %p secret', async (kvp, file, exKey, exValue, invalid) => { ])('given %p key and %p secret', async (kvp, file, exKey, exValue, invalid) => {
try { try {

View File

@ -143,6 +143,10 @@ describe('getArgs', () => {
'0.4.1', '0.4.1',
new Map<string, string>([ new Map<string, string>([
['context', '.'], ['context', '.'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -155,6 +159,10 @@ describe('getArgs', () => {
'0.4.2', '0.4.2',
new Map<string, string>([ new Map<string, string>([
['build-args', 'MY_ARG=val1,val2,val3\nARG=val'], ['build-args', 'MY_ARG=val1,val2,val3\nARG=val'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -169,6 +177,10 @@ describe('getArgs', () => {
'0.4.2', '0.4.2',
new Map<string, string>([ new Map<string, string>([
['tags', 'name/app:7.4, name/app:latest'], ['tags', 'name/app:7.4, name/app:latest'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -184,7 +196,11 @@ describe('getArgs', () => {
new Map<string, string>([ new Map<string, string>([
['context', '.'], ['context', '.'],
['labels', 'org.opencontainers.image.title=buildkit\norg.opencontainers.image.description=concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit'], ['labels', 'org.opencontainers.image.title=buildkit\norg.opencontainers.image.description=concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit'],
['outputs', 'type=local,dest=./release-out'] ['outputs', 'type=local,dest=./release-out'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -199,7 +215,11 @@ describe('getArgs', () => {
'0.4.1', '0.4.1',
new Map<string, string>([ new Map<string, string>([
['context', '.'], ['context', '.'],
['platforms', 'linux/amd64,linux/arm64'] ['platforms', 'linux/amd64,linux/arm64'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -211,7 +231,11 @@ describe('getArgs', () => {
[ [
'0.4.1', '0.4.1',
new Map<string, string>([ new Map<string, string>([
['context', '.'] ['context', '.'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -225,6 +249,10 @@ describe('getArgs', () => {
new Map<string, string>([ new Map<string, string>([
['context', '.'], ['context', '.'],
['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno=0123456789'], ['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno=0123456789'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -238,7 +266,11 @@ describe('getArgs', () => {
'0.4.2', '0.4.2',
new Map<string, string>([ new Map<string, string>([
['github-token', 'abcdefghijklmno0123456789'], ['github-token', 'abcdefghijklmno0123456789'],
['outputs', '.'] ['outputs', '.'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -257,7 +289,10 @@ describe('getArgs', () => {
['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno=0123456789'], ['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno=0123456789'],
['file', './test/Dockerfile'], ['file', './test/Dockerfile'],
['builder', 'builder-git-context-2'], ['builder', 'builder-git-context-2'],
['push', 'true'] ['load', 'false'],
['no-cache', 'false'],
['push', 'true'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -288,7 +323,10 @@ bbbb
ccc"`], ccc"`],
['file', './test/Dockerfile'], ['file', './test/Dockerfile'],
['builder', 'builder-git-context-2'], ['builder', 'builder-git-context-2'],
['push', 'true'] ['load', 'false'],
['no-cache', 'false'],
['push', 'true'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -322,7 +360,10 @@ bbbb
ccc`], ccc`],
['file', './test/Dockerfile'], ['file', './test/Dockerfile'],
['builder', 'builder-git-context-2'], ['builder', 'builder-git-context-2'],
['push', 'true'] ['load', 'false'],
['no-cache', 'false'],
['push', 'true'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -348,7 +389,10 @@ ccc`],
['file', './test/Dockerfile'], ['file', './test/Dockerfile'],
['builder', 'builder-git-context-2'], ['builder', 'builder-git-context-2'],
['network', 'host'], ['network', 'host'],
['push', 'true'] ['load', 'false'],
['no-cache', 'false'],
['push', 'true'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -367,7 +411,11 @@ ccc`],
new Map<string, string>([ new Map<string, string>([
['context', '.'], ['context', '.'],
['labels', 'org.opencontainers.image.title=filter_results_top_n\norg.opencontainers.image.description=Reference implementation of operation "filter results (top-n)"'], ['labels', 'org.opencontainers.image.title=filter_results_top_n\norg.opencontainers.image.description=Reference implementation of operation "filter results (top-n)"'],
['outputs', 'type=local,dest=./release-out'] ['outputs', 'type=local,dest=./release-out'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]), ]),
[ [
'buildx', 'buildx',
@ -377,7 +425,30 @@ ccc`],
'--output', 'type=local,dest=./release-out', '--output', 'type=local,dest=./release-out',
'.' '.'
] ]
] ],
[
'0.6.0',
new Map<string, string>([
['context', '.'],
['tag', 'localhost:5000/name/app:latest'],
['file', './test/Dockerfile'],
['network', 'host'],
['load', 'false'],
['no-cache', 'false'],
['push', 'true'],
['pull', 'false']
]),
[
'buildx',
'build',
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
'--file', './test/Dockerfile',
'--network', 'host',
'--push',
'.'
]
],
])( ])(
'given %p with %p as inputs, returns %p', 'given %p with %p as inputs, returns %p',
async (buildxVersion: string, inputs: Map<string, any>, expected: Array<string>) => { async (buildxVersion: string, inputs: Map<string, any>, expected: Array<string>) => {
@ -517,13 +588,7 @@ FOO=bar`
); );
const res = await context.getInputList('secrets', true); const res = await context.getInputList('secrets', true);
console.log(res); console.log(res);
expect(res).toEqual([ expect(res).toEqual(['GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', 'MYSECRET=aaaaaaaa', 'bbbbbbb', 'ccccccccc', 'FOO=bar']);
'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789',
'MYSECRET=aaaaaaaa',
'bbbbbbb',
'ccccccccc',
'FOO=bar'
]);
}); });
it('large multiline values', async () => { it('large multiline values', async () => {
@ -592,7 +657,7 @@ describe('setOutput', () => {
}); });
}); });
// See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67 // See: https://github.com/actions/toolkit/blob/a1b068ec31a042ff1e10a522d8fdf0b8869d53ca/packages/core/src/core.ts#L89
function getInputName(name: string): string { function getInputName(name: string): string {
return `INPUT_${name.replace(/ /g, '_').toUpperCase()}`; return `INPUT_${name.replace(/ /g, '_').toUpperCase()}`;
} }

View File

@ -79,6 +79,8 @@ inputs:
outputs: outputs:
digest: digest:
description: 'Image content-addressable identifier also called a digest' description: 'Image content-addressable identifier also called a digest'
metadata:
description: 'Build result metadata'
runs: runs:
using: 'node12' using: 'node12'

3
codecov.yml Normal file
View File

@ -0,0 +1,3 @@
comment: false
github_checks:
annotations: false

24234
dist/index.js generated vendored

File diff suppressed because one or more lines are too long

View File

@ -1,13 +1,18 @@
# Cache # Cache
* [Inline cache](#inline-cache)
* [Registry cache](#registry-cache) * [Registry cache](#registry-cache)
* [GitHub cache](#github-cache) * [GitHub cache](#github-cache)
* [Cache backend API](#cache-backend-api)
* [Local cache](#local-cache)
> More info about buildx cache: https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#cache-from > More info about cache on [BuildKit](https://github.com/moby/buildkit#export-cache) and [Buildx](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#cache-from) repositories.
## Registry cache ## Inline cache
You can import/export cache from a cache manifest or (special) image configuration on the registry. In most case you want to use the [`type=inline` cache exporter](https://github.com/moby/buildkit#inline-push-image-and-cache-together).
However, note that the `inline` cache exporter only supports `min` cache mode. To enable `max` cache mode, push the
image and the cache separately by using the `registry` cache exporter as shown in the [next example](#registry-cache).
```yaml ```yaml
name: ci name: ci
@ -44,16 +49,104 @@ jobs:
cache-to: type=inline cache-to: type=inline
``` ```
## Registry cache
You can import/export cache from a cache manifest or (special) image configuration on the registry with the
[`type=registry` cache exporter](https://github.com/moby/buildkit/tree/master#registry-push-image-and-cache-separately).
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: user/app:latest
cache-from: type=registry,ref=user/app:buildcache
cache-to: type=registry,ref=user/app:buildcache,mode=max
```
## GitHub cache ## GitHub cache
### Cache backend API
> :test_tube: This cache exporter is considered EXPERIMENTAL until further notice. Please provide feedback on
> [BuildKit repository](https://github.com/moby/buildkit) if you encounter any issues.
Since [buildx 0.6.0](https://github.com/docker/buildx/releases/tag/v0.6.0) and [BuildKit 0.9.0](https://github.com/moby/buildkit/releases/tag/v0.9.0),
you can use the [`type=gha` cache exporter](https://github.com/moby/buildkit/tree/master#github-actions-cache-experimental).
GitHub Actions cache exporter backend uses the [GitHub Cache API](https://github.com/tonistiigi/go-actions-cache/blob/master/api.md)
to fetch and upload cache blobs. That's why this type of cache should be exclusively used in a GitHub Action workflow
as the `url` (`$ACTIONS_CACHE_URL`) and `token` (`$ACTIONS_RUNTIME_TOKEN`) attributes are populated when a workflow
is started.
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: user/app:latest
cache-from: type=gha
cache-to: type=gha,mode=max
```
### Local cache
> :warning: At the moment caches are copied over the existing cache so it [keeps growing](https://github.com/docker/build-push-action/issues/252). > :warning: At the moment caches are copied over the existing cache so it [keeps growing](https://github.com/docker/build-push-action/issues/252).
> The `Move cache` step is used as a temporary fix (see https://github.com/moby/buildkit/issues/1896). > The `Move cache` step is used as a temporary fix (see https://github.com/moby/buildkit/issues/1896).
> :rocket: There is a new cache backend using GitHub cache being developed that will lighten your workflow. You can also leverage [GitHub cache](https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows)
> More info: https://github.com/docker/buildx/pull/535 using [actions/cache](https://github.com/actions/cache) and [`type=local` cache exporter](https://github.com/moby/buildkit#local-directory-1)
with this action:
You can leverage [GitHub cache](https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows)
using [actions/cache](https://github.com/actions/cache) with this action:
```yaml ```yaml
name: ci name: ci
@ -95,7 +188,7 @@ jobs:
push: true push: true
tags: user/app:latest tags: user/app:latest
cache-from: type=local,src=/tmp/.buildx-cache cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
- -
# Temp fix # Temp fix
# https://github.com/docker/build-push-action/issues/252 # https://github.com/docker/build-push-action/issues/252

View File

@ -1,5 +1,10 @@
# syntax=docker/dockerfile:1.2 # syntax=docker/dockerfile:1.2
ARG NODE_VERSION ARG NODE_VERSION
ARG DOCKER_VERSION=20.10.7
ARG BUILDX_VERSION=0.6.0
FROM docker:${DOCKER_VERSION} as docker
FROM docker/buildx-bin:${BUILDX_VERSION} as buildx
FROM node:${NODE_VERSION}-alpine AS base FROM node:${NODE_VERSION}-alpine AS base
RUN apk add --no-cache git RUN apk add --no-cache git
@ -15,8 +20,8 @@ ENV RUNNER_TEMP=/tmp/github_runner
ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache
RUN --mount=type=bind,target=.,rw \ RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/node_modules \ --mount=type=cache,target=/src/node_modules \
--mount=type=bind,from=crazymax/docker,source=/usr/libexec/docker/cli-plugins/docker-buildx,target=/usr/libexec/docker/cli-plugins/docker-buildx \ --mount=type=bind,from=docker,source=/usr/local/bin/docker,target=/usr/bin/docker \
--mount=type=bind,from=crazymax/docker,source=/usr/local/bin/docker,target=/usr/bin/docker \ --mount=type=bind,from=buildx,source=/buildx,target=/usr/libexec/docker/cli-plugins/docker-buildx \
yarn run test --coverageDirectory=/tmp/coverage yarn run test --coverageDirectory=/tmp/coverage
FROM scratch AS test-coverage FROM scratch AS test-coverage

View File

@ -28,26 +28,26 @@
], ],
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@actions/core": "^1.3.0", "@actions/core": "^1.5.0",
"@actions/exec": "^1.0.4", "@actions/exec": "^1.1.0",
"@actions/github": "^5.0.0", "@actions/github": "^5.0.0",
"csv-parse": "^4.15.4", "csv-parse": "^4.16.0",
"semver": "^7.3.5", "semver": "^7.3.5",
"tmp": "^0.2.1" "tmp": "^0.2.1"
}, },
"devDependencies": { "devDependencies": {
"@types/csv-parse": "^1.2.2", "@types/csv-parse": "^1.2.2",
"@types/jest": "^26.0.3", "@types/jest": "^26.0.23",
"@types/node": "^14.0.14", "@types/node": "^14.17.4",
"@types/tmp": "^0.2.0", "@types/tmp": "^0.2.0",
"@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

@ -2,9 +2,9 @@ import csvparse from 'csv-parse/lib/sync';
import fs from 'fs'; 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 context from './context'; import * as context from './context';
import * as exec from './exec';
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);
@ -18,6 +18,18 @@ export async function getImageID(): Promise<string | undefined> {
return fs.readFileSync(iidFile, {encoding: 'utf-8'}); return fs.readFileSync(iidFile, {encoding: 'utf-8'});
} }
export async function getMetadataFile(): Promise<string> {
return path.join(context.tmpDir(), 'metadata-file').split(path.sep).join(path.posix.sep);
}
export async function getMetadata(): Promise<string | undefined> {
const metadataFile = await getMetadataFile();
if (!fs.existsSync(metadataFile)) {
return undefined;
}
return fs.readFileSync(metadataFile, {encoding: 'utf-8'});
}
export async function getSecretString(kvp: string): Promise<string> { export async function getSecretString(kvp: string): Promise<string> {
return getSecret(kvp, false); return getSecret(kvp, false);
} }
@ -80,27 +92,41 @@ export function hasGitAuthToken(secrets: string[]): Boolean {
} }
export async function isAvailable(): Promise<Boolean> { export async function isAvailable(): Promise<Boolean> {
return await exec.exec(`docker`, ['buildx'], true).then(res => { return await exec
if (res.stderr != '' && !res.success) { .getExecOutput('docker', ['buildx'], {
return false; ignoreReturnCode: true,
} silent: true
return res.success; })
}); .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 function parseVersion(stdout: string): string {
const matches = /\sv?([0-9.]+)/.exec(stdout); const matches = /\sv?([0-9a-f]{7}|[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 matches[1];
}
export function satisfies(version: string, range: string): boolean {
return semver.satisfies(version, range) || /^[0-9a-f]{7}$/.exec(version) !== null;
} }

View File

@ -2,7 +2,6 @@ import csvparse from 'csv-parse/lib/sync';
import * as fs from 'fs'; import * as fs from 'fs';
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 tmp from 'tmp'; import * as tmp from 'tmp';
import * as core from '@actions/core'; import * as core from '@actions/core';
@ -46,9 +45,7 @@ export function defaultContext(): string {
if (github.context.sha && !ref.startsWith(`refs/pull/`)) { if (github.context.sha && !ref.startsWith(`refs/pull/`)) {
ref = github.context.sha; ref = github.context.sha;
} }
_defaultContext = `${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${ _defaultContext = `${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${github.context.repo.repo}.git#${ref}`;
github.context.repo.repo
}.git#${ref}`;
} }
return _defaultContext; return _defaultContext;
} }
@ -74,13 +71,13 @@ export async function getInputs(defaultContext: string): Promise<Inputs> {
context: core.getInput('context') || defaultContext, context: core.getInput('context') || defaultContext,
file: core.getInput('file'), file: core.getInput('file'),
labels: await getInputList('labels', true), labels: await getInputList('labels', true),
load: /true/i.test(core.getInput('load')), load: core.getBooleanInput('load'),
network: core.getInput('network'), network: core.getInput('network'),
noCache: /true/i.test(core.getInput('no-cache')), noCache: core.getBooleanInput('no-cache'),
outputs: await getInputList('outputs', true), outputs: await getInputList('outputs', true),
platforms: await getInputList('platforms'), platforms: await getInputList('platforms'),
pull: /true/i.test(core.getInput('pull')), pull: core.getBooleanInput('pull'),
push: /true/i.test(core.getInput('push')), push: core.getBooleanInput('push'),
secrets: await getInputList('secrets', true), secrets: await getInputList('secrets', true),
secretFiles: await getInputList('secret-files', true), secretFiles: await getInputList('secret-files', true),
ssh: await getInputList('ssh'), ssh: await getInputList('ssh'),
@ -121,12 +118,12 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, buildxVersio
await asyncForEach(inputs.outputs, async output => { await asyncForEach(inputs.outputs, async output => {
args.push('--output', output); args.push('--output', output);
}); });
if ( if (!buildx.isLocalOrTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || buildx.satisfies(buildxVersion, '>=0.4.2'))) {
!buildx.isLocalOrTarExporter(inputs.outputs) &&
(inputs.platforms.length == 0 || semver.satisfies(buildxVersion, '>=0.4.2'))
) {
args.push('--iidfile', await buildx.getImageIDFile()); args.push('--iidfile', await buildx.getImageIDFile());
} }
if (buildx.satisfies(buildxVersion, '>=0.6.0')) {
args.push('--metadata-file', await buildx.getMetadataFile());
}
await asyncForEach(inputs.cacheFrom, async cacheFrom => { await asyncForEach(inputs.cacheFrom, async cacheFrom => {
args.push('--cache-from', cacheFrom); args.push('--cache-from', cacheFrom);
}); });

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,9 +1,9 @@
import * as fs from 'fs'; import * as fs from 'fs';
import * as buildx from './buildx'; import * as buildx from './buildx';
import * as context from './context'; import * as context from './context';
import * as exec from './exec';
import * as stateHelper from './state-helper'; import * as stateHelper from './state-helper';
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as exec from '@actions/exec';
async function run(): Promise<void> { async function run(): Promise<void> {
try { try {
@ -23,19 +23,28 @@ async function run(): Promise<void> {
let inputs: context.Inputs = await context.getInputs(defContext); let inputs: context.Inputs = await context.getInputs(defContext);
const args: string[] = await context.getArgs(inputs, defContext, buildxVersion); const args: string[] = await context.getArgs(inputs, defContext, buildxVersion);
await exec.exec('docker', args).then(res => { await exec
if (res.stderr != '' && !res.success) { .getExecOutput('docker', args, {
throw new Error(`buildx call failed with: ${res.stderr.match(/(.*)\s*$/)![0]}`); ignoreReturnCode: true
})
.then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
throw new Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)![0].trim()}`);
}
});
await core.group(`Setting outputs`, async () => {
const imageID = await buildx.getImageID();
const metadata = await buildx.getMetadata();
if (imageID) {
core.info(`digest=${imageID}`);
context.setOutput('digest', imageID);
}
if (metadata) {
core.info(`metadata=${metadata}`);
context.setOutput('metadata', metadata);
} }
}); });
const imageID = await buildx.getImageID();
if (imageID) {
core.startGroup(`Extracting digest`);
core.info(`${imageID}`);
context.setOutput('digest', imageID);
core.endGroup();
}
} catch (error) { } catch (error) {
core.setFailed(error.message); core.setFailed(error.message);
} }

2092
yarn.lock

File diff suppressed because it is too large Load Diff