Compare commits

..

2 Commits

Author SHA1 Message Date
ab83648e2e Merge pull request #106 from docker/deprecation-notice
Add deprecation notice (v2 available)
2020-09-08 14:11:29 -07:00
35323d9aa4 Add deprecation notice (v2 available)
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2020-09-08 23:08:57 +02:00
39 changed files with 292 additions and 22571 deletions

View File

@ -1 +0,0 @@
node_modules

View File

@ -1,15 +0,0 @@
# This file is for unifying the coding style for different editors and IDEs.
# More information at http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

2
.gitattributes vendored
View File

@ -1,2 +0,0 @@
/dist/** linguist-generated=true
/lib/** linguist-generated=true

1
.github/CODEOWNERS vendored
View File

@ -1 +0,0 @@
* @crazy-max

View File

@ -1,44 +0,0 @@
## Contributing
Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great.
Contributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) to the public under the [project's open source license](LICENSE).
## Submitting a pull request
1. [Fork](https://github.com/docker/build-push-action/fork) and clone the repository
2. Configure and install the dependencies: `yarn install`
3. Make sure the tests pass on your machine: `yarn run test`
4. Create a new branch: `git checkout -b my-branch-name`
5. Make your change, add tests, and make sure the tests still pass
6. Run pre-checkin: `yarn run pre-checkin`
7. Push to your fork and [submit a pull request](https://github.com/docker/build-push-action/compare)
8. Pat your self on the back and wait for your pull request to be reviewed and merged.
## Container based developer flow
If you don't want to maintain a Node developer environment that fits this project you can use containerized commands instead of invoking yarn directly.
```
# format code and build javascript artifacts
docker buildx bake pre-checkin
# validate all code has correctly formatted and built
docker buildx bake validate
# run tests
docker buildx bake test
```
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
- Make sure the `README.md` and any other relevant **documentation are kept up-to-date**.
- We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option.
- Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as **separate pull requests**.
- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
## Resources
- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/)
- [GitHub Help](https://help.github.com)

View File

@ -1,37 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
---
### Troubleshooting
Before sumbitting a bug report please read the [Troubleshooting doc](https://github.com/docker/build-push-action/blob/master/TROUBLESHOOTING.md).
### Behaviour
#### Steps to reproduce this issue
1.
2.
3.
#### Expected behaviour
> Tell us what should happen
#### Actual behaviour
> Tell us what happens instead
### Configuration
* Repository URL (if public):
* Build URL (if public):
```yml
# paste your YAML workflow file here and remove sensitive data
```
### Logs
> Download the [log file of your build](https://help.github.com/en/actions/configuring-and-managing-workflows/managing-a-workflow-run#downloading-logs) and [attach it](https://help.github.com/en/github/managing-your-work-on-github/file-attachments-on-issues-and-pull-requests) to this issue.

31
.github/SUPPORT.md vendored
View File

@ -1,31 +0,0 @@
# Support [![](https://isitmaintained.com/badge/resolution/docker/build-push-action.svg)](https://isitmaintained.com/project/docker/build-push-action)
First, [be a good guy](https://github.com/kossnocorp/etiquette/blob/master/README.md).
## Reporting an issue
Please do a search in [open issues](https://github.com/docker/build-push-action/issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed.
If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment.
:+1: - upvote
:-1: - downvote
If you cannot find an existing issue that describes your bug or feature, submit an issue using the guidelines below.
## Writing good bug reports and feature requests
File a single issue per problem and feature request.
* Do not enumerate multiple bugs or feature requests in the same issue.
* Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes.
The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix.
You are now ready to [create a new issue](https://github.com/docker/build-push-action/issues/new/choose)!
## Closure policy
* Issues that don't have the information requested above (when applicable) will be closed immediately and the poster directed to the support guidelines.
* Issues that go a week without a response from original poster are subject to closure at our discretion.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -1,18 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
labels:
- ":game_die: dependencies"
- ":robot: bot"
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
allow:
- dependency-type: "production"
labels:
- ":game_die: dependencies"
- ":robot: bot"

79
.github/labels.yml vendored
View File

@ -1,79 +0,0 @@
## more info https://github.com/crazy-max/ghaction-github-labeler
- # automerge
name: ":bell: automerge"
color: "8f4fbc"
description: ""
- # bot
name: ":robot: bot"
color: "69cde9"
description: ""
- # bug
name: ":bug: bug"
color: "b60205"
description: ""
- # dependencies
name: ":game_die: dependencies"
color: "0366d6"
description: ""
from_name: "dependencies"
- # documentation
name: ":memo: documentation"
color: "c5def5"
description: ""
- # duplicate
name: ":busts_in_silhouette: duplicate"
color: "cccccc"
description: ""
- # enhancement
name: ":sparkles: enhancement"
color: "0054ca"
description: ""
- # feature request
name: ":bulb: feature request"
color: "0e8a16"
description: ""
- # feedback
name: ":mega: feedback"
color: "03a9f4"
description: ""
- # future maybe
name: ":rocket: future maybe"
color: "fef2c0"
description: ""
- # good first issue
name: ":hatching_chick: good first issue"
color: "7057ff"
description: ""
- # help wanted
name: ":pray: help wanted"
color: "4caf50"
description: ""
- # hold
name: ":hand: hold"
color: "24292f"
description: ""
- # invalid
name: ":no_entry_sign: invalid"
color: "e6e6e6"
description: ""
- # maybe bug
name: ":interrobang: maybe bug"
color: "ff5722"
description: ""
- # needs more info
name: ":thinking: needs more info"
color: "795548"
description: ""
- # question
name: ":question: question"
color: "3f51b5"
description: ""
from_name: "question"
- # upstream
name: ":eyes: upstream"
color: "fbca04"
description: ""
- # wontfix
name: ":coffin: wontfix"
color: "ffffff"
description: ""

View File

@ -1,604 +0,0 @@
name: ci
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- 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:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Checkout
uses: actions/checkout@v2.3.3
with:
path: action
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
with:
version: latest
driver-opts: network=host
-
name: Build and push
id: docker_build
uses: ./action
with:
file: ./test/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
tags: |
localhost:5000/name/app:latest
localhost:5000/name/app:1.0.0
-
name: Inspect
run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
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
git-context-secret:
runs-on: ubuntu-latest
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Checkout
uses: actions/checkout@v2.3.3
with:
path: action
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
with:
driver-opts: network=host
-
name: Build and push
id: docker_build
uses: ./action
with:
file: ./test/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
tags: |
localhost:5000/name/app:latest
localhost:5000/name/app:1.0.0
secrets: |
GIT_AUTH_TOKEN=${{ github.token }}
-
name: Inspect
run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
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
path-context:
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.3.3
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
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
id: docker_build
uses: ./
with:
context: ./test
file: ./test/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: |
localhost:5000/name/app:latest
localhost:5000/name/app:1.0.0
-
name: Inspect
run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
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()
uses: crazy-max/ghaction-dump-context@v1
multi:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
buildx-version:
- ""
- latest
dockerfile:
- multi
- multi-sudo
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Checkout
uses: actions/checkout@v2.3.3
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
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
id: docker_build
uses: ./
with:
context: ./test
file: ./test/Dockerfile-${{ matrix.dockerfile }}
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
tags: |
localhost:5000/name/app:latest
localhost:5000/name/app:1.0.0
-
name: Inspect
run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
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
registry-cache:
runs-on: ubuntu-latest
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Checkout
uses: actions/checkout@v2.3.3
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
with:
driver-opts: |
network=host
-
name: Build and push (1)
id: docker_build
uses: ./
with:
context: ./test
file: ./test/Dockerfile-multi
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
tags: |
localhost:5000/name/app:latest
localhost:5000/name/app:1.0.0
cache-from: type=registry,ref=localhost:5000/name/app
cache-to: type=inline
-
name: Inspect (1)
run: |
docker buildx imagetools inspect localhost:5000/name/app:latest
-
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: |
docker buildx prune -a -f --verbose
-
name: Build and push (2)
id: docker_build2
uses: ./
with:
context: ./test
file: ./test/Dockerfile-multi
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
tags: |
localhost:5000/name/app:latest
localhost:5000/name/app:1.0.0
cache-from: type=registry,ref=localhost:5000/name/app
cache-to: type=inline
-
name: Inspect (2)
run: |
docker buildx imagetools inspect localhost:5000/name/app:latest
-
name: Image digest (2)
run: echo ${{ steps.docker_build2.outputs.digest }}
-
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
echo "::error::Digests should be identical"
exit 1
fi
-
name: Dump context
if: always()
uses: crazy-max/ghaction-dump-context@v1
github-cache-first:
runs-on: ubuntu-latest
outputs:
digest: ${{ steps.docker_build.outputs.digest }}
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Checkout
uses: actions/checkout@v2.3.3
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
with:
driver-opts: |
network=host
-
name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-ghcache-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-ghcache-
-
name: Erase cache
run: |
rm -rf /tmp/.buildx-cache/*
-
name: Build and push
id: docker_build
uses: ./
with:
context: ./test
file: ./test/Dockerfile-multi
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
tags: |
localhost:5000/name/app:latest
localhost:5000/name/app:1.0.0
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
-
name: Inspect
run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
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
github-cache-hit:
runs-on: ubuntu-latest
needs: github-cache-first
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Checkout
uses: actions/checkout@v2.3.3
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
with:
driver-opts: |
network=host
-
name: Cache Docker layers
uses: actions/cache@v2
id: cache
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-ghcache-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-ghcache-
-
name: Build and push
id: docker_build
uses: ./
with:
context: ./test
file: ./test/Dockerfile-multi
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
tags: |
localhost:5000/name/app:latest
localhost:5000/name/app:1.0.0
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
-
name: Inspect
run: |
docker buildx imagetools inspect localhost:5000/name/app:1.0.0
-
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: 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
echo "::error::Digests should be identical"
exit 1
fi
-
name: Cache hit
run: echo ${{ steps.cache.outputs.cache-hit }}
-
name: Dump context
if: always()
uses: crazy-max/ghaction-dump-context@v1

View File

@ -1,103 +0,0 @@
# This workflow is provided just as an usage example and not for repo testing/verification
# See https://github.com/docker/build-push-action#complete-workflow
name: example
on:
schedule:
- cron: '0 10 * * 0' # everyday sunday at 10am
push:
branches:
- '**'
tags:
- 'v*.*.*'
pull_request:
jobs:
docker:
runs-on: ubuntu-latest
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Checkout
uses: actions/checkout@v2.3.3
-
name: Prepare
id: prep
run: |
DOCKER_IMAGE=localhost:5000/name/app
VERSION=noop
if [ "${{ github.event_name }}" = "schedule" ]; then
VERSION=nightly
elif [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
elif [[ $GITHUB_REF == refs/heads/* ]]; then
VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g')
if [ "${{ github.event.repository.default_branch }}" = "$VERSION" ]; then
VERSION=edge
fi
elif [[ $GITHUB_REF == refs/pull/* ]]; then
VERSION=pr-${{ github.event.number }}
fi
TAGS="${DOCKER_IMAGE}:${VERSION}"
if [[ $VERSION =~ ^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
MINOR=${VERSION%.*}
MAJOR=${MINOR%.*}
TAGS="$TAGS,${DOCKER_IMAGE}:${MINOR},${DOCKER_IMAGE}:${MAJOR},${DOCKER_IMAGE}:latest"
elif [ "${{ 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
uses: docker/setup-buildx-action@v1
with:
driver-opts: network=host
-
name: Build and export to Docker client
uses: ./
with:
context: ./test
file: ./test/Dockerfile
outputs: type=docker
tags: ${{ steps.prep.outputs.tags }}
labels: |
org.opencontainers.image.created=${{ steps.prep.outputs.created }}
org.opencontainers.image.url=${{ github.event.repository.html_url }}
org.opencontainers.image.source=${{ github.event.repository.clone_url }}
org.opencontainers.image.version=${{ steps.prep.outputs.version }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.licenses=${{ github.event.repository.license.spdx_id }}
-
name: Build and push to local registry
uses: ./
with:
context: ./test
file: ./test/Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.prep.outputs.tags }}
labels: |
org.opencontainers.image.created=${{ steps.prep.outputs.created }}
org.opencontainers.image.url=${{ github.event.repository.html_url }}
org.opencontainers.image.source=${{ github.event.repository.clone_url }}
org.opencontainers.image.version=${{ steps.prep.outputs.version }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.licenses=${{ github.event.repository.license.spdx_id }}
-
name: Inspect image
run: |
docker image inspect localhost:5000/name/app:${{ steps.prep.outputs.version }}
-
name: Check manifest
if: github.event_name != 'pull_request'
run: |
docker buildx imagetools inspect localhost:5000/name/app:${{ steps.prep.outputs.version }}
-
name: Dump context
if: always()
uses: crazy-max/ghaction-dump-context@v1

View File

@ -1,20 +0,0 @@
name: labels
on:
push:
branches:
- 'master'
paths:
- '.github/labels.yml'
- '.github/workflows/labels.yml'
jobs:
labeler:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2.3.3
-
name: Run Labeler
uses: crazy-max/ghaction-github-labeler@v3.1.0

37
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,37 @@
name: CI
on:
push:
branches:
- master
tags:
- '*'
pull_request:
jobs:
build:
name: build
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Run local registry
run: docker run -d -p 5000:5000 registry:2
- name: Build and push image
uses: ./
env:
DOCKER_BUILDKIT: 1
with:
registry: localhost:5000
repository: temp/workflow
tags: foo
- name: Remove local image
run: docker image rm localhost:5000/temp/workflow:foo
- name: Run image from registry
run: docker run localhost:5000/temp/workflow:foo

View File

@ -1,43 +0,0 @@
name: test
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
test-containerized:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2.3.3
-
name: Validate
run: docker buildx bake validate
-
name: Test
run: docker buildx bake test
test:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2.3.3
-
name: Install
run: yarn install
-
name: Test
run: yarn run test
-
name: Upload coverage
uses: codecov/codecov-action@v1.0.14
if: success()
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage/clover.xml

95
.gitignore vendored
View File

@ -1,95 +0,0 @@
node_modules
lib
# Jetbrains
/.idea
/*.iml
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/

View File

@ -1,11 +0,0 @@
{
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid",
"parser": "typescript"
}

View File

@ -1,52 +1,3 @@
#syntax=docker/dockerfile:1.1-experimental
FROM alpine:3
FROM node:12 AS deps
WORKDIR /src
COPY package.json yarn.lock ./
RUN --mount=type=cache,target=/usr/local/share/.cache/yarn \
yarn install
FROM scratch AS update-yarn
COPY --from=deps /src/yarn.lock /
FROM deps AS validate-yarn
COPY .git .git
RUN status=$(git status --porcelain -- yarn.lock); if [ -n "$status" ]; then echo $status; exit 1; fi
FROM deps AS base
COPY . .
FROM base AS build
RUN yarn build
FROM deps AS test
COPY --from=docker /usr/local/bin/docker /usr/bin/
ARG TARGETOS
ARG TARGETARCH
ARG BUILDX_VERSION=v0.4.2
ENV RUNNER_TEMP=/tmp/github_runner
ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache
RUN mkdir -p /usr/local/lib/docker/cli-plugins && \
curl -fsSL https://github.com/docker/buildx/releases/download/$BUILDX_VERSION/buildx-$BUILDX_VERSION.$TARGETOS-$TARGETARCH > /usr/local/lib/docker/cli-plugins/docker-buildx && \
chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx && \
docker buildx version
COPY . .
RUN yarn run test
FROM base AS run-format
RUN yarn run format
FROM scratch AS format
COPY --from=run-format /src/src/*.ts /src/
FROM base AS validate-format
RUN yarn run format-check
FROM scratch AS dist
COPY --from=build /src/dist/ /dist/
FROM build AS validate-build
RUN status=$(git status --porcelain -- dist); if [ -n "$status" ]; then echo $status; exit 1; fi
FROM base AS dev
ENTRYPOINT ["bash"]
ENTRYPOINT ["echo", "docker github actions"]

864
README.md
View File

@ -1,707 +1,243 @@
[![GitHub release](https://img.shields.io/github/release/docker/build-push-action.svg?style=flat-square)](https://github.com/docker/build-push-action/releases/latest)
[![GitHub marketplace](https://img.shields.io/badge/marketplace-build--and--push--docker--images-blue?logo=github&style=flat-square)](https://github.com/marketplace/actions/build-and-push-docker-images)
[![CI workflow](https://img.shields.io/github/workflow/status/docker/build-push-action/ci?label=ci&logo=github&style=flat-square)](https://github.com/docker/build-push-action/actions?workflow=ci)
[![Test workflow](https://img.shields.io/github/workflow/status/docker/build-push-action/test?label=test&logo=github&style=flat-square)](https://github.com/docker/build-push-action/actions?workflow=test)
[![Codecov](https://img.shields.io/codecov/c/github/docker/build-push-action?logo=codecov&style=flat-square)](https://codecov.io/gh/docker/build-push-action)
# build-push-action
## Upgrade from v1
Builds and pushes Docker images and will log in to a Docker registry if required.
`v2` of this action includes significant updates and now uses Docker [Buildx](https://github.com/docker/buildx). It
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 closed as possible of the
[GitHub Runner](https://github.com/actions/virtual-environments) during its execution.
Suggestions and issues can be posted on the repositories [issues page](https://github.com/docker/build-push-action/issues).
[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).
[Inputs](#Inputs)
* [repository](#repository)
* [username](#username)
* [password](#password)
* [registry](#registry)
* [tags](#tags)
* [tag_with_ref](#tag_with_ref)
* [tag_with_sha](#tag_with_sha)
* [path](#path)
* [dockerfile](#dockerfile)
* [target](#target)
* [always_pull](#always_pull)
* [build_args](#build_args)
* [cache_froms](#cache_froms)
* [labels](#labels)
* [add_git_labels](#add_git_labels)
* [push](#push)
## About
[Example usage](#Example-usage)
GitHub Action to build and push Docker images with [Buildx](https://github.com/docker/buildx).
## Inputs
> :bulb: See also:
> * [login](https://github.com/docker/login-action) action
> * [setup-buildx](https://github.com/docker/setup-buildx-action) action
> * [setup-qemu](https://github.com/docker/setup-qemu-action) action
### `repository`
![Screenshot](.github/build-push-action.png)
**Required** Docker repository to tag the image with.
___
### `username`
* [Usage](#usage)
* [Git context](#git-context)
* [Path context](#path-context)
* [Isolated builders](#isolated-builders)
* [Multi-platform image](#multi-platform-image)
* [Advanced usage](#advanced-usage)
* [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)
* [Customizing](#customizing)
* [inputs](#inputs)
* [outputs](#outputs)
* [Troubleshooting](#troubleshooting)
* [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot)
* [Limitation](#limitation)
Username used to log in to a Docker registry. If not set then no login will occur.
## Usage
### `password`
This action uses our [setup-buildx](https://github.com/docker/setup-buildx-action) action that extends the
`docker build` command named [buildx](https://github.com/docker/buildx) with the full support of the features
provided by [Moby BuildKit](https://github.com/moby/buildkit) builder toolkit. This includes multi-arch build,
build-secrets, remote cache, etc. and different builder deployment/namespacing options.
Password or personal access token used to log in to a Docker registry. If not set then no login will occur.
### Git context
### `registry`
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.
Server address of Docker registry. If not set then will default to Docker Hub.
### `tags`
Comma-delimited list of tags. These will be added to the registry/repository to form the image's tags.
Example:
```yaml
name: ci
on:
push:
branches: master
jobs:
main:
runs-on: ubuntu-latest
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
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
id: docker_build
uses: docker/build-push-action@v2
with:
push: true
tags: user/app:latest
build-args: |
arg1=value1
arg2=value2
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
tags: tag1,tag2
```
Building from current repository automatically uses the [GitHub Token](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token)
as provided by `secrets` so it does not need to be passed. But if you want to authenticate against another private
repository, you have to use a secret named `GIT_AUTH_TOKEN` to be able to authenticate against it with buildx:
### `tag_with_ref`
Boolean value. Defaults to `false`.
Automatically tags the built image with the git reference. The format of the tag depends on the type of git reference with all forward slashes replaced with `-`.
For pushes to a branch the reference will be `refs/heads/{branch-name}` and the tag will be `{branch-name}`. If `{branch-name}` is master then the tag will be `latest`.
For pull requests the reference will be `refs/pull/{pull-request}` and the tag will be `pr-{pull-request}`.
For git tags the reference will be `refs/tags/{git-tag}` and the tag will be `{git-tag}`.
Examples:
|Git Reference|Image tag|
|---|---|
|`refs/heads/master`|`latest`|
|`refs/heads/mybranch`|`mybranch`|
|`refs/heads/my/branch`|`my-branch`|
|`refs/pull/2/merge`|`pr-2-merge`|
|`refs/tags/v1.0.0`|`v1.0.0`|
### `tag_with_sha`
Boolean value. Defaults to `false`.
Automatically tags the built image with the git short SHA prefixed with `sha-`.
Example:
|Git SHA|Image tag|
|---|---|
|`676cae2f85471aeff6776463c72881ebd902dcf9`|`sha-676cae2`|
### `path`
Path to the build context. Defaults to `.`
### `dockerfile`
Path to the Dockerfile. Defaults to `{path}/Dockerfile`
Note when set this path is **not** relative to the `path` input but is instead relative to the current working directory.
### `target`
Sets the target stage to build.
### `always_pull`
Boolean value. Defaults to `false`.
Always attempt to pull a newer version of the image.
### `build_args`
Comma-delimited list of build-time variables.
Example:
```yaml
-
name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
push: true
tags: user/app:latest
secrets: |
GIT_AUTH_TOKEN=${{ secrets.MYTOKEN }}
build_args: arg1=value1,arg2=value2
```
> :warning: Subdir for Git context is [not yet supported](https://github.com/docker/build-push-action/issues/120).
> For the moment you can use the [path context](#path-context).
### `cache_froms`
> More info: https://docs.docker.com/engine/reference/commandline/build/#git-repositories
Comma-delimited list of images to consider as cache sources.
### Path context
Example:
```yaml
cache_froms: myorg/baseimage:latest
```
You can also use the `PATH` context alongside the [`actions/checkout`](https://github.com/actions/checkout/) action.
### `labels`
Comma-delimited list of labels to add to the built image.
Example:
```yaml
name: ci
on:
push:
branches: master
jobs:
path-context:
runs-on: ubuntu-latest
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
-
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: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/386
push: true
tags: user/app:latest
labels: label_name_1=label_value_1,label_name_2=label_value_2
```
### Isolated builders
### `add_git_labels`
Boolean value. Defaults to `false`.
Adds labels with git repository information to the built image based on the standards set out in https://github.com/opencontainers/image-spec/blob/master/annotations.md.
The labels are:
|Label key|Example value|Description|
|---|---|---|
|`org.opencontainers.image.created`|`2020-03-06T23:00:00Z`|Date and time on which the image was built (string, date-time as defined by RFC 3339).|
|`org.opencontainers.image.source`|`https://github.com/myorg/myrepository`|URL to the GitHub repository.|
|`org.opencontainers.image.revision`|`676cae2f85471aeff6776463c72881ebd902dcf9`|The full git SHA of this commit.|
### `push`
Boolean value. Defaults to `true`.
Whether to push the built image.
## Example usage
The following will build the root Dockerfile, tag the image as `myorg/myrepository:latest`, log in to Docker Hub using GitHub secrets, and push the image to the Docker Hub repository `myorg/myrepository`:
```yaml
name: ci
steps:
- name: Checkout code
uses: actions/checkout@v2
on:
push:
branches: master
jobs:
multi-builders:
runs-on: ubuntu-latest
steps:
-
uses: docker/setup-buildx-action@v1
id: builder1
-
uses: docker/setup-buildx-action@v1
id: builder2
-
name: Builder 1 name
run: echo ${{ steps.builder1.outputs.name }}
-
name: Builder 2 name
run: echo ${{ steps.builder2.outputs.name }}
-
name: Build against builder1
uses: docker/build-push-action@v2
with:
builder: ${{ steps.builder1.outputs.name }}
target: mytarget1
-
name: Build against builder2
uses: docker/build-push-action@v2
with:
builder: ${{ steps.builder2.outputs.name }}
target: mytarget2
- name: Build and push Docker images
uses: docker/build-push-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: myorg/myrepository
tags: latest
```
### Multi-platform image
The following will build the root Dockerfile, tag the image with the git reference and SHA as described above, log in to Docker Hub using GitHub secrets, and push the image to the Docker Hub repository `myorg/myrepository`:
```yaml
name: ci
steps:
- name: Checkout code
uses: actions/checkout@v2
on:
push:
branches: master
jobs:
multi:
runs-on: ubuntu-latest
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
-
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: .
file: ./Dockerfile
platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
push: true
tags: |
user/app:latest
user/app:1.0.0
- name: Build and push Docker images
uses: docker/build-push-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: myorg/myrepository
tag_with_ref: true
tag_with_sha: true
```
## Advanced usage
### Push to multi-registries
The following workflow will connect you to [DockerHub](https://github.com/docker/login-action#dockerhub)
and [GitHub Container Registry](https://github.com/docker/login-action#github-container-registry) and push the
image to these registries.
<details>
<summary><b>Show workflow</b></summary>
```yaml
name: ci
on:
push:
branches: master
jobs:
multi-registries:
runs-on: ubuntu-latest
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
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.CR_PAT }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
push: true
tags: |
user/app:latest
user/app:1.0.0
ghcr.io/user/app:latest
ghcr.io/user/app:1.0.0
```
</details>
### Cache to registry
You can import/export cache from a cache manifest or (special) image configuration on the registry.
<details>
<summary><b>Show workflow</b></summary>
```yaml
name: ci
on:
push:
branches: master
jobs:
registry-cache:
runs-on: ubuntu-latest
steps:
-
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:
push: true
tags: user/app:latest
cache-from: type=registry,ref=user/app:latest
cache-to: type=inline
```
</details>
### Local registry
For testing purposes you may need to create a [local registry](https://hub.docker.com/_/registry) to push images into:
<details>
<summary><b>Show workflow</b></summary>
```yaml
name: ci
on:
push:
branches: master
jobs:
local-registry:
runs-on: ubuntu-latest
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
driver-opts: network=host
-
name: Build and push to local registry
uses: docker/build-push-action@v2
with:
push: true
tags: localhost:5000/name/app:latest
-
name: Inspect
run: |
docker buildx imagetools inspect localhost:5000/name/app:latest
```
</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)
using [actions/cache](https://github.com/actions/cache) with this action:
<details>
<summary><b>Show workflow</b></summary>
```yaml
name: ci
on:
push:
branches: master
jobs:
github-cache:
runs-on: ubuntu-latest
steps:
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
-
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:
push: true
tags: user/app:latest
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
```
</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 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.
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 and that you will have to adapt according
to your needs:
<details>
<summary><b>Show workflow</b></summary>
```yaml
name: ci
on:
schedule:
- cron: '0 10 * * *' # everyday at 10am
push:
branches:
- '**'
tags:
- 'v*.*.*'
pull_request:
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Repo metadata
id: repo
uses: actions/github-script@v3
with:
script: |
const repo = await github.repos.get(context.repo)
return repo.data
-
name: Prepare
id: prep
run: |
DOCKER_IMAGE=name/app
VERSION=noop
if [ "${{ github.event_name }}" = "schedule" ]; then
VERSION=nightly
elif [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
elif [[ $GITHUB_REF == refs/heads/* ]]; then
VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g')
if [ "${{ github.event.repository.default_branch }}" = "$VERSION" ]; then
VERSION=edge
fi
elif [[ $GITHUB_REF == refs/pull/* ]]; then
VERSION=pr-${{ github.event.number }}
fi
TAGS="${DOCKER_IMAGE}:${VERSION}"
if [[ $VERSION =~ ^v[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
MINOR=${VERSION%.*}
MAJOR=${MINOR%.*}
TAGS="$TAGS,${DOCKER_IMAGE}:${MINOR},${DOCKER_IMAGE}:${MAJOR},${DOCKER_IMAGE}:latest"
elif [ "${{ 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 QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/386
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.prep.outputs.tags }}
labels: |
org.opencontainers.image.title=${{ fromJson(steps.repo.outputs.result).name }}
org.opencontainers.image.description=${{ fromJson(steps.repo.outputs.result).description }}
org.opencontainers.image.url=${{ fromJson(steps.repo.outputs.result).html_url }}
org.opencontainers.image.source=${{ fromJson(steps.repo.outputs.result).clone_url }}
org.opencontainers.image.version=${{ steps.prep.outputs.version }}
org.opencontainers.image.created=${{ steps.prep.outputs.created }}
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.licenses=${{ fromJson(steps.repo.outputs.result).license.spdx_id }}
```
</details>
| Event | Ref | Commit SHA | Docker Tag | Pushed |
|-----------------|-------------------------------|------------|------------------------------------|--------|
| `schedule` | | | `nightly` | Yes |
| `pull_request` | `refs/pull/2/merge` | `a123b57` | `pr-2` | No |
| `push` | `refs/heads/<default_branch>` | `676cae2` | `sha-676cae2`, `edge` | Yes |
| `push` | `refs/heads/dev` | `cf20257` | `sha-cf20257`, `dev` | Yes |
| `push` | `refs/heads/my/branch` | `a5df687` | `sha-a5df687`, `my-branch` | Yes |
| `push tag` | `refs/tags/v1.2.3` | | `v1.2.3`, `v1.2`, `v1`, `latest` | Yes |
### Update DockerHub repo 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>
<summary><b>Show workflow</b></summary>
```yaml
name: ci
on:
push:
branches: master
jobs:
main:
runs-on: ubuntu-latest
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
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:
push: true
tags: user/app:latest
-
name: Update repo description
uses: peter-evans/dockerhub-description@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
repository: user/app
```
</details>
## Customizing
### inputs
Following inputs can be used as `step.with` keys
> `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
| Name | Type | Description |
|---------------|---------|---------------------------------------|
| `digest` | String | Image content-addressable identifier also called a digest |
## Troubleshooting
See [TROUBLESHOOTING.md](TROUBLESHOOTING.md)
## Keep up-to-date with GitHub Dependabot
Since [Dependabot](https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-github-dependabot)
has [native GitHub Actions support](https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#package-ecosystem),
to enable it on your GitHub repo all you need to do is add the `.github/dependabot.yml` file:
The following will only push the image when the event that kicked off the workflow was a push of a git tag:
```yaml
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Build and push Docker images
uses: docker/build-push-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: myorg/myrepository
tag_with_ref: true
push: ${{ startsWith(github.ref, 'refs/tags/') }}
```
## Limitation
The following builds the `mytarget` stage and pushes that:
```yaml
steps:
- name: Checkout code
uses: actions/checkout@v2
This action is only available for Linux [virtual environments](https://help.github.com/en/articles/virtual-environments-for-github-actions#supported-virtual-environments-and-hardware-resources).
- name: Build and push Docker images
uses: docker/build-push-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: myorg/myrepository
tag_with_ref: true
target: mytarget
```
The following will build the root Dockerfile, tag the image as `myorg/myrepository:latest`, log in to Google Container Registry using GitHub secrets (where `DOCKER_PASSWORD` is a [JSON key](https://cloud.google.com/container-registry/docs/advanced-authentication#json-key)), and push the image to the GCR repository `myorg/myrepository`:
```yaml
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Build and push Docker images
uses: docker/build-push-action@v1
with:
username: _json_key
password: ${{ secrets.DOCKER_PASSWORD }}
registry: gcr.io
repository: myorg/myrepository
tags: latest
```

View File

@ -1,180 +0,0 @@
# Troubleshooting
* [`auto-push is currently not implemented for docker driver`](#auto-push-is-currently-not-implemented-for-docker-driver)
* [Cannot push to a registry](#cannot-push-to-a-registry)
## `auto-push is currently not implemented for docker driver`
If you're using the default builder (which uses the docker driver) without using our `setup-buildx-action`, you may
encounter this error message if you try to push your image:
```
Run docker/build-push-action@v2
📣 Buildx version: 0.4.2
🏃 Starting build...
/usr/bin/docker buildx build --tag localhost:5000/name/app:latest --iidfile /tmp/docker-build-push-eYl8PB/iidfile --file ./test/Dockerfile --push ./test
auto-push is currently not implemented for docker driver
Error: buildx call failed with: auto-push is currently not implemented for docker driver
```
While waiting for an implementation to be done on buildx/buildkit, you have the following possibilities
to solve this atm:
### With `docker-container` driver and `setup-buildx`
> Recommended solution
```yaml
jobs:
build:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login
uses: docker/login-action@v1
with:
registry: ${{ env.REGISTRY }}
username: ${{ env.USER }}
password: ${{ secrets.PASSWORD }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
tags: ${{ env.REGISTRY }}/myapp:latest
push: true
```
### With `docker` driver
```yaml
jobs:
build:
-
name: Checkout
uses: actions/checkout@v2
-
name: Login
uses: docker/login-action@v1
with:
registry: ${{ env.REGISTRY }}
username: ${{ env.USER }}
password: ${{ secrets.PASSWORD }}
-
name: Build
uses: docker/build-push-action@v2
with:
context: .
tags: ${{ env.REGISTRY }}/myapp:latest
load: true
-
name: Push
run: docker push ${{ env.REGISTRY }}/myapp:latest
```
### With `docker` driver and `setup-buildx`
```yaml
jobs:
build:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
driver: docker
-
name: Login
uses: docker/login-action@v1
with:
registry: ${{ env.REGISTRY }}
username: ${{ env.USER }}
password: ${{ secrets.PASSWORD }}
-
name: Build
uses: docker/build-push-action@v2
with:
context: .
tags: ${{ env.REGISTRY }}/myapp:latest
load: true
-
name: Push
run: docker push ${{ env.REGISTRY }}/myapp:latest
```
## Cannot push to a registry
While pushing to a registry, you may encounter these kinds of issues:
* `failed commit on ref "layer-sha256:...": invalid content digest in response: invalid checksum digest format`
* `failed commit on ref "layer-sha256:...": no response`
* `failed commit on ref "manifest-sha256:...": unexpected status: 400 Bad Request`
* `failed commit on ref "manifest-sha256:...": unexpected status: 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),
[buildkit](https://github.com/moby/buildkit), [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.
To help you solve this, you should first enable debugging in the
[setup-buildx action step](https://github.com/docker/setup-buildx-action):
```yaml
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
buildkitd-flags: --debug
```
Next you can test pushing with [containerd action](https://github.com/crazy-max/ghaction-setup-containerd) using the
following workflow. If it works then open an issue on [buildkit](https://github.com/moby/buildkit) repository.
```yaml
name: containerd
on:
push:
jobs:
containerd:
runs-on: ubuntu-latest
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:
buildkitd-flags: --debug
-
name: Set up containerd
uses: crazy-max/ghaction-setup-containerd@v1
-
name: Build Docker image
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
tags: docker.io/user/app:latest
outputs: type=oci,dest=/tmp/image.tar
-
name: Import image in containerd
run: |
sudo ctr i import --base-name docker.io/user/app --digests --all-platforms /tmp/image.tar
-
name: Push image with containerd
run: |
sudo ctr --debug i push --user "${{ secrets.DOCKER_USERNAME }}:${{ secrets.DOCKER_PASSWORD }}" docker.io/user/app:latest
```

View File

@ -1,144 +0,0 @@
# Upgrade notes
## v1 to v2
* Input `path` is now called `context` for consistency with other Docker build tools
* `path` defaults to current git repository so checkout action is not required in a workflow
* Rename `dockerfile` input to `file` for consistency with other Docker build tools
* Rename `always_pull` input to `pull` for consistency with other Docker build tools
* Add `builder` input to be able to choose a builder instance through our [setup-buildx action](https://github.com/docker/setup-buildx-action)
* Add [`platforms`](https://github.com/docker/buildx#---platformvaluevalue) input to support multi-platform builds
* Add [`allow`](https://github.com/docker/buildx#--allowentitlement) input
* Add [`load`](https://github.com/docker/buildx#--load) input
* Add [`outputs`](https://github.com/docker/buildx#-o---outputpath-typetypekeyvalue) input
* Add [`cache-from`](https://github.com/docker/buildx#--cache-fromnametypetypekeyvalue) input (`cache_froms` removed)
* Add [`cache-to`](https://github.com/docker/buildx#--cache-tonametypetypekeyvalue) input
* Add `secrets` input
* Review `tags` input
* Remove `repository` input. See [Simple workflow](#simple-workflow) for migration
* Remove `username`, `password` and `registry` inputs. Login support moved to [docker/login-action](https://github.com/docker/login-action) repo
* Remove `tag_with_sha`, `tag_with_ref`, `add_git_labels` inputs. See [Tags with ref and Git labels](#tags-with-ref-and-git-labels) for migration
* Handle Git context
* Add `digest` output
### Simple workflow
```yaml
# v1
steps:
-
name: Checkout code
uses: actions/checkout@v2
-
name: Build and push Docker images
uses: docker/build-push-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: myorg/myrepository
always_pull: true
build_args: arg1=value1,arg2=value2
cache_froms: myorg/myrepository:latest
tags: latest
```
```yaml
# v2
steps:
-
name: Checkout code
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.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
pull: true
push: true
build-args: |
arg1=value1
arg2=value2
cache-from: type=registry,ref=myorg/myrepository:latest
cache-to: type=inline
tags: myorg/myrepository:latest
```
### Tags with ref and Git labels
```yaml
# v1
steps:
-
name: Checkout code
uses: actions/checkout@v2
-
name: Build and push Docker images
uses: docker/build-push-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: myorg/myrepository
push: ${{ github.event_name != 'pull_request' }}
tag_with_ref: true
tag_with_sha: true
```
```yaml
# v2
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Prepare
id: prep
run: |
DOCKER_IMAGE=myorg/myrepository
VERSION=edge
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/}
elif [[ $GITHUB_REF == refs/heads/* ]]; then
VERSION=$(echo ${GITHUB_REF#refs/heads/} | sed -r 's#/+#-#g')
elif [[ $GITHUB_REF == refs/pull/* ]]; then
VERSION=pr-${{ github.event.number }}
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
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.prep.outputs.tags }}
labels: |
org.opencontainers.image.source=${{ github.event.repository.clone_url }}
org.opencontainers.image.created=${{ steps.prep.outputs.created }}
org.opencontainers.image.revision=${{ github.sha }}
```

View File

@ -1,132 +0,0 @@
import * as fs from 'fs';
import * as path from 'path';
import * as semver from 'semver';
import * as buildx from '../src/buildx';
import * as docker from '../src/docker';
import * as context from '../src/context';
const tmpNameSync = path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
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 tmpNameSync;
});
describe('getImageID', () => {
it('matches', async () => {
const imageIDFile = await buildx.getImageIDFile();
console.log(`imageIDFile: ${imageIDFile}`);
await fs.writeFileSync(imageIDFile, digest);
const imageID = await buildx.getImageID();
console.log(`imageID: ${imageID}`);
expect(imageID).toEqual(digest);
});
});
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', () => {
async function isDaemonRunning() {
return await docker.isDaemonRunning();
}
(isDaemonRunning() ? it : it.skip)(
'valid',
async () => {
const version = await buildx.getVersion();
console.log(`version: ${version}`);
expect(semver.valid(version)).not.toBeNull();
},
100000
);
});
describe('parseVersion', () => {
test.each([
['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.2 fb7b670b764764dc4716df3eba07ffdae4cc47b2', '0.4.2']
])('given %p', async (stdout, expected) => {
expect(await buildx.parseVersion(stdout)).toEqual(expected);
});
});
describe('getSecret', () => {
test.each([
['A_SECRET', 'abcdef0123456789'],
['GIT_AUTH_TOKEN', 'abcdefghijklmno=0123456789'],
['MY_KEY', 'c3RyaW5nLXdpdGgtZXF1YWxzCg==']
])('given %p key and %p secret', async (key, secret) => {
const secretArgs = await buildx.getSecret(`${key}=${secret}`);
console.log(`secretArgs: ${secretArgs}`);
expect(secretArgs).toEqual(`id=${key},src=${tmpNameSync}`);
const secretContent = await fs.readFileSync(tmpNameSync, 'utf-8');
console.log(`secretValue: ${secretContent}`);
expect(secretContent).toEqual(secret);
});
});

View File

@ -1,259 +0,0 @@
import * as fs from 'fs';
import * as path from 'path';
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=abcdefghijklmno=0123456789'],
]),
[
'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=abcdefghijklmno=0123456789'],
['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');
const res = await context.getInputList('foo');
console.log(res);
expect(res).toEqual(['bar']);
});
it('handles multiple lines correctly', async () => {
setInput('foo', 'bar\nbaz');
const res = await context.getInputList('foo');
console.log(res);
expect(res).toEqual(['bar', 'baz']);
});
it('remove empty lines correctly', async () => {
setInput('foo', 'bar\n\nbaz');
const res = await context.getInputList('foo');
console.log(res);
expect(res).toEqual(['bar', 'baz']);
});
it('handles comma correctly', async () => {
setInput('foo', 'bar,baz');
const res = await context.getInputList('foo');
console.log(res);
expect(res).toEqual(['bar', 'baz']);
});
it('remove empty result correctly', async () => {
setInput('foo', 'bar,baz,');
const res = await context.getInputList('foo');
console.log(res);
expect(res).toEqual(['bar', 'baz']);
});
it('handles different new lines correctly', async () => {
setInput('foo', 'bar\r\nbaz');
const res = await context.getInputList('foo');
console.log(res);
expect(res).toEqual(['bar', 'baz']);
});
it('handles different new lines and comma correctly', async () => {
setInput('foo', 'bar\r\nbaz,bat');
const res = await context.getInputList('foo');
console.log(res);
expect(res).toEqual(['bar', 'baz', 'bat']);
});
it('handles multiple lines and ignoring comma correctly', async () => {
setInput('cache-from', 'user/app:cache\ntype=local,src=path/to/dir');
const res = await context.getInputList('cache-from', true);
console.log(res);
expect(res).toEqual(['user/app:cache', 'type=local,src=path/to/dir']);
});
it('handles different new lines and ignoring comma correctly', async () => {
setInput('cache-from', 'user/app:cache\r\ntype=local,src=path/to/dir');
const res = await context.getInputList('cache-from', true);
console.log(res);
expect(res).toEqual(['user/app:cache', 'type=local,src=path/to/dir']);
});
});
describe('asyncForEach', () => {
it('executes async tasks sequentially', async () => {
const testValues = [1, 2, 3, 4, 5];
const results: number[] = [];
await context.asyncForEach(testValues, async value => {
results.push(value);
});
expect(results).toEqual(testValues);
});
});
// See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67
function getInputName(name: string): string {
return `INPUT_${name.replace(/ /g, '_').toUpperCase()}`;
}
function setInput(name: string, value: string): void {
process.env[getInputName(name)] = value;
}

View File

@ -1,78 +1,67 @@
# https://help.github.com/en/articles/metadata-syntax-for-github-actions
name: Build and push Docker images
description: Build and push Docker images with Buildx
author: docker
description: Builds and pushes Docker images and will log in to a Docker registry if required
author: Docker
branding:
icon: 'anchor'
color: 'blue'
runs:
using: docker
image: docker://docker/github-actions:v1
args:
- build-push
inputs:
builder:
description: "Builder instance"
username:
description: Username used to log in to a Docker registry. If not set then no login will occur
required: false
context:
description: "Build's context is the set of files located in the specified PATH or URL"
password:
description: Password or personal access token used to log in to a Docker registry. If not set then no login will occur
required: false
file:
description: "Path to the Dockerfile"
registry:
description: Server address of Docker registry. If not set then will default to Docker Hub
required: false
default: './Dockerfile'
build-args:
description: "List of build-time variables"
repository:
deprecationMessage: 'v2 beta is now available through docker/build-push-action@v2'
description: Docker repository to tag the image with
required: true
tags:
description: Comma-delimited list of tags. These will be added to the registry/repository to form the image's tags
required: false
tag_with_ref:
description: Automatically tags the built image with the git reference as per the readme
required: false
default: false
tag_with_sha:
description: Automatically tags the built image with the git short SHA as per the readme
required: false
default: false
path:
description: Path to the build context
required: false
default: "."
dockerfile:
description: Path to the Dockerfile (Default is '{path}/Dockerfile')
required: false
target:
description: Sets the target stage to build
required: false
always_pull:
description: Always attempt to pull a newer version of the image
required: false
default: false
build_args:
description: Comma-delimited list of build-time variables
required: false
cache_froms:
description: Comma-delimited list of images to consider as cache sources
required: false
labels:
description: "List of metadata for an image"
description: Comma-delimited list of labels to add to the built image
required: false
tags:
description: "List of tags"
add_git_labels:
description: Adds labels with git repository information to the built image
required: false
pull:
description: "Always attempt to pull a newer version of the image"
required: false
default: 'false'
target:
description: "Sets the target stage to build"
required: false
allow:
description: "List of extra privileged entitlement (eg. network.host,security.insecure)"
required: false
no-cache:
description: "Do not use cache when building the image"
required: false
default: 'false'
platforms:
description: "List of target platforms for build"
required: false
load:
description: "Load is a shorthand for --output=type=docker"
required: false
default: 'false'
default: false
push:
description: "Push is a shorthand for --output=type=registry"
description: Whether to push the image
required: false
default: 'false'
outputs:
description: "List of output destinations (format: type=local,dest=path)"
required: false
cache-from:
description: "List of external cache sources for buildx (eg. user/app:cache, type=local,src=path/to/dir)"
required: false
cache-to:
description: "List of cache export destinations for buildx (eg. user/app:cache, type=local,dest=path/to/dir)"
required: false
secrets:
description: "List of secrets to expose to the build (eg. key=value, GIT_AUTH_TOKEN=mytoken)"
required: false
github-token:
description: "GitHub Token used to authenticate against a repository for Git context"
default: ${{ github.token }}
required: false
outputs:
digest:
description: 'Image content-addressable identifier also called a digest'
runs:
using: 'node12'
main: 'dist/index.js'
post: 'dist/index.js'
default: true

15528
dist/index.js vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,42 +0,0 @@
group "default" {
targets = ["build"]
}
group "pre-checkin" {
targets = ["update-yarn", "format", "build"]
}
group "validate" {
targets = ["validate-format", "validate-build", "validate-yarn"]
}
target "update-yarn" {
target = "update-yarn"
output = ["."]
}
target "build" {
target = "dist"
output = ["."]
}
target "test" {
target = "test"
}
target "format" {
target = "format"
output = ["."]
}
target "validate-format" {
target = "validate-format"
}
target "validate-build" {
target = "validate-build"
}
target "validate-yarn" {
target = "validate-yarn"
}

View File

@ -1,12 +0,0 @@
module.exports = {
clearMocks: false,
moduleFileExtensions: ['js', 'ts'],
setupFiles: ["dotenv/config"],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: false
}

View File

@ -1,53 +0,0 @@
{
"name": "docker-build-push",
"description": "Build and push Docker images",
"main": "lib/main.js",
"scripts": {
"build": "tsc && ncc build",
"format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts",
"test": "jest --coverage",
"pre-checkin": "yarn run format && yarn run build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/docker/build-push-action.git"
},
"keywords": [
"actions",
"docker",
"build",
"push"
],
"author": "Docker",
"contributors": [
{
"name": "CrazyMax",
"url": "https://crazymax.dev"
}
],
"license": "Apache-2.0",
"dependencies": {
"@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",
"@vercel/ncc": "^0.23.0",
"dotenv": "^8.2.0",
"jest": "^26.1.0",
"jest-circus": "^26.1.0",
"jest-runtime": "^26.1.0",
"prettier": "^2.0.5",
"ts-jest": "^26.1.1",
"typescript": "^3.9.5",
"typescript-formatter": "^7.2.2"
}
}

View File

@ -1,85 +0,0 @@
import fs from 'fs';
import path from 'path';
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').split(path.sep).join(path.posix.sep);
}
export async function getImageID(): Promise<string | undefined> {
const iidFile = await getImageIDFile();
if (!fs.existsSync(iidFile)) {
return undefined;
}
return fs.readFileSync(iidFile, {encoding: 'utf-8'});
}
export async function getSecret(kvp: string): Promise<string> {
const delimiterIndex = kvp.indexOf('=');
const key = kvp.substring(0, delimiterIndex);
const value = kvp.substring(delimiterIndex + 1);
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) {
return false;
}
return res.success;
});
}
export async function getVersion(): Promise<string> {
return await exec.exec(`docker`, ['buildx', 'version'], true).then(res => {
if (res.stderr != '' && !res.success) {
throw new Error(res.stderr);
}
return parseVersion(res.stdout);
});
}
export async function parseVersion(stdout: string): Promise<string> {
const matches = /\sv?([0-9.]+)/.exec(stdout);
if (!matches) {
throw new Error(`Cannot parse Buildx version`);
}
return semver.clean(matches[1]);
}

View File

@ -1,169 +0,0 @@
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';
let _defaultContext, _tmpDir: string;
export interface Inputs {
context: string;
file: string;
buildArgs: string[];
labels: string[];
tags: string[];
pull: boolean;
target: string;
allow: string[];
noCache: boolean;
builder: string;
platforms: string[];
load: boolean;
push: boolean;
outputs: string[];
cacheFrom: string[];
cacheTo: string[];
secrets: string[];
githubToken: string;
}
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', true),
labels: await getInputList('labels', true),
tags: await getInputList('tags'),
pull: /true/i.test(core.getInput('pull')),
target: core.getInput('target'),
allow: await getInputList('allow'),
noCache: /true/i.test(core.getInput('no-cache')),
builder: core.getInput('builder'),
platforms: await getInputList('platforms'),
load: /true/i.test(core.getInput('load')),
push: /true/i.test(core.getInput('push')),
outputs: await getInputList('outputs', true),
cacheFrom: await getInputList('cache-from', true),
cacheTo: await getInputList('cache-to', true),
secrets: await getInputList('secrets', true),
githubToken: core.getInput('github-token')
};
}
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, defaultContext, buildxVersion));
args.push.apply(args, await getCommonArgs(inputs));
args.push(inputs.context);
return args;
}
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);
});
await asyncForEach(inputs.labels, async label => {
args.push('--label', label);
});
await asyncForEach(inputs.tags, async tag => {
args.push('--tag', tag);
});
if (inputs.target) {
args.push('--target', inputs.target);
}
if (inputs.allow.length > 0) {
args.push('--allow', inputs.allow.join(','));
}
if (inputs.platforms.length > 0) {
args.push('--platform', inputs.platforms.join(','));
}
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);
});
await asyncForEach(inputs.secrets, async secret => {
args.push('--secret', await buildx.getSecret(secret));
});
if (inputs.githubToken && !buildx.hasGitAuthToken(inputs.secrets) && inputs.context == defaultContext) {
args.push('--secret', await buildx.getSecret(`GIT_AUTH_TOKEN=${inputs.githubToken}`));
}
if (inputs.file) {
args.push('--file', inputs.file);
}
return args;
}
async function getCommonArgs(inputs: Inputs): Promise<Array<string>> {
let args: Array<string> = [];
if (inputs.noCache) {
args.push('--no-cache');
}
if (inputs.builder) {
args.push('--builder', inputs.builder);
}
if (inputs.pull) {
args.push('--pull');
}
if (inputs.load) {
args.push('--load');
}
if (inputs.push) {
args.push('--push');
}
return args;
}
export async function getInputList(name: string, ignoreComma?: boolean): Promise<string[]> {
const items = core.getInput(name);
if (items == '') {
return [];
}
return items
.split(/\r?\n/)
.filter(x => x)
.reduce<string[]>(
(acc, line) => acc.concat(!ignoreComma ? line.split(',').filter(x => x) : line).map(pat => pat.trim()),
[]
);
}
export const asyncForEach = async (array, callback) => {
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
};

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,56 +0,0 @@
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';
async function run(): Promise<void> {
try {
if (os.platform() !== 'linux') {
throw new Error(`Only supported on linux platform`);
}
if (!(await buildx.isAvailable())) {
throw new Error(`Buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
}
stateHelper.setTmpDir(context.tmpDir());
const buildxVersion = await buildx.getVersion();
core.info(`📣 Buildx version: ${buildxVersion}`);
const defContext = context.defaultContext();
let inputs: context.Inputs = await context.getInputs(defContext);
core.info(`🏃 Starting build...`);
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) {
core.info('🛒 Extracting digest...');
core.info(`${imageID}`);
core.setOutput('digest', imageID);
}
} catch (error) {
core.setFailed(error.message);
}
}
async function cleanup(): Promise<void> {
if (stateHelper.tmpDir.length > 0) {
core.info(`🚿 Removing temp folder ${stateHelper.tmpDir}`);
fs.rmdirSync(stateHelper.tmpDir, {recursive: true});
}
}
if (!stateHelper.IsPost) {
run();
} else {
cleanup();
}

View File

@ -1,12 +0,0 @@
import * as core from '@actions/core';
export const IsPost = !!process.env['STATE_isPost'];
export const tmpDir = process.env['STATE_tmpDir'] || '';
export function setTmpDir(tmpDir: string) {
core.saveState('tmpDir', tmpDir);
}
if (!IsPost) {
core.saveState('isPost', 'true');
}

View File

@ -1,3 +0,0 @@
FROM alpine
RUN echo "Hello world!"

View File

@ -1,8 +0,0 @@
FROM --platform=$BUILDPLATFORM golang:alpine AS build
ARG TARGETPLATFORM
ARG BUILDPLATFORM
RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM" > /log
FROM alpine
COPY --from=build /log /log

View File

@ -1,22 +0,0 @@
FROM --platform=$BUILDPLATFORM golang:alpine AS build
ARG TARGETPLATFORM
ARG BUILDPLATFORM
RUN echo "I am running on $BUILDPLATFORM, building for $TARGETPLATFORM" > /log
RUN apk --update --no-cache add \
shadow \
sudo \
&& addgroup -g 1200 buildx \
&& adduser -u 1200 -G buildx -s /sbin/nologin -D buildx \
&& echo 'buildx ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \
&& rm -rf /tmp/* /var/cache/apk/*
USER buildx
RUN sudo chown buildx. /log
USER root
FROM alpine
COPY --from=build /log /log
RUN ls -al /log

View File

@ -1,21 +0,0 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"lib": [
"es6",
"dom"
],
"newLine": "lf",
"outDir": "./lib",
"rootDir": "./src",
"strict": true,
"noImplicitAny": false,
"esModuleInterop": true,
"sourceMap": true
},
"exclude": [
"node_modules",
"**/*.test.ts"
]
}

3921
yarn.lock

File diff suppressed because it is too large Load Diff