Compare commits
No commits in common. "master" and "v1.0.4" have entirely different histories.
|
@ -1,12 +0,0 @@
|
|||
/coverage
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
|
@ -1,3 +0,0 @@
|
|||
/dist/**
|
||||
/coverage/**
|
||||
/node_modules/**
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jest": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:jest/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"jest",
|
||||
"prettier"
|
||||
]
|
||||
}
|
|
@ -1,4 +1,2 @@
|
|||
/.yarn/releases/** binary
|
||||
/.yarn/plugins/** binary
|
||||
/dist/** linguist-generated=true
|
||||
/lib/** linguist-generated=true
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
* @crazy-max
|
|
@ -1,3 +0,0 @@
|
|||
# Code of conduct
|
||||
|
||||
- [Moby community guidelines](https://github.com/moby/moby/blob/master/CONTRIBUTING.md#moby-community-guidelines)
|
|
@ -2,24 +2,35 @@
|
|||
|
||||
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://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).
|
||||
Contributions to this project are [released](https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license) to the public under the [project's open source license](LICENSE).
|
||||
|
||||
## Submitting a pull request
|
||||
|
||||
1. [Fork](https://github.com/docker/setup-buildx-action/fork) and clone the repository
|
||||
2. Configure and install the dependencies: `yarn install`
|
||||
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/setup-buildx-action/compare)
|
||||
9. Pat your self on the back and wait for your pull request to be reviewed and merged.
|
||||
4. Make your change, add tests, and make sure the tests still pass
|
||||
5. Run pre-checkin: `yarn run pre-checkin`
|
||||
6. Push to your fork and [submit a pull request](https://github.com/docker/setup-buildx-action/compare)
|
||||
7. Pat yourself on the back and wait for your pull request to be reviewed and merged.
|
||||
|
||||
## Container based developer flow
|
||||
|
||||
If you don't want to maintain a Node developer environment that fits this project you can use containerized commands instead of invoking yarn directly.
|
||||
|
||||
```
|
||||
# format code and build javascript artifacts
|
||||
docker buildx bake pre-checkin
|
||||
|
||||
# validate all code has correctly formatted and built
|
||||
docker buildx bake validate
|
||||
|
||||
# run tests
|
||||
docker buildx bake test
|
||||
```
|
||||
|
||||
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
|
||||
|
||||
- Write tests.
|
||||
- Make sure the `README.md` and any other relevant **documentation are kept up-to-date**.
|
||||
- We try to follow [SemVer v2.0.0](https://semver.org/). Randomly breaking public APIs is not an option.
|
||||
- Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as **separate pull requests**.
|
||||
|
@ -28,5 +39,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://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)
|
||||
- [GitHub Help](https://docs.github.com/en)
|
||||
- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/)
|
||||
- [GitHub Help](https://help.github.com)
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: Bug Report
|
||||
description: Report a bug
|
||||
labels:
|
||||
- status/triage
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to report a bug!
|
||||
If this is a security issue please report it to the [Docker Security team](mailto:security@docker.com).
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Contributing guidelines
|
||||
description: >
|
||||
Make sure you've read the contributing guidelines before proceeding.
|
||||
options:
|
||||
- label: I've read the [contributing guidelines](https://github.com/docker/setup-buildx-action/blob/master/.github/CONTRIBUTING.md) and wholeheartedly agree
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: "I've found a bug, and:"
|
||||
description: |
|
||||
Make sure that your request fulfills all of the following requirements.
|
||||
If one requirement cannot be satisfied, explain in detail why.
|
||||
options:
|
||||
- label: The documentation does not mention anything about my problem
|
||||
- label: There are no open or closed issues that are related to my problem
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: >
|
||||
Provide a brief description of the bug in 1-2 sentences.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected behaviour
|
||||
description: >
|
||||
Describe precisely what you'd expect to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Actual behaviour
|
||||
description: >
|
||||
Describe precisely what is actually happening.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Repository URL
|
||||
description: >
|
||||
Enter the URL of the repository where you are experiencing the
|
||||
issue. If your repository is private, provide a link to a minimal
|
||||
repository that reproduces the issue.
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Workflow run URL
|
||||
description: >
|
||||
Enter the URL of the GitHub Action workflow run if public (e.g.
|
||||
`https://github.com/<user>/<repo>/actions/runs/<id>`)
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: YAML workflow
|
||||
description: |
|
||||
Provide the YAML of the workflow that's causing the issue.
|
||||
Make sure to remove any sensitive information.
|
||||
render: yaml
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Workflow logs
|
||||
description: >
|
||||
[Attach](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/attaching-files)
|
||||
the [log file of your workflow run](https://docs.github.com/en/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs)
|
||||
and make sure to remove any sensitive information.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: BuildKit logs
|
||||
description: >
|
||||
If applicable, provide the [BuildKit container logs](https://docs.docker.com/build/ci/github-actions/configure-builder/#buildkit-container-logs)
|
||||
render: text
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional info
|
||||
description: |
|
||||
Provide any additional information that could be useful.
|
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
---
|
||||
|
||||
### Behaviour
|
||||
|
||||
#### Steps to reproduce this issue
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
#### Expected behaviour
|
||||
|
||||
> Tell us what should happen
|
||||
|
||||
#### Actual behaviour
|
||||
|
||||
> Tell us what happens instead
|
||||
|
||||
### Configuration
|
||||
|
||||
* Repository URL (if public):
|
||||
* Build URL (if public):
|
||||
|
||||
```yml
|
||||
# paste your YAML workflow file here and remove sensitive data
|
||||
```
|
||||
|
||||
### Logs
|
||||
|
||||
> Download the [log file of your build](https://help.github.com/en/actions/configuring-and-managing-workflows/managing-a-workflow-run#downloading-logs) and [attach it](https://help.github.com/en/github/managing-your-work-on-github/file-attachments-on-issues-and-pull-requests) to this issue.
|
|
@ -1,9 +0,0 @@
|
|||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: Questions and Discussions
|
||||
url: https://github.com/docker/setup-buildx-action/discussions/new
|
||||
about: Use Github Discussions to ask questions and/or open discussion topics.
|
||||
- name: Documentation
|
||||
url: https://docs.docker.com/build/ci/github-actions/
|
||||
about: Read the documentation.
|
|
@ -1,15 +0,0 @@
|
|||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
||||
name: Feature request
|
||||
description: Missing functionality? Come tell us about it!
|
||||
labels:
|
||||
- kind/enhancement
|
||||
- status/triage
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: What is the feature you want to see?
|
||||
validations:
|
||||
required: true
|
|
@ -1,12 +0,0 @@
|
|||
# Reporting security issues
|
||||
|
||||
The project maintainers take security seriously. If you discover a security
|
||||
issue, please bring it to their attention right away!
|
||||
|
||||
**Please _DO NOT_ file a public issue**, instead send your report privately to
|
||||
[security@docker.com](mailto:security@docker.com).
|
||||
|
||||
Security reports are greatly appreciated, and we will publicly thank you for it.
|
||||
We also like to send gifts—if you'd like Docker swag, make sure to let
|
||||
us know. We currently do not offer a paid security bounty program, but are not
|
||||
ruling it out in the future.
|
|
@ -0,0 +1,31 @@
|
|||
# Support [](https://isitmaintained.com/project/docker/setup-buildx-action)
|
||||
|
||||
First, [be a good guy](https://github.com/kossnocorp/etiquette/blob/master/README.md).
|
||||
|
||||
## Reporting an issue
|
||||
|
||||
Please do a search in [open issues](https://github.com/docker/setup-buildx-action/issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed.
|
||||
|
||||
If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment.
|
||||
|
||||
:+1: - upvote
|
||||
|
||||
:-1: - downvote
|
||||
|
||||
If you cannot find an existing issue that describes your bug or feature, submit an issue using the guidelines below.
|
||||
|
||||
## Writing good bug reports and feature requests
|
||||
|
||||
File a single issue per problem and feature request.
|
||||
|
||||
* Do not enumerate multiple bugs or feature requests in the same issue.
|
||||
* Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes.
|
||||
|
||||
The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix.
|
||||
|
||||
You are now ready to [create a new issue](https://github.com/docker/setup-buildx-action/issues/new/choose)!
|
||||
|
||||
## Closure policy
|
||||
|
||||
* Issues that don't have the information requested above (when applicable) will be closed immediately and the poster directed to the support guidelines.
|
||||
* Issues that go a week without a response from original poster are subject to closure at our discretion.
|
|
@ -4,16 +4,19 @@ updates:
|
|||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
time: "06:00"
|
||||
timezone: "Europe/Paris"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "bot"
|
||||
- ":game_die: dependencies"
|
||||
- ":robot: bot"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
versioning-strategy: "increase"
|
||||
time: "06:00"
|
||||
timezone: "Europe/Paris"
|
||||
allow:
|
||||
- dependency-type: "production"
|
||||
labels:
|
||||
- "dependencies"
|
||||
- "bot"
|
||||
- ":game_die: dependencies"
|
||||
- ":robot: bot"
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
## 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: ""
|
||||
- # 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: ""
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 4.5 KiB |
|
@ -1,20 +1,18 @@
|
|||
name: ci
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 10 * * *'
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
tags:
|
||||
- 'v*'
|
||||
- master
|
||||
- releases/v*
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- releases/v*
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
|
||||
jobs:
|
||||
main:
|
||||
|
@ -23,16 +21,13 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
buildx-version:
|
||||
- latest
|
||||
- v0.2.2
|
||||
- ""
|
||||
- "latest"
|
||||
- "v0.4.1"
|
||||
- "cloud:latest"
|
||||
- "cloud:v0.11.2-desktop.2"
|
||||
- "lab:latest"
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
|
@ -40,87 +35,42 @@ jobs:
|
|||
with:
|
||||
version: ${{ matrix.buildx-version }}
|
||||
-
|
||||
name: Nodes output
|
||||
run: |
|
||||
cat << EOF
|
||||
${{ steps.buildx.outputs.nodes }}
|
||||
EOF
|
||||
name: Builder instance name
|
||||
run: echo ${{ steps.buildx.outputs.name }}
|
||||
-
|
||||
name: Available platforms
|
||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||
-
|
||||
name: Dump context
|
||||
uses: crazy-max/ghaction-dump-context@v1
|
||||
|
||||
multi:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx 1
|
||||
id: buildx1
|
||||
uses: ./
|
||||
-
|
||||
name: Builder 1 instance name
|
||||
run: echo ${{ steps.buildx1.outputs.name }}
|
||||
-
|
||||
name: Set up Docker Buildx 2
|
||||
uses: ./
|
||||
|
||||
error:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Stop docker
|
||||
run: |
|
||||
sudo systemctl stop docker docker.socket
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
continue-on-error: true
|
||||
id: buildx2
|
||||
uses: ./
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
echo "${{ toJson(steps.buildx) }}"
|
||||
if [ "${{ steps.buildx.outcome }}" != "failure" ] || [ "${{ steps.buildx.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
-
|
||||
name: Dump context
|
||||
if: always()
|
||||
uses: crazy-max/ghaction-dump-context@v2
|
||||
|
||||
debug:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Create Dockerfile
|
||||
run: |
|
||||
cat > ./Dockerfile <<EOL
|
||||
FROM alpine
|
||||
RUN uname -a
|
||||
EOL
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
with:
|
||||
buildkitd-flags: --debug
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/ppc64le
|
||||
name: Builder 2 instance name
|
||||
run: echo ${{ steps.buildx2.outputs.name }}
|
||||
|
||||
install:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
|
@ -142,7 +92,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
|
@ -165,7 +115,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
|
@ -178,7 +128,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
|
@ -211,7 +161,7 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Create context
|
||||
run: |
|
||||
|
@ -225,67 +175,6 @@ jobs:
|
|||
uses: ./
|
||||
with:
|
||||
endpoint: mycontext
|
||||
env:
|
||||
DOCKER_CONTEXT: mycontext
|
||||
|
||||
config:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Create buildkitd conf
|
||||
run: |
|
||||
cat > /tmp/buildkitd.toml <<EOL
|
||||
debug = true
|
||||
[registry."docker.io"]
|
||||
mirrors = ["mirror.gcr.io"]
|
||||
EOL
|
||||
-
|
||||
name: Create Dockerfile
|
||||
run: |
|
||||
cat > ./Dockerfile <<EOL
|
||||
FROM alpine
|
||||
EOL
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
with:
|
||||
buildkitd-flags: --debug
|
||||
buildkitd-config: /tmp/buildkitd.toml
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
|
||||
config-inline:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Create Dockerfile
|
||||
run: |
|
||||
cat > ./Dockerfile <<EOL
|
||||
FROM alpine
|
||||
EOL
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
with:
|
||||
buildkitd-flags: --debug
|
||||
buildkitd-config-inline: |
|
||||
debug = true
|
||||
[registry."docker.io"]
|
||||
mirrors = ["mirror.gcr.io"]
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
|
||||
with-qemu:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -293,7 +182,8 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
buildx-version:
|
||||
- v0.9.1
|
||||
- latest
|
||||
- v0.2.2
|
||||
- ""
|
||||
qemu-platforms:
|
||||
- all
|
||||
|
@ -301,10 +191,10 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: ${{ matrix.qemu-platforms }}
|
||||
-
|
||||
|
@ -314,335 +204,8 @@ jobs:
|
|||
with:
|
||||
version: ${{ matrix.buildx-version }}
|
||||
-
|
||||
name: List builder platforms
|
||||
name: Available platforms
|
||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||
|
||||
build-ref:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
ref:
|
||||
- master
|
||||
- refs/tags/v0.5.1
|
||||
- refs/pull/731/head
|
||||
- cb185f095fd3d9444e0aa605d3789e9e05f2a1e7
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
with:
|
||||
version: https://github.com/docker/buildx.git#${{ matrix.ref }}
|
||||
-
|
||||
name: Create Dockerfile
|
||||
run: |
|
||||
cat > ./Dockerfile <<EOL
|
||||
FROM alpine
|
||||
EOL
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@master
|
||||
with:
|
||||
context: .
|
||||
|
||||
standalone-cmd:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Uninstall docker cli
|
||||
run: |
|
||||
if dpkg -s "docker-ce" >/dev/null 2>&1; then
|
||||
sudo dpkg -r --force-depends docker-ce-cli docker-buildx-plugin
|
||||
else
|
||||
sudo apt-get purge -y moby-cli moby-buildx
|
||||
fi
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
-
|
||||
name: Create Dockerfile
|
||||
run: |
|
||||
cat > ./Dockerfile <<EOL
|
||||
FROM alpine
|
||||
EOL
|
||||
-
|
||||
name: Build
|
||||
run: |
|
||||
buildx build .
|
||||
|
||||
standalone-action:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Uninstall docker cli
|
||||
run: |
|
||||
if dpkg -s "docker-ce" >/dev/null 2>&1; then
|
||||
sudo dpkg -r --force-depends docker-ce-cli docker-buildx-plugin
|
||||
else
|
||||
sudo apt-get purge -y moby-cli moby-buildx
|
||||
fi
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
with:
|
||||
version: ${{ matrix.buildx-version }}
|
||||
-
|
||||
name: Create Dockerfile
|
||||
run: |
|
||||
cat > ./Dockerfile <<EOL
|
||||
FROM alpine
|
||||
EOL
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@master
|
||||
with:
|
||||
context: .
|
||||
|
||||
standalone-install-error:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Uninstall docker cli
|
||||
run: |
|
||||
if dpkg -s "docker-ce" >/dev/null 2>&1; then
|
||||
sudo dpkg -r --force-depends docker-ce-cli docker-buildx-plugin
|
||||
else
|
||||
sudo apt-get purge -y moby-cli moby-buildx
|
||||
fi
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
install: true
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
echo "${{ toJson(steps.buildx) }}"
|
||||
if [ "${{ steps.buildx.outcome }}" != "failure" ] || [ "${{ steps.buildx.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
append:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Create dummy contexts
|
||||
run: |
|
||||
docker context create ctxbuilder2
|
||||
docker context create ctxbuilder3
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: ./
|
||||
with:
|
||||
append: |
|
||||
- name: builder2
|
||||
endpoint: ctxbuilder2
|
||||
platforms: linux/amd64
|
||||
driver-opts:
|
||||
- image=moby/buildkit:master
|
||||
- network=host
|
||||
- endpoint: ctxbuilder3
|
||||
platforms: linux/arm64
|
||||
-
|
||||
name: List builder platforms
|
||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||
|
||||
platforms:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
with:
|
||||
platforms: linux/amd64
|
||||
|
||||
docker-context:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Create Docker context
|
||||
run: |
|
||||
docker context create foo
|
||||
docker context use foo
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
with:
|
||||
driver: docker
|
||||
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
cleanup:
|
||||
- true
|
||||
- false
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
with:
|
||||
cleanup: ${{ matrix.cleanup }}
|
||||
|
||||
k3s:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version:
|
||||
- latest
|
||||
- v0.11.0
|
||||
- v0.10.5
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Install k3s
|
||||
uses: crazy-max/.github/.github/actions/install-k3s@a94383ec9e125b23907fb6fcebf7ff87964595e5
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: ./
|
||||
with:
|
||||
version: ${{ matrix.version }}
|
||||
driver: kubernetes
|
||||
platforms: linux/amd64
|
||||
driver-opts: |
|
||||
image=moby/buildkit:buildx-stable-1
|
||||
qemu.install=true
|
||||
append: |
|
||||
- platforms: linux/arm64
|
||||
driver-opts:
|
||||
- image=moby/buildkit:buildx-stable-1
|
||||
- qemu.install=true
|
||||
- platforms: linux/s390x
|
||||
driver-opts:
|
||||
- image=moby/buildkit:buildx-stable-1
|
||||
- qemu.install=true
|
||||
-
|
||||
name: Create Dockerfile
|
||||
run: |
|
||||
cat > ./Dockerfile <<EOL
|
||||
FROM alpine
|
||||
RUN uname -a
|
||||
EOL
|
||||
-
|
||||
name: Build
|
||||
uses: docker/build-push-action@master
|
||||
with:
|
||||
context: .
|
||||
|
||||
cache-binary:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
cache:
|
||||
- true
|
||||
- false
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
with:
|
||||
version: v0.11.2
|
||||
cache-binary: ${{ matrix.cache }}
|
||||
|
||||
windows-error:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
echo "${{ toJson(steps.buildx) }}"
|
||||
if [ "${{ steps.buildx.outcome }}" != "failure" ] || [ "${{ steps.buildx.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
shell: bash
|
||||
|
||||
keep-state:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
with:
|
||||
name: foo
|
||||
keep-state: true
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
with:
|
||||
name: foo
|
||||
keep-state: true
|
||||
|
||||
keep-state-error:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
id: buildx
|
||||
continue-on-error: true
|
||||
uses: ./
|
||||
with:
|
||||
driver: docker
|
||||
keep-state: true
|
||||
-
|
||||
name: Check
|
||||
run: |
|
||||
echo "${{ toJson(steps.buildx) }}"
|
||||
if [ "${{ steps.buildx.outcome }}" != "failure" ] || [ "${{ steps.buildx.conclusion }}" != "success" ]; then
|
||||
echo "::error::Should have failed"
|
||||
exit 1
|
||||
fi
|
||||
name: Builder instance name
|
||||
run: echo ${{ steps.buildx.outputs.name }}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
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
|
|
@ -1,17 +0,0 @@
|
|||
name: pr-assign-author
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
|
||||
jobs:
|
||||
run:
|
||||
uses: crazy-max/.github/.github/workflows/pr-assign-author.yml@1b673f36fad86812f538c1df9794904038a23cbf
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
|
@ -1,21 +0,0 @@
|
|||
name: publish
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: Publish
|
||||
uses: actions/publish-immutable-action@v0.0.4
|
|
@ -1,34 +1,46 @@
|
|||
name: test
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
- master
|
||||
- releases/v*
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
|
||||
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:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: ./
|
||||
name: Install
|
||||
run: yarn install
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
targets: test
|
||||
run: yarn run test
|
||||
-
|
||||
name: Upload coverage
|
||||
uses: codecov/codecov-action@v5
|
||||
uses: codecov/codecov-action@v1
|
||||
if: success()
|
||||
with:
|
||||
files: ./coverage/clover.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
file: ./coverage/clover.xml
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
name: validate
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
targets: ${{ steps.generate.outputs.targets }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
name: List targets
|
||||
id: generate
|
||||
uses: docker/bake-action/subaction/list-targets@v6
|
||||
with:
|
||||
target: validate
|
||||
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: ${{ fromJson(needs.prepare.outputs.targets) }}
|
||||
steps:
|
||||
-
|
||||
name: Validate
|
||||
uses: docker/bake-action@v6
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
|
@ -1,5 +1,12 @@
|
|||
# https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||
/.dev
|
||||
node_modules
|
||||
lib
|
||||
|
||||
# Jetbrains
|
||||
/.idea
|
||||
/*.iml
|
||||
|
||||
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
@ -7,7 +14,6 @@ npm-debug.log*
|
|||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
@ -18,14 +24,34 @@ pids
|
|||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
|
@ -35,19 +61,36 @@ jspm_packages/
|
|||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
.env.test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# yarn v2
|
||||
.yarn/
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"printWidth": 240,
|
||||
"printWidth": 120,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
|
|
17
.yarnrc.yml
17
.yarnrc.yml
|
@ -1,17 +0,0 @@
|
|||
# https://yarnpkg.com/configuration/yarnrc
|
||||
|
||||
compressionLevel: mixed
|
||||
enableGlobalCache: false
|
||||
enableHardenedMode: true
|
||||
|
||||
logFilters:
|
||||
- code: YN0013
|
||||
level: discard
|
||||
- code: YN0019
|
||||
level: discard
|
||||
- code: YN0076
|
||||
level: discard
|
||||
- code: YN0086
|
||||
level: discard
|
||||
|
||||
nodeLinker: node-modules
|
|
@ -0,0 +1,52 @@
|
|||
#syntax=docker/dockerfile:1.1-experimental
|
||||
|
||||
FROM node:14 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"]
|
217
README.md
217
README.md
|
@ -1,35 +1,37 @@
|
|||
[](https://github.com/docker/setup-buildx-action/releases/latest)
|
||||
[](https://github.com/marketplace/actions/docker-setup-buildx)
|
||||
[](https://github.com/docker/setup-buildx-action/actions?workflow=ci)
|
||||
[](https://github.com/docker/setup-buildx-action/actions?workflow=test)
|
||||
[](https://github.com/docker/setup-buildx-action/actions?workflow=ci)
|
||||
[](https://github.com/docker/setup-buildx-action/actions?workflow=test)
|
||||
[](https://codecov.io/gh/docker/setup-buildx-action)
|
||||
|
||||
## About
|
||||
|
||||
GitHub Action to set up Docker [Buildx](https://github.com/docker/buildx).
|
||||
|
||||
This action will create and boot a builder that can be used in the following
|
||||
steps of your workflow if you're using Buildx or the [`build-push` action](https://github.com/docker/build-push-action/).
|
||||
By default, the [`docker-container` driver](https://docs.docker.com/build/building/drivers/docker-container/)
|
||||
will be used to be able to build multi-platform images and export cache using
|
||||
a [BuildKit](https://github.com/moby/buildkit) container.
|
||||
> :bulb: See also:
|
||||
> * [login](https://github.com/docker/login-action) action
|
||||
> * [setup-qemu](https://github.com/docker/setup-qemu-action) action
|
||||
> * [build-push](https://github.com/docker/build-push-action) action
|
||||
|
||||

|
||||
|
||||
___
|
||||
|
||||
* [Usage](#usage)
|
||||
* [Configuring your builder](#configuring-your-builder)
|
||||
* [Quick start](#quick-start)
|
||||
* [With QEMU](#with-qemu)
|
||||
* [Install by default](#install-by-default)
|
||||
* [Customizing](#customizing)
|
||||
* [inputs](#inputs)
|
||||
* [outputs](#outputs)
|
||||
* [environment variables](#environment-variables)
|
||||
* [Notes](#notes)
|
||||
* [`nodes` output](#nodes-output)
|
||||
* [Contributing](#contributing)
|
||||
* [Keep up-to-date with GitHub Dependabot](#keep-up-to-date-with-github-dependabot)
|
||||
* [Limitation](#limitation)
|
||||
|
||||
## Usage
|
||||
|
||||
### Quick start
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
|
@ -42,126 +44,135 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
-
|
||||
# Add support for more platforms with QEMU (optional)
|
||||
# https://github.com/docker/setup-qemu-action
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Builder instance name
|
||||
run: echo ${{ steps.buildx.outputs.name }}
|
||||
-
|
||||
name: Available platforms
|
||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||
```
|
||||
|
||||
## Configuring your builder
|
||||
### With QEMU
|
||||
|
||||
* [Version pinning](https://docs.docker.com/build/ci/github-actions/configure-builder/#version-pinning): Pin to a specific Buildx or BuildKit version
|
||||
* [BuildKit container logs](https://docs.docker.com/build/ci/github-actions/configure-builder/#buildkit-container-logs): Enable BuildKit container logs for debugging purposes
|
||||
* [BuildKit Daemon configuration](https://docs.docker.com/build/ci/github-actions/configure-builder/#buildkit-daemon-configuration)
|
||||
* [Registry mirror](https://docs.docker.com/build/ci/github-actions/configure-builder/#registry-mirror): Configure a registry mirror for your builds
|
||||
* [Max parallelism](https://docs.docker.com/build/ci/github-actions/configure-builder/#max-parallelism): Configure the maximum parallelism for your builds
|
||||
* [Append additional nodes to the builder](https://docs.docker.com/build/ci/github-actions/configure-builder/#append-additional-nodes-to-the-builder): Create additional nodes for your builder
|
||||
* [Authentication for remote builders](https://docs.docker.com/build/ci/github-actions/configure-builder/#authentication-for-remote-builders)
|
||||
* [SSH authentication](https://docs.docker.com/build/ci/github-actions/configure-builder/#ssh-authentication): Authenticate to a remote builder using SSH
|
||||
* [TLS authentication](https://docs.docker.com/build/ci/github-actions/configure-builder/#tls-authentication): Authenticate to a remote builder using TLS
|
||||
* [Standalone mode](https://docs.docker.com/build/ci/github-actions/configure-builder/#standalone-mode): Use Buildx as a standalone binary (without the Docker CLI)
|
||||
* [Isolated builders](https://docs.docker.com/build/ci/github-actions/configure-builder/#isolated-builders): Create isolated builders for your builds
|
||||
If you want support for more platforms you can use our [setup-qemu](https://github.com/docker/setup-qemu-action) action:
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
buildx:
|
||||
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
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
-
|
||||
name: Available platforms
|
||||
run: echo ${{ steps.buildx.outputs.platforms }}
|
||||
```
|
||||
|
||||
### Install by default
|
||||
|
||||
Implemented with https://github.com/docker/buildx#setting-buildx-as-default-builder-in-docker-1903
|
||||
|
||||
```yaml
|
||||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
buildx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
uses: docker/setup-buildx-action@v1
|
||||
id: buildx
|
||||
with:
|
||||
install: true
|
||||
-
|
||||
name: Build
|
||||
run: |
|
||||
docker build . # will run buildx
|
||||
```
|
||||
|
||||
## Customizing
|
||||
|
||||
### inputs
|
||||
|
||||
The following inputs can be used as `step.with` keys:
|
||||
Following inputs can be used as `step.with` keys
|
||||
|
||||
> `List` type is a newline-delimited string
|
||||
| Name | Type | Description |
|
||||
|--------------------|---------|-----------------------------------|
|
||||
| `version` | String | [Buildx](https://github.com/docker/buildx) version. (eg. `v0.3.0`, `latest`) |
|
||||
| `driver` | String | Sets the [builder driver](https://github.com/docker/buildx#--driver-driver) to be used (default `docker-container`) |
|
||||
| `driver-opts` | CSV | List of additional [driver-specific options](https://github.com/docker/buildx#--driver-opt-options) (eg. `image=moby/buildkit:master`) |
|
||||
| `buildkitd-flags` | String | [Flags for buildkitd](https://github.com/moby/buildkit/blob/master/docs/buildkitd.toml.md) daemon (since [buildx v0.3.0](https://github.com/docker/buildx/releases/tag/v0.3.0)) |
|
||||
| `install` | Bool | Sets up `docker build` command as an alias to `docker buildx` (default `false`) |
|
||||
| `use` | Bool | Switch to this builder instance (default `true`) |
|
||||
| `endpoint` | String | [Optional address for docker socket](https://github.com/docker/buildx#buildx-create-options-contextendpoint) or context from `docker context ls` |
|
||||
|
||||
> `CSV` type must be a newline-delimited string
|
||||
> ```yaml
|
||||
> driver-opts: image=moby/buildkit:master
|
||||
> ```
|
||||
> ```yaml
|
||||
> driver-opts: |
|
||||
> image=moby/buildkit:master
|
||||
> network=host
|
||||
> ```
|
||||
|
||||
> `CSV` type must be a comma-delimited string
|
||||
> ```yaml
|
||||
> platforms: linux/amd64,linux/arm64
|
||||
> ```
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|------------------------------|----------|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `version` | String | | [Buildx](https://github.com/docker/buildx) version. (eg. `v0.3.0`, `latest`, `https://github.com/docker/buildx.git#master`) |
|
||||
| `name` | String | | Name of the builder. If not specified, one will be generated or if it already exists, it will be used instead of creating a new one |
|
||||
| `driver` | String | `docker-container` | Sets the [builder driver](https://docs.docker.com/engine/reference/commandline/buildx_create/#driver) to be used |
|
||||
| `driver-opts` | List | | List of additional [driver-specific options](https://docs.docker.com/engine/reference/commandline/buildx_create/#driver-opt) (eg. `image=moby/buildkit:master`) |
|
||||
| `buildkitd-flags` | String | | [BuildKit daemon flags](https://docs.docker.com/engine/reference/commandline/buildx_create/#buildkitd-flags) |
|
||||
| `buildkitd-config` \* | String | | [BuildKit daemon config file](https://docs.docker.com/engine/reference/commandline/buildx_create/#config) |
|
||||
| `buildkitd-config-inline` \* | String | | Same as `buildkitd-config` but inline |
|
||||
| `install` | Bool | `false` | Sets up `docker build` command as an alias to `docker buildx` |
|
||||
| `use` | Bool | `true` | Switch to this builder instance |
|
||||
| `endpoint` | String | | [Optional address for docker socket](https://docs.docker.com/engine/reference/commandline/buildx_create/#description) or context from `docker context ls` |
|
||||
| `platforms` | List/CSV | | Fixed [platforms](https://docs.docker.com/engine/reference/commandline/buildx_create/#platform) for current node. If not empty, values take priority over the detected ones |
|
||||
| `append` | YAML | | [Append additional nodes](https://docs.docker.com/build/ci/github-actions/configure-builder/#append-additional-nodes-to-the-builder) to the builder |
|
||||
| `keep-state` | Bool | `false` | Keep BuildKit state on `cleanup`. This is only useful on persistent self-hosted runners |
|
||||
| `cache-binary` | Bool | `true` | Cache buildx binary to GitHub Actions cache backend |
|
||||
| `cleanup` | Bool | `true` | Cleanup temp files and remove builder at the end of a job |
|
||||
|
||||
> [!IMPORTANT]
|
||||
> If you set the `buildkitd-flags` input, the default flags (`--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host`)
|
||||
> will be reset. If you want to retain the default behavior, make sure to
|
||||
> include these flags in your custom `buildkitd-flags` value.
|
||||
|
||||
> [!NOTE]
|
||||
> `buildkitd-config` and `buildkitd-config-inline` are mutually exclusive.
|
||||
|
||||
### outputs
|
||||
|
||||
The following outputs are available:
|
||||
Following outputs are available
|
||||
|
||||
| Name | Type | Description |
|
||||
|-------------|--------|-----------------------------------------------------|
|
||||
| `name` | String | Builder name |
|
||||
| `driver` | String | Builder driver |
|
||||
| `platforms` | String | Builder node platforms (preferred and/or available) |
|
||||
| `nodes` | JSON | Builder [nodes metadata](#nodes-output) |
|
||||
| Name | Type | Description |
|
||||
|---------------|---------|---------------------------------------|
|
||||
| `name` | String | Builder instance name |
|
||||
| `platforms` | String | Available platforms (comma separated) |
|
||||
|
||||
### environment variables
|
||||
|
||||
The following [official docker environment variables](https://docs.docker.com/engine/reference/commandline/cli/#environment-variables) are supported:
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|-----------------|--------|-------------|-------------------------------------------------|
|
||||
| `DOCKER_CONFIG` | String | `~/.docker` | The location of your client configuration files |
|
||||
| Name | Type | Default | Description |
|
||||
|-----------------|---------|-------------|-------------------------------------------------|
|
||||
| `DOCKER_CONFIG` | String | `~/.docker` | The location of your client configuration files |
|
||||
|
||||
## Notes
|
||||
## Keep up-to-date with GitHub Dependabot
|
||||
|
||||
### `nodes` output
|
||||
Since [Dependabot](https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-github-dependabot)
|
||||
has [native GitHub Actions support](https://docs.github.com/en/github/administering-a-repository/configuration-options-for-dependency-updates#package-ecosystem),
|
||||
to enable it on your GitHub repo all you need to do is add the `.github/dependabot.yml` file:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"name": "builder-3820d274-502c-4498-ae24-d4c32b3023d90",
|
||||
"endpoint": "unix:///var/run/docker.sock",
|
||||
"driver-opts": [
|
||||
"network=host",
|
||||
"image=moby/buildkit:master"
|
||||
],
|
||||
"status": "running",
|
||||
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
|
||||
"buildkit": "3fab389",
|
||||
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/386"
|
||||
}
|
||||
]
|
||||
```yaml
|
||||
version: 2
|
||||
updates:
|
||||
# Maintain dependencies for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
```
|
||||
|
||||
| Name | Type | Description |
|
||||
|-------------------|--------|----------------------------|
|
||||
| `name` | String | Node name |
|
||||
| `endpoint` | String | Node endpoint |
|
||||
| `driver-opts` | List | Options for the driver |
|
||||
| `status` | String | Node status |
|
||||
| `buildkitd-flags` | String | Flags for buildkitd daemon |
|
||||
| `buildkit` | String | BuildKit version |
|
||||
| `platforms` | String | Platforms available |
|
||||
## Limitation
|
||||
|
||||
## Contributing
|
||||
|
||||
Want to contribute? Awesome! You can find information about contributing to
|
||||
this project in the [CONTRIBUTING.md](/.github/CONTRIBUTING.md)
|
||||
This action is only available for Linux [virtual environments](https://docs.github.com/en/actions/reference/virtual-environments-for-github-hosted-runners#supported-virtual-environments-and-hardware-resources).
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
import fs = require('fs');
|
||||
import * as docker from '../src/docker';
|
||||
import * as buildx from '../src/buildx';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import * as semver from 'semver';
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
describe('getVersion', () => {
|
||||
it('valid', async () => {
|
||||
await exec.exec('docker', ['buildx', 'version']);
|
||||
const version = await buildx.getVersion();
|
||||
console.log(`version: ${version}`);
|
||||
expect(semver.valid(version)).not.toBeNull();
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('parseVersion', () => {
|
||||
test.each([
|
||||
['github.com/docker/buildx 0.4.1+azure bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'],
|
||||
['github.com/docker/buildx v0.4.1 bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'],
|
||||
['github.com/docker/buildx v0.4.2 fb7b670b764764dc4716df3eba07ffdae4cc47b2', '0.4.2']
|
||||
])('given %p', async (stdout, expected) => {
|
||||
expect(await buildx.parseVersion(stdout)).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('platforms', () => {
|
||||
async function isDaemonRunning() {
|
||||
return await docker.isDaemonRunning();
|
||||
}
|
||||
(isDaemonRunning() ? it : it.skip)(
|
||||
'valid',
|
||||
async () => {
|
||||
const platforms = buildx.platforms();
|
||||
console.log(`platforms: ${platforms}`);
|
||||
expect(platforms).not.toBeUndefined();
|
||||
expect(platforms).not.toEqual('');
|
||||
},
|
||||
100000
|
||||
);
|
||||
});
|
||||
|
||||
describe('countBuilders', () => {
|
||||
it('valid', async () => {
|
||||
const countBuilders = await buildx.countBuilders();
|
||||
console.log(`countBuilders: ${countBuilders}`);
|
||||
expect(countBuilders).toBeGreaterThan(0);
|
||||
}, 100000);
|
||||
});
|
||||
|
||||
describe('install', () => {
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-buildx-'));
|
||||
it('acquires v0.2.2 version of buildx', async () => {
|
||||
const buildxBin = await buildx.install('v0.2.2', tmpDir);
|
||||
console.log(buildxBin);
|
||||
expect(fs.existsSync(buildxBin)).toBe(true);
|
||||
}, 100000);
|
||||
it('acquires latest version of buildx', async () => {
|
||||
const buildxBin = await buildx.install('latest', tmpDir);
|
||||
console.log(buildxBin);
|
||||
expect(fs.existsSync(buildxBin)).toBe(true);
|
||||
}, 100000);
|
||||
});
|
|
@ -1,519 +1,81 @@
|
|||
import {beforeEach, describe, expect, jest, test} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx';
|
||||
import {Context} from '@docker/actions-toolkit/lib/context';
|
||||
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
|
||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
|
||||
import {Node} from '@docker/actions-toolkit/lib/types/buildx/builder';
|
||||
|
||||
import * as context from '../src/context';
|
||||
|
||||
const fixturesDir = path.join(__dirname, 'fixtures');
|
||||
// prettier-ignore
|
||||
const tmpDir = path.join(process.env.TEMP || '/tmp', 'setup-buildx-jest');
|
||||
const tmpName = path.join(tmpDir, '.tmpname-jest');
|
||||
|
||||
jest.spyOn(Context, 'tmpDir').mockImplementation((): string => {
|
||||
if (!fs.existsSync(tmpDir)) {
|
||||
fs.mkdirSync(tmpDir, {recursive: true});
|
||||
}
|
||||
return tmpDir;
|
||||
});
|
||||
|
||||
jest.spyOn(Context, 'tmpName').mockImplementation((): string => {
|
||||
return tmpName;
|
||||
});
|
||||
|
||||
jest.mock('crypto', () => {
|
||||
return {
|
||||
...(jest.requireActual('crypto') as object),
|
||||
randomUUID: jest.fn(() => '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d')
|
||||
};
|
||||
});
|
||||
|
||||
jest.spyOn(Docker, 'context').mockImplementation((): Promise<string> => {
|
||||
return Promise.resolve('default');
|
||||
});
|
||||
|
||||
describe('getCreateArgs', () => {
|
||||
beforeEach(() => {
|
||||
process.env = Object.keys(process.env).reduce((object, key) => {
|
||||
if (!key.startsWith('INPUT_')) {
|
||||
object[key] = process.env[key];
|
||||
}
|
||||
return object;
|
||||
}, {});
|
||||
describe('getInputList', () => {
|
||||
it('handles single line correctly', async () => {
|
||||
await setInput('foo', 'bar');
|
||||
const res = await context.getInputList('foo');
|
||||
console.log(res);
|
||||
expect(res).toEqual(['bar']);
|
||||
});
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[
|
||||
0,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
||||
'--driver', 'docker-container',
|
||||
'--buildkitd-flags', '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
|
||||
'--use'
|
||||
]
|
||||
],
|
||||
[
|
||||
1,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['driver', 'docker'],
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'default',
|
||||
'--driver', 'docker',
|
||||
'--buildkitd-flags', '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
|
||||
'--use'
|
||||
]
|
||||
],
|
||||
[
|
||||
2,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['install', 'false'],
|
||||
['use', 'false'],
|
||||
['driver-opts', 'image=moby/buildkit:master\nnetwork=host'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
||||
'--driver', 'docker-container',
|
||||
'--driver-opt', 'image=moby/buildkit:master',
|
||||
'--driver-opt', 'network=host',
|
||||
'--buildkitd-flags', '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host'
|
||||
]
|
||||
],
|
||||
[
|
||||
3,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['driver', 'remote'],
|
||||
['endpoint', 'tls://foo:1234'],
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
||||
'--driver', 'remote',
|
||||
'--use',
|
||||
'tls://foo:1234'
|
||||
]
|
||||
],
|
||||
[
|
||||
4,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['driver', 'remote'],
|
||||
['platforms', 'linux/arm64,linux/arm/v7'],
|
||||
['endpoint', 'tls://foo:1234'],
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
||||
'--driver', 'remote',
|
||||
'--platform', 'linux/arm64,linux/arm/v7',
|
||||
'--use',
|
||||
'tls://foo:1234'
|
||||
]
|
||||
],
|
||||
[
|
||||
5,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['install', 'false'],
|
||||
['use', 'false'],
|
||||
['driver-opts', `"env.no_proxy=localhost,127.0.0.1,.mydomain"`],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false'],
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
||||
'--driver', 'docker-container',
|
||||
'--driver-opt', '"env.no_proxy=localhost,127.0.0.1,.mydomain"',
|
||||
'--buildkitd-flags', '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host'
|
||||
]
|
||||
],
|
||||
[
|
||||
6,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['install', 'false'],
|
||||
['use', 'false'],
|
||||
['platforms', 'linux/amd64\n"linux/arm64,linux/arm/v7"'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false'],
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
||||
'--driver', 'docker-container',
|
||||
'--buildkitd-flags', '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
|
||||
'--platform', 'linux/amd64,linux/arm64,linux/arm/v7'
|
||||
]
|
||||
],
|
||||
[
|
||||
7,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['install', 'false'],
|
||||
['use', 'false'],
|
||||
['driver', 'unknown'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false'],
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
||||
'--driver', 'unknown',
|
||||
]
|
||||
],
|
||||
[
|
||||
8,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['install', 'false'],
|
||||
['use', 'false'],
|
||||
['buildkitd-config', path.join(fixturesDir, 'buildkitd.toml')],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false'],
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
||||
'--driver', 'docker-container',
|
||||
'--buildkitd-flags', '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
|
||||
'--config', tmpName,
|
||||
]
|
||||
],
|
||||
[
|
||||
9,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['install', 'false'],
|
||||
['use', 'false'],
|
||||
['buildkitd-config-inline', 'debug = true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false'],
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
||||
'--driver', 'docker-container',
|
||||
'--buildkitd-flags', '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
|
||||
'--config', tmpName,
|
||||
]
|
||||
],
|
||||
[
|
||||
10,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['install', 'false'],
|
||||
['use', 'false'],
|
||||
['driver', 'cloud'],
|
||||
['buildkitd-flags', '--allow-insecure-entitlement network.host'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false'],
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
||||
'--driver', 'cloud',
|
||||
'--buildkitd-flags', '--allow-insecure-entitlement network.host',
|
||||
]
|
||||
],
|
||||
[
|
||||
11,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['keep-state', 'false'],
|
||||
['name', 'test-builder-name'],
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'test-builder-name',
|
||||
'--driver', 'docker-container',
|
||||
'--buildkitd-flags', '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
|
||||
'--use'
|
||||
]
|
||||
],
|
||||
[
|
||||
12,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['keep-state', 'true'],
|
||||
['name', 'test-builder-name'],
|
||||
]),
|
||||
[
|
||||
'create',
|
||||
'--name', 'test-builder-name',
|
||||
'--driver', 'docker-container',
|
||||
'--buildkitd-flags', '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
|
||||
'--use',
|
||||
]
|
||||
],
|
||||
])(
|
||||
'[%d] given buildx %s and %p as inputs, returns %p',
|
||||
async (num: number, buildxVersion: string, inputs: Map<string, string>, expected: Array<string>) => {
|
||||
inputs.forEach((value: string, name: string) => {
|
||||
setInput(name, value);
|
||||
});
|
||||
const toolkit = new Toolkit();
|
||||
jest.spyOn(Buildx.prototype, 'version').mockImplementation(async (): Promise<string> => {
|
||||
return buildxVersion;
|
||||
});
|
||||
const inp = await context.getInputs();
|
||||
const res = await context.getCreateArgs(inp, toolkit);
|
||||
expect(res).toEqual(expected);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('getAppendArgs', () => {
|
||||
beforeEach(() => {
|
||||
process.env = Object.keys(process.env).reduce((object, key) => {
|
||||
if (!key.startsWith('INPUT_')) {
|
||||
object[key] = process.env[key];
|
||||
}
|
||||
return object;
|
||||
}, {});
|
||||
it('handles multiple lines correctly', async () => {
|
||||
setInput('foo', 'bar\nbaz');
|
||||
const res = await context.getInputList('foo');
|
||||
console.log(res);
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[
|
||||
0,
|
||||
'v0.10.3',
|
||||
new Map<string, string>([
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
{
|
||||
"name": "aws_graviton2",
|
||||
"endpoint": "ssh://me@graviton2",
|
||||
"driver-opts": [
|
||||
"image=moby/buildkit:latest"
|
||||
],
|
||||
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
|
||||
"platforms": "linux/arm64"
|
||||
},
|
||||
[
|
||||
'create',
|
||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
||||
'--append',
|
||||
'--node', 'aws_graviton2',
|
||||
'--driver-opt', 'image=moby/buildkit:latest',
|
||||
'--buildkitd-flags', '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
|
||||
'--platform', 'linux/arm64',
|
||||
'ssh://me@graviton2'
|
||||
]
|
||||
]
|
||||
])(
|
||||
'[%d] given buildx %s and %p as inputs, returns %p',
|
||||
async (num: number, buildxVersion: string, inputs: Map<string, string>, node: Node, expected: Array<string>) => {
|
||||
inputs.forEach((value: string, name: string) => {
|
||||
setInput(name, value);
|
||||
});
|
||||
const toolkit = new Toolkit();
|
||||
jest.spyOn(Buildx.prototype, 'version').mockImplementation(async (): Promise<string> => {
|
||||
return buildxVersion;
|
||||
});
|
||||
const inp = await context.getInputs();
|
||||
const res = await context.getAppendArgs(inp, node, toolkit);
|
||||
expect(res).toEqual(expected);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('getVersion', () => {
|
||||
beforeEach(() => {
|
||||
process.env = Object.keys(process.env).reduce((object, key) => {
|
||||
if (!key.startsWith('INPUT_')) {
|
||||
object[key] = process.env[key];
|
||||
}
|
||||
return object;
|
||||
}, {});
|
||||
it('remove empty lines correctly', async () => {
|
||||
setInput('foo', 'bar\n\nbaz');
|
||||
const res = await context.getInputList('foo');
|
||||
console.log(res);
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
// prettier-ignore
|
||||
test.each([
|
||||
[
|
||||
0,
|
||||
new Map<string, string>([
|
||||
// defaults
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
''
|
||||
],
|
||||
[
|
||||
1,
|
||||
new Map<string, string>([
|
||||
['version', 'latest'],
|
||||
// defaults
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
'latest'
|
||||
],
|
||||
[
|
||||
2,
|
||||
new Map<string, string>([
|
||||
['version', 'edge'],
|
||||
// defaults
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
'edge'
|
||||
],
|
||||
[
|
||||
3,
|
||||
new Map<string, string>([
|
||||
['version', 'v0.19.2'],
|
||||
// defaults
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
'v0.19.2'
|
||||
],
|
||||
[
|
||||
4,
|
||||
new Map<string, string>([
|
||||
['version', 'latest'],
|
||||
['driver', 'cloud'],
|
||||
// defaults
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
'cloud:latest'
|
||||
],
|
||||
[
|
||||
5,
|
||||
new Map<string, string>([
|
||||
['version', 'edge'],
|
||||
['driver', 'cloud'],
|
||||
// defaults
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
'cloud:edge'
|
||||
],
|
||||
[
|
||||
6,
|
||||
new Map<string, string>([
|
||||
['driver', 'cloud'],
|
||||
// defaults
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
'cloud:latest'
|
||||
],
|
||||
[
|
||||
7,
|
||||
new Map<string, string>([
|
||||
['version', 'cloud:v0.11.2-desktop.2'],
|
||||
['driver', 'cloud'],
|
||||
// defaults
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
'cloud:v0.11.2-desktop.2'
|
||||
],
|
||||
[
|
||||
8,
|
||||
new Map<string, string>([
|
||||
['version', 'cloud:v0.11.2-desktop.2'],
|
||||
// defaults
|
||||
['install', 'false'],
|
||||
['use', 'true'],
|
||||
['cache-binary', 'true'],
|
||||
['cleanup', 'true'],
|
||||
['keep-state', 'false']
|
||||
]),
|
||||
'cloud:v0.11.2-desktop.2'
|
||||
],
|
||||
])(
|
||||
'[%d] given %p as inputs, returns version %p',
|
||||
async (num: number, inputs: Map<string, string>, expected: string) => {
|
||||
inputs.forEach((value: string, name: string) => {
|
||||
setInput(name, value);
|
||||
});
|
||||
const inp = await context.getInputs();
|
||||
expect(context.getVersion(inp)).toEqual(expected);
|
||||
}
|
||||
);
|
||||
it('handles comma correctly', async () => {
|
||||
setInput('foo', 'bar,baz');
|
||||
const res = await context.getInputList('foo');
|
||||
console.log(res);
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('remove empty result correctly', async () => {
|
||||
setInput('foo', 'bar,baz,');
|
||||
const res = await context.getInputList('foo');
|
||||
console.log(res);
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('handles different new lines correctly', async () => {
|
||||
setInput('foo', 'bar\r\nbaz');
|
||||
const res = await context.getInputList('foo');
|
||||
console.log(res);
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('handles different new lines and comma correctly', async () => {
|
||||
setInput('foo', 'bar\r\nbaz,bat');
|
||||
const res = await context.getInputList('foo');
|
||||
console.log(res);
|
||||
expect(res).toEqual(['bar', 'baz', 'bat']);
|
||||
});
|
||||
|
||||
it('handles multiple lines and ignoring comma correctly', async () => {
|
||||
setInput('driver-opts', 'image=moby/buildkit:master\nnetwork=host');
|
||||
const res = await context.getInputList('driver-opts', true);
|
||||
console.log(res);
|
||||
expect(res).toEqual(['image=moby/buildkit:master', 'network=host']);
|
||||
});
|
||||
|
||||
it('handles different new lines and ignoring comma correctly', async () => {
|
||||
setInput('driver-opts', 'image=moby/buildkit:master\r\nnetwork=host');
|
||||
const res = await context.getInputList('driver-opts', true);
|
||||
console.log(res);
|
||||
expect(res).toEqual(['image=moby/buildkit:master', 'network=host']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('asyncForEach', () => {
|
||||
it('executes async tasks sequentially', async () => {
|
||||
const testValues = [1, 2, 3, 4, 5];
|
||||
const results: number[] = [];
|
||||
|
||||
await context.asyncForEach(testValues, async value => {
|
||||
results.push(value);
|
||||
});
|
||||
|
||||
expect(results).toEqual(testValues);
|
||||
});
|
||||
});
|
||||
|
||||
// See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
debug = true
|
|
@ -0,0 +1,17 @@
|
|||
import * as github from '../src/github';
|
||||
|
||||
describe('github', () => {
|
||||
it('returns latest buildx GitHub release', async () => {
|
||||
const release = await github.getRelease('latest');
|
||||
console.log(release);
|
||||
expect(release).not.toBeNull();
|
||||
expect(release?.tag_name).not.toEqual('');
|
||||
});
|
||||
|
||||
it('returns v0.2.2 buildx GitHub release', async () => {
|
||||
const release = await github.getRelease('v0.2.2');
|
||||
console.log(release);
|
||||
expect(release).not.toBeNull();
|
||||
expect(release?.tag_name).toEqual('v0.2.2');
|
||||
});
|
||||
});
|
57
action.yml
57
action.yml
|
@ -18,73 +18,28 @@ inputs:
|
|||
description: 'List of additional driver-specific options. (eg. image=moby/buildkit:master)'
|
||||
required: false
|
||||
buildkitd-flags:
|
||||
description: 'BuildKit daemon flags'
|
||||
required: false
|
||||
buildkitd-config:
|
||||
description: 'BuildKit daemon config file'
|
||||
required: false
|
||||
buildkitd-config-inline:
|
||||
description: 'Inline BuildKit daemon config'
|
||||
description: 'Flags for buildkitd daemon'
|
||||
default: '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host'
|
||||
required: false
|
||||
install:
|
||||
description: 'Sets up docker build command as an alias to docker buildx build'
|
||||
description: 'Sets up docker build command as an alias to docker buildx'
|
||||
default: 'false'
|
||||
required: false
|
||||
use:
|
||||
description: 'Switch to this builder instance'
|
||||
default: 'true'
|
||||
required: false
|
||||
name:
|
||||
description: 'Name of the builder. If not specified, one will be generated or if it already exists, it will be used instead of creating a new one.'
|
||||
required: false
|
||||
endpoint:
|
||||
description: 'Optional address for docker socket or context from `docker context ls`'
|
||||
required: false
|
||||
platforms:
|
||||
description: 'Fixed platforms for current node. If not empty, values take priority over the detected ones'
|
||||
required: false
|
||||
append:
|
||||
description: 'Append additional nodes to the builder'
|
||||
required: false
|
||||
keep-state:
|
||||
description: 'Keep BuildKit state on cleanup. This is only useful on persistent self-hosted runners.'
|
||||
default: 'false'
|
||||
required: false
|
||||
cache-binary:
|
||||
description: 'Cache buildx binary to GitHub Actions cache backend'
|
||||
default: 'true'
|
||||
required: false
|
||||
cleanup:
|
||||
description: 'Cleanup temp files and remove builder at the end of a job'
|
||||
default: 'true'
|
||||
required: false
|
||||
# TODO: remove deprecated config and config-inline inputs
|
||||
config:
|
||||
description: 'BuildKit daemon config file'
|
||||
deprecationMessage: 'Use buildkitd-config instead'
|
||||
required: false
|
||||
config-inline:
|
||||
description: 'Inline BuildKit daemon config'
|
||||
deprecationMessage: 'Use buildkitd-config-inline instead'
|
||||
required: false
|
||||
|
||||
outputs:
|
||||
name:
|
||||
description: 'Builder name'
|
||||
driver:
|
||||
description: 'Builder driver'
|
||||
description: 'Builder instance name'
|
||||
platforms:
|
||||
description: 'Builder node platforms (preferred or available)'
|
||||
nodes:
|
||||
description: 'Builder nodes metadata'
|
||||
endpoint:
|
||||
description: 'Builder node endpoint (deprecated, use nodes output instead)'
|
||||
status:
|
||||
description: 'Builder node status (deprecated, use nodes output instead)'
|
||||
flags:
|
||||
description: 'Builder node flags (deprecated, use nodes output instead)'
|
||||
description: 'Available platforms (comma separated)'
|
||||
|
||||
runs:
|
||||
using: 'node20'
|
||||
using: 'node12'
|
||||
main: 'dist/index.js'
|
||||
post: 'dist/index.js'
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
comment: false
|
||||
github_checks:
|
||||
annotations: false
|
|
@ -1,80 +0,0 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG NODE_VERSION=20
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine AS base
|
||||
RUN apk add --no-cache cpio findutils git
|
||||
WORKDIR /src
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache <<EOT
|
||||
corepack enable
|
||||
yarn --version
|
||||
yarn config set --home enableTelemetry 0
|
||||
EOT
|
||||
|
||||
FROM base AS deps
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn install && mkdir /vendor && cp yarn.lock /vendor
|
||||
|
||||
FROM scratch AS vendor-update
|
||||
COPY --from=deps /vendor /
|
||||
|
||||
FROM deps AS vendor-validate
|
||||
RUN --mount=type=bind,target=.,rw <<EOT
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /vendor/* .
|
||||
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then
|
||||
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor"'
|
||||
git status --porcelain -- yarn.lock
|
||||
exit 1
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM deps AS build
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--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 <<EOT
|
||||
set -e
|
||||
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
|
||||
EOT
|
||||
|
||||
FROM deps AS format
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run format \
|
||||
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' -not -path './.yarn/*' | cpio -pdm /out
|
||||
|
||||
FROM scratch AS format-update
|
||||
COPY --from=format /out /
|
||||
|
||||
FROM deps AS lint
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run lint
|
||||
|
||||
FROM deps AS test
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run test --coverage --coverageDirectory=/tmp/coverage
|
||||
|
||||
FROM scratch AS test-coverage
|
||||
COPY --from=test /tmp/coverage /
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -1,66 +1,42 @@
|
|||
target "_common" {
|
||||
args = {
|
||||
BUILDKIT_CONTEXT_KEEP_GIT_DIR = 1
|
||||
}
|
||||
}
|
||||
|
||||
group "default" {
|
||||
targets = ["build"]
|
||||
}
|
||||
|
||||
group "pre-checkin" {
|
||||
targets = ["vendor", "format", "build"]
|
||||
targets = ["update-yarn", "format", "build"]
|
||||
}
|
||||
|
||||
group "validate" {
|
||||
targets = ["lint", "build-validate", "vendor-validate"]
|
||||
targets = ["validate-format", "validate-build", "validate-yarn"]
|
||||
}
|
||||
|
||||
target "update-yarn" {
|
||||
target = "update-yarn"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "build" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "build-update"
|
||||
target = "dist"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "build-validate" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "build-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "format" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "format-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "lint" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "lint"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "vendor" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "vendor-update"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "vendor-validate" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "vendor-validate"
|
||||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "test" {
|
||||
inherits = ["_common"]
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "test-coverage"
|
||||
output = ["./coverage"]
|
||||
target = "test"
|
||||
}
|
||||
|
||||
target "format" {
|
||||
target = "format"
|
||||
output = ["."]
|
||||
}
|
||||
|
||||
target "validate-format" {
|
||||
target = "validate-format"
|
||||
}
|
||||
|
||||
target "validate-build" {
|
||||
target = "validate-build"
|
||||
}
|
||||
|
||||
target "validate-yarn" {
|
||||
target = "validate-yarn"
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
iidfile=$(mktemp -t docker-iidfile.XXXXXXXXXX)
|
||||
DOCKER_BUILDKIT=1 docker build --iidfile $iidfile --progress=plain .
|
||||
docker run -it --rm $(cat $iidfile)
|
||||
docker rmi $(cat $iidfile)
|
|
@ -0,0 +1,12 @@
|
|||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
setupFiles: ["dotenv/config"],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
testRunner: 'jest-circus/runner',
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: false
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-setup-buildx-action-')).split(path.sep).join(path.posix.sep);
|
||||
|
||||
process.env = Object.assign({}, process.env, {
|
||||
TEMP: tmpDir,
|
||||
GITHUB_REPOSITORY: 'docker/setup-buildx-action',
|
||||
RUNNER_TEMP: path.join(tmpDir, 'runner-temp').split(path.sep).join(path.posix.sep),
|
||||
RUNNER_TOOL_CACHE: path.join(tmpDir, 'runner-tool-cache').split(path.sep).join(path.posix.sep)
|
||||
}) as {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testMatch: ['**/*.test.ts'],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
moduleNameMapper: {
|
||||
'^csv-parse/sync': '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs'
|
||||
},
|
||||
collectCoverageFrom: ['src/**/{!(main.ts),}.ts'],
|
||||
coveragePathIgnorePatterns: ['lib/', 'node_modules/', '__tests__/'],
|
||||
verbose: true
|
||||
};
|
58
package.json
58
package.json
|
@ -1,16 +1,13 @@
|
|||
{
|
||||
"name": "docker-setup-buildx",
|
||||
"description": "Set up Docker Buildx",
|
||||
"main": "src/main.ts",
|
||||
"main": "lib/main.js",
|
||||
"scripts": {
|
||||
"build": "ncc build --source-map --minify --license licenses.txt",
|
||||
"lint": "yarn run prettier && yarn run eslint",
|
||||
"format": "yarn run prettier:fix && yarn run eslint:fix",
|
||||
"eslint": "eslint --max-warnings=0 .",
|
||||
"eslint:fix": "eslint --fix .",
|
||||
"prettier": "prettier --check \"./**/*.ts\"",
|
||||
"prettier:fix": "prettier --write \"./**/*.ts\"",
|
||||
"test": "jest"
|
||||
"build": "tsc && ncc build",
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"test": "jest --coverage",
|
||||
"pre-checkin": "yarn run format && yarn run build"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -21,29 +18,32 @@
|
|||
"docker",
|
||||
"buildx"
|
||||
],
|
||||
"author": "Docker Inc.",
|
||||
"author": "Docker",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "CrazyMax",
|
||||
"url": "https://crazymax.dev"
|
||||
}
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"packageManager": "yarn@4.9.2",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.11.1",
|
||||
"@docker/actions-toolkit": "^0.63.0",
|
||||
"js-yaml": "^4.1.0"
|
||||
"@actions/core": "^1.2.6",
|
||||
"@actions/exec": "^1.0.4",
|
||||
"@actions/http-client": "^1.0.9",
|
||||
"@actions/tool-cache": "^1.6.1",
|
||||
"semver": "^7.3.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/node": "^20.19.9",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
||||
"@typescript-eslint/parser": "^7.18.0",
|
||||
"@vercel/ncc": "^0.38.3",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-prettier": "^9.1.2",
|
||||
"eslint-plugin-jest": "^28.14.0",
|
||||
"eslint-plugin-prettier": "^5.5.4",
|
||||
"jest": "^29.7.0",
|
||||
"prettier": "^3.6.2",
|
||||
"ts-jest": "^29.4.1",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.9.2"
|
||||
"@types/jest": "^26.0.3",
|
||||
"@types/node": "^14.0.14",
|
||||
"@vercel/ncc": "^0.23.0",
|
||||
"dotenv": "^8.2.0",
|
||||
"jest": "^26.1.0",
|
||||
"jest-circus": "^26.1.0",
|
||||
"jest-runtime": "^26.1.0",
|
||||
"prettier": "^2.0.5",
|
||||
"ts-jest": "^26.1.1",
|
||||
"typescript": "^3.9.5",
|
||||
"typescript-formatter": "^7.2.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as util from 'util';
|
||||
import * as context from './context';
|
||||
import * as exec from './exec';
|
||||
import * as github from './github';
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
|
||||
export async function getVersion(): Promise<string> {
|
||||
return await exec.exec(`docker`, ['buildx', 'version'], true).then(res => {
|
||||
if (res.stderr != '' && !res.success) {
|
||||
throw new Error(res.stderr);
|
||||
}
|
||||
return parseVersion(res.stdout);
|
||||
});
|
||||
}
|
||||
|
||||
export async function parseVersion(stdout: string): Promise<string> {
|
||||
const matches = /\sv?([0-9.]+)/.exec(stdout);
|
||||
if (!matches) {
|
||||
throw new Error(`Cannot parse Buildx version`);
|
||||
}
|
||||
return semver.clean(matches[1]);
|
||||
}
|
||||
|
||||
export async function isAvailable(): Promise<Boolean> {
|
||||
return await exec.exec(`docker`, ['buildx'], true).then(res => {
|
||||
if (res.stderr != '' && !res.success) {
|
||||
return false;
|
||||
}
|
||||
return res.success;
|
||||
});
|
||||
}
|
||||
|
||||
export async function countBuilders(): Promise<number> {
|
||||
return await exec.exec(`docker`, ['buildx', 'ls'], true).then(res => {
|
||||
if (res.stderr != '' && !res.success) {
|
||||
throw new Error(`Cannot list builders: ${res.stderr}`);
|
||||
}
|
||||
return (res.stdout.trim().split(`\n`).length - 1) / 2;
|
||||
});
|
||||
}
|
||||
|
||||
export async function platforms(): Promise<String | undefined> {
|
||||
return await exec.exec(`docker`, ['buildx', 'inspect'], true).then(res => {
|
||||
if (res.stderr != '' && !res.success) {
|
||||
throw new Error(res.stderr);
|
||||
}
|
||||
for (const line of res.stdout.trim().split(`\n`)) {
|
||||
if (line.startsWith('Platforms')) {
|
||||
return line.replace('Platforms: ', '').replace(/\s/g, '').trim();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export async function install(inputVersion: string, dockerConfigHome: string): Promise<string> {
|
||||
const release: github.GitHubRelease | null = await github.getRelease(inputVersion);
|
||||
if (!release) {
|
||||
throw new Error(`Cannot find buildx ${inputVersion} release`);
|
||||
}
|
||||
core.debug(`Release found: ${release.tag_name}`);
|
||||
const version = release.tag_name.replace(/^v+|v+$/g, '');
|
||||
|
||||
let toolPath: string;
|
||||
toolPath = tc.find('buildx', version);
|
||||
if (!toolPath) {
|
||||
const c = semver.clean(version) || '';
|
||||
if (!semver.valid(c)) {
|
||||
throw new Error(`Invalid Buildx version "${version}".`);
|
||||
}
|
||||
toolPath = await download(version);
|
||||
}
|
||||
|
||||
const pluginsDir: string = path.join(dockerConfigHome, 'cli-plugins');
|
||||
core.debug(`Plugins dir is ${pluginsDir}`);
|
||||
if (!fs.existsSync(pluginsDir)) {
|
||||
fs.mkdirSync(pluginsDir, {recursive: true});
|
||||
}
|
||||
|
||||
const filename: string = context.osPlat == 'win32' ? 'docker-buildx.exe' : 'docker-buildx';
|
||||
const pluginPath: string = path.join(pluginsDir, filename);
|
||||
core.debug(`Plugin path is ${pluginPath}`);
|
||||
fs.copyFileSync(path.join(toolPath, filename), pluginPath);
|
||||
|
||||
core.info('🔨 Fixing perms...');
|
||||
fs.chmodSync(pluginPath, '0755');
|
||||
|
||||
return pluginPath;
|
||||
}
|
||||
|
||||
async function download(version: string): Promise<string> {
|
||||
const targetFile: string = context.osPlat == 'win32' ? 'docker-buildx.exe' : 'docker-buildx';
|
||||
const downloadUrl = util.format(
|
||||
'https://github.com/docker/buildx/releases/download/v%s/%s',
|
||||
version,
|
||||
await filename(version)
|
||||
);
|
||||
let downloadPath: string;
|
||||
|
||||
try {
|
||||
core.info(`⬇️ Downloading ${downloadUrl}...`);
|
||||
downloadPath = await tc.downloadTool(downloadUrl);
|
||||
core.debug(`Downloaded to ${downloadPath}`);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return await tc.cacheFile(downloadPath, targetFile, 'buildx', version);
|
||||
}
|
||||
|
||||
async function filename(version: string): Promise<string> {
|
||||
let arch: string;
|
||||
switch (context.osArch) {
|
||||
case 'x64': {
|
||||
arch = 'amd64';
|
||||
break;
|
||||
}
|
||||
case 'ppc64': {
|
||||
arch = 'ppc64le';
|
||||
break;
|
||||
}
|
||||
case 'arm': {
|
||||
const arm_version = (process.config.variables as any).arm_version;
|
||||
arch = arm_version ? 'arm-v' + arm_version : 'arm';
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
arch = context.osArch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const platform: string = context.osPlat == 'win32' ? 'windows' : context.osPlat;
|
||||
const ext: string = context.osPlat == 'win32' ? '.exe' : '';
|
||||
return util.format('buildx-v%s.%s-%s%s', version, platform, arch, ext);
|
||||
}
|
137
src/context.ts
137
src/context.ts
|
@ -1,134 +1,49 @@
|
|||
import * as crypto from 'crypto';
|
||||
import * as os from 'os';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
|
||||
import {Util} from '@docker/actions-toolkit/lib/util';
|
||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
|
||||
|
||||
import {Node} from '@docker/actions-toolkit/lib/types/buildx/builder';
|
||||
|
||||
export const builderNodeEnvPrefix = 'BUILDER_NODE';
|
||||
const defaultBuildkitdFlags = '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host';
|
||||
export const osPlat: string = os.platform();
|
||||
export const osArch: string = os.arch();
|
||||
|
||||
export interface Inputs {
|
||||
version: string;
|
||||
name: string;
|
||||
driver: string;
|
||||
driverOpts: string[];
|
||||
buildkitdFlags: string;
|
||||
buildkitdConfig: string;
|
||||
buildkitdConfigInline: string;
|
||||
platforms: string[];
|
||||
install: boolean;
|
||||
use: boolean;
|
||||
endpoint: string;
|
||||
append: string;
|
||||
cacheBinary: boolean;
|
||||
cleanup: boolean;
|
||||
keepState: boolean;
|
||||
}
|
||||
|
||||
export async function getInputs(): Promise<Inputs> {
|
||||
return {
|
||||
version: core.getInput('version'),
|
||||
name: await getBuilderName(core.getInput('name'), core.getInput('driver') || 'docker-container'),
|
||||
driver: core.getInput('driver') || 'docker-container',
|
||||
driverOpts: Util.getInputList('driver-opts', {ignoreComma: true, quote: false}),
|
||||
buildkitdFlags: core.getInput('buildkitd-flags'),
|
||||
platforms: Util.getInputList('platforms'),
|
||||
install: core.getBooleanInput('install'),
|
||||
use: core.getBooleanInput('use'),
|
||||
endpoint: core.getInput('endpoint'),
|
||||
buildkitdConfig: core.getInput('buildkitd-config') || core.getInput('config'),
|
||||
buildkitdConfigInline: core.getInput('buildkitd-config-inline') || core.getInput('config-inline'),
|
||||
append: core.getInput('append'),
|
||||
keepState: core.getBooleanInput('keep-state'),
|
||||
cacheBinary: core.getBooleanInput('cache-binary'),
|
||||
cleanup: core.getBooleanInput('cleanup')
|
||||
driverOpts: await getInputList('driver-opts', true),
|
||||
buildkitdFlags:
|
||||
core.getInput('buildkitd-flags') ||
|
||||
'--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
|
||||
install: /true/i.test(core.getInput('install')),
|
||||
use: /true/i.test(core.getInput('use')),
|
||||
endpoint: core.getInput('endpoint')
|
||||
};
|
||||
}
|
||||
|
||||
export async function getBuilderName(name: string, driver: string): Promise<string> {
|
||||
return driver == 'docker' ? await Docker.context() : name || `builder-${crypto.randomUUID()}`;
|
||||
export async function getInputList(name: string, ignoreComma?: boolean): Promise<string[]> {
|
||||
const items = core.getInput(name);
|
||||
if (items == '') {
|
||||
return [];
|
||||
}
|
||||
return items
|
||||
.split(/\r?\n/)
|
||||
.filter(x => x)
|
||||
.reduce<string[]>(
|
||||
(acc, line) => acc.concat(!ignoreComma ? line.split(',').filter(x => x) : line).map(pat => pat.trim()),
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
export async function getCreateArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> {
|
||||
const args: Array<string> = ['create', '--name', inputs.name, '--driver', inputs.driver];
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.3.0')) {
|
||||
await Util.asyncForEach(inputs.driverOpts, async (driverOpt: string) => {
|
||||
args.push('--driver-opt', driverOpt);
|
||||
});
|
||||
if (inputs.buildkitdFlags) {
|
||||
args.push('--buildkitd-flags', inputs.buildkitdFlags);
|
||||
} else if (driverSupportsBuildkitdFlags(inputs.driver)) {
|
||||
args.push('--buildkitd-flags', defaultBuildkitdFlags);
|
||||
}
|
||||
export const asyncForEach = async (array, callback) => {
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
await callback(array[index], index, array);
|
||||
}
|
||||
if (inputs.platforms.length > 0) {
|
||||
args.push('--platform', inputs.platforms.join(','));
|
||||
}
|
||||
if (inputs.use) {
|
||||
args.push('--use');
|
||||
}
|
||||
if (inputs.buildkitdConfig) {
|
||||
args.push('--config', toolkit.buildkit.config.resolveFromFile(inputs.buildkitdConfig));
|
||||
} else if (inputs.buildkitdConfigInline) {
|
||||
args.push('--config', toolkit.buildkit.config.resolveFromString(inputs.buildkitdConfigInline));
|
||||
}
|
||||
if (inputs.endpoint) {
|
||||
args.push(inputs.endpoint);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
export async function getAppendArgs(inputs: Inputs, node: Node, toolkit: Toolkit): Promise<Array<string>> {
|
||||
const args: Array<string> = ['create', '--name', inputs.name, '--append'];
|
||||
if (node.name) {
|
||||
args.push('--node', node.name);
|
||||
} else if (inputs.driver == 'kubernetes' && (await toolkit.buildx.versionSatisfies('<0.11.0'))) {
|
||||
args.push('--node', `node-${crypto.randomUUID()}`);
|
||||
}
|
||||
if (node['driver-opts'] && (await toolkit.buildx.versionSatisfies('>=0.3.0'))) {
|
||||
await Util.asyncForEach(node['driver-opts'], async (driverOpt: string) => {
|
||||
args.push('--driver-opt', driverOpt);
|
||||
});
|
||||
if (node['buildkitd-flags']) {
|
||||
args.push('--buildkitd-flags', node['buildkitd-flags']);
|
||||
} else if (driverSupportsBuildkitdFlags(inputs.driver)) {
|
||||
args.push('--buildkitd-flags', defaultBuildkitdFlags);
|
||||
}
|
||||
}
|
||||
if (node.platforms) {
|
||||
args.push('--platform', node.platforms);
|
||||
}
|
||||
if (node.endpoint) {
|
||||
args.push(node.endpoint);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
export async function getInspectArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> {
|
||||
const args: Array<string> = ['inspect', '--bootstrap'];
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.4.0')) {
|
||||
args.push('--builder', inputs.name);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function driverSupportsBuildkitdFlags(driver: string): boolean {
|
||||
return driver == '' || driver == 'docker-container' || driver == 'docker' || driver == 'kubernetes';
|
||||
}
|
||||
|
||||
export function getVersion(inputs: Inputs): string {
|
||||
const version = inputs.version;
|
||||
if (inputs.driver === 'cloud') {
|
||||
if (!version || version === 'latest') {
|
||||
return 'cloud:latest';
|
||||
}
|
||||
if (version.startsWith('cloud:') || version.startsWith('lab:')) {
|
||||
return version;
|
||||
}
|
||||
return `cloud:${version}`;
|
||||
}
|
||||
return version;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
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;
|
||||
});
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
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()
|
||||
};
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
import * as httpm from '@actions/http-client';
|
||||
|
||||
export interface GitHubRelease {
|
||||
id: number;
|
||||
tag_name: string;
|
||||
}
|
||||
|
||||
export const getRelease = async (version: string): Promise<GitHubRelease | null> => {
|
||||
const url: string = `https://github.com/docker/buildx/releases/${version}`;
|
||||
const http: httpm.HttpClient = new httpm.HttpClient('setup-buildx');
|
||||
return (await http.getJson<GitHubRelease>(url)).result;
|
||||
};
|
371
src/main.ts
371
src/main.ts
|
@ -1,306 +1,91 @@
|
|||
import * as crypto from 'crypto';
|
||||
import * as fs from 'fs';
|
||||
import * as yaml from 'js-yaml';
|
||||
import * as core from '@actions/core';
|
||||
import * as actionsToolkit from '@docker/actions-toolkit';
|
||||
|
||||
import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx';
|
||||
import {Builder} from '@docker/actions-toolkit/lib/buildx/builder';
|
||||
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
|
||||
import {Exec} from '@docker/actions-toolkit/lib/exec';
|
||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
|
||||
import {Util} from '@docker/actions-toolkit/lib/util';
|
||||
|
||||
import {Node} from '@docker/actions-toolkit/lib/types/buildx/builder';
|
||||
import {ContextInfo} from '@docker/actions-toolkit/lib/types/docker/docker';
|
||||
|
||||
import * as exec from '@actions/exec';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as semver from 'semver';
|
||||
import * as buildx from './buildx';
|
||||
import * as context from './context';
|
||||
import * as mexec from './exec';
|
||||
import * as stateHelper from './state-helper';
|
||||
|
||||
actionsToolkit.run(
|
||||
// main
|
||||
async () => {
|
||||
const inputs: context.Inputs = await context.getInputs();
|
||||
stateHelper.setCleanup(inputs.cleanup);
|
||||
const version = context.getVersion(inputs);
|
||||
|
||||
const toolkit = new Toolkit();
|
||||
const standalone = await toolkit.buildx.isStandalone();
|
||||
stateHelper.setStandalone(standalone);
|
||||
|
||||
if (inputs.keepState && inputs.driver !== 'docker-container') {
|
||||
// https://docs.docker.com/reference/cli/docker/buildx/rm/#keep-state
|
||||
throw new Error(`Cannot use keep-state with ${inputs.driver} driver`);
|
||||
}
|
||||
stateHelper.setKeepState(inputs.keepState);
|
||||
|
||||
await core.group(`Docker info`, async () => {
|
||||
try {
|
||||
await Docker.printVersion();
|
||||
await Docker.printInfo();
|
||||
} catch (e) {
|
||||
core.info(e.message);
|
||||
}
|
||||
});
|
||||
|
||||
let toolPath;
|
||||
if (Util.isValidRef(version)) {
|
||||
if (standalone) {
|
||||
throw new Error(`Cannot build from source without the Docker CLI`);
|
||||
}
|
||||
await core.group(`Build buildx from source`, async () => {
|
||||
toolPath = await toolkit.buildxInstall.build(version, !inputs.cacheBinary);
|
||||
});
|
||||
} else if (!(await toolkit.buildx.isAvailable()) || version) {
|
||||
await core.group(`Download buildx from GitHub Releases`, async () => {
|
||||
toolPath = await toolkit.buildxInstall.download(version || 'latest', !inputs.cacheBinary);
|
||||
});
|
||||
}
|
||||
if (toolPath) {
|
||||
await core.group(`Install buildx`, async () => {
|
||||
if (standalone) {
|
||||
await toolkit.buildxInstall.installStandalone(toolPath);
|
||||
} else {
|
||||
await toolkit.buildxInstall.installPlugin(toolPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await core.group(`Buildx version`, async () => {
|
||||
await toolkit.buildx.printVersion();
|
||||
});
|
||||
|
||||
core.setOutput('name', inputs.name);
|
||||
stateHelper.setBuilderName(inputs.name);
|
||||
stateHelper.setBuilderDriver(inputs.driver);
|
||||
|
||||
fs.mkdirSync(Buildx.certsDir, {recursive: true});
|
||||
stateHelper.setCertsDir(Buildx.certsDir);
|
||||
|
||||
// if the default context has TLS data loaded and endpoint is not set, then
|
||||
// we create a temporary docker context only if driver is docker-container
|
||||
// https://github.com/docker/buildx/blob/b96ad59f64d40873e4959336d294b648bb3937fe/builder/builder.go#L489
|
||||
// https://github.com/docker/setup-buildx-action/issues/105
|
||||
if (!standalone && inputs.driver == 'docker-container' && (await Docker.context()) == 'default' && inputs.endpoint.length == 0) {
|
||||
let defaultContextWithTLS: boolean = false;
|
||||
await core.group(`Inspecting default docker context`, async () => {
|
||||
await Docker.getExecOutput(['context', 'inspect', '--format=json', 'default'], {
|
||||
ignoreReturnCode: true,
|
||||
silent: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
core.info(`Cannot inspect default docker context: ${res.stderr.trim()}`);
|
||||
} else {
|
||||
try {
|
||||
const contextInfo = (<Array<ContextInfo>>JSON.parse(res.stdout.trim()))[0];
|
||||
core.info(JSON.stringify(JSON.parse(res.stdout.trim()), undefined, 2));
|
||||
const hasTLSData = Object.keys(contextInfo.Endpoints).length > 0 && Object.values(contextInfo.Endpoints)[0].TLSData !== undefined;
|
||||
const hasTLSMaterial = Object.keys(contextInfo.TLSMaterial).length > 0 && Object.values(contextInfo.TLSMaterial)[0].length > 0;
|
||||
defaultContextWithTLS = hasTLSData || hasTLSMaterial;
|
||||
} catch (e) {
|
||||
core.info(`Unable to parse default docker context info: ${e}`);
|
||||
core.info(res.stdout.trim());
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
if (defaultContextWithTLS) {
|
||||
const tmpDockerContext = `buildx-${crypto.randomUUID()}`;
|
||||
await core.group(`Creating temp docker context (TLS data loaded in default one)`, async () => {
|
||||
await Docker.getExecOutput(['context', 'create', tmpDockerContext], {
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
core.warning(`Cannot create docker context ${tmpDockerContext}: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
||||
} else {
|
||||
core.info(`Setting builder endpoint to ${tmpDockerContext} context`);
|
||||
inputs.endpoint = tmpDockerContext;
|
||||
stateHelper.setTmpDockerContext(tmpDockerContext);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (inputs.driver !== 'docker') {
|
||||
await core.group(`Creating a new builder instance`, async () => {
|
||||
if (await toolkit.builder.exists(inputs.name)) {
|
||||
core.info(`Builder ${inputs.name} already exists, skipping creation`);
|
||||
} else {
|
||||
const certsDriverOpts = Buildx.resolveCertsDriverOpts(inputs.driver, inputs.endpoint, {
|
||||
cacert: process.env[`${context.builderNodeEnvPrefix}_0_AUTH_TLS_CACERT`],
|
||||
cert: process.env[`${context.builderNodeEnvPrefix}_0_AUTH_TLS_CERT`],
|
||||
key: process.env[`${context.builderNodeEnvPrefix}_0_AUTH_TLS_KEY`]
|
||||
});
|
||||
if (certsDriverOpts.length > 0) {
|
||||
inputs.driverOpts = [...inputs.driverOpts, ...certsDriverOpts];
|
||||
}
|
||||
const createCmd = await toolkit.buildx.getCommand(await context.getCreateArgs(inputs, toolkit));
|
||||
await Exec.getExecOutput(createCmd.command, createCmd.args, {
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (inputs.append) {
|
||||
await core.group(`Appending node(s) to builder`, async () => {
|
||||
let nodeIndex = 1;
|
||||
const nodes = yaml.load(inputs.append) as Node[];
|
||||
for (const node of nodes) {
|
||||
const certsDriverOpts = Buildx.resolveCertsDriverOpts(inputs.driver, `${node.endpoint}`, {
|
||||
cacert: process.env[`${context.builderNodeEnvPrefix}_${nodeIndex}_AUTH_TLS_CACERT`],
|
||||
cert: process.env[`${context.builderNodeEnvPrefix}_${nodeIndex}_AUTH_TLS_CERT`],
|
||||
key: process.env[`${context.builderNodeEnvPrefix}_${nodeIndex}_AUTH_TLS_KEY`]
|
||||
});
|
||||
if (certsDriverOpts.length > 0) {
|
||||
node['driver-opts'] = [...(node['driver-opts'] || []), ...certsDriverOpts];
|
||||
}
|
||||
const appendCmd = await toolkit.buildx.getCommand(await context.getAppendArgs(inputs, node, toolkit));
|
||||
await Exec.getExecOutput(appendCmd.command, appendCmd.args, {
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(`Failed to append node ${node.name}: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
||||
}
|
||||
});
|
||||
nodeIndex++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
await core.group(`Booting builder`, async () => {
|
||||
const inspectCmd = await toolkit.buildx.getCommand(await context.getInspectArgs(inputs, toolkit));
|
||||
await Exec.getExecOutput(inspectCmd.command, inspectCmd.args, {
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (inputs.install) {
|
||||
if (standalone) {
|
||||
throw new Error(`Cannot set buildx as default builder without the Docker CLI`);
|
||||
}
|
||||
await core.group(`Setting buildx as default builder`, async () => {
|
||||
stateHelper.setBuildxIsDefaultBuilder(true);
|
||||
const installCmd = await toolkit.buildx.getCommand(['install']);
|
||||
await Exec.getExecOutput(installCmd.command, installCmd.args, {
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
throw new Error(res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const builderInspect = await toolkit.builder.inspect(inputs.name);
|
||||
const firstNode = builderInspect.nodes[0];
|
||||
|
||||
await core.group(`Inspect builder`, async () => {
|
||||
const reducedPlatforms: Array<string> = [];
|
||||
for (const node of builderInspect.nodes) {
|
||||
for (const platform of node.platforms?.split(',') || []) {
|
||||
if (reducedPlatforms.indexOf(platform) > -1) {
|
||||
continue;
|
||||
}
|
||||
reducedPlatforms.push(platform);
|
||||
}
|
||||
}
|
||||
core.info(JSON.stringify(builderInspect, undefined, 2));
|
||||
core.setOutput('driver', builderInspect.driver);
|
||||
core.setOutput('platforms', reducedPlatforms.join(','));
|
||||
core.setOutput('nodes', JSON.stringify(builderInspect.nodes, undefined, 2));
|
||||
core.setOutput('endpoint', firstNode.endpoint); // TODO: deprecated, to be removed in a later version
|
||||
core.setOutput('status', firstNode.status); // TODO: deprecated, to be removed in a later version
|
||||
core.setOutput('flags', firstNode['buildkitd-flags']); // TODO: deprecated, to be removed in a later version
|
||||
});
|
||||
|
||||
if (!standalone && builderInspect.driver == 'docker-container') {
|
||||
stateHelper.setContainerName(`${Buildx.containerNamePrefix}${firstNode.name}`);
|
||||
await core.group(`BuildKit version`, async () => {
|
||||
for (const node of builderInspect.nodes) {
|
||||
const buildkitVersion = await toolkit.buildkit.getVersion(node);
|
||||
core.info(`${node.name}: ${buildkitVersion}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (core.isDebug() || firstNode['buildkitd-flags']?.includes('--debug')) {
|
||||
stateHelper.setDebug('true');
|
||||
}
|
||||
},
|
||||
// post
|
||||
async () => {
|
||||
if (stateHelper.IsDebug && stateHelper.containerName.length > 0) {
|
||||
await core.group(`BuildKit container logs`, async () => {
|
||||
await Docker.getExecOutput(['logs', `${stateHelper.containerName}`], {
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
core.warning(res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (!stateHelper.cleanup) {
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
if (os.platform() !== 'linux') {
|
||||
core.setFailed('Only supported on linux platform');
|
||||
return;
|
||||
}
|
||||
|
||||
if (stateHelper.builderDriver != 'docker' && stateHelper.builderName.length > 0) {
|
||||
await core.group(`Removing builder`, async () => {
|
||||
const buildx = new Buildx({standalone: stateHelper.standalone});
|
||||
const builder = new Builder({buildx: buildx});
|
||||
if (await builder.exists(stateHelper.builderName)) {
|
||||
const rmCmd = await buildx.getCommand(['rm', stateHelper.builderName, ...(stateHelper.keepState ? ['--keep-state'] : [])]);
|
||||
await Exec.getExecOutput(rmCmd.command, rmCmd.args, {
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
core.warning(res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
core.info(`${stateHelper.builderName} does not exist`);
|
||||
const inputs: context.Inputs = await context.getInputs();
|
||||
const dockerConfigHome: string = process.env.DOCKER_CONFIG || path.join(os.homedir(), '.docker');
|
||||
|
||||
if (!(await buildx.isAvailable()) || inputs.version) {
|
||||
core.startGroup(`👉 Installing Buildx`);
|
||||
await buildx.install(inputs.version || 'latest', dockerConfigHome);
|
||||
core.endGroup();
|
||||
}
|
||||
|
||||
const buildxVersion = await buildx.getVersion();
|
||||
core.info(`📣 Buildx version: ${buildxVersion}`);
|
||||
|
||||
const builderName: string =
|
||||
inputs.driver == 'docker' ? 'default' : `builder-${process.env.GITHUB_JOB}-${(await buildx.countBuilders()) + 1}`;
|
||||
core.setOutput('name', builderName);
|
||||
stateHelper.setBuilderName(builderName);
|
||||
|
||||
if (inputs.driver !== 'docker') {
|
||||
core.startGroup(`🔨 Creating a new builder instance`);
|
||||
let createArgs: Array<string> = ['buildx', 'create', '--name', builderName, '--driver', inputs.driver];
|
||||
if (semver.satisfies(buildxVersion, '>=0.3.0')) {
|
||||
await context.asyncForEach(inputs.driverOpts, async driverOpt => {
|
||||
createArgs.push('--driver-opt', driverOpt);
|
||||
});
|
||||
if (inputs.buildkitdFlags) {
|
||||
createArgs.push('--buildkitd-flags', inputs.buildkitdFlags);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (inputs.use) {
|
||||
createArgs.push('--use');
|
||||
}
|
||||
if (inputs.endpoint) {
|
||||
createArgs.push(inputs.endpoint);
|
||||
}
|
||||
await exec.exec('docker', createArgs);
|
||||
core.endGroup();
|
||||
|
||||
core.startGroup(`🏃 Booting builder`);
|
||||
await exec.exec('docker', ['buildx', 'inspect', '--bootstrap']);
|
||||
core.endGroup();
|
||||
}
|
||||
|
||||
if (stateHelper.tmpDockerContext) {
|
||||
await core.group(`Removing temp docker context`, async () => {
|
||||
await Exec.getExecOutput('docker', ['context', 'rm', '-f', stateHelper.tmpDockerContext], {
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
core.warning(`${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (inputs.install) {
|
||||
core.startGroup(`🤝 Setting buildx as default builder`);
|
||||
await exec.exec('docker', ['buildx', 'install']);
|
||||
core.endGroup();
|
||||
}
|
||||
|
||||
if (stateHelper.certsDir.length > 0 && fs.existsSync(stateHelper.certsDir)) {
|
||||
await core.group(`Cleaning up certificates`, async () => {
|
||||
fs.rmSync(stateHelper.certsDir, {recursive: true});
|
||||
});
|
||||
}
|
||||
|
||||
if (stateHelper.buildxIsDefaultBuilder) {
|
||||
await core.group(`Restoring default builder`, async () => {
|
||||
await Exec.getExecOutput('docker', ['buildx', 'uninstall'], {
|
||||
ignoreReturnCode: true
|
||||
}).then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
core.warning(`${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
core.startGroup(`🛒 Extracting available platforms`);
|
||||
const platforms = await buildx.platforms();
|
||||
core.info(`${platforms}`);
|
||||
core.setOutput('platforms', platforms);
|
||||
core.endGroup();
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async function cleanup(): Promise<void> {
|
||||
if (stateHelper.builderName.length == 0) {
|
||||
return;
|
||||
}
|
||||
await mexec.exec('docker', ['buildx', 'rm', `${stateHelper.builderName}`], false).then(res => {
|
||||
if (res.stderr != '' && !res.success) {
|
||||
core.warning(res.stderr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!stateHelper.IsPost) {
|
||||
run();
|
||||
} else {
|
||||
cleanup();
|
||||
}
|
||||
|
|
|
@ -1,52 +1,12 @@
|
|||
import * as core from '@actions/core';
|
||||
|
||||
export const IsDebug = !!process.env['STATE_isDebug'];
|
||||
export const standalone = /true/i.test(process.env['STATE_standalone'] || '');
|
||||
export const IsPost = !!process.env['STATE_isPost'];
|
||||
export const builderName = process.env['STATE_builderName'] || '';
|
||||
export const builderDriver = process.env['STATE_builderDriver'] || '';
|
||||
export const containerName = process.env['STATE_containerName'] || '';
|
||||
export const certsDir = process.env['STATE_certsDir'] || '';
|
||||
export const tmpDockerContext = process.env['STATE_tmpDockerContext'] || '';
|
||||
export const cleanup = /true/i.test(process.env['STATE_cleanup'] || '');
|
||||
export const buildxIsDefaultBuilder = /true/i.test(process.env['STATE_buildxIsDefaultBuilder'] || '');
|
||||
export const keepState = /true/i.test(process.env['STATE_keepState'] || '');
|
||||
|
||||
export function setDebug(debug: string) {
|
||||
core.saveState('isDebug', debug);
|
||||
}
|
||||
|
||||
export function setStandalone(standalone: boolean) {
|
||||
core.saveState('standalone', standalone);
|
||||
}
|
||||
|
||||
export function setBuilderName(builderName: string) {
|
||||
core.saveState('builderName', builderName);
|
||||
}
|
||||
|
||||
export function setBuilderDriver(builderDriver: string) {
|
||||
core.saveState('builderDriver', builderDriver);
|
||||
}
|
||||
|
||||
export function setContainerName(containerName: string) {
|
||||
core.saveState('containerName', containerName);
|
||||
}
|
||||
|
||||
export function setCertsDir(certsDir: string) {
|
||||
core.saveState('certsDir', certsDir);
|
||||
}
|
||||
|
||||
export function setTmpDockerContext(tmpDockerContext: string) {
|
||||
core.saveState('tmpDockerContext', tmpDockerContext);
|
||||
}
|
||||
|
||||
export function setCleanup(cleanup: boolean) {
|
||||
core.saveState('cleanup', cleanup);
|
||||
}
|
||||
|
||||
export function setBuildxIsDefaultBuilder(buildxIsDefaultBuilder: boolean) {
|
||||
core.saveState('buildxIsDefaultBuilder', buildxIsDefaultBuilder);
|
||||
}
|
||||
|
||||
export function setKeepState(keepState: boolean) {
|
||||
core.saveState('keepState', keepState);
|
||||
if (!IsPost) {
|
||||
core.saveState('isPost', 'true');
|
||||
}
|
||||
|
|
|
@ -1,21 +1,18 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"strict": true,
|
||||
"lib": [
|
||||
"es6",
|
||||
"dom"
|
||||
],
|
||||
"newLine": "lf",
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"resolveJsonModule": true,
|
||||
"useUnknownInCatchVariables": false,
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
"exclude": [
|
||||
"./__tests__/**/*",
|
||||
"./lib/**/*",
|
||||
"node_modules",
|
||||
"jest.config.ts"
|
||||
]
|
||||
"exclude": ["node_modules", "**/*.test.ts"]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue