mirror of
https://github.com/docker/build-push-action.git
synced 2025-04-01 20:50:09 +02:00
Merge branch 'master' into patch-1
Signed-off-by: Nitesh Oswal <nit.oswal@gmail.com>
This commit is contained in:
commit
b1339bc24d
14 changed files with 2178 additions and 390 deletions
206
.github/workflows/ci.yml
vendored
206
.github/workflows/ci.yml
vendored
|
@ -1,6 +1,7 @@
|
|||
name: ci
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
@ -9,6 +10,27 @@ on:
|
|||
- master
|
||||
|
||||
jobs:
|
||||
minimal:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2.3.3
|
||||
with:
|
||||
path: action
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Build
|
||||
uses: ./action
|
||||
with:
|
||||
file: ./test/Dockerfile
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
uses: crazy-max/ghaction-dump-context@v1
|
||||
|
||||
git-context:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
|
@ -25,8 +47,6 @@ jobs:
|
|||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: all
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
|
@ -53,6 +73,13 @@ jobs:
|
|||
-
|
||||
name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
-
|
||||
name: Check digest
|
||||
run: |
|
||||
if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
|
||||
echo "::error::Digest should not be empty"
|
||||
exit 1
|
||||
fi
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
|
@ -74,14 +101,11 @@ jobs:
|
|||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: all
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
version: ${{ matrix.buildx-version }}
|
||||
driver-opts: network=host
|
||||
-
|
||||
name: Build and push
|
||||
|
@ -104,6 +128,13 @@ jobs:
|
|||
-
|
||||
name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
-
|
||||
name: Check digest
|
||||
run: |
|
||||
if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
|
||||
echo "::error::Digest should not be empty"
|
||||
exit 1
|
||||
fi
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
|
@ -129,8 +160,6 @@ jobs:
|
|||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: all
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
|
@ -157,6 +186,115 @@ jobs:
|
|||
-
|
||||
name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
-
|
||||
name: Check digest
|
||||
run: |
|
||||
if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
|
||||
echo "::error::Digest should not be empty"
|
||||
exit 1
|
||||
fi
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
uses: crazy-max/ghaction-dump-context@v1
|
||||
|
||||
error:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2.3.3
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Build
|
||||
id: docker_build
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
context: ./test
|
||||
file: ./test/Dockerfile
|
||||
platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
|
||||
push: true
|
||||
tags: localhost:5000/name/app:latest
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
echo "${{ toJson(steps.docker_build) }}"
|
||||
if [ "${{ steps.docker_build.outcome }}" != "failure" ] || [ "${{ steps.docker_build.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
uses: crazy-max/ghaction-dump-context@v1
|
||||
|
||||
docker-driver:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
push:
|
||||
- true
|
||||
- false
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
ports:
|
||||
- 5000:5000
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2.3.3
|
||||
-
|
||||
name: Build
|
||||
id: docker_build
|
||||
continue-on-error: ${{ matrix.push }}
|
||||
uses: ./
|
||||
with:
|
||||
context: ./test
|
||||
file: ./test/Dockerfile
|
||||
push: ${{ matrix.push }}
|
||||
tags: localhost:5000/name/app:latest
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
echo "${{ toJson(steps.docker_build) }}"
|
||||
if [ "${{ matrix.push }}" = "false" ]; then
|
||||
exit 0
|
||||
fi
|
||||
if [ "${{ steps.docker_build.outcome }}" != "failure" ] || [ "${{ steps.docker_build.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
uses: crazy-max/ghaction-dump-context@v1
|
||||
|
||||
export-docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2.3.3
|
||||
-
|
||||
name: Build
|
||||
uses: ./
|
||||
with:
|
||||
context: ./test
|
||||
file: ./test/Dockerfile
|
||||
load: true
|
||||
tags: myimage:latest
|
||||
-
|
||||
name: Inspect
|
||||
run: |
|
||||
docker image inspect myimage:latest
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
|
@ -185,8 +323,6 @@ jobs:
|
|||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: all
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
|
@ -214,6 +350,13 @@ jobs:
|
|||
-
|
||||
name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
-
|
||||
name: Check digest
|
||||
run: |
|
||||
if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
|
||||
echo "::error::Digest should not be empty"
|
||||
exit 1
|
||||
fi
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
|
@ -233,13 +376,12 @@ jobs:
|
|||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: all
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
# TODO: Remove image=moby/buildkit:buildx-stable-1 when moby/buildkit#1727 fixed
|
||||
driver-opts: |
|
||||
network=host
|
||||
image=moby/buildkit:buildx-stable-1
|
||||
|
@ -265,6 +407,13 @@ jobs:
|
|||
-
|
||||
name: Image digest (1)
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
-
|
||||
name: Check digest (1)
|
||||
run: |
|
||||
if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
|
||||
echo "::error::Digest should not be empty"
|
||||
exit 1
|
||||
fi
|
||||
-
|
||||
name: Prune
|
||||
run: |
|
||||
|
@ -292,7 +441,14 @@ jobs:
|
|||
name: Image digest (2)
|
||||
run: echo ${{ steps.docker_build2.outputs.digest }}
|
||||
-
|
||||
name: Check digests
|
||||
name: Check digest (2)
|
||||
run: |
|
||||
if [ -z "${{ steps.docker_build2.outputs.digest }}" ]; then
|
||||
echo "::error::Digest should not be empty"
|
||||
exit 1
|
||||
fi
|
||||
-
|
||||
name: Compare digests
|
||||
run: |
|
||||
echo Compare "${{ steps.docker_build.outputs.digest }}" with "${{ steps.docker_build2.outputs.digest }}"
|
||||
if [ "${{ steps.docker_build.outputs.digest }}" != "${{ steps.docker_build2.outputs.digest }}" ]; then
|
||||
|
@ -320,13 +476,12 @@ jobs:
|
|||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: all
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
# TODO: Remove image=moby/buildkit:buildx-stable-1 when moby/buildkit#1727 fixed
|
||||
driver-opts: |
|
||||
network=host
|
||||
image=moby/buildkit:buildx-stable-1
|
||||
|
@ -348,7 +503,7 @@ jobs:
|
|||
uses: ./
|
||||
with:
|
||||
context: ./test
|
||||
file: ./test/Dockerfile-multi-golang
|
||||
file: ./test/Dockerfile-multi
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
|
@ -364,6 +519,13 @@ jobs:
|
|||
-
|
||||
name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
-
|
||||
name: Check digest
|
||||
run: |
|
||||
if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
|
||||
echo "::error::Digest should not be empty"
|
||||
exit 1
|
||||
fi
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
|
@ -384,13 +546,12 @@ jobs:
|
|||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: all
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
# TODO: Remove image=moby/buildkit:buildx-stable-1 when moby/buildkit#1727 fixed
|
||||
driver-opts: |
|
||||
network=host
|
||||
image=moby/buildkit:buildx-stable-1
|
||||
|
@ -409,7 +570,7 @@ jobs:
|
|||
uses: ./
|
||||
with:
|
||||
context: ./test
|
||||
file: ./test/Dockerfile-multi-golang
|
||||
file: ./test/Dockerfile-multi
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
|
@ -426,7 +587,14 @@ jobs:
|
|||
name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
-
|
||||
name: Check digests
|
||||
name: Check digest
|
||||
run: |
|
||||
if [ -z "${{ steps.docker_build.outputs.digest }}" ]; then
|
||||
echo "::error::Digest should not be empty"
|
||||
exit 1
|
||||
fi
|
||||
-
|
||||
name: Compare digests
|
||||
run: |
|
||||
echo Compare "${{ needs.github-cache-first.outputs.digest }}" with "${{ steps.docker_build.outputs.digest }}"
|
||||
if [ "${{ needs.github-cache-first.outputs.digest }}" != "${{ steps.docker_build.outputs.digest }}" ]; then
|
||||
|
|
130
README.md
130
README.md
|
@ -7,10 +7,10 @@
|
|||
## Upgrade from v1
|
||||
|
||||
`v2` of this action includes significant updates and now uses Docker [Buildx](https://github.com/docker/buildx). It
|
||||
works with 3 new optional actions ([login](https://github.com/docker/login-action), [setup-buildx](https://github.com/docker/setup-buildx-action)
|
||||
works with 3 new actions ([login](https://github.com/docker/login-action), [setup-buildx](https://github.com/docker/setup-buildx-action)
|
||||
and [setup-qemu](https://github.com/docker/setup-qemu-action)) that we have created. It's also rewritten as a
|
||||
[typescript-action](https://github.com/actions/typescript-action/) to be as close as possible of the
|
||||
[GitHub Runner](https://github.com/actions/virtual-environments) during its execution (#71 #92).
|
||||
[typescript-action](https://github.com/actions/typescript-action/) to be as closed as possible of the
|
||||
[GitHub Runner](https://github.com/actions/virtual-environments) during its execution.
|
||||
|
||||
[Upgrade notes](UPGRADE.md) and many [usage examples](#usage) have been added to handle most use cases but `v1` is
|
||||
still available through [`releases/v1` branch](https://github.com/docker/build-push-action/tree/releases/v1).
|
||||
|
@ -37,6 +37,7 @@ ___
|
|||
* [Push to multi-registries](#push-to-multi-registries)
|
||||
* [Cache to registry](#push-to-multi-registries)
|
||||
* [Local registry](#local-registry)
|
||||
* [Export image to Docker](#export-image-to-docker)
|
||||
* [Leverage GitHub cache](#leverage-github-cache)
|
||||
* [Complete workflow](#complete-workflow)
|
||||
* [Update DockerHub repo description](#update-dockerhub-repo-description)
|
||||
|
@ -56,7 +57,8 @@ build-secrets, remote cache, etc. and different builder deployment/namespacing o
|
|||
|
||||
### Git context
|
||||
|
||||
The default behavior of this action is to use the [Git context invoked by your workflow](https://github.com/docker/build-push-action/blob/master/src/context.ts#L10-L12).
|
||||
The default behavior of this action is to use the [Git context invoked](https://github.com/docker/build-push-action/blob/master/src/context.ts#L31-L35)
|
||||
by your workflow.
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
@ -88,6 +90,9 @@ jobs:
|
|||
with:
|
||||
push: true
|
||||
tags: user/app:latest
|
||||
build-args: |
|
||||
arg1=value1
|
||||
arg2=value2
|
||||
-
|
||||
name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
|
@ -377,6 +382,46 @@ For testing purposes you may need to create a [local registry](https://hub.docke
|
|||
```
|
||||
</details>
|
||||
|
||||
### Export image to Docker
|
||||
|
||||
You may want your build result to be available in the Docker client through `docker images` to be able to use it
|
||||
in another step of your workflow:
|
||||
|
||||
<details>
|
||||
<summary><b>Show workflow</b></summary>
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: master
|
||||
|
||||
jobs:
|
||||
export-docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
load: true
|
||||
tags: myimage:latest
|
||||
-
|
||||
name: Inspect
|
||||
run: |
|
||||
docker image inspect myimage:latest
|
||||
```
|
||||
</details>
|
||||
|
||||
### Leverage GitHub cache
|
||||
|
||||
You can leverage [GitHub cache](https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows)
|
||||
|
@ -424,15 +469,20 @@ using [actions/cache](https://github.com/actions/cache) with this action:
|
|||
```
|
||||
</details>
|
||||
|
||||
> If you want to [export layers for all stages](https://github.com/docker/buildx#--cache-tonametypetypekeyvalue),
|
||||
> you have to specify `mode=max` attribute in `cache-to`.
|
||||
|
||||
### Complete workflow
|
||||
|
||||
If you come from [`v1`](https://github.com/docker/build-push-action/tree/releases/v1#readme) and you want an
|
||||
If you come from [`v1`](https://github.com/docker/build-push-action/tree/releases/v1#readme) and want an
|
||||
"automatic" tag management through Git reference and [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/master/annotations.md)
|
||||
for labels, you will have to do it in a dedicated step [for now](https://github.com/docker/build-push-action/issues/116).
|
||||
for labels, you will have to do it in a dedicated step.
|
||||
|
||||
The following workflow with the `Prepare` step will generate some [outputs](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjobs_idoutputs)
|
||||
to handle tags and labels based on GitHub actions events. This is just an example to show many cases that you
|
||||
might want to use:
|
||||
to handle tags and labels based on GitHub actions events.
|
||||
|
||||
This is just an example to show many cases that you might want to use and that you will have to adapt according
|
||||
to your needs:
|
||||
|
||||
<details>
|
||||
<summary><b>Show workflow</b></summary>
|
||||
|
@ -540,8 +590,8 @@ might want to use:
|
|||
|
||||
### Update DockerHub repo description
|
||||
|
||||
You can update the [Docker Hub repository description](https://docs.docker.com/docker-hub/repos/) using
|
||||
a third-party action called [Docker Hub Description](https://github.com/peter-evans/dockerhub-description)
|
||||
You can update the [DockerHub repository description](https://docs.docker.com/docker-hub/repos/) using
|
||||
a third-party action called [DockerHub Description](https://github.com/peter-evans/dockerhub-description)
|
||||
with this action:
|
||||
|
||||
<details>
|
||||
|
@ -592,46 +642,38 @@ with this action:
|
|||
|
||||
Following inputs can be used as `step.with` keys
|
||||
|
||||
| Name | Type | Description |
|
||||
|---------------------|---------|------------------------------------|
|
||||
| `builder` | String | Builder instance (see [setup-buildx](https://github.com/docker/setup-buildx-action) action) |
|
||||
| `context` | String | Build's context is the set of files located in the specified [`PATH` or `URL`](https://docs.docker.com/engine/reference/commandline/build/) (default [Git context](#git-context)) |
|
||||
| `file` | String | Path to the Dockerfile (default `Dockerfile`) |
|
||||
| `build-args` | List | List of build-time variables |
|
||||
| `labels` | List | List of metadata for an image |
|
||||
| `tags` | List | List of tags |
|
||||
| `pull` | Bool | Always attempt to pull a newer version of the image (default `false`) |
|
||||
| `target` | String | Sets the target stage to build |
|
||||
| `allow` | List | List of [extra privileged entitlement](https://github.com/docker/buildx#--allowentitlement) (eg. `network.host,security.insecure`) |
|
||||
| `no-cache` | Bool | Do not use cache when building the image (default `false`) |
|
||||
| `platforms` | List | List of [target platforms](https://github.com/docker/buildx#---platformvaluevalue) for build |
|
||||
| `load` | Bool | [Load](https://github.com/docker/buildx#--load) is a shorthand for `--output=type=docker` (default `false`) |
|
||||
| `push` | Bool | [Push](https://github.com/docker/buildx#--push) is a shorthand for `--output=type=registry` (default `false`) |
|
||||
| `outputs` | CSV | List of [output destinations](https://github.com/docker/buildx#-o---outputpath-typetypekeyvalue) (format: `type=local,dest=path`) |
|
||||
| `cache-from` | CSV | List of [external cache sources](https://github.com/docker/buildx#--cache-fromnametypetypekeyvalue) (eg. `type=local,src=path/to/dir`) |
|
||||
| `cache-to` | CSV | List of [cache export destinations](https://github.com/docker/buildx#--cache-tonametypetypekeyvalue) (eg. `type=local,dest=path/to/dir`) |
|
||||
| `secrets` | CSV | List of secrets to expose to the build (eg. `key=value`, `GIT_AUTH_TOKEN=mytoken`) |
|
||||
|
||||
> `List` type can be a comma or newline-delimited string
|
||||
> ```yaml
|
||||
> tags: name/app:latest,name/app:1.0.0
|
||||
> ```
|
||||
> ```yaml
|
||||
> tags: |
|
||||
> name/app:latest
|
||||
> name/app:1.0.0
|
||||
> ```
|
||||
|
||||
> `CSV` type must be a newline-delimited string
|
||||
> ```yaml
|
||||
> cache-from: user/app:cache
|
||||
> ```
|
||||
> `List` type is a newline-delimited string
|
||||
> ```yaml
|
||||
> cache-from: |
|
||||
> user/app:cache
|
||||
> type=local,src=path/to/dir
|
||||
> ```
|
||||
|
||||
> `CSV` type is a comma-delimited string
|
||||
> ```yaml
|
||||
> tags: name/app:latest,name/app:1.0.0
|
||||
> ```
|
||||
|
||||
| Name | Type | Description |
|
||||
|---------------------|----------|------------------------------------|
|
||||
| `builder` | String | Builder instance (see [setup-buildx](https://github.com/docker/setup-buildx-action) action) |
|
||||
| `context` | String | Build's context is the set of files located in the specified [`PATH` or `URL`](https://docs.docker.com/engine/reference/commandline/build/) (default [Git context](#git-context)) |
|
||||
| `file` | String | Path to the Dockerfile (default `Dockerfile`) |
|
||||
| `build-args` | List | List of build-time variables |
|
||||
| `labels` | List | List of metadata for an image |
|
||||
| `tags` | List/CSV | List of tags |
|
||||
| `pull` | Bool | Always attempt to pull a newer version of the image (default `false`) |
|
||||
| `target` | String | Sets the target stage to build |
|
||||
| `allow` | List/CSV | List of [extra privileged entitlement](https://github.com/docker/buildx#--allowentitlement) (eg. `network.host,security.insecure`) |
|
||||
| `no-cache` | Bool | Do not use cache when building the image (default `false`) |
|
||||
| `platforms` | List/CSV | List of [target platforms](https://github.com/docker/buildx#---platformvaluevalue) for build |
|
||||
| `load` | Bool | [Load](https://github.com/docker/buildx#--load) is a shorthand for `--output=type=docker` (default `false`) |
|
||||
| `push` | Bool | [Push](https://github.com/docker/buildx#--push) is a shorthand for `--output=type=registry` (default `false`) |
|
||||
| `outputs` | List | List of [output destinations](https://github.com/docker/buildx#-o---outputpath-typetypekeyvalue) (format: `type=local,dest=path`) |
|
||||
| `cache-from` | List | List of [external cache sources](https://github.com/docker/buildx#--cache-fromnametypetypekeyvalue) (eg. `type=local,src=path/to/dir`) |
|
||||
| `cache-to` | List | List of [cache export destinations](https://github.com/docker/buildx#--cache-tonametypetypekeyvalue) (eg. `type=local,dest=path/to/dir`) |
|
||||
| `secrets` | List | List of secrets to expose to the build (eg. `key=value`, `GIT_AUTH_TOKEN=mytoken`) |
|
||||
|
||||
### outputs
|
||||
|
||||
Following outputs are available
|
||||
|
|
|
@ -65,7 +65,9 @@ steps:
|
|||
file: ./Dockerfile
|
||||
pull: true
|
||||
push: true
|
||||
build-args: arg1=value1,arg2=value2
|
||||
build-args: |
|
||||
arg1=value1
|
||||
arg2=value2
|
||||
cache-from: type=registry,ref=myorg/myrepository:latest
|
||||
cache-to: type=inline
|
||||
tags: myorg/myrepository:latest
|
||||
|
|
|
@ -1,10 +1,24 @@
|
|||
import fs from 'fs';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as buildx from '../src/buildx';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as context from '../src/context';
|
||||
|
||||
const digest = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9';
|
||||
|
||||
jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
|
||||
const tmpDir = path.join('/tmp/.docker-build-push-jest').split(path.sep).join(path.posix.sep);
|
||||
if (!fs.existsSync(tmpDir)) {
|
||||
fs.mkdirSync(tmpDir, {recursive: true});
|
||||
}
|
||||
return tmpDir;
|
||||
});
|
||||
|
||||
jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => {
|
||||
return path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
|
||||
});
|
||||
|
||||
describe('getImageID', () => {
|
||||
it('matches', async () => {
|
||||
const imageIDFile = await buildx.getImageIDFile();
|
||||
|
@ -16,9 +30,68 @@ describe('getImageID', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('isLocalOrTarExporter', () => {
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[
|
||||
[
|
||||
'type=registry,ref=user/app',
|
||||
],
|
||||
false
|
||||
],
|
||||
[
|
||||
[
|
||||
'type=docker',
|
||||
],
|
||||
false
|
||||
],
|
||||
[
|
||||
[
|
||||
'type=local,dest=./release-out'
|
||||
],
|
||||
true
|
||||
],
|
||||
[
|
||||
[
|
||||
'type=tar,dest=/tmp/image.tar'
|
||||
],
|
||||
true
|
||||
],
|
||||
[
|
||||
[
|
||||
'type=docker',
|
||||
'type=tar,dest=/tmp/image.tar'
|
||||
],
|
||||
true
|
||||
],
|
||||
[
|
||||
[
|
||||
'"type=tar","dest=/tmp/image.tar"'
|
||||
],
|
||||
true
|
||||
],
|
||||
[
|
||||
[
|
||||
'" type= local" , dest=./release-out'
|
||||
],
|
||||
true
|
||||
],
|
||||
[
|
||||
[
|
||||
'.'
|
||||
],
|
||||
true
|
||||
],
|
||||
])(
|
||||
'given %p returns %p',
|
||||
async (outputs: Array<string>, expected: boolean) => {
|
||||
expect(buildx.isLocalOrTarExporter(outputs)).toEqual(expected);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('getVersion', () => {
|
||||
it('valid', async () => {
|
||||
await exec.exec('docker', ['buildx', 'version']);
|
||||
const version = await buildx.getVersion();
|
||||
console.log(`version: ${version}`);
|
||||
expect(semver.valid(version)).not.toBeNull();
|
||||
|
|
|
@ -1,5 +1,177 @@
|
|||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as buildx from '../src/buildx';
|
||||
import * as context from '../src/context';
|
||||
|
||||
jest.spyOn(context, 'defaultContext').mockImplementation((): string => {
|
||||
return 'https://github.com/docker/build-push-action.git#test-jest';
|
||||
});
|
||||
|
||||
jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
|
||||
const tmpDir = path.join('/tmp/.docker-build-push-jest').split(path.sep).join(path.posix.sep);
|
||||
if (!fs.existsSync(tmpDir)) {
|
||||
fs.mkdirSync(tmpDir, {recursive: true});
|
||||
}
|
||||
return tmpDir;
|
||||
});
|
||||
|
||||
jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => {
|
||||
return path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
|
||||
});
|
||||
|
||||
describe('getArgs', () => {
|
||||
beforeEach(() => {
|
||||
process.env = Object.keys(process.env).reduce((object, key) => {
|
||||
if (!key.startsWith('INPUT_')) {
|
||||
object[key] = process.env[key];
|
||||
}
|
||||
return object;
|
||||
}, {});
|
||||
});
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[
|
||||
'0.4.1',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
]),
|
||||
[
|
||||
'buildx',
|
||||
'build',
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--file', 'Dockerfile',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
'0.4.2',
|
||||
new Map<string, string>([
|
||||
['build-args', 'MY_ARG=val1,val2,val3\nARG=val'],
|
||||
]),
|
||||
[
|
||||
'buildx',
|
||||
'build',
|
||||
'--build-arg', 'MY_ARG=val1,val2,val3',
|
||||
'--build-arg', 'ARG=val',
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--file', 'Dockerfile',
|
||||
'https://github.com/docker/build-push-action.git#test-jest'
|
||||
]
|
||||
],
|
||||
[
|
||||
'0.4.2',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['labels', 'org.opencontainers.image.title=buildkit\norg.opencontainers.image.description=concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit'],
|
||||
['outputs', 'type=local,dest=./release-out']
|
||||
]),
|
||||
[
|
||||
'buildx',
|
||||
'build',
|
||||
'--label', 'org.opencontainers.image.title=buildkit',
|
||||
'--label', 'org.opencontainers.image.description=concurrent, cache-efficient, and Dockerfile-agnostic builder toolkit',
|
||||
'--output', 'type=local,dest=./release-out',
|
||||
'--file', 'Dockerfile',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
'0.4.1',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['platforms', 'linux/amd64,linux/arm64']
|
||||
]),
|
||||
[
|
||||
'buildx',
|
||||
'build',
|
||||
'--platform', 'linux/amd64,linux/arm64',
|
||||
'--file', 'Dockerfile',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
'0.4.1',
|
||||
new Map<string, string>([
|
||||
['context', '.']
|
||||
]),
|
||||
[
|
||||
'buildx',
|
||||
'build',
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--file', 'Dockerfile',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
'0.4.2',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno0123456789'],
|
||||
]),
|
||||
[
|
||||
'buildx',
|
||||
'build',
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--file', 'Dockerfile',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
'0.4.2',
|
||||
new Map<string, string>([
|
||||
['github-token', 'abcdefghijklmno0123456789'],
|
||||
['outputs', '.']
|
||||
]),
|
||||
[
|
||||
'buildx',
|
||||
'build',
|
||||
'--output', '.',
|
||||
'--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--file', 'Dockerfile',
|
||||
'https://github.com/docker/build-push-action.git#test-jest'
|
||||
]
|
||||
],
|
||||
[
|
||||
'0.4.2',
|
||||
new Map<string, string>([
|
||||
['context', 'https://github.com/docker/build-push-action.git#heads/master'],
|
||||
['tag', 'localhost:5000/name/app:latest'],
|
||||
['platforms', 'linux/amd64,linux/arm64'],
|
||||
['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno0123456789'],
|
||||
['file', './test/Dockerfile'],
|
||||
['builder', 'builder-git-context-2'],
|
||||
['push', 'true']
|
||||
]),
|
||||
[
|
||||
'buildx',
|
||||
'build',
|
||||
'--platform', 'linux/amd64,linux/arm64',
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--file', './test/Dockerfile',
|
||||
'--builder', 'builder-git-context-2',
|
||||
'--push',
|
||||
'https://github.com/docker/build-push-action.git#heads/master'
|
||||
]
|
||||
]
|
||||
])(
|
||||
'given %p with %p as inputs, returns %p',
|
||||
async (buildxVersion: string, inputs: Map<string, any>, expected: Array<string>) => {
|
||||
await inputs.forEach((value: string, name: string) => {
|
||||
setInput(name, value);
|
||||
});
|
||||
const defContext = context.defaultContext();
|
||||
const inp = await context.getInputs(defContext);
|
||||
console.log(inp);
|
||||
const res = await context.getArgs(inp, defContext, buildxVersion);
|
||||
console.log(res);
|
||||
expect(res).toEqual(expected);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('getInputList', () => {
|
||||
it('handles single line correctly', async () => {
|
||||
await setInput('foo', 'bar');
|
||||
|
|
1819
dist/index.js
generated
vendored
1819
dist/index.js
generated
vendored
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
|||
module.exports = {
|
||||
clearMocks: true,
|
||||
clearMocks: false,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
setupFiles: ["dotenv/config"],
|
||||
testEnvironment: 'node',
|
||||
|
|
|
@ -31,10 +31,12 @@
|
|||
"@actions/core": "^1.2.6",
|
||||
"@actions/exec": "^1.0.4",
|
||||
"@actions/github": "^4.0.0",
|
||||
"csv-parse": "^4.12.0",
|
||||
"semver": "^7.3.2",
|
||||
"tmp": "^0.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/csv-parse": "^1.2.2",
|
||||
"@types/jest": "^26.0.3",
|
||||
"@types/node": "^14.0.14",
|
||||
"@types/tmp": "^0.2.0",
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import tmp from 'tmp';
|
||||
import csvparse from 'csv-parse/lib/sync';
|
||||
import * as semver from 'semver';
|
||||
import * as context from './context';
|
||||
import * as exec from './exec';
|
||||
|
||||
export async function getImageIDFile(): Promise<string> {
|
||||
return path.join(context.tmpDir, 'iidfile');
|
||||
return path.join(context.tmpDir(), 'iidfile').split(path.sep).join(path.posix.sep);
|
||||
}
|
||||
|
||||
export async function getImageID(): Promise<string | undefined> {
|
||||
|
@ -19,13 +19,43 @@ export async function getImageID(): Promise<string | undefined> {
|
|||
|
||||
export async function getSecret(kvp: string): Promise<string> {
|
||||
const [key, value] = kvp.split('=');
|
||||
const secretFile = tmp.tmpNameSync({
|
||||
tmpdir: context.tmpDir
|
||||
const secretFile = context.tmpNameSync({
|
||||
tmpdir: context.tmpDir()
|
||||
});
|
||||
await fs.writeFileSync(secretFile, value);
|
||||
return `id=${key},src=${secretFile}`;
|
||||
}
|
||||
|
||||
export function isLocalOrTarExporter(outputs: string[]): Boolean {
|
||||
for (let output of csvparse(outputs.join(`\n`), {
|
||||
delimiter: ',',
|
||||
trim: true,
|
||||
columns: false,
|
||||
relax_column_count: true
|
||||
})) {
|
||||
// Local if no type is defined
|
||||
// https://github.com/docker/buildx/blob/d2bf42f8b4784d83fde17acb3ed84703ddc2156b/build/output.go#L29-L43
|
||||
if (output.length == 1 && !output[0].startsWith('type=')) {
|
||||
return true;
|
||||
}
|
||||
for (let [key, value] of output.map(chunk => chunk.split('=').map(item => item.trim()))) {
|
||||
if (key == 'type' && (value == 'local' || value == 'tar')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function hasGitAuthToken(secrets: string[]): Boolean {
|
||||
for (let secret of secrets) {
|
||||
if (secret.startsWith('GIT_AUTH_TOKEN=')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function isAvailable(): Promise<Boolean> {
|
||||
return await exec.exec(`docker`, ['buildx'], true).then(res => {
|
||||
if (res.stderr != '' && !res.success) {
|
||||
|
|
|
@ -2,14 +2,12 @@ import * as fs from 'fs';
|
|||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as tmp from 'tmp';
|
||||
import * as buildx from './buildx';
|
||||
import * as core from '@actions/core';
|
||||
import * as github from '@actions/github';
|
||||
|
||||
export const tmpDir: string = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-build-push-'));
|
||||
const defaultContext: string = `https://github.com/${github.context.repo.owner}/${
|
||||
github.context.repo.repo
|
||||
}.git#${github.context.ref.replace(/^refs\//, '')}`;
|
||||
let _defaultContext, _tmpDir: string;
|
||||
|
||||
export interface Inputs {
|
||||
context: string;
|
||||
|
@ -32,12 +30,32 @@ export interface Inputs {
|
|||
githubToken: string;
|
||||
}
|
||||
|
||||
export async function getInputs(): Promise<Inputs> {
|
||||
export function defaultContext(): string {
|
||||
if (!_defaultContext) {
|
||||
_defaultContext = `https://github.com/${github.context.repo.owner}/${
|
||||
github.context.repo.repo
|
||||
}.git#${github.context?.ref?.replace(/^refs\//, '')}`;
|
||||
}
|
||||
return _defaultContext;
|
||||
}
|
||||
|
||||
export function tmpDir(): string {
|
||||
if (!_tmpDir) {
|
||||
_tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-build-push-')).split(path.sep).join(path.posix.sep);
|
||||
}
|
||||
return _tmpDir;
|
||||
}
|
||||
|
||||
export function tmpNameSync(options?: tmp.TmpNameOptions): string {
|
||||
return tmp.tmpNameSync(options);
|
||||
}
|
||||
|
||||
export async function getInputs(defaultContext: string): Promise<Inputs> {
|
||||
return {
|
||||
context: core.getInput('context') || defaultContext,
|
||||
file: core.getInput('file') || 'Dockerfile',
|
||||
buildArgs: await getInputList('build-args'),
|
||||
labels: await getInputList('labels'),
|
||||
buildArgs: await getInputList('build-args', true),
|
||||
labels: await getInputList('labels', true),
|
||||
tags: await getInputList('tags'),
|
||||
pull: /true/i.test(core.getInput('pull')),
|
||||
target: core.getInput('target'),
|
||||
|
@ -55,15 +73,15 @@ export async function getInputs(): Promise<Inputs> {
|
|||
};
|
||||
}
|
||||
|
||||
export async function getArgs(inputs: Inputs, buildxVersion: string): Promise<Array<string>> {
|
||||
export async function getArgs(inputs: Inputs, defaultContext: string, buildxVersion: string): Promise<Array<string>> {
|
||||
let args: Array<string> = ['buildx'];
|
||||
args.push.apply(args, await getBuildArgs(inputs, buildxVersion));
|
||||
args.push.apply(args, await getBuildArgs(inputs, defaultContext, buildxVersion));
|
||||
args.push.apply(args, await getCommonArgs(inputs));
|
||||
args.push(inputs.context);
|
||||
return args;
|
||||
}
|
||||
|
||||
async function getBuildArgs(inputs: Inputs, buildxVersion: string): Promise<Array<string>> {
|
||||
async function getBuildArgs(inputs: Inputs, defaultContext: string, buildxVersion: string): Promise<Array<string>> {
|
||||
let args: Array<string> = ['build'];
|
||||
await asyncForEach(inputs.buildArgs, async buildArg => {
|
||||
args.push('--build-arg', buildArg);
|
||||
|
@ -83,26 +101,25 @@ async function getBuildArgs(inputs: Inputs, buildxVersion: string): Promise<Arra
|
|||
if (inputs.platforms.length > 0) {
|
||||
args.push('--platform', inputs.platforms.join(','));
|
||||
}
|
||||
if (inputs.platforms.length == 0 || semver.satisfies(buildxVersion, '>=0.4.2')) {
|
||||
args.push('--iidfile', await buildx.getImageIDFile());
|
||||
}
|
||||
await asyncForEach(inputs.outputs, async output => {
|
||||
args.push('--output', output);
|
||||
});
|
||||
if (
|
||||
!buildx.isLocalOrTarExporter(inputs.outputs) &&
|
||||
(inputs.platforms.length == 0 || semver.satisfies(buildxVersion, '>=0.4.2'))
|
||||
) {
|
||||
args.push('--iidfile', await buildx.getImageIDFile());
|
||||
}
|
||||
await asyncForEach(inputs.cacheFrom, async cacheFrom => {
|
||||
args.push('--cache-from', cacheFrom);
|
||||
});
|
||||
await asyncForEach(inputs.cacheTo, async cacheTo => {
|
||||
args.push('--cache-to', cacheTo);
|
||||
});
|
||||
let hasGitAuthToken: boolean = false;
|
||||
await asyncForEach(inputs.secrets, async secret => {
|
||||
if (secret.startsWith('GIT_AUTH_TOKEN=')) {
|
||||
hasGitAuthToken = true;
|
||||
}
|
||||
args.push('--secret', await buildx.getSecret(secret));
|
||||
});
|
||||
if (inputs.githubToken && !hasGitAuthToken && inputs.context == defaultContext) {
|
||||
if (inputs.githubToken && !buildx.hasGitAuthToken(inputs.secrets) && inputs.context == defaultContext) {
|
||||
args.push('--secret', await buildx.getSecret(`GIT_AUTH_TOKEN=${inputs.githubToken}`));
|
||||
}
|
||||
if (inputs.file) {
|
||||
|
|
|
@ -7,7 +7,7 @@ export interface ExecResult {
|
|||
stderr: string;
|
||||
}
|
||||
|
||||
export const exec = async (command: string, args: string[] = [], silent: boolean): Promise<ExecResult> => {
|
||||
export const exec = async (command: string, args: string[] = [], silent?: boolean): Promise<ExecResult> => {
|
||||
let stdout: string = '';
|
||||
let stderr: string = '';
|
||||
|
||||
|
|
21
src/main.ts
21
src/main.ts
|
@ -2,31 +2,34 @@ import * as fs from 'fs';
|
|||
import * as os from 'os';
|
||||
import * as buildx from './buildx';
|
||||
import * as context from './context';
|
||||
import * as exec from './exec';
|
||||
import * as stateHelper from './state-helper';
|
||||
import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
if (os.platform() !== 'linux') {
|
||||
core.setFailed('Only supported on linux platform');
|
||||
return;
|
||||
throw new Error(`Only supported on linux platform`);
|
||||
}
|
||||
|
||||
if (!(await buildx.isAvailable())) {
|
||||
core.setFailed(`Buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
|
||||
return;
|
||||
throw new Error(`Buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
|
||||
}
|
||||
stateHelper.setTmpDir(context.tmpDir);
|
||||
stateHelper.setTmpDir(context.tmpDir());
|
||||
|
||||
const buildxVersion = await buildx.getVersion();
|
||||
core.info(`📣 Buildx version: ${buildxVersion}`);
|
||||
|
||||
let inputs: context.Inputs = await context.getInputs();
|
||||
const defContext = context.defaultContext();
|
||||
let inputs: context.Inputs = await context.getInputs(defContext);
|
||||
|
||||
core.info(`🏃 Starting build...`);
|
||||
const args: string[] = await context.getArgs(inputs, buildxVersion);
|
||||
await exec.exec('docker', args);
|
||||
const args: string[] = await context.getArgs(inputs, defContext, buildxVersion);
|
||||
await exec.exec('docker', args).then(res => {
|
||||
if (res.stderr != '' && !res.success) {
|
||||
throw new Error(`buildx call failed with: ${res.stderr.match(/(.*)\s*$/)![0]}`);
|
||||
}
|
||||
});
|
||||
|
||||
const imageID = await buildx.getImageID();
|
||||
if (imageID) {
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
FROM --platform=${BUILDPLATFORM:-linux/amd64} tonistiigi/xx:golang AS xgo
|
||||
FROM --platform=${BUILDPLATFORM:-linux/amd64} golang:1.13-alpine AS builder
|
||||
|
||||
ENV CGO_ENABLED 0
|
||||
ENV GO111MODULE on
|
||||
ENV GOPROXY https://goproxy.io
|
||||
COPY --from=xgo / /
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
RUN go env
|
||||
|
||||
RUN apk --update --no-cache add \
|
||||
build-base \
|
||||
gcc \
|
||||
git \
|
||||
&& rm -rf /tmp/* /var/cache/apk/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ENV DIUN_VERSION="v4.4.0"
|
||||
|
||||
RUN git clone --branch ${DIUN_VERSION} https://github.com/crazy-max/diun .
|
||||
RUN go mod download
|
||||
RUN go build -ldflags "-w -s -X 'main.version=test'" -v -o diun cmd/main.go
|
||||
|
||||
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine:latest
|
||||
|
||||
COPY --from=builder /app/diun /usr/local/bin/diun
|
||||
COPY --from=builder /usr/local/go/lib/time/zoneinfo.zip /usr/local/go/lib/time/zoneinfo.zip
|
||||
RUN diun --version
|
12
yarn.lock
12
yarn.lock
|
@ -636,6 +636,13 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
|
||||
integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
|
||||
|
||||
"@types/csv-parse@^1.2.2":
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/csv-parse/-/csv-parse-1.2.2.tgz#713486235759d615dc8e6a6a979170ada76701d5"
|
||||
integrity sha512-k33tLtRKTQxf7hQfMlkWoS2TQYsnpk1ibZN+rzbuCkeBs8m23nHTeDTF1wb/e7/MSLdtgCzqu3oM1I101kd6yw==
|
||||
dependencies:
|
||||
csv-parse "*"
|
||||
|
||||
"@types/graceful-fs@^4.1.2":
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.3.tgz#039af35fe26bec35003e8d86d2ee9c586354348f"
|
||||
|
@ -1229,6 +1236,11 @@ cssstyle@^2.2.0:
|
|||
dependencies:
|
||||
cssom "~0.3.6"
|
||||
|
||||
csv-parse@*, csv-parse@^4.12.0:
|
||||
version "4.12.0"
|
||||
resolved "https://registry.yarnpkg.com/csv-parse/-/csv-parse-4.12.0.tgz#fd42d6291bbaadd51d3009f6cadbb3e53b4ce026"
|
||||
integrity sha512-wPQl3H79vWLPI8cgKFcQXl0NBgYYEqVnT1i6/So7OjMpsI540oD7p93r3w6fDSyPvwkTepG05F69/7AViX2lXg==
|
||||
|
||||
dashdash@^1.12.0:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
|
||||
|
|
Loading…
Add table
Reference in a new issue