Compare commits

..

98 Commits

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-22 13:34:01 +00:00
cc01c17e75 Merge pull request #382 from docker/dependabot/npm_and_yarn/actions/exec-1.1.0
Bump @actions/exec from 1.0.4 to 1.1.0
2021-06-22 15:32:21 +02:00
90850ba046 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-22 15:30:39 +02:00
915370c72f Bump @actions/exec from 1.0.4 to 1.1.0
Bumps [@actions/exec](https://github.com/actions/toolkit/tree/HEAD/packages/exec) from 1.0.4 to 1.1.0.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/exec/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/@actions/core@1.1.0/packages/exec)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-22 12:53:49 +00:00
f87b75314d Merge pull request #383 from docker/dependabot/npm_and_yarn/actions/core-1.4.0
Bump @actions/core from 1.3.0 to 1.4.0
2021-06-22 14:51:44 +02:00
ecbc0634e4 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-06-22 14:46:28 +02:00
06b9aae8bc Bump @actions/core from 1.3.0 to 1.4.0
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-06-08 05:24:02 +00:00
779802e2ee Merge pull request #375 from docker/dependabot/npm_and_yarn/ws-7.4.6
Bump ws from 7.3.1 to 7.4.6
2021-05-30 21:58:54 +02:00
dd8c19ed49 Bump ws from 7.3.1 to 7.4.6
Bumps [ws](https://github.com/websockets/ws) from 7.3.1 to 7.4.6.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.3.1...7.4.6)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-30 19:56:33 +00:00
ad44023a93 Merge pull request #371 from crazy-max/console-output
Enhance console output
2021-05-26 14:29:35 +02:00
57f367c048 Enhance console output
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-05-26 14:26:38 +02:00
74242a33cc Merge pull request #347 from crazy-max/fix-ref-spec
Fix ref spec for default Git context
2021-05-26 13:00:32 +02:00
2b2d125b68 Merge pull request #370 from docker/dependabot/npm_and_yarn/actions/core-1.3.0
Bump @actions/core from 1.2.7 to 1.3.0
2021-05-25 00:08:33 +02:00
5ac438e8df Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-05-25 00:02:51 +02:00
ae91a8353f Bump @actions/core from 1.2.7 to 1.3.0
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.7 to 1.3.0.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-24 06:14:32 +00:00
ca26f5b713 Merge pull request #369 from crazy-max/preserve-quotes
Preserve quotes inside unquoted field
2021-05-23 15:30:37 +02:00
c9589d1941 Preserve quotes inside unquoted field
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-05-23 02:41:02 +02:00
95f997534a Merge pull request #362 from akhilerm/add-tag-push-action
Add tag-push action to advanced usage section
2021-05-21 17:36:43 +02:00
655d1f6b37 Merge pull request #368 from crazy-max/share-image
Share built image between jobs
2021-05-21 17:10:30 +02:00
6f4938aa75 Share built image between jobs
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-05-21 17:05:21 +02:00
18fa566857 Merge pull request #364 from docker/dependabot/npm_and_yarn/actions/github-5.0.0
Bump @actions/github from 4.0.0 to 5.0.0
2021-05-18 20:51:52 +02:00
11f0499b05 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-05-18 20:49:30 +02:00
f3f2d78b13 Bump @actions/github from 4.0.0 to 5.0.0
Bumps [@actions/github](https://github.com/actions/toolkit/tree/HEAD/packages/github) from 4.0.0 to 5.0.0.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/github/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/github)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-17 06:22:04 +00:00
5b3f377cdd add tag-push action to advanced usage section
Signed-off-by: Akhil Mohan <akhil.mohan@mayadata.io>
2021-05-12 15:56:02 +05:30
cc23ce7e44 Merge pull request #356 from docker/dependabot/npm_and_yarn/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9
2021-05-12 00:25:48 +02:00
64708ddf75 Bump hosted-git-info from 2.8.8 to 2.8.9
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 22:23:32 +00:00
8e208dd401 Merge pull request #355 from docker/dependabot/npm_and_yarn/lodash-4.17.21
Bump lodash from 4.17.20 to 4.17.21
2021-05-12 00:22:21 +02:00
bb77c476bd Bump lodash from 4.17.20 to 4.17.21
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 22:19:58 +00:00
8e1d874ee2 Merge pull request #354 from crazy-max/docker-metadata
Update examples with `docker/metadata-action`
2021-05-10 18:19:54 +02:00
3a090ce0da Update examples with docker/metadata-action
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-05-10 18:01:34 +02:00
17822e4df4 Merge pull request #350 from crazy-max/fix-setoutput
Fix setOutput
2021-04-27 16:34:06 +02:00
5e92e6623e Fix setOutput
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-27 16:30:22 +02:00
3ce082ae8d Merge pull request #349 from crazy-max/remove-os-limitation
Remove os limitation
2021-04-27 16:19:03 +02:00
d619a7ff00 Remove os limitation
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-27 16:16:28 +02:00
19c07384dc Fix ref spec for default Git context
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-26 11:04:27 +02:00
4cef7b9d89 Merge pull request #348 from crazy-max/doc
Update troubleshooting notes
2021-04-25 00:12:32 +02:00
5676f00637 Update troubleshooting notes
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-23 23:34:43 +02:00
c0c3e27be3 Merge pull request #345 from docker/dependabot/npm_and_yarn/csv-parse-4.15.4
Bump csv-parse from 4.15.3 to 4.15.4
2021-04-16 13:25:50 +02:00
c9b5cc4c4e Merge pull request #344 from docker/dependabot/npm_and_yarn/actions/core-1.2.7
Bump @actions/core from 1.2.6 to 1.2.7
2021-04-16 13:22:39 +02:00
6e53d9494f Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-16 13:22:09 +02:00
01f4a7369d Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-16 13:20:36 +02:00
91bb504133 Bump csv-parse from 4.15.3 to 4.15.4
Bumps [csv-parse](https://github.com/wdavidw/node-csv-parse) from 4.15.3 to 4.15.4.
- [Release notes](https://github.com/wdavidw/node-csv-parse/releases)
- [Changelog](https://github.com/adaltas/node-csv-parse/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wdavidw/node-csv-parse/compare/v4.15.3...v4.15.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-16 05:49:53 +00:00
c4742793d5 Bump @actions/core from 1.2.6 to 1.2.7
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.2.6 to 1.2.7.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Signed-off-by: dependabot[bot] <support@github.com>
2021-04-14 05:48:43 +00:00
e1b7f96249 Merge pull request #338 from crazy-max/network
Add network input
2021-04-06 23:42:58 +02:00
5a4a26c0fc Add network input
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-06 14:49:15 +02:00
8891861577 Merge pull request #337 from crazy-max/sort-inputs
Sort inputs
2021-04-06 13:56:35 +02:00
f6a733366a Sort inputs
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-06 13:55:04 +02:00
eb4f14646c Merge pull request #331 from crazy-max/doc
Fix doc links
2021-04-06 13:11:23 +02:00
646552f0a1 Fix doc links
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-03 20:41:36 +02:00
2ec8f1d346 Merge pull request #328 from crazy-max/github-serverurl
Handle GitHub server URL for default context
2021-04-01 23:59:21 +02:00
8f5c91aad9 Handle GitHub server URL for default context
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-04-01 20:07:51 +02:00
6a12baa867 Merge pull request #325 from docker/dependabot/npm_and_yarn/y18n-4.0.1
Bump y18n from 4.0.0 to 4.0.1
2021-03-30 13:13:45 +02:00
da940a9403 Bump y18n from 4.0.0 to 4.0.1
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-29 21:52:47 +00:00
9cf6eb2b16 Merge pull request #318 from docker/dependabot/npm_and_yarn/semver-7.3.5
Bump semver from 7.3.4 to 7.3.5
2021-03-29 23:51:27 +02:00
3c2d8e5269 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-03-29 23:47:36 +02:00
d693655c74 Merge pull request #323 from crazy-max/meta-v2
Meta action v2
2021-03-29 22:22:23 +02:00
bfea497a8e Merge pull request #322 from crazy-max/workflow
Enhance workflow
2021-03-29 22:09:29 +02:00
8ca2ca55d4 Meta action v2
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-03-29 14:33:52 +02:00
460e0e47f5 Enhance workflow
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-03-28 16:43:57 +02:00
edb2e175f1 Bump semver from 7.3.4 to 7.3.5
Bumps [semver](https://github.com/npm/node-semver) from 7.3.4 to 7.3.5.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/master/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.3.4...v7.3.5)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-23 05:56:49 +00:00
09f8407c80 Merge pull request #303 from docker/dependabot/npm_and_yarn/csv-parse-4.15.3
Bump csv-parse from 4.15.1 to 4.15.3
2021-03-18 20:50:28 +01:00
614833a85f Bump csv-parse from 4.15.1 to 4.15.3
Bumps [csv-parse](https://github.com/wdavidw/node-csv-parse) from 4.15.1 to 4.15.3.
- [Release notes](https://github.com/wdavidw/node-csv-parse/releases)
- [Changelog](https://github.com/adaltas/node-csv-parse/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wdavidw/node-csv-parse/compare/v4.15.1...v4.15.3)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-18 19:48:26 +00:00
0ec1157bb5 Merge pull request #305 from TanguyChiffoleau/master
Fix wrong link for login action repo
2021-02-24 23:55:51 +01:00
22d49d64f5 Fix wrong link for login action repo
Signed-off-by: TanguyChiffoleau <55456592+TanguyChiffoleau@users.noreply.github.com>
2021-02-24 23:44:08 +01:00
9379083e42 Merge pull request #299 from crazy-max/split-docs
Enhance documentation
2021-02-17 19:08:07 +01:00
a63b18dea2 Enhance documentation
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-02-17 18:53:20 +01:00
af867d4937 Merge pull request #296 from crazy-max/secret-file
Allow to use secret file mount
2021-02-16 13:15:29 +01:00
33eec1587d Update action.yml
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-02-16 11:56:02 +01:00
3db4797dd2 Merge pull request #298 from crazy-max/virtual-env
Enhance virtual-env workflow
2021-02-15 20:48:57 +01:00
659fcba376 Enhance virtual-env workflow
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-02-15 20:39:21 +01:00
080cadd33e Allow to use secret file mount
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-02-15 10:08:25 +01:00
dc4c1fca8b Merge pull request #297 from crazy-max/labels
Remove label workflow
2021-02-14 23:17:33 +01:00
b280b0485b Merge pull request #287 from docker/dependabot/npm_and_yarn/csv-parse-4.15.1
Bump csv-parse from 4.14.2 to 4.15.1
2021-02-14 23:13:24 +01:00
b87564a5cc Remove label workflow
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-02-14 23:12:36 +01:00
d2bc6a5d16 Update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-02-14 22:41:16 +01:00
e5f26cdae4 Merge pull request #295 from crazy-max/update-buildx
Update buildx
2021-02-14 22:30:37 +01:00
616efcd405 Update buildx
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-02-14 22:28:22 +01:00
0539e1a717 Bump csv-parse from 4.14.2 to 4.15.1
Bumps [csv-parse](https://github.com/wdavidw/node-csv-parse) from 4.14.2 to 4.15.1.
- [Release notes](https://github.com/wdavidw/node-csv-parse/releases)
- [Changelog](https://github.com/adaltas/node-csv-parse/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wdavidw/node-csv-parse/compare/v4.14.2...v4.15.1)

Signed-off-by: dependabot[bot] <support@github.com>
2021-02-02 05:59:48 +00:00
636b4540ec Merge pull request #273 from crazy-max/fix-workflow
Fix workflow for auto-push impl
2021-01-15 19:36:02 -08:00
af932bfb2e Fix workflow for auto-push impl
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-01-15 19:21:19 +01:00
2db03de115 Merge pull request #272 from crazy-max/virtual-env
Add virtual-env workflow
2021-01-15 19:17:18 +01:00
4643aec7c4 Add virtual-env workflow
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2021-01-15 19:13:45 +01:00
47 changed files with 15645 additions and 14973 deletions

View File

@ -1 +1,2 @@
node_modules
/coverage
/node_modules

View File

@ -2,33 +2,20 @@
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).
Contributions to this project are [released](https://docs.github.com/en/github/site-policy/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
```
3. Create a new branch: `git checkout -b my-branch-name`
4. Make your changes
5. Make sure the tests pass: `docker buildx bake test`
6. Format code and build javascript artifacts: `docker buildx bake pre-checkin`
7. Validate all code has correctly formatted and built: `docker buildx bake validate`
8. Push to your fork and [submit a pull request](https://github.com/docker/build-push-action/compare)
9. Pat your self on the back and wait for your pull request to be reviewed and merged.
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
@ -40,5 +27,5 @@ Here are a few things you can do that will increase the likelihood of your pull
## 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)
- [Using Pull Requests](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)
- [GitHub Help](https://docs.github.com/en)

View File

@ -5,7 +5,7 @@ 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).
Before submitting a bug report please read the [Troubleshooting doc](https://github.com/docker/build-push-action/blob/master/TROUBLESHOOTING.md).
### Behaviour
@ -34,4 +34,4 @@ Before sumbitting a bug report please read the [Troubleshooting doc](https://git
### 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.
> Download the [log file of your build](https://docs.github.com/en/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs) and [attach it](https://docs.github.com/en/github/managing-your-work-on-github/file-attachments-on-issues-and-pull-requests) to this issue.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 29 KiB

View File

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

111
.github/labels.yml vendored
View File

@ -1,111 +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: ""
- # upstream
name: ":eyes: upstream"
color: "fbca04"
description: ""
- # wontfix
name: ":coffin: wontfix"
color: "ffffff"
description: ""
- # registry-aws-ecr
name: "registry-aws-ecr"
color: "84858A"
description: ""
- # registry-azure-acr
name: "registry-azure-acr"
color: "84858A"
description: ""
- # registry-dockerhub
name: "registry-dockerhub"
color: "84858A"
description: ""
- # registry-github
name: "registry-github"
color: "84858A"
description: ""
- # registry-google-gar
name: "registry-google-gar"
color: "84858A"
description: ""
- # registry-google-gcr
name: "registry-google-gcr"
color: "84858A"
description: ""
- # registry-nexus
name: "registry-nexus"
color: "84858A"
description: ""
- # registry-quay
name: "registry-quay"
color: "84858A"
description: ""

View File

@ -207,6 +207,37 @@ jobs:
uses: crazy-max/ghaction-dump-context@v1
error:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Stop docker
run: |
sudo systemctl stop docker
-
name: Build
id: docker_build
continue-on-error: true
uses: ./
with:
context: ./test
file: ./test/Dockerfile
-
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
error-buildx:
runs-on: ubuntu-latest
steps:
-
@ -244,12 +275,6 @@ jobs:
docker-driver:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
push:
- true
- false
services:
registry:
image: registry:2
@ -262,24 +287,12 @@ jobs:
-
name: Build
id: docker_build
continue-on-error: ${{ matrix.push }}
uses: ./
with:
context: ./test
file: ./test/Dockerfile
push: ${{ matrix.push }}
push: true
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()
@ -308,6 +321,30 @@ jobs:
if: always()
uses: crazy-max/ghaction-dump-context@v1
network:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: List networks
run: docker network ls
-
name: Build
uses: ./
with:
context: ./test
tags: name/app:latest
network: host
-
name: Dump context
if: always()
uses: crazy-max/ghaction-dump-context@v1
multi:
runs-on: ubuntu-latest
strategy:
@ -344,7 +381,7 @@ jobs:
uses: ./
with:
context: ./test
file: ./test/Dockerfile-${{ matrix.dockerfile }}
file: ./test/${{ matrix.dockerfile }}.Dockerfile
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
@ -397,7 +434,7 @@ jobs:
uses: ./
with:
context: ./test
file: ./test/Dockerfile-multi
file: ./test/multi.Dockerfile
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
@ -430,7 +467,7 @@ jobs:
uses: ./
with:
context: ./test
file: ./test/Dockerfile-multi
file: ./test/multi.Dockerfile
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
@ -507,7 +544,7 @@ jobs:
uses: ./
with:
context: ./test
file: ./test/Dockerfile-multi
file: ./test/multi.Dockerfile
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true
@ -572,7 +609,7 @@ jobs:
uses: ./
with:
context: ./test
file: ./test/Dockerfile-multi
file: ./test/multi.Dockerfile
builder: ${{ steps.buildx.outputs.name }}
platforms: linux/amd64,linux/arm64
push: true

View File

@ -58,8 +58,8 @@ jobs:
uses: actions/checkout@v2
-
name: Docker meta
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v1
id: meta
uses: docker/metadata-action@v3
with:
images: ${{ matrix.slug }}
-
@ -81,24 +81,24 @@ jobs:
uses: ./
with:
context: ./test
file: ./test/Dockerfile-multi
file: ./test/multi.Dockerfile
platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ matrix.slug }}:master
cache-to: type=inline
-
name: Inspect image
if: github.event_name != 'pull_request'
run: |
docker pull ${{ matrix.slug }}:${{ steps.docker_meta.outputs.version }}
docker image inspect ${{ matrix.slug }}:${{ steps.docker_meta.outputs.version }}
docker pull ${{ matrix.slug }}:${{ steps.meta.outputs.version }}
docker image inspect ${{ matrix.slug }}:${{ steps.meta.outputs.version }}
-
name: Check manifest
if: github.event_name != 'pull_request'
run: |
docker buildx imagetools inspect ${{ matrix.slug }}:${{ steps.docker_meta.outputs.version }}
docker buildx imagetools inspect ${{ matrix.slug }}:${{ steps.meta.outputs.version }}
-
name: Dump context
if: always()

View File

@ -28,11 +28,18 @@ jobs:
uses: actions/checkout@v2
-
name: Docker meta
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v1
id: meta
uses: docker/metadata-action@v3
with:
images: ${{ env.DOCKER_IMAGE }} # list of Docker images to use as base name for tags
tag-sha: true # add git short SHA as Docker tag
images: ${{ env.DOCKER_IMAGE }}
tags: |
type=schedule
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
@ -45,8 +52,8 @@ jobs:
context: ./test
file: ./test/Dockerfile
load: true
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
-
name: Build and push to local registry
uses: ./
@ -54,17 +61,17 @@ jobs:
context: ./test
file: ./test/Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
-
name: Inspect image
run: |
docker image inspect ${{ env.DOCKER_IMAGE }}:${{ steps.docker_meta.outputs.version }}
docker image inspect ${{ env.DOCKER_IMAGE }}:${{ steps.meta.outputs.version }}
-
name: Check manifest
if: github.event_name != 'pull_request'
run: |
docker buildx imagetools inspect ${{ env.DOCKER_IMAGE }}:${{ steps.docker_meta.outputs.version }}
docker buildx imagetools inspect ${{ env.DOCKER_IMAGE }}:${{ steps.meta.outputs.version }}
-
name: Dump context
if: always()

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
-
name: Run Labeler
uses: crazy-max/ghaction-github-labeler@v3

View File

@ -3,25 +3,12 @@ name: test
on:
push:
branches:
- master
- 'master'
pull_request:
branches:
- master
- 'master'
jobs:
test-containerized:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Validate
run: docker buildx bake validate
-
name: Test
run: docker buildx bake test
test:
runs-on: ubuntu-latest
steps:
@ -29,15 +16,17 @@ jobs:
name: Checkout
uses: actions/checkout@v2
-
name: Install
run: yarn install
name: Validate
uses: docker/bake-action@v1
with:
targets: validate
-
name: Test
run: yarn run test
uses: docker/bake-action@v1
with:
targets: test
-
name: Upload coverage
uses: codecov/codecov-action@v1
if: success()
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage/clover.xml

38
.github/workflows/virtual-env.yml vendored Normal file
View File

@ -0,0 +1,38 @@
name: virtual-env
on:
workflow_dispatch:
schedule:
- cron: '0 10 * * *' # everyday at 10am
jobs:
os:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- ubuntu-20.04
- ubuntu-18.04
- ubuntu-16.04
steps:
-
name: List install packages
run: apt list --installed
-
name: Docker info
run: docker info
-
name: Docker version
run: docker version
-
name: buildx version
run: docker buildx version
-
name: containerd version
run: containerd --version
-
name: Dump context
if: always()
uses: crazy-max/ghaction-dump-context@v1

View File

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

View File

@ -1,52 +0,0 @@
#syntax=docker/dockerfile:1.1-experimental
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"]

594
README.md
View File

@ -6,23 +6,18 @@
## 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 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.
`v2` of this action includes significant updates and now uses Docker [Buildx](https://github.com/docker/buildx). 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.
[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).
[Upgrade notes](UPGRADE.md) with many [usage examples](#advanced-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).
## About
GitHub Action to build and push Docker images with [Buildx](https://github.com/docker/buildx).
> :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
GitHub Action to build and push Docker images with [Buildx](https://github.com/docker/buildx) with full support of the
features provided by [Moby BuildKit](https://github.com/moby/buildkit) builder toolkit. This includes multi-platform
build, secrets, remote cache, etc. and different builder deployment/namespacing options.
![Screenshot](.github/build-push-action.png)
@ -31,46 +26,59 @@ ___
* [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](#cache-to-registry)
* [Local registry](#local-registry)
* [Export image to Docker](#export-image-to-docker)
* [Leverage GitHub cache](#leverage-github-cache)
* [Handle tags and labels](#handle-tags-and-labels)
* [Update DockerHub repo description](#update-dockerhub-repo-description)
* [Multi-platform image](docs/advanced/multi-platform.md)
* [Secrets](docs/advanced/secrets.md)
* [Isolated builders](docs/advanced/isolated-builders.md)
* [Push to multi-registries](docs/advanced/push-multi-registries.md)
* [Copy between registries](docs/advanced/copy-between-registries.md)
* [Cache](docs/advanced/cache.md)
* [Registry cache](docs/advanced/cache.md#registry-cache)
* [GitHub cache](docs/advanced/cache.md#github-cache)
* [Local registry](docs/advanced/local-registry.md)
* [Export image to Docker](docs/advanced/export-docker.md)
* [Share built image between jobs](docs/advanced/share-image-jobs.md)
* [Handle tags and labels](docs/advanced/tags-labels.md)
* [Update DockerHub repo description](docs/advanced/dockerhub-desc.md)
* [Customizing](#customizing)
* [inputs](#inputs)
* [outputs](#outputs)
* [Notes](#notes)
* [Multi-line secret value](#multi-line-secret-value)
* [Troubleshooting](#troubleshooting)
* [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot)
* [Limitation](#limitation)
## Usage
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.
By default, this action uses the [Git context](#git-context) so you don't need to use the
[`actions/checkout`](https://github.com/actions/checkout/) action to checkout the repository because this will be
done directly by buildkit. The git reference will be based on the [event that triggered your workflow](https://docs.github.com/en/actions/reference/events-that-trigger-workflows)
and will result in the following context: `https://github.com/<owner>/<repo>.git#<ref>`.
Be careful because **any file mutation in the steps that precede the build step will be ignored** since
the context is based on the git reference. However, you can use the [Path context](#path-context) using the
[`context` input](#inputs) alongside the [`actions/checkout`](https://github.com/actions/checkout/) action to remove
this restriction.
In the examples below we are using 3 other actions:
* [`setup-buildx`](https://github.com/docker/setup-buildx-action) action will create and boot a builder using by
default the `docker-container` [builder driver](https://github.com/docker/buildx/blob/master/docs/reference/buildx_create.md#driver).
This is **not required but recommended** using it to be able to build multi-platform images, export cache, etc.
* [`setup-qemu`](https://github.com/docker/setup-qemu-action) action can be useful if you want
to add emulation support with QEMU to be able to build against more platforms.
* [`login`](https://github.com/docker/login-action) action will take care to log in against a Docker registry.
### Git context
The default behavior of this action is to use the Git context invoked by your workflow.
(eg. `https://github.com/<owner>/<repo>.git#<ref>`)
```yaml
name: ci
on:
push:
branches: master
branches:
- 'master'
jobs:
main:
docker:
runs-on: ubuntu-latest
steps:
-
@ -92,17 +100,14 @@ jobs:
with:
push: true
tags: user/app:latest
build-args: |
arg1=value1
arg2=value2
-
name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
```
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:
Building from the current repository automatically uses the [GitHub Token](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token)
so it does not need to be passed. If you want to authenticate against another private repository, you have to use
a [secret](docs/advanced/secrets.md) named `GIT_AUTH_TOKEN` to be able to authenticate against it with buildx:
```yaml
-
@ -117,23 +122,20 @@ repository, you have to use a secret named `GIT_AUTH_TOKEN` to be able to authen
```
> :warning: Subdir for Git context is not yet supported ([moby/buildkit#1684](https://github.com/moby/buildkit/issues/1684))
> but you can use the [path context](#path-context) in the meantime.
> More info: https://docs.docker.com/engine/reference/commandline/build/#git-repositories
> but you can use the [path context](#path-context) in the meantime. More info on [Docker docs website](https://docs.docker.com/engine/reference/commandline/build/#git-repositories).
### Path context
You can also use the `PATH` context alongside the [`actions/checkout`](https://github.com/actions/checkout/) action.
```yaml
name: ci
on:
push:
branches: master
branches:
- 'master'
jobs:
path-context:
docker:
runs-on: ubuntu-latest
steps:
-
@ -156,435 +158,25 @@ jobs:
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/386
push: true
tags: user/app:latest
```
### Isolated builders
```yaml
name: ci
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
```
### Multi-platform image
```yaml
name: ci
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
```
## 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`.
### Handle tags and labels
If you come from [`v1`](https://github.com/docker/build-push-action/tree/releases/v1#readme) and want an
"automatic" tag management and [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/master/annotations.md)
for labels, you can do it in a dedicated step. The following workflow will use the [Docker meta action](https://github.com/crazy-max/ghaction-docker-meta)
to handle tags and labels based on GitHub actions events and Git metadata.
<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: Docker meta
id: docker_meta
uses: crazy-max/ghaction-docker-meta@v1
with:
images: name/app # list of Docker images to use as base name for tags
tag-sha: true # add git short SHA as Docker tag
-
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.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}
```
</details>
### 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>
* [Multi-platform image](docs/advanced/multi-platform.md)
* [Secrets](docs/advanced/secrets.md)
* [Isolated builders](docs/advanced/isolated-builders.md)
* [Push to multi-registries](docs/advanced/push-multi-registries.md)
* [Copy between registries](docs/advanced/copy-between-registries.md)
* [Cache](docs/advanced/cache.md)
* [Registry cache](docs/advanced/cache.md#registry-cache)
* [GitHub cache](docs/advanced/cache.md#github-cache)
* [Local registry](docs/advanced/local-registry.md)
* [Export image to Docker](docs/advanced/export-docker.md)
* [Share built image between jobs](docs/advanced/share-image-jobs.md)
* [Handle tags and labels](docs/advanced/tags-labels.md)
* [Update DockerHub repo description](docs/advanced/dockerhub-desc.md)
## Customizing
@ -606,24 +198,26 @@ Following inputs can be used as `step.with` keys
| Name | Type | Description |
|---------------------|----------|------------------------------------|
| `allow` | List/CSV | List of [extra privileged entitlement](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#allow) (eg. `network.host,security.insecure`) |
| `builder` | String | Builder instance (see [setup-buildx](https://github.com/docker/setup-buildx-action) action) |
| `build-args` | List | List of build-time variables |
| `cache-from` | List | List of [external cache sources](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#cache-from) (eg. `type=local,src=path/to/dir`) |
| `cache-to` | List | List of [cache export destinations](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#cache-to) (eg. `type=local,dest=path/to/dir`) |
| `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 `{context}/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`) |
| `load` | Bool | [Load](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#load) is a shorthand for `--output=type=docker` (default `false`) |
| `network` | String | Set the networking mode for the `RUN` instructions during build |
| `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` | List | List of [output destinations](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#output) (format: `type=local,dest=path`) |
| `platforms` | List/CSV | List of [target platforms](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#platform) for build |
| `pull` | Bool | Always attempt to pull a newer version of the image (default `false`) |
| `push` | Bool | [Push](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#push) is a shorthand for `--output=type=registry` (default `false`) |
| `secrets` | List | List of secrets to expose to the build (eg. `key=string`, `GIT_AUTH_TOKEN=mytoken`) |
| `secret-files` | List | List of secret files to expose to the build (eg. `key=filename`, `MY_SECRET=./secret.txt`) |
| `ssh` | List | List of SSH agent socket or keys to expose to the build |
| `tags` | List/CSV | List of tags |
| `target` | String | Sets the target stage to build |
### outputs
@ -633,38 +227,6 @@ Following outputs are available
|---------------|---------|---------------------------------------|
| `digest` | String | Image content-addressable identifier also called a digest |
## Notes
### Multi-line secret value
To handle multi-line value for a secret, you will need to place the key-value pair between quotes:
```yaml
secrets: |
"MYSECRET=${{ secrets.GPG_KEY }}"
GIT_AUTH_TOKEN=abcdefghi,jklmno=0123456789
"MYSECRET=aaaaaaaa
bbbbbbb
ccccccccc"
FOO=bar
"EMPTYLINE=aaaa
bbbb
ccc"
"JSON_SECRET={""key1"":""value1"",""key2"":""value2""}"
```
| Key | Value |
|--------------------|--------------------------------------------------|
| `MYSECRET` | `***********************` |
| `GIT_AUTH_TOKEN` | `abcdefghi,jklmno=0123456789` |
| `MYSECRET` | `aaaaaaaa\nbbbbbbb\nccccccccc` |
| `FOO` | `bar` |
| `EMPTYLINE` | `aaaa\n\nbbbb\nccc` |
| `JSON_SECRET` | `{"key1":"value1","key2":"value2"}` |
> Note: all quote signs need to be doubled for escaping.
## Troubleshooting
See [TROUBLESHOOTING.md](TROUBLESHOOTING.md)
@ -684,7 +246,3 @@ updates:
schedule:
interval: "daily"
```
## Limitation
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).

View File

@ -1,112 +1,8 @@
# 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
```
* [BuildKit container logs](#buildkit-container-logs)
* [With containerd](#with-containerd)
## Cannot push to a registry
@ -122,16 +18,12 @@ These issues are not directly related to this action but are rather linked to [b
[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):
### BuildKit container logs
```yaml
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
buildkitd-flags: --debug
```
To help you solve this, you have to [enable debugging in the setup-buildx](https://github.com/docker/setup-buildx-action#buildkit-container-logs)
action step and attach BuildKit container logs to your issue.
### With containerd
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.
@ -165,8 +57,7 @@ jobs:
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
platforms: linux/amd64,linux/arm64
tags: docker.io/user/app:latest
outputs: type=oci,dest=/tmp/image.tar
-

View File

@ -7,12 +7,12 @@
* 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 `platforms` input to support multi-platform builds
* Add `allow` input
* Add `load` input
* Add `outputs` input
* Add `cache-from` input (`cache_froms` removed)
* Add `cache-to` input
* Rename `build_args` input to `build-args` for consistency with other Docker build tools
* Add `secrets` input
* Review `tags` input
@ -63,7 +63,6 @@ steps:
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
pull: true
push: true
build-args: |
@ -136,7 +135,6 @@ steps:
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.prep.outputs.tags }}
labels: |
@ -145,5 +143,5 @@ steps:
org.opencontainers.image.revision=${{ github.sha }}
```
> You can also use the [Docker meta action](https://github.com/crazy-max/ghaction-docker-meta) to handle tags and
> labels based on GitHub actions events and Git metadata. A workflow example is available in the [README](README.md#handle-tags-and-labels).
> You can also use the [Docker meta action to handle tags and labels](docs/advanced/tags-labels.md) based on GitHub
> actions events and Git metadata.

View File

@ -1,10 +1,10 @@
import * as fs from 'fs';
import * as path from 'path';
import * as semver from 'semver';
import * as exec from '@actions/exec';
import * as buildx from '../src/buildx';
import * as context from '../src/context';
import * as docker from '../src/docker';
const tmpNameSync = path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
const digest = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9';
@ -92,9 +92,26 @@ describe('isLocalOrTarExporter', () => {
);
});
describe('isAvailable', () => {
const execSpy: jest.SpyInstance = jest.spyOn(exec, 'getExecOutput');
buildx.isAvailable();
expect(execSpy).toHaveBeenCalledWith(`docker`, ['buildx'], {
silent: true,
ignoreReturnCode: true
});
});
describe('getVersion', () => {
async function isDaemonRunning() {
return await docker.isDaemonRunning();
return await exec
.getExecOutput(`docker`, ['version', '--format', '{{.Server.Os}}'], {
ignoreReturnCode: true,
silent: true
})
.then(res => {
return !res.stdout.includes(' ') && res.exitCode == 0;
});
}
(isDaemonRunning() ? it : it.skip)(
'valid',
@ -111,29 +128,47 @@ 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']
['github.com/docker/buildx v0.4.2 fb7b670b764764dc4716df3eba07ffdae4cc47b2', '0.4.2'],
['github.com/docker/buildx f117971 f11797113e5a9b86bd976329c5dbb8a8bfdfadfa', 'f117971']
])('given %p', async (stdout, expected) => {
expect(await buildx.parseVersion(stdout)).toEqual(expected);
expect(buildx.parseVersion(stdout)).toEqual(expected);
});
});
describe('satisfies', () => {
test.each([
['0.4.1', '>=0.3.2', true],
['bda4882a65349ca359216b135896bddc1d92461c', '>0.1.0', false],
['f117971', '>0.6.0', true]
])('given %p', async (version, range, expected) => {
expect(buildx.satisfies(version, range)).toBe(expected);
});
});
describe('getSecret', () => {
test.each([
['A_SECRET=abcdef0123456789', 'A_SECRET', 'abcdef0123456789', false],
['GIT_AUTH_TOKEN=abcdefghijklmno=0123456789', 'GIT_AUTH_TOKEN', 'abcdefghijklmno=0123456789', false],
['MY_KEY=c3RyaW5nLXdpdGgtZXF1YWxzCg==', 'MY_KEY', 'c3RyaW5nLXdpdGgtZXF1YWxzCg==', false],
['aaaaaaaa', '', '', true],
['aaaaaaaa=', '', '', true],
['=bbbbbbb', '', '', true]
])('given %p key and %p secret', async (kvp, key, secret, invalid) => {
['A_SECRET=abcdef0123456789', false, 'A_SECRET', 'abcdef0123456789', false],
['GIT_AUTH_TOKEN=abcdefghijklmno=0123456789', false, 'GIT_AUTH_TOKEN', 'abcdefghijklmno=0123456789', false],
['MY_KEY=c3RyaW5nLXdpdGgtZXF1YWxzCg==', false, 'MY_KEY', 'c3RyaW5nLXdpdGgtZXF1YWxzCg==', false],
['aaaaaaaa', false, '', '', true],
['aaaaaaaa=', false, '', '', true],
['=bbbbbbb', false, '', '', true],
[`foo=${path.join(__dirname, 'fixtures', 'secret.txt').split(path.sep).join(path.posix.sep)}`, true, 'foo', 'bar', false],
[`notfound=secret`, true, '', '', true]
])('given %p key and %p secret', async (kvp, file, exKey, exValue, invalid) => {
try {
const secretArgs = await buildx.getSecret(kvp);
let secret: string;
if (file) {
secret = await buildx.getSecretFile(kvp);
} else {
secret = await buildx.getSecretString(kvp);
}
expect(true).toBe(!invalid);
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);
console.log(`secret: ${secret}`);
expect(secret).toEqual(`id=${exKey},src=${tmpNameSync}`);
const secretValue = await fs.readFileSync(tmpNameSync, 'utf-8');
console.log(`secretValue: ${secretValue}`);
expect(secretValue).toEqual(exValue);
} catch (err) {
expect(true).toBe(invalid);
}

View File

@ -1,4 +1,5 @@
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as context from '../src/context';
@ -111,7 +112,7 @@ PejgXO0uIRolYQ3sz2tMGhx1MfBqH64=
-----END PGP PRIVATE KEY BLOCK-----`;
jest.spyOn(context, 'defaultContext').mockImplementation((): string => {
return 'https://github.com/docker/build-push-action.git#test-jest';
return 'https://github.com/docker/build-push-action.git#refs/heads/test-jest';
});
jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
@ -142,6 +143,10 @@ describe('getArgs', () => {
'0.4.1',
new Map<string, string>([
['context', '.'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]),
[
'buildx',
@ -154,6 +159,10 @@ describe('getArgs', () => {
'0.4.2',
new Map<string, string>([
['build-args', 'MY_ARG=val1,val2,val3\nARG=val'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]),
[
'buildx',
@ -161,13 +170,17 @@ describe('getArgs', () => {
'--build-arg', 'MY_ARG=val1,val2,val3',
'--build-arg', 'ARG=val',
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
'https://github.com/docker/build-push-action.git#test-jest'
'https://github.com/docker/build-push-action.git#refs/heads/test-jest'
]
],
[
'0.4.2',
new Map<string, string>([
['tags', 'name/app:7.4, name/app:latest'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]),
[
'buildx',
@ -175,7 +188,7 @@ describe('getArgs', () => {
'--tag', 'name/app:7.4',
'--tag', 'name/app:latest',
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
'https://github.com/docker/build-push-action.git#test-jest'
'https://github.com/docker/build-push-action.git#refs/heads/test-jest'
]
],
[
@ -183,7 +196,11 @@ describe('getArgs', () => {
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']
['outputs', 'type=local,dest=./release-out'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]),
[
'buildx',
@ -198,7 +215,11 @@ describe('getArgs', () => {
'0.4.1',
new Map<string, string>([
['context', '.'],
['platforms', 'linux/amd64,linux/arm64']
['platforms', 'linux/amd64,linux/arm64'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]),
[
'buildx',
@ -210,7 +231,11 @@ describe('getArgs', () => {
[
'0.4.1',
new Map<string, string>([
['context', '.']
['context', '.'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]),
[
'buildx',
@ -224,6 +249,10 @@ describe('getArgs', () => {
new Map<string, string>([
['context', '.'],
['secrets', 'GIT_AUTH_TOKEN=abcdefghijklmno=0123456789'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]),
[
'buildx',
@ -237,26 +266,33 @@ describe('getArgs', () => {
'0.4.2',
new Map<string, string>([
['github-token', 'abcdefghijklmno0123456789'],
['outputs', '.']
['outputs', '.'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]),
[
'buildx',
'build',
'--output', '.',
'--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest',
'https://github.com/docker/build-push-action.git#test-jest'
'https://github.com/docker/build-push-action.git#refs/heads/test-jest'
]
],
[
'0.4.2',
new Map<string, string>([
['context', 'https://github.com/docker/build-push-action.git#heads/master'],
['context', 'https://github.com/docker/build-push-action.git#refs/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']
['load', 'false'],
['no-cache', 'false'],
['push', 'true'],
['pull', 'false']
]),
[
'buildx',
@ -267,13 +303,13 @@ describe('getArgs', () => {
'--file', './test/Dockerfile',
'--builder', 'builder-git-context-2',
'--push',
'https://github.com/docker/build-push-action.git#heads/master'
'https://github.com/docker/build-push-action.git#refs/heads/master'
]
],
[
'0.4.2',
new Map<string, string>([
['context', 'https://github.com/docker/build-push-action.git#heads/master'],
['context', 'https://github.com/docker/build-push-action.git#refs/heads/master'],
['tag', 'localhost:5000/name/app:latest'],
['platforms', 'linux/amd64,linux/arm64'],
['secrets', `GIT_AUTH_TOKEN=abcdefghi,jklmno=0123456789
@ -287,7 +323,10 @@ bbbb
ccc"`],
['file', './test/Dockerfile'],
['builder', 'builder-git-context-2'],
['push', 'true']
['load', 'false'],
['no-cache', 'false'],
['push', 'true'],
['pull', 'false']
]),
[
'buildx',
@ -301,13 +340,13 @@ ccc"`],
'--file', './test/Dockerfile',
'--builder', 'builder-git-context-2',
'--push',
'https://github.com/docker/build-push-action.git#heads/master'
'https://github.com/docker/build-push-action.git#refs/heads/master'
]
],
[
'0.4.2',
new Map<string, string>([
['context', 'https://github.com/docker/build-push-action.git#heads/master'],
['context', 'https://github.com/docker/build-push-action.git#refs/heads/master'],
['tag', 'localhost:5000/name/app:latest'],
['platforms', 'linux/amd64,linux/arm64'],
['secrets', `GIT_AUTH_TOKEN=abcdefghi,jklmno=0123456789
@ -321,7 +360,10 @@ bbbb
ccc`],
['file', './test/Dockerfile'],
['builder', 'builder-git-context-2'],
['push', 'true']
['load', 'false'],
['no-cache', 'false'],
['push', 'true'],
['pull', 'false']
]),
[
'buildx',
@ -335,7 +377,53 @@ ccc`],
'--file', './test/Dockerfile',
'--builder', 'builder-git-context-2',
'--push',
'https://github.com/docker/build-push-action.git#heads/master'
'https://github.com/docker/build-push-action.git#refs/heads/master'
]
],
[
'0.5.1',
new Map<string, string>([
['context', 'https://github.com/docker/build-push-action.git#refs/heads/master'],
['tag', 'localhost:5000/name/app:latest'],
['secret-files', `MY_SECRET=${path.join(__dirname, 'fixtures', 'secret.txt').split(path.sep).join(path.posix.sep)}`],
['file', './test/Dockerfile'],
['builder', 'builder-git-context-2'],
['network', 'host'],
['load', 'false'],
['no-cache', 'false'],
['push', 'true'],
['pull', 'false']
]),
[
'buildx',
'build',
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
'--secret', 'id=MY_SECRET,src=/tmp/.docker-build-push-jest/.tmpname-jest',
'--file', './test/Dockerfile',
'--builder', 'builder-git-context-2',
'--network', 'host',
'--push',
'https://github.com/docker/build-push-action.git#refs/heads/master'
]
],
[
'0.4.2',
new Map<string, string>([
['context', '.'],
['labels', 'org.opencontainers.image.title=filter_results_top_n\norg.opencontainers.image.description=Reference implementation of operation "filter results (top-n)"'],
['outputs', 'type=local,dest=./release-out'],
['load', 'false'],
['no-cache', 'false'],
['push', 'false'],
['pull', 'false']
]),
[
'buildx',
'build',
'--label', 'org.opencontainers.image.title=filter_results_top_n',
'--label', 'org.opencontainers.image.description=Reference implementation of operation "filter results (top-n)"',
'--output', 'type=local,dest=./release-out',
'.'
]
]
])(
@ -477,13 +565,7 @@ FOO=bar`
);
const res = await context.getInputList('secrets', true);
console.log(res);
expect(res).toEqual([
'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789',
'MYSECRET=aaaaaaaa',
'bbbbbbb',
'ccccccccc',
'FOO=bar'
]);
expect(res).toEqual(['GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', 'MYSECRET=aaaaaaaa', 'bbbbbbb', 'ccccccccc', 'FOO=bar']);
});
it('large multiline values', async () => {
@ -531,7 +613,28 @@ describe('asyncForEach', () => {
});
});
// See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67
describe('setOutput', () => {
beforeEach(() => {
process.stdout.write = jest.fn();
});
it('setOutput produces the correct command', () => {
context.setOutput('some output', 'some value');
assertWriteCalls([`::set-output name=some output::some value${os.EOL}`]);
});
it('setOutput handles bools', () => {
context.setOutput('some output', false);
assertWriteCalls([`::set-output name=some output::false${os.EOL}`]);
});
it('setOutput handles numbers', () => {
context.setOutput('some output', 1.01);
assertWriteCalls([`::set-output name=some output::1.01${os.EOL}`]);
});
});
// See: https://github.com/actions/toolkit/blob/a1b068ec31a042ff1e10a522d8fdf0b8869d53ca/packages/core/src/core.ts#L89
function getInputName(name: string): string {
return `INPUT_${name.replace(/ /g, '_').toUpperCase()}`;
}
@ -539,3 +642,11 @@ function getInputName(name: string): string {
function setInput(name: string, value: string): void {
process.env[getInputName(name)] = value;
}
// Assert that process.stdout.write calls called only with the given arguments.
function assertWriteCalls(calls: string[]): void {
expect(process.stdout.write).toHaveBeenCalledTimes(calls.length);
for (let i = 0; i < calls.length; i++) {
expect(process.stdout.write).toHaveBeenNthCalledWith(i + 1, calls[i]);
}
}

View File

@ -0,0 +1 @@
bar

View File

@ -7,51 +7,14 @@ branding:
color: 'blue'
inputs:
builder:
description: "Builder instance"
required: false
context:
description: "Build's context is the set of files located in the specified PATH or URL"
required: false
file:
description: "Path to the Dockerfile"
allow:
description: "List of extra privileged entitlement (eg. network.host,security.insecure)"
required: false
build-args:
description: "List of build-time variables"
required: false
labels:
description: "List of metadata for an image"
required: false
tags:
description: "List of tags"
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'
push:
description: "Push is a shorthand for --output=type=registry"
required: false
default: 'false'
outputs:
description: "List of output destinations (format: type=local,dest=path)"
builder:
description: "Builder instance"
required: false
cache-from:
description: "List of external cache sources for buildx (eg. user/app:cache, type=local,src=path/to/dir)"
@ -59,16 +22,59 @@ inputs:
cache-to:
description: "List of cache export destinations for buildx (eg. user/app:cache, type=local,dest=path/to/dir)"
required: false
context:
description: "Build's context is the set of files located in the specified PATH or URL"
required: false
file:
description: "Path to the Dockerfile"
required: false
labels:
description: "List of metadata for an image"
required: false
load:
description: "Load is a shorthand for --output=type=docker"
required: false
default: 'false'
network:
description: "Set the networking mode for the RUN instructions during build"
required: false
no-cache:
description: "Do not use cache when building the image"
required: false
default: 'false'
outputs:
description: "List of output destinations (format: type=local,dest=path)"
required: false
platforms:
description: "List of target platforms for build"
required: false
pull:
description: "Always attempt to pull a newer version of the image"
required: false
default: 'false'
push:
description: "Push is a shorthand for --output=type=registry"
required: false
default: 'false'
secrets:
description: "List of secrets to expose to the build (eg. key=value, GIT_AUTH_TOKEN=mytoken)"
description: "List of secrets to expose to the build (eg. key=string, GIT_AUTH_TOKEN=mytoken)"
required: false
secret-files:
description: "List of secret files to expose to the build (eg. key=filename, MY_SECRET=./secret.txt)"
required: false
ssh:
description: "List of SSH agent socket or keys to expose to the build"
required: false
tags:
description: "List of tags"
required: false
target:
description: "Sets the target stage to build"
required: false
github-token:
description: "GitHub Token used to authenticate against a repository for Git context"
default: ${{ github.token }}
required: false
ssh:
description: "List of SSH agent socket or keys to expose to the build"
required: false
outputs:
digest:

3
codecov.yml Normal file
View File

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

25779
dist/index.js generated vendored

File diff suppressed because one or more lines are too long

View File

@ -1,42 +1,67 @@
variable "NODE_VERSION" {
default = "12"
}
target "node-version" {
args = {
NODE_VERSION = NODE_VERSION
}
}
group "default" {
targets = ["build"]
}
group "pre-checkin" {
targets = ["update-yarn", "format", "build"]
targets = ["vendor-update", "format", "build"]
}
group "validate" {
targets = ["validate-format", "validate-build", "validate-yarn"]
}
target "update-yarn" {
target = "update-yarn"
output = ["."]
targets = ["format-validate", "build-validate", "vendor-validate"]
}
target "build" {
target = "dist"
inherits = ["node-version"]
dockerfile = "./hack/build.Dockerfile"
target = "build-update"
output = ["."]
}
target "test" {
target = "test"
target "build-validate" {
inherits = ["node-version"]
dockerfile = "./hack/build.Dockerfile"
target = "build-validate"
}
target "format" {
target = "format"
inherits = ["node-version"]
dockerfile = "./hack/build.Dockerfile"
target = "format-update"
output = ["."]
}
target "validate-format" {
target = "validate-format"
target "format-validate" {
inherits = ["node-version"]
dockerfile = "./hack/build.Dockerfile"
target = "format-validate"
}
target "validate-build" {
target = "validate-build"
target "vendor-update" {
inherits = ["node-version"]
dockerfile = "./hack/vendor.Dockerfile"
target = "update"
output = ["."]
}
target "validate-yarn" {
target = "validate-yarn"
target "vendor-validate" {
inherits = ["node-version"]
dockerfile = "./hack/vendor.Dockerfile"
target = "validate"
}
target "test" {
inherits = ["node-version"]
dockerfile = "./hack/test.Dockerfile"
target = "test-coverage"
output = ["./coverage"]
}

107
docs/advanced/cache.md Normal file
View File

@ -0,0 +1,107 @@
# Cache
* [Registry cache](#registry-cache)
* [GitHub cache](#github-cache)
> More info about buildx cache: https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#cache-from
## Registry cache
You can import/export cache from a cache manifest or (special) image configuration on the registry.
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: user/app:latest
cache-from: type=registry,ref=user/app:latest
cache-to: type=inline
```
## GitHub cache
> :warning: At the moment caches are copied over the existing cache so it [keeps growing](https://github.com/docker/build-push-action/issues/252).
> The `Move cache` step is used as a temporary fix (see https://github.com/moby/buildkit/issues/1896).
> :rocket: There is a new cache backend using GitHub cache being developed that will lighten your workflow.
> More info: https://github.com/docker/buildx/pull/535
You can leverage [GitHub cache](https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows)
using [actions/cache](https://github.com/actions/cache) with this action:
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: 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:
context: .
push: true
tags: user/app:latest
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
-
# Temp fix
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
```

View File

@ -0,0 +1,73 @@
# Copy images between registries
Multi-platform images built using buildx can be copied from one registry to another without
changing the image SHA using the [tag-push-action](https://github.com/akhilerm/tag-push-action).
The following workflow will first push the image to dockerhub, run some tests using the images
and then push to quay and ghcr
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
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
- # quay and ghcr logins for pushing image after testing
name: Login to Quay Registry
uses: docker/login-action@v1
with:
registry: quay.io
username: ${{ secrets.QUAY_USERNAME }}
password: ${{ secrets.QUAY_TOKEN }}
-
name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
-
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: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
user/app:latest
user/app:1.0.0
- # run tests using image from docker hub
name: Run Tests
run: make tests
- # copy multiplatform image from dockerhub to quay and ghcr
name: Push Image to multiple registries
uses: akhilerm/tag-push-action@v1.0.0
with:
src: docker.io/user/app:1.0.0
dst: |
quay.io/user/app:latest
quay.io/user/app:1.0.0
ghcr.io/user/app:latest
ghcr.io/user/app:1.0.0
```

View File

@ -0,0 +1,48 @@
# 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:
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
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: .
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
```

View File

@ -0,0 +1,35 @@
# 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:
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Build
uses: docker/build-push-action@v2
with:
context: .
load: true
tags: myimage:latest
-
name: Inspect
run: |
docker image inspect myimage:latest
```

View File

@ -0,0 +1,44 @@
# Isolated builders
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
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 }}
context: .
target: mytarget1
-
name: Build against builder2
uses: docker/build-push-action@v2
with:
builder: ${{ steps.builder2.outputs.name }}
context: .
target: mytarget2
```

View File

@ -0,0 +1,44 @@
# Local registry
For testing purposes you may need to create a [local registry](https://hub.docker.com/_/registry) to push images into:
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
runs-on: ubuntu-latest
services:
registry:
image: registry:2
ports:
- 5000:5000
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
driver-opts: network=host
-
name: Build and push to local registry
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: localhost:5000/name/app:latest
-
name: Inspect
run: |
docker buildx imagetools inspect localhost:5000/name/app:latest
```

View File

@ -0,0 +1,44 @@
# Multi-platform image
You can build multi-platform images using the [`platforms` input](../../README.md#inputs) as described below.
> :bulb: List of available platforms will be displayed and available through our [setup-buildx](https://github.com/docker/setup-buildx-action#about) action.
> :bulb: If you want support for more platforms, you can use QEMU with our [setup-qemu](https://github.com/docker/setup-qemu-action) action.
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
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: .
platforms: linux/amd64,linux/arm64
push: true
tags: user/app:latest
```

View File

@ -0,0 +1,57 @@
# Push to multi-registries
* [Docker Hub and GHCR](#docker-hub-and-ghcr)
## Docker Hub and GHCR
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.
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
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.GITHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
user/app:latest
user/app:1.0.0
ghcr.io/user/app:latest
ghcr.io/user/app:1.0.0
```

84
docs/advanced/secrets.md Normal file
View File

@ -0,0 +1,84 @@
# Secrets
In the following example we will expose and use the [GITHUB_TOKEN secret](https://docs.github.com/en/actions/reference/authentication-in-a-workflow#about-the-github_token-secret)
as provided by GitHub in your workflow.
First let's create our `Dockerfile` to use our secret:
```Dockerfile
#syntax=docker/dockerfile:1.2
FROM alpine
RUN --mount=type=secret,id=github_token \
cat /run/secrets/github_token
```
As you can see we have named our secret `github_token`. Here is the workflow you can use to expose this secret using
the [`secrets` input](../../README.md#inputs):
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
docker:
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: Build
uses: docker/build-push-action@v2
with:
context: .
platforms: linux/amd64,linux/arm64
tags: user/app:latest
secrets: |
"github_token=${{ secrets.GITHUB_TOKEN }}"
```
> :bulb: You can also expose a secret file to the build with [`secret-files`](../../README.md#inputs) input:
> ```yaml
> secret-files: |
> "MY_SECRET=./secret.txt"
> ```
If you're using [GitHub secrets](https://docs.github.com/en/actions/reference/encrypted-secrets) and need to handle
multi-line value, you will need to place the key-value pair between quotes:
```yaml
secrets: |
"MYSECRET=${{ secrets.GPG_KEY }}"
GIT_AUTH_TOKEN=abcdefghi,jklmno=0123456789
"MYSECRET=aaaaaaaa
bbbbbbb
ccccccccc"
FOO=bar
"EMPTYLINE=aaaa
bbbb
ccc"
"JSON_SECRET={""key1"":""value1"",""key2"":""value2""}"
```
| Key | Value |
|--------------------|--------------------------------------------------|
| `MYSECRET` | `***********************` |
| `GIT_AUTH_TOKEN` | `abcdefghi,jklmno=0123456789` |
| `MYSECRET` | `aaaaaaaa\nbbbbbbb\nccccccccc` |
| `FOO` | `bar` |
| `EMPTYLINE` | `aaaa\n\nbbbb\nccc` |
| `JSON_SECRET` | `{"key1":"value1","key2":"value2"}` |
> :bulb: All quote signs need to be doubled for escaping.

View File

@ -0,0 +1,58 @@
# Share built image between jobs
As each job is isolated in its own runner you cannot use your built image between jobs (except for [self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners)).
However, you can [pass data between jobs in a workflow](https://docs.github.com/en/actions/guides/storing-workflow-data-as-artifacts#passing-data-between-jobs-in-a-workflow)
using the [actions/upload-artifact](https://github.com/actions/upload-artifact) and [actions/download-artifact](https://github.com/actions/download-artifact)
actions:
```yaml
name: ci
on:
push:
branches:
- 'master'
jobs:
build:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Build and export
uses: docker/build-push-action@v2
with:
context: .
tags: myimage:latest
outputs: type=docker,dest=/tmp/myimage.tar
-
name: Upload artifact
uses: actions/upload-artifact@v2
with:
name: myimage
path: /tmp/myimage.tar
use:
runs-on: ubuntu-latest
needs: build
steps:
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Download artifact
uses: actions/download-artifact@v2
with:
name: myimage
path: /tmp
-
name: Load image
run: |
docker load --input /tmp/myimage.tar
docker image ls -a
```

View File

@ -0,0 +1,77 @@
# Handle tags and labels
If you come from [`v1`](https://github.com/docker/build-push-action/tree/releases/v1#readme) and want an
"automatic" tag management and [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/master/annotations.md)
for labels, you can do it in a dedicated step. The following workflow will use the [Docker metadata action](https://github.com/docker/metadata-action)
to handle tags and labels based on GitHub actions events and Git metadata.
```yaml
name: ci
on:
schedule:
- cron: '0 10 * * *' # everyday at 10am
push:
branches:
- '**'
tags:
- 'v*.*.*'
pull_request:
branches:
- 'master'
jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Docker meta
id: meta
uses: docker/metadata-action@v3
with:
# list of Docker images to use as base name for tags
images: |
name/app
ghcr.io/username/app
# generate Docker tags based on the following events/attributes
tags: |
type=schedule
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
-
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: Login to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v2
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
```

42
hack/build.Dockerfile Normal file
View File

@ -0,0 +1,42 @@
# syntax=docker/dockerfile:1.2
ARG NODE_VERSION
FROM node:${NODE_VERSION}-alpine AS base
RUN apk add --no-cache cpio findutils git
WORKDIR /src
FROM base AS deps
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/node_modules \
yarn install
FROM deps AS build
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/node_modules \
yarn run build && mkdir /out && cp -Rf dist /out/
FROM scratch AS build-update
COPY --from=build /out /
FROM build AS build-validate
RUN --mount=type=bind,target=.,rw \
git add -A && cp -rf /out/* .; \
if [ -n "$(git status --porcelain -- dist)" ]; then \
echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"'; \
git status --porcelain -- dist; \
exit 1; \
fi
FROM deps AS format
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/node_modules \
yarn run format \
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' | cpio -pdm /out
FROM scratch AS format-update
COPY --from=format /out /
FROM deps AS format-validate
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/node_modules \
yarn run format-check \

23
hack/test.Dockerfile Normal file
View File

@ -0,0 +1,23 @@
# syntax=docker/dockerfile:1.2
ARG NODE_VERSION
FROM node:${NODE_VERSION}-alpine AS base
RUN apk add --no-cache git
WORKDIR /src
FROM base AS deps
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/node_modules \
yarn install
FROM deps AS test
ENV RUNNER_TEMP=/tmp/github_runner
ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/node_modules \
--mount=type=bind,from=crazymax/docker,source=/usr/libexec/docker/cli-plugins/docker-buildx,target=/usr/libexec/docker/cli-plugins/docker-buildx \
--mount=type=bind,from=crazymax/docker,source=/usr/local/bin/docker,target=/usr/bin/docker \
yarn run test --coverageDirectory=/tmp/coverage
FROM scratch AS test-coverage
COPY --from=test /tmp/coverage /

23
hack/vendor.Dockerfile Normal file
View File

@ -0,0 +1,23 @@
# syntax=docker/dockerfile:1.2
ARG NODE_VERSION
FROM node:${NODE_VERSION}-alpine AS base
RUN apk add --no-cache git
WORKDIR /src
FROM base AS vendored
RUN --mount=type=bind,target=.,rw \
--mount=type=cache,target=/src/node_modules \
yarn install && mkdir /out && cp yarn.lock /out
FROM scratch AS update
COPY --from=vendored /out /
FROM vendored AS validate
RUN --mount=type=bind,target=.,rw \
git add -A && cp -rf /out/* .; \
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then \
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor-update"'; \
git status --porcelain -- yarn.lock; \
exit 1; \
fi

View File

@ -28,26 +28,26 @@
],
"license": "Apache-2.0",
"dependencies": {
"@actions/core": "^1.2.6",
"@actions/exec": "^1.0.4",
"@actions/github": "^4.0.0",
"csv-parse": "^4.14.2",
"semver": "^7.3.4",
"@actions/core": "^1.4.0",
"@actions/exec": "^1.1.0",
"@actions/github": "^5.0.0",
"csv-parse": "^4.16.0",
"semver": "^7.3.5",
"tmp": "^0.2.1"
},
"devDependencies": {
"@types/csv-parse": "^1.2.2",
"@types/jest": "^26.0.3",
"@types/node": "^14.0.14",
"@types/jest": "^26.0.23",
"@types/node": "^14.17.4",
"@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",
"@vercel/ncc": "^0.28.6",
"dotenv": "^8.6.0",
"jest": "^26.6.3",
"jest-circus": "^26.6.3",
"jest-runtime": "^26.6.3",
"prettier": "^2.3.1",
"ts-jest": "^26.5.6",
"typescript": "^4.3.4",
"typescript-formatter": "^7.2.2"
}
}

View File

@ -2,9 +2,9 @@ import csvparse from 'csv-parse/lib/sync';
import fs from 'fs';
import path from 'path';
import * as semver from 'semver';
import * as exec from '@actions/exec';
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);
@ -18,17 +18,34 @@ export async function getImageID(): Promise<string | undefined> {
return fs.readFileSync(iidFile, {encoding: 'utf-8'});
}
export async function getSecret(kvp: string): Promise<string> {
export async function getSecretString(kvp: string): Promise<string> {
return getSecret(kvp, false);
}
export async function getSecretFile(kvp: string): Promise<string> {
return getSecret(kvp, true);
}
export async function getSecret(kvp: string, file: boolean): Promise<string> {
const delimiterIndex = kvp.indexOf('=');
const key = kvp.substring(0, delimiterIndex);
const value = kvp.substring(delimiterIndex + 1);
let value = kvp.substring(delimiterIndex + 1);
if (key.length == 0 || value.length == 0) {
throw new Error(`${kvp} is not a valid secret`);
}
if (file) {
if (!fs.existsSync(value)) {
throw new Error(`secret file ${value} not found`);
}
value = fs.readFileSync(value, {encoding: 'utf-8'});
}
const secretFile = context.tmpNameSync({
tmpdir: context.tmpDir()
});
await fs.writeFileSync(secretFile, value);
fs.writeFileSync(secretFile, value);
return `id=${key},src=${secretFile}`;
}
@ -63,27 +80,41 @@ export function hasGitAuthToken(secrets: string[]): Boolean {
}
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;
});
return await exec
.getExecOutput('docker', ['buildx'], {
ignoreReturnCode: true,
silent: true
})
.then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
return false;
}
return res.exitCode == 0;
});
}
export async function getVersion(): Promise<string> {
return await exec.exec(`docker`, ['buildx', 'version'], true).then(res => {
if (res.stderr != '' && !res.success) {
throw new Error(res.stderr);
}
return parseVersion(res.stdout);
});
return await exec
.getExecOutput('docker', ['buildx', 'version'], {
ignoreReturnCode: true,
silent: true
})
.then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
throw new Error(res.stderr.trim());
}
return parseVersion(res.stdout.trim());
});
}
export async function parseVersion(stdout: string): Promise<string> {
const matches = /\sv?([0-9.]+)/.exec(stdout);
export function parseVersion(stdout: string): string {
const matches = /\sv?([0-9a-f]{7}|[0-9.]+)/.exec(stdout);
if (!matches) {
throw new Error(`Cannot parse Buildx version`);
throw new Error(`Cannot parse buildx version`);
}
return semver.clean(matches[1]);
return matches[1];
}
export function satisfies(version: string, range: string): boolean {
return semver.satisfies(version, range) || /^[0-9a-f]{7}$/.exec(version) !== null;
}

View File

@ -6,6 +6,7 @@ import * as semver from 'semver';
import * as tmp from 'tmp';
import * as core from '@actions/core';
import {issueCommand} from '@actions/core/lib/command';
import * as github from '@actions/github';
import * as buildx from './buildx';
@ -13,32 +14,39 @@ import * as buildx from './buildx';
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;
buildArgs: string[];
builder: string;
platforms: string[];
load: boolean;
push: boolean;
outputs: string[];
cacheFrom: string[];
cacheTo: string[];
context: string;
file: string;
labels: string[];
load: boolean;
network: string;
noCache: boolean;
outputs: string[];
platforms: string[];
pull: boolean;
push: boolean;
secrets: string[];
githubToken: string;
secretFiles: string[];
ssh: string[];
tags: string[];
target: 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\//, '')}`;
let ref = github.context.ref;
if (github.context.sha && ref && !ref.startsWith('refs/')) {
ref = `refs/heads/${github.context.ref}`;
}
if (github.context.sha && !ref.startsWith(`refs/pull/`)) {
ref = github.context.sha;
}
_defaultContext = `${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${github.context.repo.repo}.git#${ref}`;
}
return _defaultContext;
}
@ -56,25 +64,27 @@ export function tmpNameSync(options?: tmp.TmpNameOptions): string {
export async function getInputs(defaultContext: string): Promise<Inputs> {
return {
context: core.getInput('context') || defaultContext,
file: core.getInput('file'),
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')),
buildArgs: await getInputList('build-args', true),
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),
context: core.getInput('context') || defaultContext,
file: core.getInput('file'),
labels: await getInputList('labels', true),
load: core.getBooleanInput('load'),
network: core.getInput('network'),
noCache: core.getBooleanInput('no-cache'),
outputs: await getInputList('outputs', true),
platforms: await getInputList('platforms'),
pull: core.getBooleanInput('pull'),
push: core.getBooleanInput('push'),
secrets: await getInputList('secrets', true),
githubToken: core.getInput('github-token'),
ssh: await getInputList('ssh')
secretFiles: await getInputList('secret-files', true),
ssh: await getInputList('ssh'),
tags: await getInputList('tags'),
target: core.getInput('target'),
githubToken: core.getInput('github-token')
};
}
@ -109,10 +119,7 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, buildxVersio
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'))
) {
if (!buildx.isLocalOrTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || buildx.satisfies(buildxVersion, '>=0.4.2'))) {
args.push('--iidfile', await buildx.getImageIDFile());
}
await asyncForEach(inputs.cacheFrom, async cacheFrom => {
@ -123,13 +130,20 @@ async function getBuildArgs(inputs: Inputs, defaultContext: string, buildxVersio
});
await asyncForEach(inputs.secrets, async secret => {
try {
args.push('--secret', await buildx.getSecret(secret));
args.push('--secret', await buildx.getSecretString(secret));
} catch (err) {
core.warning(err.message);
}
});
await asyncForEach(inputs.secretFiles, async secretFile => {
try {
args.push('--secret', await buildx.getSecretFile(secretFile));
} catch (err) {
core.warning(err.message);
}
});
if (inputs.githubToken && !buildx.hasGitAuthToken(inputs.secrets) && inputs.context == defaultContext) {
args.push('--secret', await buildx.getSecret(`GIT_AUTH_TOKEN=${inputs.githubToken}`));
args.push('--secret', await buildx.getSecretString(`GIT_AUTH_TOKEN=${inputs.githubToken}`));
}
await asyncForEach(inputs.ssh, async ssh => {
args.push('--ssh', ssh);
@ -154,6 +168,9 @@ async function getCommonArgs(inputs: Inputs): Promise<Array<string>> {
if (inputs.load) {
args.push('--load');
}
if (inputs.network) {
args.push('--network', inputs.network);
}
if (inputs.push) {
args.push('--push');
}
@ -170,6 +187,7 @@ export async function getInputList(name: string, ignoreComma?: boolean): Promise
for (let output of (await csvparse(items, {
columns: false,
relax: true,
relaxColumnCount: true,
skipLinesWithEmptyValues: true
})) as Array<string[]>) {
@ -191,3 +209,8 @@ export const asyncForEach = async (array, callback) => {
await callback(array[index], index, array);
}
};
// FIXME: Temp fix https://github.com/actions/toolkit/issues/777
export function setOutput(name: string, value: any): void {
issueCommand('set-output', {name}, value);
}

View File

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

View File

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

View File

@ -1,41 +1,44 @@
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') {
throw new Error(`Only supported on linux platform`);
}
core.startGroup(`Docker info`);
await exec.exec('docker', ['version']);
await exec.exec('docker', ['info']);
core.endGroup();
if (!(await buildx.isAvailable())) {
throw new Error(`Buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
core.setFailed(`Docker buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
return;
}
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]}`);
}
});
await exec
.getExecOutput('docker', args, {
ignoreReturnCode: true
})
.then(res => {
if (res.stderr.length > 0 && res.exitCode != 0) {
throw new Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)![0].trim()}`);
}
});
const imageID = await buildx.getImageID();
if (imageID) {
core.info('🛒 Extracting digest...');
core.startGroup(`Extracting digest`);
core.info(`${imageID}`);
core.setOutput('digest', imageID);
context.setOutput('digest', imageID);
core.endGroup();
}
} catch (error) {
core.setFailed(error.message);
@ -44,8 +47,9 @@ async function run(): Promise<void> {
async function cleanup(): Promise<void> {
if (stateHelper.tmpDir.length > 0) {
core.info(`🚿 Removing temp folder ${stateHelper.tmpDir}`);
core.startGroup(`Removing temp folder ${stateHelper.tmpDir}`);
fs.rmdirSync(stateHelper.tmpDir, {recursive: true});
core.endGroup();
}
}

2249
yarn.lock

File diff suppressed because it is too large Load Diff