mirror of
https://github.com/docker/setup-buildx-action.git
synced 2025-04-22 10:19:30 +02:00
Compare commits
No commits in common. "master" and "v2.3.0" have entirely different histories.
@ -1,12 +1,2 @@
|
|||||||
/coverage
|
/coverage
|
||||||
|
/node_modules
|
||||||
# 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,12 +1,11 @@
|
|||||||
{
|
{
|
||||||
"env": {
|
"env": {
|
||||||
"node": true,
|
"node": true,
|
||||||
"es6": true,
|
"es2021": true,
|
||||||
"jest": true
|
"jest/globals": true
|
||||||
},
|
},
|
||||||
"extends": [
|
"extends": [
|
||||||
"eslint:recommended",
|
"eslint:recommended",
|
||||||
"plugin:@typescript-eslint/eslint-recommended",
|
|
||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:@typescript-eslint/recommended",
|
||||||
"plugin:jest/recommended",
|
"plugin:jest/recommended",
|
||||||
"plugin:prettier/recommended"
|
"plugin:prettier/recommended"
|
||||||
|
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -1,4 +1,2 @@
|
|||||||
/.yarn/releases/** binary
|
|
||||||
/.yarn/plugins/** binary
|
|
||||||
/dist/** linguist-generated=true
|
/dist/** linguist-generated=true
|
||||||
/lib/** linguist-generated=true
|
/lib/** linguist-generated=true
|
||||||
|
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
* @crazy-max
|
3
.github/CODE_OF_CONDUCT.md
vendored
3
.github/CODE_OF_CONDUCT.md
vendored
@ -1,3 +0,0 @@
|
|||||||
# Code of conduct
|
|
||||||
|
|
||||||
- [Moby community guidelines](https://github.com/moby/moby/blob/master/CONTRIBUTING.md#moby-community-guidelines)
|
|
101
.github/ISSUE_TEMPLATE/bug.yml
vendored
101
.github/ISSUE_TEMPLATE/bug.yml
vendored
@ -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.
|
|
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
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://docs.github.com/en/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs)
|
||||||
|
> and [attach it](https://docs.github.com/en/github/managing-your-work-on-github/file-attachments-on-issues-and-pull-requests) to this issue.
|
9
.github/ISSUE_TEMPLATE/config.yml
vendored
9
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -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.
|
|
15
.github/ISSUE_TEMPLATE/feature.yml
vendored
15
.github/ISSUE_TEMPLATE/feature.yml
vendored
@ -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
|
|
12
.github/SECURITY.md
vendored
12
.github/SECURITY.md
vendored
@ -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.
|
|
31
.github/SUPPORT.md
vendored
Normal file
31
.github/SUPPORT.md
vendored
Normal file
@ -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.
|
1
.github/dependabot.yml
vendored
1
.github/dependabot.yml
vendored
@ -11,7 +11,6 @@ updates:
|
|||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
versioning-strategy: "increase"
|
|
||||||
allow:
|
allow:
|
||||||
- dependency-type: "production"
|
- dependency-type: "production"
|
||||||
labels:
|
labels:
|
||||||
|
BIN
.github/setup-buildx-action.png
vendored
BIN
.github/setup-buildx-action.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 11 KiB |
211
.github/workflows/ci.yml
vendored
211
.github/workflows/ci.yml
vendored
@ -1,13 +1,8 @@
|
|||||||
name: ci
|
name: ci
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 10 * * *'
|
- cron: '0 10 * * *' # everyday at 10am
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'master'
|
- 'master'
|
||||||
@ -15,6 +10,9 @@ on:
|
|||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- 'v*'
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
- 'releases/v*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
main:
|
main:
|
||||||
@ -23,16 +21,13 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
buildx-version:
|
buildx-version:
|
||||||
|
- latest
|
||||||
|
- v0.4.1
|
||||||
- ""
|
- ""
|
||||||
- "latest"
|
|
||||||
- "v0.4.1"
|
|
||||||
- "cloud:latest"
|
|
||||||
- "cloud:v0.11.2-desktop.2"
|
|
||||||
- "lab:latest"
|
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
id: buildx
|
id: buildx
|
||||||
@ -51,7 +46,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx 1
|
name: Set up Docker Buildx 1
|
||||||
uses: ./
|
uses: ./
|
||||||
@ -64,11 +59,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Stop docker
|
name: Stop docker
|
||||||
run: |
|
run: |
|
||||||
sudo systemctl stop docker docker.socket
|
sudo systemctl stop docker
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
id: buildx
|
id: buildx
|
||||||
@ -85,14 +80,14 @@ jobs:
|
|||||||
-
|
-
|
||||||
name: Dump context
|
name: Dump context
|
||||||
if: always()
|
if: always()
|
||||||
uses: crazy-max/ghaction-dump-context@v2
|
uses: crazy-max/ghaction-dump-context@v1
|
||||||
|
|
||||||
debug:
|
debug:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Create Dockerfile
|
name: Create Dockerfile
|
||||||
run: |
|
run: |
|
||||||
@ -102,7 +97,7 @@ jobs:
|
|||||||
EOL
|
EOL
|
||||||
-
|
-
|
||||||
name: Set up QEMU
|
name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v2
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: ./
|
uses: ./
|
||||||
@ -110,7 +105,7 @@ jobs:
|
|||||||
buildkitd-flags: --debug
|
buildkitd-flags: --debug
|
||||||
-
|
-
|
||||||
name: Build
|
name: Build
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64,linux/ppc64le
|
platforms: linux/amd64,linux/arm64,linux/ppc64le
|
||||||
@ -120,7 +115,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: ./
|
uses: ./
|
||||||
@ -142,7 +137,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: ./
|
uses: ./
|
||||||
@ -165,7 +160,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: ./
|
uses: ./
|
||||||
@ -178,7 +173,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: ./
|
uses: ./
|
||||||
@ -211,7 +206,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Create context
|
name: Create context
|
||||||
run: |
|
run: |
|
||||||
@ -233,7 +228,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Create buildkitd conf
|
name: Create buildkitd conf
|
||||||
run: |
|
run: |
|
||||||
@ -253,10 +248,10 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
buildkitd-flags: --debug
|
buildkitd-flags: --debug
|
||||||
buildkitd-config: /tmp/buildkitd.toml
|
config: /tmp/buildkitd.toml
|
||||||
-
|
-
|
||||||
name: Build
|
name: Build
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
|
||||||
@ -265,7 +260,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Create Dockerfile
|
name: Create Dockerfile
|
||||||
run: |
|
run: |
|
||||||
@ -277,13 +272,13 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
buildkitd-flags: --debug
|
buildkitd-flags: --debug
|
||||||
buildkitd-config-inline: |
|
config-inline: |
|
||||||
debug = true
|
debug = true
|
||||||
[registry."docker.io"]
|
[registry."docker.io"]
|
||||||
mirrors = ["mirror.gcr.io"]
|
mirrors = ["mirror.gcr.io"]
|
||||||
-
|
-
|
||||||
name: Build
|
name: Build
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
|
||||||
@ -293,7 +288,8 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
buildx-version:
|
buildx-version:
|
||||||
- v0.9.1
|
- latest
|
||||||
|
- v0.4.1
|
||||||
- ""
|
- ""
|
||||||
qemu-platforms:
|
qemu-platforms:
|
||||||
- all
|
- all
|
||||||
@ -301,10 +297,10 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Set up QEMU
|
name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v2
|
||||||
with:
|
with:
|
||||||
platforms: ${{ matrix.qemu-platforms }}
|
platforms: ${{ matrix.qemu-platforms }}
|
||||||
-
|
-
|
||||||
@ -330,7 +326,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: ./
|
uses: ./
|
||||||
@ -353,15 +349,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Uninstall docker cli
|
name: Uninstall docker cli
|
||||||
run: |
|
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
|
sudo apt-get purge -y moby-cli moby-buildx
|
||||||
fi
|
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: ./
|
uses: ./
|
||||||
@ -381,15 +373,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Uninstall docker cli
|
name: Uninstall docker cli
|
||||||
run: |
|
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
|
sudo apt-get purge -y moby-cli moby-buildx
|
||||||
fi
|
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: ./
|
uses: ./
|
||||||
@ -412,15 +400,11 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Uninstall docker cli
|
name: Uninstall docker cli
|
||||||
run: |
|
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
|
sudo apt-get purge -y moby-cli moby-buildx
|
||||||
fi
|
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
id: buildx
|
id: buildx
|
||||||
@ -442,7 +426,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Create dummy contexts
|
name: Create dummy contexts
|
||||||
run: |
|
run: |
|
||||||
@ -471,135 +455,12 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
name: Set up QEMU
|
name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v2
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
|
|
||||||
docker-context:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
-
|
|
||||||
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@v4
|
|
||||||
-
|
|
||||||
name: Set up Docker Buildx
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
cleanup: ${{ matrix.cleanup }}
|
|
||||||
|
|
||||||
k3s:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
version:
|
|
||||||
- v0.11.0
|
|
||||||
- v0.10.5
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
-
|
|
||||||
name: Install k3s
|
|
||||||
uses: crazy-max/.github/.github/actions/install-k3s@f5cb4a109b7a3b466a2ac293ef4bb13f1571acd7
|
|
||||||
-
|
|
||||||
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@v4
|
|
||||||
-
|
|
||||||
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@v4
|
|
||||||
-
|
|
||||||
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
|
|
||||||
|
21
.github/workflows/publish.yml
vendored
21
.github/workflows/publish.yml
vendored
@ -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@v4
|
|
||||||
-
|
|
||||||
name: Publish
|
|
||||||
uses: actions/publish-immutable-action@v0.0.4
|
|
23
.github/workflows/test.yml
vendored
23
.github/workflows/test.yml
vendored
@ -1,15 +1,14 @@
|
|||||||
name: test
|
name: test
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'master'
|
- 'master'
|
||||||
- 'releases/v*'
|
- 'releases/v*'
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
- 'releases/v*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
@ -17,18 +16,24 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Validate
|
||||||
|
uses: docker/bake-action@v2
|
||||||
|
with:
|
||||||
|
targets: validate
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: ./
|
uses: ./
|
||||||
-
|
-
|
||||||
name: Test
|
name: Test
|
||||||
uses: docker/bake-action@v6
|
uses: docker/bake-action@v2
|
||||||
with:
|
with:
|
||||||
targets: test
|
targets: test
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
-
|
-
|
||||||
name: Upload coverage
|
name: Upload coverage
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v3
|
||||||
with:
|
with:
|
||||||
files: ./coverage/clover.xml
|
file: ./coverage/clover.xml
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
43
.github/workflows/validate.yml
vendored
43
.github/workflows/validate.yml
vendored
@ -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@v4
|
|
||||||
-
|
|
||||||
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 }}
|
|
71
.gitignore
vendored
71
.gitignore
vendored
@ -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
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
@ -7,7 +14,6 @@ npm-debug.log*
|
|||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
lerna-debug.log*
|
lerna-debug.log*
|
||||||
.pnpm-debug.log*
|
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
@ -18,14 +24,34 @@ pids
|
|||||||
*.seed
|
*.seed
|
||||||
*.pid.lock
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
# Coverage directory used by tools like istanbul
|
||||||
coverage
|
coverage
|
||||||
*.lcov
|
*.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
|
# Dependency directories
|
||||||
node_modules/
|
|
||||||
jspm_packages/
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
# TypeScript cache
|
# TypeScript cache
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
|
|
||||||
@ -35,19 +61,36 @@ jspm_packages/
|
|||||||
# Optional eslint cache
|
# Optional eslint cache
|
||||||
.eslintcache
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
# Yarn Integrity file
|
# Yarn Integrity file
|
||||||
.yarn-integrity
|
.yarn-integrity
|
||||||
|
|
||||||
# dotenv environment variable files
|
# dotenv environment variables file
|
||||||
.env
|
.env
|
||||||
.env.development.local
|
.env.test
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
.env.local
|
|
||||||
|
|
||||||
# yarn v2
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
.yarn/cache
|
.cache
|
||||||
.yarn/unplugged
|
|
||||||
.yarn/build-state.yml
|
# next.js build output
|
||||||
.yarn/install-state.gz
|
.next
|
||||||
.pnp.*
|
|
||||||
|
# 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/
|
|
541
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
541
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
File diff suppressed because one or more lines are too long
13
.yarnrc.yml
13
.yarnrc.yml
@ -1,13 +0,0 @@
|
|||||||
logFilters:
|
|
||||||
- code: YN0013
|
|
||||||
level: discard
|
|
||||||
- code: YN0019
|
|
||||||
level: discard
|
|
||||||
- code: YN0076
|
|
||||||
level: discard
|
|
||||||
|
|
||||||
nodeLinker: node-modules
|
|
||||||
|
|
||||||
plugins:
|
|
||||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
|
||||||
spec: "@yarnpkg/plugin-interactive-tools"
|
|
127
README.md
127
README.md
@ -20,12 +20,15 @@ ___
|
|||||||
|
|
||||||
* [Usage](#usage)
|
* [Usage](#usage)
|
||||||
* [Configuring your builder](#configuring-your-builder)
|
* [Configuring your builder](#configuring-your-builder)
|
||||||
|
* [Version pinning](#version-pinning)
|
||||||
* [Customizing](#customizing)
|
* [Customizing](#customizing)
|
||||||
* [inputs](#inputs)
|
* [inputs](#inputs)
|
||||||
* [outputs](#outputs)
|
* [outputs](#outputs)
|
||||||
* [environment variables](#environment-variables)
|
* [environment variables](#environment-variables)
|
||||||
* [Notes](#notes)
|
* [Notes](#notes)
|
||||||
* [`nodes` output](#nodes-output)
|
* [`nodes` output](#nodes-output)
|
||||||
|
* [BuildKit container logs](#buildkit-container-logs)
|
||||||
|
* [Using on GHES](#using-on-ghes)
|
||||||
* [Contributing](#contributing)
|
* [Contributing](#contributing)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@ -42,36 +45,53 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v3
|
||||||
-
|
-
|
||||||
# Add support for more platforms with QEMU (optional)
|
# Add support for more platforms with QEMU (optional)
|
||||||
# https://github.com/docker/setup-qemu-action
|
# https://github.com/docker/setup-qemu-action
|
||||||
name: Set up QEMU
|
name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v2
|
||||||
-
|
-
|
||||||
name: Set up Docker Buildx
|
name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v2
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuring your builder
|
## Configuring your builder
|
||||||
|
|
||||||
* [Version pinning](https://docs.docker.com/build/ci/github-actions/configure-builder/#version-pinning): Pin to a specific Buildx or BuildKit version
|
See https://docs.docker.com/build/ci/github-actions/configure-builder/
|
||||||
* [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)
|
## Version pinning
|
||||||
* [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
|
This action builds images using [Buildx](https://github.com/docker/buildx) and
|
||||||
* [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
|
[BuildKit](https://github.com/moby/buildkit). By default, the action will
|
||||||
* [Authentication for remote builders](https://docs.docker.com/build/ci/github-actions/configure-builder/#authentication-for-remote-builders)
|
attempt to use the latest version of Buildx available on the GitHub Runner
|
||||||
* [SSH authentication](https://docs.docker.com/build/ci/github-actions/configure-builder/#ssh-authentication): Authenticate to a remote builder using SSH
|
(the build client) and the latest release of BuildKit (the build server).
|
||||||
* [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)
|
To pin to a specific version of Buildx, use the `version` input. For example,
|
||||||
* [Isolated builders](https://docs.docker.com/build/ci/github-actions/configure-builder/#isolated-builders): Create isolated builders for your builds
|
to pin to Buildx v0.10.0:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
version: v0.10.0
|
||||||
|
```
|
||||||
|
|
||||||
|
To pin to a specific version of BuildKit, use the `image` option in the
|
||||||
|
`driver-opts` input. For example, to pin to BuildKit v0.11.0:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
driver-opts: image=moby/buildkit:v0.11.0
|
||||||
|
```
|
||||||
|
|
||||||
## Customizing
|
## Customizing
|
||||||
|
|
||||||
### inputs
|
### 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
|
> `List` type is a newline-delimited string
|
||||||
> ```yaml
|
> ```yaml
|
||||||
@ -80,44 +100,36 @@ The following inputs can be used as `step.with` keys:
|
|||||||
> network=host
|
> network=host
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
> `CSV` type must be a comma-delimited string
|
> `CSV` type must be a newline-delimited string
|
||||||
> ```yaml
|
> ```yaml
|
||||||
> platforms: linux/amd64,linux/arm64
|
> platforms: linux/amd64,linux/arm64
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Description |
|
||||||
|------------------------------|----------|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|-------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `version` | String | | [Buildx](https://github.com/docker/buildx) version. (eg. `v0.3.0`, `latest`, `https://github.com/docker/buildx.git#master`) |
|
| `version` | String | [Buildx](https://github.com/docker/buildx) version. (eg. `v0.3.0`, `latest`, `https://github.com/docker/buildx.git#master`) |
|
||||||
| `driver` | String | `docker-container` | Sets the [builder driver](https://docs.docker.com/engine/reference/commandline/buildx_create/#driver) to be used |
|
| `driver` | String | Sets the [builder driver](https://docs.docker.com/engine/reference/commandline/buildx_create/#driver) to be used (default `docker-container`) |
|
||||||
| `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`) |
|
| `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-flags` | String | [Flags for buildkitd](https://docs.docker.com/engine/reference/commandline/buildx_create/#buildkitd-flags) daemon (since [buildx v0.3.0](https://github.com/docker/buildx/releases/tag/v0.3.0)) |
|
||||||
| `buildkitd-config` \* | String | | [BuildKit daemon config file](https://docs.docker.com/engine/reference/commandline/buildx_create/#config) |
|
| `install` | Bool | Sets up `docker build` command as an alias to `docker buildx` (default `false`) |
|
||||||
| `buildkitd-config-inline` \* | String | | Same as `buildkitd-config` but inline |
|
| `use` | Bool | Switch to this builder instance (default `true`) |
|
||||||
| `install` | Bool | `false` | Sets up `docker build` command as an alias to `docker buildx` |
|
| `endpoint` | String | [Optional address for docker socket](https://docs.docker.com/engine/reference/commandline/buildx_create/#description) or context from `docker context ls` |
|
||||||
| `use` | Bool | `true` | Switch to this builder instance |
|
| `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. |
|
||||||
| `endpoint` | String | | [Optional address for docker socket](https://docs.docker.com/engine/reference/commandline/buildx_create/#description) or context from `docker context ls` |
|
| `config`¹ | String | [BuildKit config file](https://docs.docker.com/engine/reference/commandline/buildx_create/#config) |
|
||||||
| `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. |
|
| `config-inline`¹ | String | Same as `config` but inline |
|
||||||
| `append` | YAML | | [Append additional nodes](https://docs.docker.com/build/ci/github-actions/configure-builder/#append-additional-nodes-to-the-builder) to the builder |
|
| `append` | YAML | [Append additional nodes](docs/advanced/append-nodes.md) to the builder |
|
||||||
| `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]
|
> * ¹ `config` and `config-inline` are mutually exclusive
|
||||||
> 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
|
### outputs
|
||||||
|
|
||||||
The following outputs are available:
|
Following outputs are available
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
|-------------|--------|-----------------------------------------------------|
|
|-------------|--------|-------------------------------------------------|
|
||||||
| `name` | String | Builder name |
|
| `name` | String | Builder name |
|
||||||
| `driver` | String | Builder driver |
|
| `driver` | String | Builder driver |
|
||||||
| `platforms` | String | Builder node platforms (preferred and/or available) |
|
| `platforms` | String | Builder node platforms (preferred or available) |
|
||||||
| `nodes` | JSON | Builder [nodes metadata](#nodes-output) |
|
| `nodes` | JSON | Builder [nodes metadata](#nodes-output) |
|
||||||
|
|
||||||
### environment variables
|
### environment variables
|
||||||
@ -159,6 +171,39 @@ The following [official docker environment variables](https://docs.docker.com/en
|
|||||||
| `buildkit` | String | BuildKit version |
|
| `buildkit` | String | BuildKit version |
|
||||||
| `platforms` | String | Platforms available |
|
| `platforms` | String | Platforms available |
|
||||||
|
|
||||||
|
### BuildKit container logs
|
||||||
|
|
||||||
|
See https://docs.docker.com/build/ci/github-actions/configure-builder/#buildkit-container-logs
|
||||||
|
|
||||||
|
## Using on GHES
|
||||||
|
|
||||||
|
GitHub Runners come [pre-installed with Docker Buildx](https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2204-Readme.md)
|
||||||
|
following your virtual environment. If you specify a version or `latest` of
|
||||||
|
Docker Buildx in your workflow, the version will be downloaded from [GitHub Releases in `docker/buildx`](https://github.com/docker/buildx/releases)
|
||||||
|
repository. These calls to `docker/buildx` are made via unauthenticated requests,
|
||||||
|
which are limited to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting).
|
||||||
|
|
||||||
|
If more requests are made within the time frame, then you will start to see
|
||||||
|
rate-limit errors during downloading that looks like:
|
||||||
|
|
||||||
|
```
|
||||||
|
##[error]API rate limit exceeded for...
|
||||||
|
```
|
||||||
|
|
||||||
|
To get a higher rate limit, you can [generate a personal access token on github.com](https://github.com/settings/tokens/new)
|
||||||
|
and pass it as the `github_token` input for the action:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GH_DOTCOM_TOKEN }}
|
||||||
|
version: v0.10.1
|
||||||
|
```
|
||||||
|
|
||||||
|
If the runner is not able to access `github.com`, it will take the default one
|
||||||
|
available on the GitHub Runner or runner's tool cache. See "[Setting up the tool cache on self-hosted runners without internet access](https://docs.github.com/en/enterprise-server@3.2/admin/github-actions/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access)"
|
||||||
|
for more information.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Want to contribute? Awesome! You can find information about contributing to
|
Want to contribute? Awesome! You can find information about contributing to
|
||||||
|
88
__tests__/auth.test.ts
Normal file
88
__tests__/auth.test.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import {describe, expect, test, beforeEach} from '@jest/globals';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as os from 'os';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as auth from '../src/auth';
|
||||||
|
|
||||||
|
const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-setup-buildx-jest')).split(path.sep).join(path.posix.sep);
|
||||||
|
const dockerConfigHome = path.join(tmpdir, '.docker');
|
||||||
|
const credsdir = path.join(dockerConfigHome, 'buildx', 'creds');
|
||||||
|
|
||||||
|
describe('setCredentials', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
process.env = Object.keys(process.env).reduce((object, key) => {
|
||||||
|
if (!key.startsWith(auth.envPrefix)) {
|
||||||
|
object[key] = process.env[key];
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}, {});
|
||||||
|
});
|
||||||
|
|
||||||
|
// prettier-ignore
|
||||||
|
test.each([
|
||||||
|
[
|
||||||
|
'mycontext',
|
||||||
|
'docker-container',
|
||||||
|
{},
|
||||||
|
[],
|
||||||
|
[]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'docker-container://mycontainer',
|
||||||
|
'docker-container',
|
||||||
|
{},
|
||||||
|
[],
|
||||||
|
[]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'tcp://graviton2:1234',
|
||||||
|
'remote',
|
||||||
|
{},
|
||||||
|
[],
|
||||||
|
[]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'tcp://graviton2:1234',
|
||||||
|
'remote',
|
||||||
|
{
|
||||||
|
'BUILDER_NODE_0_AUTH_TLS_CACERT': 'foo',
|
||||||
|
'BUILDER_NODE_0_AUTH_TLS_CERT': 'foo',
|
||||||
|
'BUILDER_NODE_0_AUTH_TLS_KEY': 'foo'
|
||||||
|
},
|
||||||
|
[
|
||||||
|
path.join(credsdir, 'cacert_graviton2-1234.pem'),
|
||||||
|
path.join(credsdir, 'cert_graviton2-1234.pem'),
|
||||||
|
path.join(credsdir, 'key_graviton2-1234.pem')
|
||||||
|
],
|
||||||
|
[
|
||||||
|
`cacert=${path.join(credsdir, 'cacert_graviton2-1234.pem')}`,
|
||||||
|
`cert=${path.join(credsdir, 'cert_graviton2-1234.pem')}`,
|
||||||
|
`key=${path.join(credsdir, 'key_graviton2-1234.pem')}`
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'tcp://graviton2:1234',
|
||||||
|
'docker-container',
|
||||||
|
{
|
||||||
|
'BUILDER_NODE_0_AUTH_TLS_CACERT': 'foo',
|
||||||
|
'BUILDER_NODE_0_AUTH_TLS_CERT': 'foo',
|
||||||
|
'BUILDER_NODE_0_AUTH_TLS_KEY': 'foo'
|
||||||
|
},
|
||||||
|
[
|
||||||
|
path.join(credsdir, 'cacert_graviton2-1234.pem'),
|
||||||
|
path.join(credsdir, 'cert_graviton2-1234.pem'),
|
||||||
|
path.join(credsdir, 'key_graviton2-1234.pem')
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
],
|
||||||
|
])('given %p endpoint', async (endpoint: string, driver: string, envs: Record<string, string>, expectedFiles: Array<string>, expectedOpts: Array<string>) => {
|
||||||
|
fs.mkdirSync(credsdir, {recursive: true});
|
||||||
|
for (const [key, value] of Object.entries(envs)) {
|
||||||
|
process.env[key] = value;
|
||||||
|
}
|
||||||
|
expect(auth.setCredentials(credsdir, 0, driver, endpoint)).toEqual(expectedOpts);
|
||||||
|
expectedFiles.forEach( (file) => {
|
||||||
|
expect(fs.existsSync(file)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
261
__tests__/buildx.test.ts
Normal file
261
__tests__/buildx.test.ts
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
import {describe, expect, it, jest, test} from '@jest/globals';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as os from 'os';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as buildx from '../src/buildx';
|
||||||
|
import * as context from '../src/context';
|
||||||
|
import * as semver from 'semver';
|
||||||
|
import * as exec from '@actions/exec';
|
||||||
|
|
||||||
|
const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-setup-buildx-')).split(path.sep).join(path.posix.sep);
|
||||||
|
jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
|
||||||
|
return tmpdir;
|
||||||
|
});
|
||||||
|
|
||||||
|
const tmpname = path.join(tmpdir, '.tmpname').split(path.sep).join(path.posix.sep);
|
||||||
|
jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => {
|
||||||
|
return tmpname;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isAvailable', () => {
|
||||||
|
const execSpy = jest.spyOn(exec, 'getExecOutput');
|
||||||
|
buildx.isAvailable();
|
||||||
|
|
||||||
|
// eslint-disable-next-line jest/no-standalone-expect
|
||||||
|
expect(execSpy).toHaveBeenCalledWith(`docker`, ['buildx'], {
|
||||||
|
silent: true,
|
||||||
|
ignoreReturnCode: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isAvailable standalone', () => {
|
||||||
|
const execSpy = jest.spyOn(exec, 'getExecOutput');
|
||||||
|
buildx.isAvailable(true);
|
||||||
|
|
||||||
|
// eslint-disable-next-line jest/no-standalone-expect
|
||||||
|
expect(execSpy).toHaveBeenCalledWith(`buildx`, [], {
|
||||||
|
silent: true,
|
||||||
|
ignoreReturnCode: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getVersion', () => {
|
||||||
|
it('valid', async () => {
|
||||||
|
const version = await buildx.getVersion();
|
||||||
|
expect(semver.valid(version)).not.toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('parseVersion', () => {
|
||||||
|
test.each([
|
||||||
|
['github.com/docker/buildx 0.4.1+azure bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'],
|
||||||
|
['github.com/docker/buildx v0.4.1 bda4882a65349ca359216b135896bddc1d92461c', '0.4.1'],
|
||||||
|
['github.com/docker/buildx v0.4.2 fb7b670b764764dc4716df3eba07ffdae4cc47b2', '0.4.2'],
|
||||||
|
['github.com/docker/buildx f117971 f11797113e5a9b86bd976329c5dbb8a8bfdfadfa', 'f117971']
|
||||||
|
])('given %p', async (stdout, expected) => {
|
||||||
|
expect(buildx.parseVersion(stdout)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('satisfies', () => {
|
||||||
|
test.each([
|
||||||
|
['0.4.1', '>=0.3.2', true],
|
||||||
|
['bda4882a65349ca359216b135896bddc1d92461c', '>0.1.0', false],
|
||||||
|
['f117971', '>0.6.0', true]
|
||||||
|
])('given %p', async (version, range, expected) => {
|
||||||
|
expect(buildx.satisfies(version, range)).toBe(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('inspect', () => {
|
||||||
|
it('valid', async () => {
|
||||||
|
const builder = await buildx.inspect('');
|
||||||
|
expect(builder).not.toBeUndefined();
|
||||||
|
expect(builder.name).not.toEqual('');
|
||||||
|
expect(builder.driver).not.toEqual('');
|
||||||
|
expect(builder.nodes).not.toEqual({});
|
||||||
|
}, 100000);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('parseInspect', () => {
|
||||||
|
// prettier-ignore
|
||||||
|
test.each([
|
||||||
|
[
|
||||||
|
'inspect1.txt',
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"name": "builder-5cb467f7-0940-47e1-b94b-d51f54054d620",
|
||||||
|
"endpoint": "unix:///var/run/docker.sock",
|
||||||
|
"status": "running",
|
||||||
|
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
|
||||||
|
"buildkit": "v0.10.4",
|
||||||
|
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/arm64,linux/riscv64,linux/386,linux/arm/v7,linux/arm/v6"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "builder-5cb467f7-0940-47e1-b94b-d51f54054d62",
|
||||||
|
"driver": "docker-container"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'inspect2.txt',
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"name": "builder-5f449644-ff29-48af-8344-abb0292d06730",
|
||||||
|
"endpoint": "unix:///var/run/docker.sock",
|
||||||
|
"driver-opts": [
|
||||||
|
"image=moby/buildkit:latest"
|
||||||
|
],
|
||||||
|
"status": "running",
|
||||||
|
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
|
||||||
|
"buildkit": "v0.10.4",
|
||||||
|
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4,linux/386"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "builder-5f449644-ff29-48af-8344-abb0292d0673",
|
||||||
|
"driver": "docker-container"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'inspect3.txt',
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"name": "builder-9929e463-7954-4dc3-89cd-514cca29ff800",
|
||||||
|
"endpoint": "unix:///var/run/docker.sock",
|
||||||
|
"driver-opts": [
|
||||||
|
"image=moby/buildkit:master",
|
||||||
|
"network=host"
|
||||||
|
],
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "builder-9929e463-7954-4dc3-89cd-514cca29ff80",
|
||||||
|
"driver": "docker-container"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'inspect4.txt',
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"name": "default",
|
||||||
|
"endpoint": "default",
|
||||||
|
"status": "running",
|
||||||
|
"buildkit": "20.10.17",
|
||||||
|
"platforms": "linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "default",
|
||||||
|
"driver": "docker"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'inspect5.txt',
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"name": "aws_graviton2",
|
||||||
|
"endpoint": "tcp://1.23.45.67:1234",
|
||||||
|
"driver-opts": [
|
||||||
|
"cert=/home/user/.certs/aws_graviton2/cert.pem",
|
||||||
|
"key=/home/user/.certs/aws_graviton2/key.pem",
|
||||||
|
"cacert=/home/user/.certs/aws_graviton2/ca.pem"
|
||||||
|
],
|
||||||
|
"status": "running",
|
||||||
|
"platforms": "darwin/arm64,linux/arm64,linux/arm/v5,linux/arm/v6,linux/arm/v7,windows/arm64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "remote-builder",
|
||||||
|
"driver": "remote"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'inspect6.txt',
|
||||||
|
{
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"name": "builder-17cfff01-48d9-4c3d-9332-9992e308a5100",
|
||||||
|
"endpoint": "unix:///var/run/docker.sock",
|
||||||
|
"status": "running",
|
||||||
|
"buildkitd-flags": "--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host",
|
||||||
|
"platforms": "linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/386"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "builder-17cfff01-48d9-4c3d-9332-9992e308a510",
|
||||||
|
"driver": "docker-container"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
])('given %p', async (inspectFile, expected) => {
|
||||||
|
expect(await buildx.parseInspect(fs.readFileSync(path.join(__dirname, 'fixtures', inspectFile)).toString())).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('build', () => {
|
||||||
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-buildx-'));
|
||||||
|
|
||||||
|
// eslint-disable-next-line jest/no-disabled-tests
|
||||||
|
it.skip('builds refs/pull/648/head', async () => {
|
||||||
|
const buildxBin = await buildx.build('https://github.com/docker/buildx.git#refs/pull/648/head', tmpDir, false);
|
||||||
|
expect(fs.existsSync(buildxBin)).toBe(true);
|
||||||
|
}, 100000);
|
||||||
|
|
||||||
|
// eslint-disable-next-line jest/no-disabled-tests
|
||||||
|
it.skip('builds 67bd6f4dc82a9cd96f34133dab3f6f7af803bb14', async () => {
|
||||||
|
const buildxBin = await buildx.build('https://github.com/docker/buildx.git#67bd6f4dc82a9cd96f34133dab3f6f7af803bb14', tmpDir, false);
|
||||||
|
expect(fs.existsSync(buildxBin)).toBe(true);
|
||||||
|
}, 100000);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('install', () => {
|
||||||
|
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-buildx-'));
|
||||||
|
test.each([
|
||||||
|
['v0.4.1', false],
|
||||||
|
['latest', false],
|
||||||
|
['v0.4.1', true],
|
||||||
|
['latest', true]
|
||||||
|
])(
|
||||||
|
'acquires %p of buildx (standalone: %p)',
|
||||||
|
async (version, standalone) => {
|
||||||
|
const buildxBin = await buildx.install(version, process.env.GITHUB_TOKEN || '', tmpDir, standalone);
|
||||||
|
expect(fs.existsSync(buildxBin)).toBe(true);
|
||||||
|
},
|
||||||
|
100000
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getConfig', () => {
|
||||||
|
test.each([
|
||||||
|
['debug = true', false, 'debug = true', false],
|
||||||
|
[`notfound.toml`, true, '', true],
|
||||||
|
[
|
||||||
|
`${path.join(__dirname, 'fixtures', 'buildkitd.toml').split(path.sep).join(path.posix.sep)}`,
|
||||||
|
true,
|
||||||
|
`debug = true
|
||||||
|
[registry."docker.io"]
|
||||||
|
mirrors = ["mirror.gcr.io"]
|
||||||
|
`,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
])('given %p config', async (val, file, exValue, invalid) => {
|
||||||
|
try {
|
||||||
|
let config: string;
|
||||||
|
if (file) {
|
||||||
|
config = await buildx.getConfigFile(val);
|
||||||
|
} else {
|
||||||
|
config = await buildx.getConfigInline(val);
|
||||||
|
}
|
||||||
|
expect(true).toBe(!invalid);
|
||||||
|
expect(config).toEqual(tmpname);
|
||||||
|
const configValue = fs.readFileSync(tmpname, 'utf-8');
|
||||||
|
expect(configValue).toEqual(exValue);
|
||||||
|
} catch (err) {
|
||||||
|
// eslint-disable-next-line jest/no-conditional-expect
|
||||||
|
expect(true).toBe(invalid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -1,40 +1,22 @@
|
|||||||
import {beforeEach, describe, expect, jest, test} from '@jest/globals';
|
import {beforeEach, describe, expect, it, jest, test} from '@jest/globals';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx';
|
import * as uuid from 'uuid';
|
||||||
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';
|
import * as context from '../src/context';
|
||||||
|
import * as nodes from '../src/nodes';
|
||||||
|
|
||||||
const fixturesDir = path.join(__dirname, 'fixtures');
|
const tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-setup-buildx-')).split(path.sep).join(path.posix.sep);
|
||||||
// prettier-ignore
|
jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
|
||||||
const tmpDir = path.join(process.env.TEMP || '/tmp', 'setup-buildx-jest');
|
return tmpdir;
|
||||||
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 => {
|
jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => {
|
||||||
return tmpName;
|
return path.join(tmpdir, '.tmpname').split(path.sep).join(path.posix.sep);
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('crypto', () => {
|
jest.mock('uuid');
|
||||||
return {
|
jest.spyOn(uuid, 'v4').mockReturnValue('9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d');
|
||||||
...(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', () => {
|
describe('getCreateArgs', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -50,12 +32,9 @@ describe('getCreateArgs', () => {
|
|||||||
test.each([
|
test.each([
|
||||||
[
|
[
|
||||||
0,
|
0,
|
||||||
'v0.10.3',
|
|
||||||
new Map<string, string>([
|
new Map<string, string>([
|
||||||
['install', 'false'],
|
['install', 'false'],
|
||||||
['use', 'true'],
|
['use', 'true'],
|
||||||
['cache-binary', 'true'],
|
|
||||||
['cleanup', 'true'],
|
|
||||||
]),
|
]),
|
||||||
[
|
[
|
||||||
'create',
|
'create',
|
||||||
@ -67,13 +46,10 @@ describe('getCreateArgs', () => {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
1,
|
1,
|
||||||
'v0.10.3',
|
|
||||||
new Map<string, string>([
|
new Map<string, string>([
|
||||||
['driver', 'docker'],
|
['driver', 'docker'],
|
||||||
['install', 'false'],
|
['install', 'false'],
|
||||||
['use', 'true'],
|
['use', 'true'],
|
||||||
['cache-binary', 'true'],
|
|
||||||
['cleanup', 'true'],
|
|
||||||
]),
|
]),
|
||||||
[
|
[
|
||||||
'create',
|
'create',
|
||||||
@ -85,13 +61,10 @@ describe('getCreateArgs', () => {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
2,
|
2,
|
||||||
'v0.10.3',
|
|
||||||
new Map<string, string>([
|
new Map<string, string>([
|
||||||
['install', 'false'],
|
['install', 'false'],
|
||||||
['use', 'false'],
|
['use', 'false'],
|
||||||
['driver-opts', 'image=moby/buildkit:master\nnetwork=host'],
|
['driver-opts', 'image=moby/buildkit:master\nnetwork=host'],
|
||||||
['cache-binary', 'true'],
|
|
||||||
['cleanup', 'true'],
|
|
||||||
]),
|
]),
|
||||||
[
|
[
|
||||||
'create',
|
'create',
|
||||||
@ -104,14 +77,11 @@ describe('getCreateArgs', () => {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
3,
|
3,
|
||||||
'v0.10.3',
|
|
||||||
new Map<string, string>([
|
new Map<string, string>([
|
||||||
['driver', 'remote'],
|
['driver', 'remote'],
|
||||||
['endpoint', 'tls://foo:1234'],
|
['endpoint', 'tls://foo:1234'],
|
||||||
['install', 'false'],
|
['install', 'false'],
|
||||||
['use', 'true'],
|
['use', 'true'],
|
||||||
['cache-binary', 'true'],
|
|
||||||
['cleanup', 'true'],
|
|
||||||
]),
|
]),
|
||||||
[
|
[
|
||||||
'create',
|
'create',
|
||||||
@ -123,15 +93,12 @@ describe('getCreateArgs', () => {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
4,
|
4,
|
||||||
'v0.10.3',
|
|
||||||
new Map<string, string>([
|
new Map<string, string>([
|
||||||
['driver', 'remote'],
|
['driver', 'remote'],
|
||||||
['platforms', 'linux/arm64,linux/arm/v7'],
|
['platforms', 'linux/arm64,linux/arm/v7'],
|
||||||
['endpoint', 'tls://foo:1234'],
|
['endpoint', 'tls://foo:1234'],
|
||||||
['install', 'false'],
|
['install', 'false'],
|
||||||
['use', 'true'],
|
['use', 'true'],
|
||||||
['cache-binary', 'true'],
|
|
||||||
['cleanup', 'true'],
|
|
||||||
]),
|
]),
|
||||||
[
|
[
|
||||||
'create',
|
'create',
|
||||||
@ -144,13 +111,10 @@ describe('getCreateArgs', () => {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
5,
|
5,
|
||||||
'v0.10.3',
|
|
||||||
new Map<string, string>([
|
new Map<string, string>([
|
||||||
['install', 'false'],
|
['install', 'false'],
|
||||||
['use', 'false'],
|
['use', 'false'],
|
||||||
['driver-opts', `"env.no_proxy=localhost,127.0.0.1,.mydomain"`],
|
['driver-opts', `"env.no_proxy=localhost,127.0.0.1,.mydomain"`],
|
||||||
['cache-binary', 'true'],
|
|
||||||
['cleanup', 'true'],
|
|
||||||
]),
|
]),
|
||||||
[
|
[
|
||||||
'create',
|
'create',
|
||||||
@ -162,13 +126,10 @@ describe('getCreateArgs', () => {
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
6,
|
6,
|
||||||
'v0.10.3',
|
|
||||||
new Map<string, string>([
|
new Map<string, string>([
|
||||||
['install', 'false'],
|
['install', 'false'],
|
||||||
['use', 'false'],
|
['use', 'false'],
|
||||||
['platforms', 'linux/amd64\n"linux/arm64,linux/arm/v7"'],
|
['platforms', 'linux/amd64\n"linux/arm64,linux/arm/v7"'],
|
||||||
['cache-binary', 'true'],
|
|
||||||
['cleanup', 'true'],
|
|
||||||
]),
|
]),
|
||||||
[
|
[
|
||||||
'create',
|
'create',
|
||||||
@ -178,88 +139,14 @@ describe('getCreateArgs', () => {
|
|||||||
'--platform', 'linux/amd64,linux/arm64,linux/arm/v7'
|
'--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'],
|
|
||||||
]),
|
|
||||||
[
|
|
||||||
'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'],
|
|
||||||
]),
|
|
||||||
[
|
|
||||||
'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'],
|
|
||||||
]),
|
|
||||||
[
|
|
||||||
'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'],
|
|
||||||
]),
|
|
||||||
[
|
|
||||||
'create',
|
|
||||||
'--name', 'builder-9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d',
|
|
||||||
'--driver', 'cloud',
|
|
||||||
'--buildkitd-flags', '--allow-insecure-entitlement network.host',
|
|
||||||
]
|
|
||||||
]
|
|
||||||
])(
|
])(
|
||||||
'[%d] given buildx %s and %p as inputs, returns %p',
|
'[%d] given %p as inputs, returns %p',
|
||||||
async (num: number, buildxVersion: string, inputs: Map<string, string>, expected: Array<string>) => {
|
async (num: number, inputs: Map<string, string>, expected: Array<string>) => {
|
||||||
inputs.forEach((value: string, name: string) => {
|
inputs.forEach((value: string, name: string) => {
|
||||||
setInput(name, value);
|
setInput(name, value);
|
||||||
});
|
});
|
||||||
const toolkit = new Toolkit();
|
|
||||||
jest.spyOn(Buildx.prototype, 'version').mockImplementation(async (): Promise<string> => {
|
|
||||||
return buildxVersion;
|
|
||||||
});
|
|
||||||
const inp = await context.getInputs();
|
const inp = await context.getInputs();
|
||||||
const res = await context.getCreateArgs(inp, toolkit);
|
const res = await context.getCreateArgs(inp, '0.9.0');
|
||||||
expect(res).toEqual(expected);
|
expect(res).toEqual(expected);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -279,12 +166,9 @@ describe('getAppendArgs', () => {
|
|||||||
test.each([
|
test.each([
|
||||||
[
|
[
|
||||||
0,
|
0,
|
||||||
'v0.10.3',
|
|
||||||
new Map<string, string>([
|
new Map<string, string>([
|
||||||
['install', 'false'],
|
['install', 'false'],
|
||||||
['use', 'true'],
|
['use', 'true'],
|
||||||
['cache-binary', 'true'],
|
|
||||||
['cleanup', 'true'],
|
|
||||||
]),
|
]),
|
||||||
{
|
{
|
||||||
"name": "aws_graviton2",
|
"name": "aws_graviton2",
|
||||||
@ -307,154 +191,85 @@ describe('getAppendArgs', () => {
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
])(
|
])(
|
||||||
'[%d] given buildx %s and %p as inputs, returns %p',
|
'[%d] given %p as inputs, returns %p',
|
||||||
async (num: number, buildxVersion: string, inputs: Map<string, string>, node: Node, expected: Array<string>) => {
|
async (num: number, inputs: Map<string, string>, node: nodes.Node, expected: Array<string>) => {
|
||||||
inputs.forEach((value: string, name: string) => {
|
inputs.forEach((value: string, name: string) => {
|
||||||
setInput(name, value);
|
setInput(name, value);
|
||||||
});
|
});
|
||||||
const toolkit = new Toolkit();
|
|
||||||
jest.spyOn(Buildx.prototype, 'version').mockImplementation(async (): Promise<string> => {
|
|
||||||
return buildxVersion;
|
|
||||||
});
|
|
||||||
const inp = await context.getInputs();
|
const inp = await context.getInputs();
|
||||||
const res = await context.getAppendArgs(inp, node, toolkit);
|
const res = await context.getAppendArgs(inp, node, '0.9.0');
|
||||||
expect(res).toEqual(expected);
|
expect(res).toEqual(expected);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getVersion', () => {
|
describe('getInputList', () => {
|
||||||
beforeEach(() => {
|
it('handles single line correctly', async () => {
|
||||||
process.env = Object.keys(process.env).reduce((object, key) => {
|
await setInput('foo', 'bar');
|
||||||
if (!key.startsWith('INPUT_')) {
|
const res = await context.getInputList('foo');
|
||||||
object[key] = process.env[key];
|
expect(res).toEqual(['bar']);
|
||||||
}
|
|
||||||
return object;
|
|
||||||
}, {});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// prettier-ignore
|
it('handles multiple lines correctly', async () => {
|
||||||
test.each([
|
setInput('foo', 'bar\nbaz');
|
||||||
[
|
const res = await context.getInputList('foo');
|
||||||
0,
|
expect(res).toEqual(['bar', 'baz']);
|
||||||
new Map<string, string>([
|
});
|
||||||
// defaults
|
|
||||||
['install', 'false'],
|
it('remove empty lines correctly', async () => {
|
||||||
['use', 'true'],
|
setInput('foo', 'bar\n\nbaz');
|
||||||
['cache-binary', 'true'],
|
const res = await context.getInputList('foo');
|
||||||
['cleanup', 'true'],
|
expect(res).toEqual(['bar', 'baz']);
|
||||||
]),
|
});
|
||||||
''
|
|
||||||
],
|
it('handles comma correctly', async () => {
|
||||||
[
|
setInput('foo', 'bar,baz');
|
||||||
1,
|
const res = await context.getInputList('foo');
|
||||||
new Map<string, string>([
|
expect(res).toEqual(['bar', 'baz']);
|
||||||
['version', 'latest'],
|
});
|
||||||
// defaults
|
|
||||||
['install', 'false'],
|
it('remove empty result correctly', async () => {
|
||||||
['use', 'true'],
|
setInput('foo', 'bar,baz,');
|
||||||
['cache-binary', 'true'],
|
const res = await context.getInputList('foo');
|
||||||
['cleanup', 'true']
|
expect(res).toEqual(['bar', 'baz']);
|
||||||
]),
|
});
|
||||||
'latest'
|
|
||||||
],
|
it('handles different new lines correctly', async () => {
|
||||||
[
|
setInput('foo', 'bar\r\nbaz');
|
||||||
2,
|
const res = await context.getInputList('foo');
|
||||||
new Map<string, string>([
|
expect(res).toEqual(['bar', 'baz']);
|
||||||
['version', 'edge'],
|
});
|
||||||
// defaults
|
|
||||||
['install', 'false'],
|
it('handles different new lines and comma correctly', async () => {
|
||||||
['use', 'true'],
|
setInput('foo', 'bar\r\nbaz,bat');
|
||||||
['cache-binary', 'true'],
|
const res = await context.getInputList('foo');
|
||||||
['cleanup', 'true']
|
expect(res).toEqual(['bar', 'baz', 'bat']);
|
||||||
]),
|
});
|
||||||
'edge'
|
|
||||||
],
|
it('handles multiple lines and ignoring comma correctly', async () => {
|
||||||
[
|
setInput('driver-opts', 'image=moby/buildkit:master\nnetwork=host');
|
||||||
3,
|
const res = await context.getInputList('driver-opts', true);
|
||||||
new Map<string, string>([
|
expect(res).toEqual(['image=moby/buildkit:master', 'network=host']);
|
||||||
['version', 'v0.19.2'],
|
});
|
||||||
// defaults
|
|
||||||
['install', 'false'],
|
it('handles different new lines and ignoring comma correctly', async () => {
|
||||||
['use', 'true'],
|
setInput('driver-opts', 'image=moby/buildkit:master\r\nnetwork=host');
|
||||||
['cache-binary', 'true'],
|
const res = await context.getInputList('driver-opts', true);
|
||||||
['cleanup', 'true']
|
expect(res).toEqual(['image=moby/buildkit:master', 'network=host']);
|
||||||
]),
|
});
|
||||||
'v0.19.2'
|
});
|
||||||
],
|
|
||||||
[
|
describe('asyncForEach', () => {
|
||||||
4,
|
it('executes async tasks sequentially', async () => {
|
||||||
new Map<string, string>([
|
const testValues = [1, 2, 3, 4, 5];
|
||||||
['version', 'latest'],
|
const results: number[] = [];
|
||||||
['driver', 'cloud'],
|
|
||||||
// defaults
|
await context.asyncForEach(testValues, async value => {
|
||||||
['install', 'false'],
|
results.push(value);
|
||||||
['use', 'true'],
|
});
|
||||||
['cache-binary', 'true'],
|
|
||||||
['cleanup', 'true']
|
expect(results).toEqual(testValues);
|
||||||
]),
|
|
||||||
'cloud:latest'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
5,
|
|
||||||
new Map<string, string>([
|
|
||||||
['version', 'edge'],
|
|
||||||
['driver', 'cloud'],
|
|
||||||
// defaults
|
|
||||||
['install', 'false'],
|
|
||||||
['use', 'true'],
|
|
||||||
['cache-binary', 'true'],
|
|
||||||
['cleanup', 'true']
|
|
||||||
]),
|
|
||||||
'cloud:edge'
|
|
||||||
],
|
|
||||||
[
|
|
||||||
6,
|
|
||||||
new Map<string, string>([
|
|
||||||
['driver', 'cloud'],
|
|
||||||
// defaults
|
|
||||||
['install', 'false'],
|
|
||||||
['use', 'true'],
|
|
||||||
['cache-binary', 'true'],
|
|
||||||
['cleanup', 'true'],
|
|
||||||
]),
|
|
||||||
'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'],
|
|
||||||
]),
|
|
||||||
'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'],
|
|
||||||
]),
|
|
||||||
'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);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67
|
// See: https://github.com/actions/toolkit/blob/master/packages/core/src/core.ts#L67
|
||||||
|
16
__tests__/docker.test.ts
Normal file
16
__tests__/docker.test.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import {describe, expect, it, jest} from '@jest/globals';
|
||||||
|
import * as docker from '../src/docker';
|
||||||
|
import * as exec from '@actions/exec';
|
||||||
|
|
||||||
|
describe('isAvailable', () => {
|
||||||
|
it('cli', () => {
|
||||||
|
const execSpy = jest.spyOn(exec, 'getExecOutput');
|
||||||
|
docker.isAvailable();
|
||||||
|
|
||||||
|
// eslint-disable-next-line jest/no-standalone-expect
|
||||||
|
expect(execSpy).toHaveBeenCalledWith(`docker`, undefined, {
|
||||||
|
silent: true,
|
||||||
|
ignoreReturnCode: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1 +1,3 @@
|
|||||||
debug = true
|
debug = true
|
||||||
|
[registry."docker.io"]
|
||||||
|
mirrors = ["mirror.gcr.io"]
|
||||||
|
10
__tests__/fixtures/inspect1.txt
Normal file
10
__tests__/fixtures/inspect1.txt
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Name: builder-5cb467f7-0940-47e1-b94b-d51f54054d62
|
||||||
|
Driver: docker-container
|
||||||
|
|
||||||
|
Nodes:
|
||||||
|
Name: builder-5cb467f7-0940-47e1-b94b-d51f54054d620
|
||||||
|
Endpoint: unix:///var/run/docker.sock
|
||||||
|
Status: running
|
||||||
|
Flags: --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host
|
||||||
|
Buildkit: v0.10.4
|
||||||
|
Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/arm64, linux/riscv64, linux/386, linux/arm/v7, linux/arm/v6
|
11
__tests__/fixtures/inspect2.txt
Normal file
11
__tests__/fixtures/inspect2.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Name: builder-5f449644-ff29-48af-8344-abb0292d0673
|
||||||
|
Driver: docker-container
|
||||||
|
|
||||||
|
Nodes:
|
||||||
|
Name: builder-5f449644-ff29-48af-8344-abb0292d06730
|
||||||
|
Endpoint: unix:///var/run/docker.sock
|
||||||
|
Driver Options: image="moby/buildkit:latest"
|
||||||
|
Status: running
|
||||||
|
Flags: --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host
|
||||||
|
Buildkit: v0.10.4
|
||||||
|
Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/amd64/v4, linux/386
|
11
__tests__/fixtures/inspect3.txt
Normal file
11
__tests__/fixtures/inspect3.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
Name: builder-9929e463-7954-4dc3-89cd-514cca29ff80
|
||||||
|
Driver: docker-container
|
||||||
|
|
||||||
|
Nodes:
|
||||||
|
Name: builder-9929e463-7954-4dc3-89cd-514cca29ff800
|
||||||
|
Endpoint: unix:///var/run/docker.sock
|
||||||
|
Driver Options: image="moby/buildkit:master" network="host"
|
||||||
|
Status: running
|
||||||
|
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
|
9
__tests__/fixtures/inspect4.txt
Normal file
9
__tests__/fixtures/inspect4.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Name: default
|
||||||
|
Driver: docker
|
||||||
|
|
||||||
|
Nodes:
|
||||||
|
Name: default
|
||||||
|
Endpoint: default
|
||||||
|
Status: running
|
||||||
|
Buildkit: 20.10.17
|
||||||
|
Platforms: linux/amd64, linux/arm64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
|
9
__tests__/fixtures/inspect5.txt
Normal file
9
__tests__/fixtures/inspect5.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Name: remote-builder
|
||||||
|
Driver: remote
|
||||||
|
|
||||||
|
Nodes:
|
||||||
|
Name: aws_graviton2
|
||||||
|
Endpoint: tcp://1.23.45.67:1234
|
||||||
|
Driver Options: cert="/home/user/.certs/aws_graviton2/cert.pem" key="/home/user/.certs/aws_graviton2/key.pem" cacert="/home/user/.certs/aws_graviton2/ca.pem"
|
||||||
|
Status: running
|
||||||
|
Platforms: darwin/arm64*, linux/arm64*, linux/arm/v5*, linux/arm/v6*, linux/arm/v7*, windows/arm64*, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/mips64le, linux/mips64
|
9
__tests__/fixtures/inspect6.txt
Normal file
9
__tests__/fixtures/inspect6.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Name: builder-17cfff01-48d9-4c3d-9332-9992e308a510
|
||||||
|
Driver: docker-container
|
||||||
|
|
||||||
|
Nodes:
|
||||||
|
Name: builder-17cfff01-48d9-4c3d-9332-9992e308a5100
|
||||||
|
Endpoint: unix:///var/run/docker.sock
|
||||||
|
Status: running
|
||||||
|
Flags: --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host
|
||||||
|
Platforms: linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386
|
9
__tests__/git.test.ts
Normal file
9
__tests__/git.test.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import {describe, expect, it} from '@jest/globals';
|
||||||
|
import * as git from '../src/git';
|
||||||
|
|
||||||
|
describe('git', () => {
|
||||||
|
it('returns git remote ref', async () => {
|
||||||
|
const ref: string = await git.getRemoteSha('https://github.com/docker/buildx.git', 'refs/pull/648/head');
|
||||||
|
expect(ref).toEqual('f11797113e5a9b86bd976329c5dbb8a8bfdfadfa');
|
||||||
|
});
|
||||||
|
});
|
20
__tests__/github.test.ts
Normal file
20
__tests__/github.test.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import {describe, expect, it} from '@jest/globals';
|
||||||
|
import * as github from '../src/github';
|
||||||
|
|
||||||
|
describe('github', () => {
|
||||||
|
it('returns latest buildx GitHub release', async () => {
|
||||||
|
const release = await github.getLatestRelease(process.env.GITHUB_TOKEN || '');
|
||||||
|
expect(release).not.toBeNull();
|
||||||
|
expect(release?.tag_name).not.toEqual('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns v0.2.2 buildx GitHub release', async () => {
|
||||||
|
const release = await github.getReleaseTag('v0.2.2', process.env.GITHUB_TOKEN || '');
|
||||||
|
expect(release).not.toBeNull();
|
||||||
|
expect(release?.tag_name).toEqual('v0.2.2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('unknown release', async () => {
|
||||||
|
await expect(github.getReleaseTag('foo', process.env.GITHUB_TOKEN || '')).rejects.toThrowError(new Error('Cannot get release foo: HttpError: Not Found'));
|
||||||
|
});
|
||||||
|
});
|
12
__tests__/util.test.ts
Normal file
12
__tests__/util.test.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import {describe, expect, test} from '@jest/globals';
|
||||||
|
import * as util from '../src/util';
|
||||||
|
|
||||||
|
describe('isValidUrl', () => {
|
||||||
|
test.each([
|
||||||
|
['https://github.com/docker/buildx.git', true],
|
||||||
|
['https://github.com/docker/buildx.git#refs/pull/648/head', true],
|
||||||
|
['v0.4.1', false]
|
||||||
|
])('given %p', async (url, expected) => {
|
||||||
|
expect(util.isValidUrl(url)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
43
action.yml
43
action.yml
@ -18,13 +18,8 @@ inputs:
|
|||||||
description: 'List of additional driver-specific options. (eg. image=moby/buildkit:master)'
|
description: 'List of additional driver-specific options. (eg. image=moby/buildkit:master)'
|
||||||
required: false
|
required: false
|
||||||
buildkitd-flags:
|
buildkitd-flags:
|
||||||
description: 'BuildKit daemon flags'
|
description: 'Flags for buildkitd daemon'
|
||||||
required: false
|
default: '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host'
|
||||||
buildkitd-config:
|
|
||||||
description: 'BuildKit daemon config file'
|
|
||||||
required: false
|
|
||||||
buildkitd-config-inline:
|
|
||||||
description: 'Inline BuildKit daemon config'
|
|
||||||
required: false
|
required: false
|
||||||
install:
|
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 build'
|
||||||
@ -40,26 +35,24 @@ inputs:
|
|||||||
platforms:
|
platforms:
|
||||||
description: 'Fixed platforms for current node. If not empty, values take priority over the detected ones'
|
description: 'Fixed platforms for current node. If not empty, values take priority over the detected ones'
|
||||||
required: false
|
required: false
|
||||||
|
config:
|
||||||
|
description: 'BuildKit config file'
|
||||||
|
required: false
|
||||||
|
config-inline:
|
||||||
|
description: 'Inline BuildKit config'
|
||||||
|
required: false
|
||||||
append:
|
append:
|
||||||
description: 'Append additional nodes to the builder'
|
description: 'Append additional nodes to the builder'
|
||||||
required: false
|
required: false
|
||||||
cache-binary:
|
github_token:
|
||||||
description: 'Cache buildx binary to GitHub Actions cache backend'
|
# https://github.com/actions/setup-go/blob/21459d0b7b1d63741429b748885bf5a4974593b4/action.yml#L12-L14
|
||||||
default: 'true'
|
description: >
|
||||||
required: false
|
Used to verifiy the Git tag exists on docker/buildx repo. Since there's a
|
||||||
cleanup:
|
default, this is typically not supplied by the user. When running this
|
||||||
description: 'Cleanup temp files and remove builder at the end of a job'
|
action on github.com, the default value is sufficient. When running on
|
||||||
default: 'true'
|
GHES, you can pass a personal access token for github.com if you are
|
||||||
required: false
|
experiencing rate limiting.
|
||||||
# TODO: remove deprecated config and config-inline inputs
|
default: ${{ github.server_url == 'https://github.com' && github.token || '' }}
|
||||||
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:
|
outputs:
|
||||||
name:
|
name:
|
||||||
@ -78,6 +71,6 @@ outputs:
|
|||||||
description: 'Builder node flags (deprecated, use nodes output instead)'
|
description: 'Builder node flags (deprecated, use nodes output instead)'
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: 'node20'
|
using: 'node16'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
post: 'dist/index.js'
|
post: 'dist/index.js'
|
||||||
|
@ -1,20 +1,15 @@
|
|||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
ARG NODE_VERSION=20
|
ARG NODE_VERSION=16
|
||||||
|
ARG DOCKER_VERSION=20.10.13
|
||||||
|
ARG BUILDX_VERSION=0.8.1
|
||||||
|
|
||||||
FROM node:${NODE_VERSION}-alpine AS base
|
FROM node:${NODE_VERSION}-alpine AS base
|
||||||
RUN apk add --no-cache cpio findutils git
|
RUN apk add --no-cache cpio findutils git
|
||||||
WORKDIR /src
|
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
|
FROM base AS deps
|
||||||
RUN --mount=type=bind,target=.,rw \
|
RUN --mount=type=bind,target=.,rw \
|
||||||
--mount=type=cache,target=/src/.yarn/cache \
|
|
||||||
--mount=type=cache,target=/src/node_modules \
|
--mount=type=cache,target=/src/node_modules \
|
||||||
yarn install && mkdir /vendor && cp yarn.lock /vendor
|
yarn install && mkdir /vendor && cp yarn.lock /vendor
|
||||||
|
|
||||||
@ -23,19 +18,18 @@ COPY --from=deps /vendor /
|
|||||||
|
|
||||||
FROM deps AS vendor-validate
|
FROM deps AS vendor-validate
|
||||||
RUN --mount=type=bind,target=.,rw <<EOT
|
RUN --mount=type=bind,target=.,rw <<EOT
|
||||||
set -e
|
set -e
|
||||||
git add -A
|
git add -A
|
||||||
cp -rf /vendor/* .
|
cp -rf /vendor/* .
|
||||||
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then
|
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then
|
||||||
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor"'
|
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor-update"'
|
||||||
git status --porcelain -- yarn.lock
|
git status --porcelain -- yarn.lock
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
FROM deps AS build
|
FROM deps AS build
|
||||||
RUN --mount=type=bind,target=.,rw \
|
RUN --mount=type=bind,target=.,rw \
|
||||||
--mount=type=cache,target=/src/.yarn/cache \
|
|
||||||
--mount=type=cache,target=/src/node_modules \
|
--mount=type=cache,target=/src/node_modules \
|
||||||
yarn run build && mkdir /out && cp -Rf dist /out/
|
yarn run build && mkdir /out && cp -Rf dist /out/
|
||||||
|
|
||||||
@ -44,37 +38,42 @@ COPY --from=build /out /
|
|||||||
|
|
||||||
FROM build AS build-validate
|
FROM build AS build-validate
|
||||||
RUN --mount=type=bind,target=.,rw <<EOT
|
RUN --mount=type=bind,target=.,rw <<EOT
|
||||||
set -e
|
set -e
|
||||||
git add -A
|
git add -A
|
||||||
cp -rf /out/* .
|
cp -rf /out/* .
|
||||||
if [ -n "$(git status --porcelain -- dist)" ]; then
|
if [ -n "$(git status --porcelain -- dist)" ]; then
|
||||||
echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"'
|
echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"'
|
||||||
git status --porcelain -- dist
|
git status --porcelain -- dist
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
FROM deps AS format
|
FROM deps AS format
|
||||||
RUN --mount=type=bind,target=.,rw \
|
RUN --mount=type=bind,target=.,rw \
|
||||||
--mount=type=cache,target=/src/.yarn/cache \
|
|
||||||
--mount=type=cache,target=/src/node_modules \
|
--mount=type=cache,target=/src/node_modules \
|
||||||
yarn run format \
|
yarn run format \
|
||||||
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' -not -path './.yarn/*' | cpio -pdm /out
|
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' | cpio -pdm /out
|
||||||
|
|
||||||
FROM scratch AS format-update
|
FROM scratch AS format-update
|
||||||
COPY --from=format /out /
|
COPY --from=format /out /
|
||||||
|
|
||||||
FROM deps AS lint
|
FROM deps AS lint
|
||||||
RUN --mount=type=bind,target=.,rw \
|
RUN --mount=type=bind,target=.,rw \
|
||||||
--mount=type=cache,target=/src/.yarn/cache \
|
|
||||||
--mount=type=cache,target=/src/node_modules \
|
--mount=type=cache,target=/src/node_modules \
|
||||||
yarn run lint
|
yarn run lint
|
||||||
|
|
||||||
|
FROM docker:${DOCKER_VERSION} as docker
|
||||||
|
FROM docker/buildx-bin:${BUILDX_VERSION} as buildx
|
||||||
|
|
||||||
FROM deps AS test
|
FROM deps AS test
|
||||||
|
ENV RUNNER_TEMP=/tmp/github_runner
|
||||||
|
ENV RUNNER_TOOL_CACHE=/tmp/github_tool_cache
|
||||||
RUN --mount=type=bind,target=.,rw \
|
RUN --mount=type=bind,target=.,rw \
|
||||||
--mount=type=cache,target=/src/.yarn/cache \
|
|
||||||
--mount=type=cache,target=/src/node_modules \
|
--mount=type=cache,target=/src/node_modules \
|
||||||
yarn run test --coverage --coverageDirectory=/tmp/coverage
|
--mount=type=bind,from=docker,source=/usr/local/bin/docker,target=/usr/bin/docker \
|
||||||
|
--mount=type=bind,from=buildx,source=/buildx,target=/usr/libexec/docker/cli-plugins/docker-buildx \
|
||||||
|
--mount=type=secret,id=GITHUB_TOKEN \
|
||||||
|
GITHUB_TOKEN=$(cat /run/secrets/GITHUB_TOKEN) yarn run test --coverageDirectory=/tmp/coverage
|
||||||
|
|
||||||
FROM scratch AS test-coverage
|
FROM scratch AS test-coverage
|
||||||
COPY --from=test /tmp/coverage /
|
COPY --from=test /tmp/coverage /
|
||||||
|
93
dist/index.js
generated
vendored
93
dist/index.js
generated
vendored
File diff suppressed because one or more lines are too long
2
dist/index.js.map
generated
vendored
2
dist/index.js.map
generated
vendored
File diff suppressed because one or more lines are too long
2942
dist/licenses.txt
generated
vendored
2942
dist/licenses.txt
generated
vendored
File diff suppressed because it is too large
Load Diff
2
dist/sourcemap-register.js
generated
vendored
2
dist/sourcemap-register.js
generated
vendored
File diff suppressed because one or more lines are too long
@ -1,15 +1,9 @@
|
|||||||
target "_common" {
|
|
||||||
args = {
|
|
||||||
BUILDKIT_CONTEXT_KEEP_GIT_DIR = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
group "default" {
|
group "default" {
|
||||||
targets = ["build"]
|
targets = ["build"]
|
||||||
}
|
}
|
||||||
|
|
||||||
group "pre-checkin" {
|
group "pre-checkin" {
|
||||||
targets = ["vendor", "format", "build"]
|
targets = ["vendor-update", "format", "build"]
|
||||||
}
|
}
|
||||||
|
|
||||||
group "validate" {
|
group "validate" {
|
||||||
@ -17,50 +11,44 @@ group "validate" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
target "build" {
|
target "build" {
|
||||||
inherits = ["_common"]
|
|
||||||
dockerfile = "dev.Dockerfile"
|
dockerfile = "dev.Dockerfile"
|
||||||
target = "build-update"
|
target = "build-update"
|
||||||
output = ["."]
|
output = ["."]
|
||||||
}
|
}
|
||||||
|
|
||||||
target "build-validate" {
|
target "build-validate" {
|
||||||
inherits = ["_common"]
|
|
||||||
dockerfile = "dev.Dockerfile"
|
dockerfile = "dev.Dockerfile"
|
||||||
target = "build-validate"
|
target = "build-validate"
|
||||||
output = ["type=cacheonly"]
|
output = ["type=cacheonly"]
|
||||||
}
|
}
|
||||||
|
|
||||||
target "format" {
|
target "format" {
|
||||||
inherits = ["_common"]
|
|
||||||
dockerfile = "dev.Dockerfile"
|
dockerfile = "dev.Dockerfile"
|
||||||
target = "format-update"
|
target = "format-update"
|
||||||
output = ["."]
|
output = ["."]
|
||||||
}
|
}
|
||||||
|
|
||||||
target "lint" {
|
target "lint" {
|
||||||
inherits = ["_common"]
|
|
||||||
dockerfile = "dev.Dockerfile"
|
dockerfile = "dev.Dockerfile"
|
||||||
target = "lint"
|
target = "lint"
|
||||||
output = ["type=cacheonly"]
|
output = ["type=cacheonly"]
|
||||||
}
|
}
|
||||||
|
|
||||||
target "vendor" {
|
target "vendor-update" {
|
||||||
inherits = ["_common"]
|
|
||||||
dockerfile = "dev.Dockerfile"
|
dockerfile = "dev.Dockerfile"
|
||||||
target = "vendor-update"
|
target = "vendor-update"
|
||||||
output = ["."]
|
output = ["."]
|
||||||
}
|
}
|
||||||
|
|
||||||
target "vendor-validate" {
|
target "vendor-validate" {
|
||||||
inherits = ["_common"]
|
|
||||||
dockerfile = "dev.Dockerfile"
|
dockerfile = "dev.Dockerfile"
|
||||||
target = "vendor-validate"
|
target = "vendor-validate"
|
||||||
output = ["type=cacheonly"]
|
output = ["type=cacheonly"]
|
||||||
}
|
}
|
||||||
|
|
||||||
target "test" {
|
target "test" {
|
||||||
inherits = ["_common"]
|
|
||||||
dockerfile = "dev.Dockerfile"
|
dockerfile = "dev.Dockerfile"
|
||||||
target = "test-coverage"
|
target = "test-coverage"
|
||||||
output = ["./coverage"]
|
output = ["./coverage"]
|
||||||
|
secret = ["id=GITHUB_TOKEN,env=GITHUB_TOKEN"]
|
||||||
}
|
}
|
||||||
|
3
docs/advanced/append-nodes.md
Normal file
3
docs/advanced/append-nodes.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Append additional nodes to the builder
|
||||||
|
|
||||||
|
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/configure-builder/#append-additional-nodes-to-the-builder)
|
3
docs/advanced/auth.md
Normal file
3
docs/advanced/auth.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Authentication support
|
||||||
|
|
||||||
|
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/configure-builder/#authentication-for-remote-builders)
|
3
docs/advanced/buildkit-config.md
Normal file
3
docs/advanced/buildkit-config.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# BuildKit daemon configuration
|
||||||
|
|
||||||
|
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/configure-builder/#daemon-configuration)
|
3
docs/advanced/standalone.md
Normal file
3
docs/advanced/standalone.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Standalone mode
|
||||||
|
|
||||||
|
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/configure-builder/#standalone-mode)
|
@ -1,21 +1,7 @@
|
|||||||
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 = {
|
module.exports = {
|
||||||
clearMocks: true,
|
clearMocks: true,
|
||||||
moduleFileExtensions: ['js', 'ts'],
|
moduleFileExtensions: ['js', 'ts'],
|
||||||
|
setupFiles: ['dotenv/config'],
|
||||||
testMatch: ['**/*.test.ts'],
|
testMatch: ['**/*.test.ts'],
|
||||||
transform: {
|
transform: {
|
||||||
'^.+\\.ts$': 'ts-jest'
|
'^.+\\.ts$': 'ts-jest'
|
||||||
@ -23,7 +9,5 @@ module.exports = {
|
|||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
'^csv-parse/sync': '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs'
|
'^csv-parse/sync': '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs'
|
||||||
},
|
},
|
||||||
collectCoverageFrom: ['src/**/{!(main.ts),}.ts'],
|
|
||||||
coveragePathIgnorePatterns: ['lib/', 'node_modules/', '__tests__/'],
|
|
||||||
verbose: true
|
verbose: true
|
||||||
};
|
};
|
||||||
|
67
package.json
67
package.json
@ -1,16 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "docker-setup-buildx",
|
"name": "docker-setup-buildx",
|
||||||
"description": "Set up Docker Buildx",
|
"description": "Set up Docker Buildx",
|
||||||
"main": "src/main.ts",
|
"main": "lib/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "ncc build --source-map --minify --license licenses.txt",
|
"build": "ncc build src/main.ts --source-map --minify --license licenses.txt",
|
||||||
"lint": "yarn run prettier && yarn run eslint",
|
"lint": "eslint src/**/*.ts __tests__/**/*.ts",
|
||||||
"format": "yarn run prettier:fix && yarn run eslint:fix",
|
"format": "eslint --fix src/**/*.ts __tests__/**/*.ts",
|
||||||
"eslint": "eslint --max-warnings=0 .",
|
"test": "jest --coverage",
|
||||||
"eslint:fix": "eslint --fix .",
|
"all": "yarn run build && yarn run format && yarn test"
|
||||||
"prettier": "prettier --check \"./**/*.ts\"",
|
|
||||||
"prettier:fix": "prettier --write \"./**/*.ts\"",
|
|
||||||
"test": "jest"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -21,29 +18,41 @@
|
|||||||
"docker",
|
"docker",
|
||||||
"buildx"
|
"buildx"
|
||||||
],
|
],
|
||||||
"author": "Docker Inc.",
|
"author": "Docker",
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"name": "CrazyMax",
|
||||||
|
"url": "https://crazymax.dev"
|
||||||
|
}
|
||||||
|
],
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"packageManager": "yarn@3.6.3",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.11.1",
|
"@actions/core": "^1.10.0",
|
||||||
"@docker/actions-toolkit": "^0.56.0",
|
"@actions/exec": "^1.1.1",
|
||||||
"js-yaml": "^4.1.0"
|
"@actions/github": "^5.1.1",
|
||||||
|
"@actions/tool-cache": "^2.0.1",
|
||||||
|
"csv-parse": "^5.3.3",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"semver": "^7.3.7",
|
||||||
|
"tmp": "^0.2.1",
|
||||||
|
"uuid": "^9.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/js-yaml": "^4.0.9",
|
"@types/node": "^16.11.26",
|
||||||
"@types/node": "^20.12.12",
|
"@types/semver": "^7.3.9",
|
||||||
"@types/uuid": "^10.0.0",
|
"@types/tmp": "^0.2.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^7.9.0",
|
"@typescript-eslint/eslint-plugin": "^5.14.0",
|
||||||
"@typescript-eslint/parser": "^7.9.0",
|
"@typescript-eslint/parser": "^5.14.0",
|
||||||
"@vercel/ncc": "^0.38.1",
|
"@vercel/ncc": "^0.33.3",
|
||||||
"eslint": "^8.57.0",
|
"dotenv": "^16.0.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint": "^8.11.0",
|
||||||
"eslint-plugin-jest": "^28.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-jest": "^26.1.1",
|
||||||
"jest": "^29.7.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"prettier": "^3.2.5",
|
"jest": "^27.2.5",
|
||||||
"ts-jest": "^29.1.2",
|
"prettier": "^2.3.1",
|
||||||
"ts-node": "^10.9.2",
|
"ts-jest": "^27.1.2",
|
||||||
"typescript": "^5.4.5"
|
"ts-node": "^10.7.0",
|
||||||
|
"typescript": "^4.4.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
51
src/auth.ts
Normal file
51
src/auth.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
|
export const envPrefix = 'BUILDER_NODE';
|
||||||
|
|
||||||
|
export function setCredentials(credsdir: string, index: number, driver: string, endpoint: string): Array<string> {
|
||||||
|
let url: URL;
|
||||||
|
try {
|
||||||
|
url = new URL(endpoint);
|
||||||
|
} catch (e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
switch (url.protocol) {
|
||||||
|
case 'tcp:': {
|
||||||
|
return setBuildKitClientCerts(credsdir, index, driver, url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBuildKitClientCerts(credsdir: string, index: number, driver: string, endpoint: URL): Array<string> {
|
||||||
|
const driverOpts: Array<string> = [];
|
||||||
|
const buildkitCacert = process.env[`${envPrefix}_${index}_AUTH_TLS_CACERT`] || '';
|
||||||
|
const buildkitCert = process.env[`${envPrefix}_${index}_AUTH_TLS_CERT`] || '';
|
||||||
|
const buildkitKey = process.env[`${envPrefix}_${index}_AUTH_TLS_KEY`] || '';
|
||||||
|
if (buildkitCacert.length == 0 && buildkitCert.length == 0 && buildkitKey.length == 0) {
|
||||||
|
return driverOpts;
|
||||||
|
}
|
||||||
|
let host = endpoint.hostname;
|
||||||
|
if (endpoint.port.length > 0) {
|
||||||
|
host += `-${endpoint.port}`;
|
||||||
|
}
|
||||||
|
if (buildkitCacert.length > 0) {
|
||||||
|
const cacertpath = `${credsdir}/cacert_${host}.pem`;
|
||||||
|
fs.writeFileSync(cacertpath, buildkitCacert);
|
||||||
|
driverOpts.push(`cacert=${cacertpath}`);
|
||||||
|
}
|
||||||
|
if (buildkitCert.length > 0) {
|
||||||
|
const certpath = `${credsdir}/cert_${host}.pem`;
|
||||||
|
fs.writeFileSync(certpath, buildkitCert);
|
||||||
|
driverOpts.push(`cert=${certpath}`);
|
||||||
|
}
|
||||||
|
if (buildkitKey.length > 0) {
|
||||||
|
const keypath = `${credsdir}/key_${host}.pem`;
|
||||||
|
fs.writeFileSync(keypath, buildkitKey);
|
||||||
|
driverOpts.push(`key=${keypath}`);
|
||||||
|
}
|
||||||
|
if (driver != 'remote') {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return driverOpts;
|
||||||
|
}
|
380
src/buildx.ts
Normal file
380
src/buildx.ts
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
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 git from './git';
|
||||||
|
import * as github from './github';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
import * as exec from '@actions/exec';
|
||||||
|
import * as tc from '@actions/tool-cache';
|
||||||
|
|
||||||
|
export type Builder = {
|
||||||
|
name?: string;
|
||||||
|
driver?: string;
|
||||||
|
nodes: Node[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Node = {
|
||||||
|
name?: string;
|
||||||
|
endpoint?: string;
|
||||||
|
'driver-opts'?: Array<string>;
|
||||||
|
status?: string;
|
||||||
|
'buildkitd-flags'?: string;
|
||||||
|
buildkit?: string;
|
||||||
|
platforms?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function getConfigInline(s: string): Promise<string> {
|
||||||
|
return getConfig(s, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getConfigFile(s: string): Promise<string> {
|
||||||
|
return getConfig(s, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getConfig(s: string, file: boolean): Promise<string> {
|
||||||
|
if (file) {
|
||||||
|
if (!fs.existsSync(s)) {
|
||||||
|
throw new Error(`config file ${s} not found`);
|
||||||
|
}
|
||||||
|
s = fs.readFileSync(s, {encoding: 'utf-8'});
|
||||||
|
}
|
||||||
|
const configFile = context.tmpNameSync({
|
||||||
|
tmpdir: context.tmpDir()
|
||||||
|
});
|
||||||
|
fs.writeFileSync(configFile, s);
|
||||||
|
return configFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function isAvailable(standalone?: boolean): Promise<boolean> {
|
||||||
|
const cmd = getCommand([], standalone);
|
||||||
|
return await exec
|
||||||
|
.getExecOutput(cmd.commandLine, cmd.args, {
|
||||||
|
ignoreReturnCode: true,
|
||||||
|
silent: true
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return res.exitCode == 0;
|
||||||
|
})
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
.catch(error => {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getVersion(standalone?: boolean): Promise<string> {
|
||||||
|
const cmd = getCommand(['version'], standalone);
|
||||||
|
return await exec
|
||||||
|
.getExecOutput(cmd.commandLine, cmd.args, {
|
||||||
|
ignoreReturnCode: true,
|
||||||
|
silent: true
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||||
|
throw new Error(res.stderr.trim());
|
||||||
|
}
|
||||||
|
return parseVersion(res.stdout.trim());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseVersion(stdout: string): string {
|
||||||
|
const matches = /\sv?([0-9a-f]{7}|[0-9.]+)/.exec(stdout);
|
||||||
|
if (!matches) {
|
||||||
|
throw new Error(`Cannot parse buildx version`);
|
||||||
|
}
|
||||||
|
return matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function satisfies(version: string, range: string): boolean {
|
||||||
|
return semver.satisfies(version, range) || /^[0-9a-f]{7}$/.exec(version) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function inspect(name: string, standalone?: boolean): Promise<Builder> {
|
||||||
|
const cmd = getCommand(['inspect', name], standalone);
|
||||||
|
return await exec
|
||||||
|
.getExecOutput(cmd.commandLine, cmd.args, {
|
||||||
|
ignoreReturnCode: true,
|
||||||
|
silent: true
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||||
|
throw new Error(res.stderr.trim());
|
||||||
|
}
|
||||||
|
return parseInspect(res.stdout);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function parseInspect(data: string): Promise<Builder> {
|
||||||
|
const builder: Builder = {
|
||||||
|
nodes: []
|
||||||
|
};
|
||||||
|
let node: Node = {};
|
||||||
|
for (const line of data.trim().split(`\n`)) {
|
||||||
|
const [key, ...rest] = line.split(':');
|
||||||
|
const value = rest.map(v => v.trim()).join(':');
|
||||||
|
if (key.length == 0 || value.length == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (key.toLowerCase()) {
|
||||||
|
case 'name': {
|
||||||
|
if (builder.name == undefined) {
|
||||||
|
builder.name = value;
|
||||||
|
} else {
|
||||||
|
if (Object.keys(node).length > 0) {
|
||||||
|
builder.nodes.push(node);
|
||||||
|
node = {};
|
||||||
|
}
|
||||||
|
node.name = value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'driver': {
|
||||||
|
builder.driver = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'endpoint': {
|
||||||
|
node.endpoint = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'driver options': {
|
||||||
|
node['driver-opts'] = (value.match(/(\w+)="([^"]*)"/g) || []).map(v => v.replace(/^(.*)="(.*)"$/g, '$1=$2'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'status': {
|
||||||
|
node.status = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'flags': {
|
||||||
|
node['buildkitd-flags'] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'buildkit': {
|
||||||
|
node.buildkit = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'platforms': {
|
||||||
|
let platforms: Array<string> = [];
|
||||||
|
// if a preferred platform is being set then use only these
|
||||||
|
// https://docs.docker.com/engine/reference/commandline/buildx_inspect/#get-information-about-a-builder-instance
|
||||||
|
if (value.includes('*')) {
|
||||||
|
for (const platform of value.split(', ')) {
|
||||||
|
if (platform.includes('*')) {
|
||||||
|
platforms.push(platform.replace('*', ''));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// otherwise set all platforms available
|
||||||
|
platforms = value.split(', ');
|
||||||
|
}
|
||||||
|
node.platforms = platforms.join(',');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Object.keys(node).length > 0) {
|
||||||
|
builder.nodes.push(node);
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function build(inputBuildRef: string, dest: string, standalone: boolean): Promise<string> {
|
||||||
|
// eslint-disable-next-line prefer-const
|
||||||
|
let [repo, ref] = inputBuildRef.split('#');
|
||||||
|
if (ref.length == 0) {
|
||||||
|
ref = 'master';
|
||||||
|
}
|
||||||
|
|
||||||
|
let vspec: string;
|
||||||
|
if (ref.match(/^[0-9a-fA-F]{40}$/)) {
|
||||||
|
vspec = ref;
|
||||||
|
} else {
|
||||||
|
vspec = await git.getRemoteSha(repo, ref);
|
||||||
|
}
|
||||||
|
core.debug(`Tool version spec ${vspec}`);
|
||||||
|
|
||||||
|
let toolPath: string;
|
||||||
|
toolPath = tc.find('buildx', vspec);
|
||||||
|
if (!toolPath) {
|
||||||
|
const outFolder = path.join(context.tmpDir(), 'out').split(path.sep).join(path.posix.sep);
|
||||||
|
let buildWithStandalone = false;
|
||||||
|
const standaloneFound = await isAvailable(true);
|
||||||
|
const pluginFound = await isAvailable(false);
|
||||||
|
if (standalone && standaloneFound) {
|
||||||
|
core.debug(`Buildx standalone found, build with it`);
|
||||||
|
buildWithStandalone = true;
|
||||||
|
} else if (!standalone && pluginFound) {
|
||||||
|
core.debug(`Buildx plugin found, build with it`);
|
||||||
|
buildWithStandalone = false;
|
||||||
|
} else if (standaloneFound) {
|
||||||
|
core.debug(`Buildx plugin not found, but standalone found so trying to build with it`);
|
||||||
|
buildWithStandalone = true;
|
||||||
|
} else if (pluginFound) {
|
||||||
|
core.debug(`Buildx standalone not found, but plugin found so trying to build with it`);
|
||||||
|
buildWithStandalone = false;
|
||||||
|
} else {
|
||||||
|
throw new Error(`Neither buildx standalone or plugin have been found to build from ref`);
|
||||||
|
}
|
||||||
|
const buildCmd = getCommand(['build', '--target', 'binaries', '--build-arg', 'BUILDKIT_CONTEXT_KEEP_GIT_DIR=1', '--output', `type=local,dest=${outFolder}`, inputBuildRef], buildWithStandalone);
|
||||||
|
toolPath = await exec
|
||||||
|
.getExecOutput(buildCmd.commandLine, buildCmd.args, {
|
||||||
|
ignoreReturnCode: true
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||||
|
core.warning(res.stderr.trim());
|
||||||
|
}
|
||||||
|
return tc.cacheFile(`${outFolder}/buildx`, context.osPlat == 'win32' ? 'docker-buildx.exe' : 'docker-buildx', 'buildx', vspec);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (standalone) {
|
||||||
|
return setStandalone(toolPath, dest);
|
||||||
|
}
|
||||||
|
return setPlugin(toolPath, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function install(inputVersion: string, githubToken: string, dest: string, standalone: boolean): Promise<string> {
|
||||||
|
let release: github.Release;
|
||||||
|
if (inputVersion == 'latest') {
|
||||||
|
release = await github.getLatestRelease(githubToken);
|
||||||
|
} else {
|
||||||
|
release = await github.getReleaseTag(inputVersion, githubToken);
|
||||||
|
}
|
||||||
|
core.debug(`Release ${release.tag_name} found`);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (standalone) {
|
||||||
|
return setStandalone(toolPath, dest);
|
||||||
|
}
|
||||||
|
return setPlugin(toolPath, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setStandalone(toolPath: string, dest: string): Promise<string> {
|
||||||
|
core.info('Standalone mode');
|
||||||
|
const toolBinPath = path.join(toolPath, context.osPlat == 'win32' ? 'docker-buildx.exe' : 'docker-buildx');
|
||||||
|
|
||||||
|
const binDir = path.join(dest, 'bin');
|
||||||
|
core.debug(`Bin dir is ${binDir}`);
|
||||||
|
if (!fs.existsSync(binDir)) {
|
||||||
|
fs.mkdirSync(binDir, {recursive: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
const filename: string = context.osPlat == 'win32' ? 'buildx.exe' : 'buildx';
|
||||||
|
const buildxPath: string = path.join(binDir, filename);
|
||||||
|
core.debug(`Bin path is ${buildxPath}`);
|
||||||
|
fs.copyFileSync(toolBinPath, buildxPath);
|
||||||
|
|
||||||
|
core.info('Fixing perms');
|
||||||
|
fs.chmodSync(buildxPath, '0755');
|
||||||
|
|
||||||
|
core.addPath(binDir);
|
||||||
|
core.info('Added buildx to the path');
|
||||||
|
|
||||||
|
return buildxPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setPlugin(toolPath: string, dockerConfigHome: string): Promise<string> {
|
||||||
|
core.info('Docker plugin mode');
|
||||||
|
const toolBinPath = path.join(toolPath, context.osPlat == 'win32' ? 'docker-buildx.exe' : 'docker-buildx');
|
||||||
|
|
||||||
|
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(toolBinPath, 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));
|
||||||
|
core.info(`Downloading ${downloadUrl}`);
|
||||||
|
const downloadPath = await tc.downloadTool(downloadUrl);
|
||||||
|
core.debug(`Downloaded to ${downloadPath}`);
|
||||||
|
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': {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getBuildKitVersion(containerID: string): Promise<string> {
|
||||||
|
return exec
|
||||||
|
.getExecOutput(`docker`, ['inspect', '--format', '{{.Config.Image}}', containerID], {
|
||||||
|
ignoreReturnCode: true,
|
||||||
|
silent: true
|
||||||
|
})
|
||||||
|
.then(bkitimage => {
|
||||||
|
if (bkitimage.exitCode == 0 && bkitimage.stdout.length > 0) {
|
||||||
|
return exec
|
||||||
|
.getExecOutput(`docker`, ['run', '--rm', bkitimage.stdout.trim(), '--version'], {
|
||||||
|
ignoreReturnCode: true,
|
||||||
|
silent: true
|
||||||
|
})
|
||||||
|
.then(bkitversion => {
|
||||||
|
if (bkitversion.exitCode == 0 && bkitversion.stdout.length > 0) {
|
||||||
|
return `${bkitimage.stdout.trim()} => ${bkitversion.stdout.trim()}`;
|
||||||
|
} else if (bkitversion.stderr.length > 0) {
|
||||||
|
core.warning(bkitversion.stderr.trim());
|
||||||
|
}
|
||||||
|
return bkitversion.stdout.trim();
|
||||||
|
});
|
||||||
|
} else if (bkitimage.stderr.length > 0) {
|
||||||
|
core.warning(bkitimage.stderr.trim());
|
||||||
|
}
|
||||||
|
return bkitimage.stdout.trim();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCommand(args: Array<string>, standalone?: boolean) {
|
||||||
|
return {
|
||||||
|
commandLine: standalone ? 'buildx' : 'docker',
|
||||||
|
args: standalone ? args : ['buildx', ...args]
|
||||||
|
};
|
||||||
|
}
|
136
src/context.ts
136
src/context.ts
@ -1,14 +1,27 @@
|
|||||||
import * as crypto from 'crypto';
|
import fs from 'fs';
|
||||||
|
import * as os from 'os';
|
||||||
|
import path from 'path';
|
||||||
|
import * as tmp from 'tmp';
|
||||||
|
import * as uuid from 'uuid';
|
||||||
|
import {parse} from 'csv-parse/sync';
|
||||||
|
import * as buildx from './buildx';
|
||||||
|
import * as nodes from './nodes';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
|
let _tmpDir: string;
|
||||||
import {Util} from '@docker/actions-toolkit/lib/util';
|
export const osPlat: string = os.platform();
|
||||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
|
export const osArch: string = os.arch();
|
||||||
|
|
||||||
import {Node} from '@docker/actions-toolkit/lib/types/buildx/builder';
|
export function tmpDir(): string {
|
||||||
|
if (!_tmpDir) {
|
||||||
|
_tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-setup-buildx-')).split(path.sep).join(path.posix.sep);
|
||||||
|
}
|
||||||
|
return _tmpDir;
|
||||||
|
}
|
||||||
|
|
||||||
export const builderNodeEnvPrefix = 'BUILDER_NODE';
|
export function tmpNameSync(options?: tmp.TmpNameOptions): string {
|
||||||
const defaultBuildkitdFlags = '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host';
|
return tmp.tmpNameSync(options);
|
||||||
|
}
|
||||||
|
|
||||||
export interface Inputs {
|
export interface Inputs {
|
||||||
version: string;
|
version: string;
|
||||||
@ -16,50 +29,46 @@ export interface Inputs {
|
|||||||
driver: string;
|
driver: string;
|
||||||
driverOpts: string[];
|
driverOpts: string[];
|
||||||
buildkitdFlags: string;
|
buildkitdFlags: string;
|
||||||
buildkitdConfig: string;
|
|
||||||
buildkitdConfigInline: string;
|
|
||||||
platforms: string[];
|
platforms: string[];
|
||||||
install: boolean;
|
install: boolean;
|
||||||
use: boolean;
|
use: boolean;
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
|
config: string;
|
||||||
|
configInline: string;
|
||||||
append: string;
|
append: string;
|
||||||
cacheBinary: boolean;
|
githubToken: string;
|
||||||
cleanup: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getInputs(): Promise<Inputs> {
|
export async function getInputs(): Promise<Inputs> {
|
||||||
return {
|
return {
|
||||||
version: core.getInput('version'),
|
version: core.getInput('version'),
|
||||||
name: await getBuilderName(core.getInput('driver') || 'docker-container'),
|
name: getBuilderName(core.getInput('driver') || 'docker-container'),
|
||||||
driver: core.getInput('driver') || 'docker-container',
|
driver: core.getInput('driver') || 'docker-container',
|
||||||
driverOpts: Util.getInputList('driver-opts', {ignoreComma: true, quote: false}),
|
driverOpts: await getInputList('driver-opts', true),
|
||||||
buildkitdFlags: core.getInput('buildkitd-flags'),
|
buildkitdFlags: core.getInput('buildkitd-flags') || '--allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
|
||||||
platforms: Util.getInputList('platforms'),
|
platforms: await getInputList('platforms', false, true),
|
||||||
install: core.getBooleanInput('install'),
|
install: core.getBooleanInput('install'),
|
||||||
use: core.getBooleanInput('use'),
|
use: core.getBooleanInput('use'),
|
||||||
endpoint: core.getInput('endpoint'),
|
endpoint: core.getInput('endpoint'),
|
||||||
buildkitdConfig: core.getInput('buildkitd-config') || core.getInput('config'),
|
config: core.getInput('config'),
|
||||||
buildkitdConfigInline: core.getInput('buildkitd-config-inline') || core.getInput('config-inline'),
|
configInline: core.getInput('config-inline'),
|
||||||
append: core.getInput('append'),
|
append: core.getInput('append'),
|
||||||
cacheBinary: core.getBooleanInput('cache-binary'),
|
githubToken: core.getInput('github_token')
|
||||||
cleanup: core.getBooleanInput('cleanup')
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getBuilderName(driver: string): Promise<string> {
|
export function getBuilderName(driver: string): string {
|
||||||
return driver == 'docker' ? await Docker.context() : `builder-${crypto.randomUUID()}`;
|
return driver == 'docker' ? 'default' : `builder-${uuid.v4()}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getCreateArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> {
|
export async function getCreateArgs(inputs: Inputs, buildxVersion: string): Promise<Array<string>> {
|
||||||
const args: Array<string> = ['create', '--name', inputs.name, '--driver', inputs.driver];
|
const args: Array<string> = ['create', '--name', inputs.name, '--driver', inputs.driver];
|
||||||
if (await toolkit.buildx.versionSatisfies('>=0.3.0')) {
|
if (buildx.satisfies(buildxVersion, '>=0.3.0')) {
|
||||||
await Util.asyncForEach(inputs.driverOpts, async (driverOpt: string) => {
|
await asyncForEach(inputs.driverOpts, async driverOpt => {
|
||||||
args.push('--driver-opt', driverOpt);
|
args.push('--driver-opt', driverOpt);
|
||||||
});
|
});
|
||||||
if (inputs.buildkitdFlags) {
|
if (inputs.driver != 'remote' && inputs.buildkitdFlags) {
|
||||||
args.push('--buildkitd-flags', inputs.buildkitdFlags);
|
args.push('--buildkitd-flags', inputs.buildkitdFlags);
|
||||||
} else if (driverSupportsBuildkitdFlags(inputs.driver)) {
|
|
||||||
args.push('--buildkitd-flags', defaultBuildkitdFlags);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inputs.platforms.length > 0) {
|
if (inputs.platforms.length > 0) {
|
||||||
@ -68,10 +77,12 @@ export async function getCreateArgs(inputs: Inputs, toolkit: Toolkit): Promise<A
|
|||||||
if (inputs.use) {
|
if (inputs.use) {
|
||||||
args.push('--use');
|
args.push('--use');
|
||||||
}
|
}
|
||||||
if (inputs.buildkitdConfig) {
|
if (inputs.driver != 'remote') {
|
||||||
args.push('--config', toolkit.buildkit.config.resolveFromFile(inputs.buildkitdConfig));
|
if (inputs.config) {
|
||||||
} else if (inputs.buildkitdConfigInline) {
|
args.push('--config', await buildx.getConfigFile(inputs.config));
|
||||||
args.push('--config', toolkit.buildkit.config.resolveFromString(inputs.buildkitdConfigInline));
|
} else if (inputs.configInline) {
|
||||||
|
args.push('--config', await buildx.getConfigInline(inputs.configInline));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (inputs.endpoint) {
|
if (inputs.endpoint) {
|
||||||
args.push(inputs.endpoint);
|
args.push(inputs.endpoint);
|
||||||
@ -79,21 +90,17 @@ export async function getCreateArgs(inputs: Inputs, toolkit: Toolkit): Promise<A
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getAppendArgs(inputs: Inputs, node: Node, toolkit: Toolkit): Promise<Array<string>> {
|
export async function getAppendArgs(inputs: Inputs, node: nodes.Node, buildxVersion: string): Promise<Array<string>> {
|
||||||
const args: Array<string> = ['create', '--name', inputs.name, '--append'];
|
const args: Array<string> = ['create', '--name', inputs.name, '--append'];
|
||||||
if (node.name) {
|
if (node.name) {
|
||||||
args.push('--node', 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'))) {
|
if (node['driver-opts'] && buildx.satisfies(buildxVersion, '>=0.3.0')) {
|
||||||
await Util.asyncForEach(node['driver-opts'], async (driverOpt: string) => {
|
await asyncForEach(node['driver-opts'], async driverOpt => {
|
||||||
args.push('--driver-opt', driverOpt);
|
args.push('--driver-opt', driverOpt);
|
||||||
});
|
});
|
||||||
if (node['buildkitd-flags']) {
|
if (inputs.driver != 'remote' && node['buildkitd-flags']) {
|
||||||
args.push('--buildkitd-flags', node['buildkitd-flags']);
|
args.push('--buildkitd-flags', node['buildkitd-flags']);
|
||||||
} else if (driverSupportsBuildkitdFlags(inputs.driver)) {
|
|
||||||
args.push('--buildkitd-flags', defaultBuildkitdFlags);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node.platforms) {
|
if (node.platforms) {
|
||||||
@ -105,28 +112,47 @@ export async function getAppendArgs(inputs: Inputs, node: Node, toolkit: Toolkit
|
|||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getInspectArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> {
|
export async function getInspectArgs(inputs: Inputs, buildxVersion: string): Promise<Array<string>> {
|
||||||
const args: Array<string> = ['inspect', '--bootstrap'];
|
const args: Array<string> = ['inspect', '--bootstrap'];
|
||||||
if (await toolkit.buildx.versionSatisfies('>=0.4.0')) {
|
if (buildx.satisfies(buildxVersion, '>=0.4.0')) {
|
||||||
args.push('--builder', inputs.name);
|
args.push('--builder', inputs.name);
|
||||||
}
|
}
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
function driverSupportsBuildkitdFlags(driver: string): boolean {
|
export async function getInputList(name: string, ignoreComma?: boolean, escapeQuotes?: boolean): Promise<string[]> {
|
||||||
return driver == '' || driver == 'docker-container' || driver == 'docker' || driver == 'kubernetes';
|
const res: Array<string> = [];
|
||||||
|
|
||||||
|
const items = core.getInput(name);
|
||||||
|
if (items == '') {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const records = parse(items, {
|
||||||
|
columns: false,
|
||||||
|
relaxQuotes: true,
|
||||||
|
comment: '#',
|
||||||
|
relaxColumnCount: true,
|
||||||
|
skipEmptyLines: true,
|
||||||
|
quote: escapeQuotes ? `"` : false
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const record of records as Array<string[]>) {
|
||||||
|
if (record.length == 1) {
|
||||||
|
res.push(record[0]);
|
||||||
|
continue;
|
||||||
|
} else if (!ignoreComma) {
|
||||||
|
res.push(...record);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
res.push(record.join(','));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.filter(item => item).map(pat => pat.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getVersion(inputs: Inputs): string {
|
export const asyncForEach = async (array, callback) => {
|
||||||
const version = inputs.version;
|
for (let index = 0; index < array.length; index++) {
|
||||||
if (inputs.driver === 'cloud') {
|
await callback(array[index], index, array);
|
||||||
if (!version || version === 'latest') {
|
|
||||||
return 'cloud:latest';
|
|
||||||
}
|
}
|
||||||
if (version.startsWith('cloud:') || version.startsWith('lab:')) {
|
};
|
||||||
return version;
|
|
||||||
}
|
|
||||||
return `cloud:${version}`;
|
|
||||||
}
|
|
||||||
return version;
|
|
||||||
}
|
|
||||||
|
19
src/docker.ts
Normal file
19
src/docker.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import * as exec from '@actions/exec';
|
||||||
|
|
||||||
|
export async function isAvailable(): Promise<boolean> {
|
||||||
|
return await exec
|
||||||
|
.getExecOutput('docker', undefined, {
|
||||||
|
ignoreReturnCode: true,
|
||||||
|
silent: true
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return res.exitCode == 0;
|
||||||
|
})
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
.catch(error => {
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
19
src/git.ts
Normal file
19
src/git.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import * as exec from '@actions/exec';
|
||||||
|
|
||||||
|
export async function getRemoteSha(repo: string, ref: string): Promise<string> {
|
||||||
|
return await exec
|
||||||
|
.getExecOutput(`git`, ['ls-remote', repo, ref], {
|
||||||
|
ignoreReturnCode: true,
|
||||||
|
silent: true
|
||||||
|
})
|
||||||
|
.then(res => {
|
||||||
|
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||||
|
throw new Error(res.stderr);
|
||||||
|
}
|
||||||
|
const [rsha] = res.stdout.trim().split(/[\s\t]/);
|
||||||
|
if (rsha.length == 0) {
|
||||||
|
throw new Error(`Cannot find remote ref for ${repo}#${ref}`);
|
||||||
|
}
|
||||||
|
return rsha;
|
||||||
|
});
|
||||||
|
}
|
41
src/github.ts
Normal file
41
src/github.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import * as github from '@actions/github';
|
||||||
|
|
||||||
|
export interface Release {
|
||||||
|
id: number;
|
||||||
|
tag_name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [owner, repo] = 'docker/buildx'.split('/');
|
||||||
|
|
||||||
|
export const getReleaseTag = async (tag: string, githubToken: string): Promise<Release> => {
|
||||||
|
return (
|
||||||
|
await github
|
||||||
|
.getOctokit(githubToken, {
|
||||||
|
baseUrl: 'https://api.github.com'
|
||||||
|
})
|
||||||
|
.rest.repos.getReleaseByTag({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
tag
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
throw new Error(`Cannot get release ${tag}: ${error}`);
|
||||||
|
})
|
||||||
|
).data as Release;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getLatestRelease = async (githubToken: string): Promise<Release> => {
|
||||||
|
return (
|
||||||
|
await github
|
||||||
|
.getOctokit(githubToken, {
|
||||||
|
baseUrl: 'https://api.github.com'
|
||||||
|
})
|
||||||
|
.rest.repos.getLatestRelease({
|
||||||
|
owner,
|
||||||
|
repo
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
throw new Error(`Cannot get latest release: ${error}`);
|
||||||
|
})
|
||||||
|
).data as Release;
|
||||||
|
};
|
319
src/main.ts
319
src/main.ts
@ -1,201 +1,111 @@
|
|||||||
import * as crypto from 'crypto';
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as yaml from 'js-yaml';
|
import * as os from 'os';
|
||||||
import * as core from '@actions/core';
|
import * as path from 'path';
|
||||||
import * as actionsToolkit from '@docker/actions-toolkit';
|
import * as auth from './auth';
|
||||||
|
import * as buildx from './buildx';
|
||||||
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 context from './context';
|
import * as context from './context';
|
||||||
|
import * as docker from './docker';
|
||||||
|
import * as nodes from './nodes';
|
||||||
import * as stateHelper from './state-helper';
|
import * as stateHelper from './state-helper';
|
||||||
|
import * as util from './util';
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
import * as exec from '@actions/exec';
|
||||||
|
|
||||||
actionsToolkit.run(
|
async function run(): Promise<void> {
|
||||||
// main
|
try {
|
||||||
async () => {
|
|
||||||
const inputs: context.Inputs = await context.getInputs();
|
const inputs: context.Inputs = await context.getInputs();
|
||||||
stateHelper.setCleanup(inputs.cleanup);
|
const dockerConfigHome: string = process.env.DOCKER_CONFIG || path.join(os.homedir(), '.docker');
|
||||||
const version = context.getVersion(inputs);
|
|
||||||
|
|
||||||
const toolkit = new Toolkit();
|
// standalone if docker cli not available
|
||||||
const standalone = await toolkit.buildx.isStandalone();
|
const standalone = !(await docker.isAvailable());
|
||||||
stateHelper.setStandalone(standalone);
|
stateHelper.setStandalone(standalone);
|
||||||
|
|
||||||
await core.group(`Docker info`, async () => {
|
core.startGroup(`Docker info`);
|
||||||
try {
|
if (standalone) {
|
||||||
await Docker.printVersion();
|
core.info(`Docker info skipped in standalone mode`);
|
||||||
await Docker.printInfo();
|
} else {
|
||||||
} catch (e) {
|
await exec.exec('docker', ['version'], {
|
||||||
core.info(e.message);
|
failOnStdErr: false
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
await exec.exec('docker', ['info'], {
|
||||||
|
failOnStdErr: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
core.endGroup();
|
||||||
|
|
||||||
let toolPath;
|
if (util.isValidUrl(inputs.version)) {
|
||||||
if (Util.isValidRef(version)) {
|
|
||||||
if (standalone) {
|
if (standalone) {
|
||||||
throw new Error(`Cannot build from source without the Docker CLI`);
|
throw new Error(`Cannot build from source without the Docker CLI`);
|
||||||
}
|
}
|
||||||
await core.group(`Build buildx from source`, async () => {
|
core.startGroup(`Build and install buildx`);
|
||||||
toolPath = await toolkit.buildxInstall.build(version, !inputs.cacheBinary);
|
await buildx.build(inputs.version, dockerConfigHome, standalone);
|
||||||
});
|
core.endGroup();
|
||||||
} else if (!(await toolkit.buildx.isAvailable()) || version) {
|
} else if (!(await buildx.isAvailable(standalone)) || inputs.version) {
|
||||||
await core.group(`Download buildx from GitHub Releases`, async () => {
|
core.startGroup(`Download and install buildx`);
|
||||||
toolPath = await toolkit.buildxInstall.download(version || 'latest', !inputs.cacheBinary);
|
await buildx.install(inputs.version || 'latest', inputs.githubToken, standalone ? context.tmpDir() : dockerConfigHome, standalone);
|
||||||
});
|
core.endGroup();
|
||||||
}
|
|
||||||
if (toolPath) {
|
|
||||||
await core.group(`Install buildx`, async () => {
|
|
||||||
if (standalone) {
|
|
||||||
await toolkit.buildxInstall.installStandalone(toolPath);
|
|
||||||
} else {
|
|
||||||
await toolkit.buildxInstall.installPlugin(toolPath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const buildxVersion = await buildx.getVersion(standalone);
|
||||||
await core.group(`Buildx version`, async () => {
|
await core.group(`Buildx version`, async () => {
|
||||||
await toolkit.buildx.printVersion();
|
const versionCmd = buildx.getCommand(['version'], standalone);
|
||||||
|
await exec.exec(versionCmd.commandLine, versionCmd.args, {
|
||||||
|
failOnStdErr: false
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
core.setOutput('name', inputs.name);
|
core.setOutput('name', inputs.name);
|
||||||
stateHelper.setBuilderName(inputs.name);
|
stateHelper.setBuilderName(inputs.name);
|
||||||
stateHelper.setBuilderDriver(inputs.driver);
|
|
||||||
|
|
||||||
fs.mkdirSync(Buildx.certsDir, {recursive: true});
|
const credsdir = path.join(dockerConfigHome, 'buildx', 'creds', inputs.name);
|
||||||
stateHelper.setCertsDir(Buildx.certsDir);
|
fs.mkdirSync(credsdir, {recursive: true});
|
||||||
|
stateHelper.setCredsDir(credsdir);
|
||||||
// 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') {
|
if (inputs.driver !== 'docker') {
|
||||||
await core.group(`Creating a new builder instance`, async () => {
|
core.startGroup(`Creating a new builder instance`);
|
||||||
const certsDriverOpts = Buildx.resolveCertsDriverOpts(inputs.driver, inputs.endpoint, {
|
const authOpts = auth.setCredentials(credsdir, 0, inputs.driver, inputs.endpoint);
|
||||||
cacert: process.env[`${context.builderNodeEnvPrefix}_0_AUTH_TLS_CACERT`],
|
if (authOpts.length > 0) {
|
||||||
cert: process.env[`${context.builderNodeEnvPrefix}_0_AUTH_TLS_CERT`],
|
inputs.driverOpts = [...inputs.driverOpts, ...authOpts];
|
||||||
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));
|
const createCmd = buildx.getCommand(await context.getCreateArgs(inputs, buildxVersion), standalone);
|
||||||
await Exec.getExecOutput(createCmd.command, createCmd.args, {
|
await exec.exec(createCmd.commandLine, createCmd.args);
|
||||||
ignoreReturnCode: true
|
core.endGroup();
|
||||||
}).then(res => {
|
|
||||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
|
||||||
throw new Error(res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputs.append) {
|
if (inputs.append) {
|
||||||
await core.group(`Appending node(s) to builder`, async () => {
|
core.startGroup(`Appending node(s) to builder`);
|
||||||
let nodeIndex = 1;
|
let nodeIndex = 1;
|
||||||
const nodes = yaml.load(inputs.append) as Node[];
|
for (const node of nodes.Parse(inputs.append)) {
|
||||||
for (const node of nodes) {
|
const authOpts = auth.setCredentials(credsdir, nodeIndex, inputs.driver, node.endpoint || '');
|
||||||
const certsDriverOpts = Buildx.resolveCertsDriverOpts(inputs.driver, `${node.endpoint}`, {
|
if (authOpts.length > 0) {
|
||||||
cacert: process.env[`${context.builderNodeEnvPrefix}_${nodeIndex}_AUTH_TLS_CACERT`],
|
node['driver-opts'] = [...(node['driver-opts'] || []), ...authOpts];
|
||||||
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));
|
const appendCmd = buildx.getCommand(await context.getAppendArgs(inputs, node, buildxVersion), standalone);
|
||||||
await Exec.getExecOutput(appendCmd.command, appendCmd.args, {
|
await exec.exec(appendCmd.commandLine, 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++;
|
nodeIndex++;
|
||||||
}
|
}
|
||||||
});
|
core.endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
await core.group(`Booting builder`, async () => {
|
core.startGroup(`Booting builder`);
|
||||||
const inspectCmd = await toolkit.buildx.getCommand(await context.getInspectArgs(inputs, toolkit));
|
const inspectCmd = buildx.getCommand(await context.getInspectArgs(inputs, buildxVersion), standalone);
|
||||||
await Exec.getExecOutput(inspectCmd.command, inspectCmd.args, {
|
await exec.exec(inspectCmd.commandLine, inspectCmd.args);
|
||||||
ignoreReturnCode: true
|
core.endGroup();
|
||||||
}).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 (inputs.install) {
|
||||||
if (standalone) {
|
if (standalone) {
|
||||||
throw new Error(`Cannot set buildx as default builder without the Docker CLI`);
|
throw new Error(`Cannot set buildx as default builder without the Docker CLI`);
|
||||||
}
|
}
|
||||||
await core.group(`Setting buildx as default builder`, async () => {
|
core.startGroup(`Setting buildx as default builder`);
|
||||||
const installCmd = await toolkit.buildx.getCommand(['install']);
|
await exec.exec('docker', ['buildx', 'install']);
|
||||||
await Exec.getExecOutput(installCmd.command, installCmd.args, {
|
core.endGroup();
|
||||||
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);
|
core.startGroup(`Inspect builder`);
|
||||||
const firstNode = builderInspect.nodes[0];
|
const builder = await buildx.inspect(inputs.name, standalone);
|
||||||
|
const firstNode = builder.nodes[0];
|
||||||
await core.group(`Inspect builder`, async () => {
|
|
||||||
const reducedPlatforms: Array<string> = [];
|
const reducedPlatforms: Array<string> = [];
|
||||||
for (const node of builderInspect.nodes) {
|
for (const node of builder.nodes) {
|
||||||
for (const platform of node.platforms?.split(',') || []) {
|
for (const platform of node.platforms?.split(',') || []) {
|
||||||
if (reducedPlatforms.indexOf(platform) > -1) {
|
if (reducedPlatforms.indexOf(platform) > -1) {
|
||||||
continue;
|
continue;
|
||||||
@ -203,81 +113,70 @@ actionsToolkit.run(
|
|||||||
reducedPlatforms.push(platform);
|
reducedPlatforms.push(platform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
core.info(JSON.stringify(builderInspect, undefined, 2));
|
core.info(JSON.stringify(builder, undefined, 2));
|
||||||
core.setOutput('driver', builderInspect.driver);
|
core.setOutput('driver', builder.driver);
|
||||||
core.setOutput('platforms', reducedPlatforms.join(','));
|
core.setOutput('platforms', reducedPlatforms.join(','));
|
||||||
core.setOutput('nodes', JSON.stringify(builderInspect.nodes, undefined, 2));
|
core.setOutput('nodes', JSON.stringify(builder.nodes, undefined, 2));
|
||||||
core.setOutput('endpoint', firstNode.endpoint); // TODO: deprecated, to be removed in a later version
|
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('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
|
core.setOutput('flags', firstNode['buildkitd-flags']); // TODO: deprecated, to be removed in a later version
|
||||||
});
|
core.endGroup();
|
||||||
|
|
||||||
if (!standalone && builderInspect.driver == 'docker-container') {
|
if (!standalone && builder.driver == 'docker-container') {
|
||||||
stateHelper.setContainerName(`${Buildx.containerNamePrefix}${firstNode.name}`);
|
stateHelper.setContainerName(`buildx_buildkit_${firstNode.name}`);
|
||||||
await core.group(`BuildKit version`, async () => {
|
core.startGroup(`BuildKit version`);
|
||||||
for (const node of builderInspect.nodes) {
|
for (const node of builder.nodes) {
|
||||||
const buildkitVersion = await toolkit.buildkit.getVersion(node);
|
const bkvers = await buildx.getBuildKitVersion(`buildx_buildkit_${node.name}`);
|
||||||
core.info(`${node.name}: ${buildkitVersion}`);
|
core.info(`${node.name}: ${bkvers}`);
|
||||||
}
|
}
|
||||||
});
|
core.endGroup();
|
||||||
}
|
}
|
||||||
if (core.isDebug() || firstNode['buildkitd-flags']?.includes('--debug')) {
|
if (core.isDebug() || firstNode['buildkitd-flags']?.includes('--debug')) {
|
||||||
stateHelper.setDebug('true');
|
stateHelper.setDebug('true');
|
||||||
}
|
}
|
||||||
},
|
} catch (error) {
|
||||||
// post
|
core.setFailed(error.message);
|
||||||
async () => {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function cleanup(): Promise<void> {
|
||||||
if (stateHelper.IsDebug && stateHelper.containerName.length > 0) {
|
if (stateHelper.IsDebug && stateHelper.containerName.length > 0) {
|
||||||
await core.group(`BuildKit container logs`, async () => {
|
core.startGroup(`BuildKit container logs`);
|
||||||
await Docker.getExecOutput(['logs', `${stateHelper.containerName}`], {
|
await exec
|
||||||
|
.getExecOutput('docker', ['logs', `${stateHelper.containerName}`], {
|
||||||
ignoreReturnCode: true
|
ignoreReturnCode: true
|
||||||
}).then(res => {
|
})
|
||||||
|
.then(res => {
|
||||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||||
core.warning(res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error');
|
core.warning(res.stderr.trim());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
core.endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!stateHelper.cleanup) {
|
if (stateHelper.builderName.length > 0) {
|
||||||
return;
|
core.startGroup(`Removing builder`);
|
||||||
}
|
const rmCmd = buildx.getCommand(['rm', stateHelper.builderName], /true/i.test(stateHelper.standalone));
|
||||||
|
await exec
|
||||||
if (stateHelper.builderDriver != 'docker' && stateHelper.builderName.length > 0) {
|
.getExecOutput(rmCmd.commandLine, rmCmd.args, {
|
||||||
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]);
|
|
||||||
await Exec.getExecOutput(rmCmd.command, rmCmd.args, {
|
|
||||||
ignoreReturnCode: true
|
ignoreReturnCode: true
|
||||||
}).then(res => {
|
})
|
||||||
|
.then(res => {
|
||||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||||
core.warning(res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error');
|
core.warning(res.stderr.trim());
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
core.info(`${stateHelper.builderName} does not exist`);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
core.endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stateHelper.tmpDockerContext) {
|
if (stateHelper.credsDir.length > 0 && fs.existsSync(stateHelper.credsDir)) {
|
||||||
await core.group(`Removing temp docker context`, async () => {
|
core.info(`Cleaning up credentials`);
|
||||||
await Exec.getExecOutput('docker', ['context', 'rm', '-f', stateHelper.tmpDockerContext], {
|
fs.rmSync(stateHelper.credsDir, {recursive: true});
|
||||||
ignoreReturnCode: true
|
|
||||||
}).then(res => {
|
|
||||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
|
||||||
core.warning(`${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (stateHelper.certsDir.length > 0 && fs.existsSync(stateHelper.certsDir)) {
|
if (!stateHelper.IsPost) {
|
||||||
await core.group(`Cleaning up certificates`, async () => {
|
run();
|
||||||
fs.rmSync(stateHelper.certsDir, {recursive: true});
|
} else {
|
||||||
});
|
cleanup();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
);
|
|
||||||
|
13
src/nodes.ts
Normal file
13
src/nodes.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import * as yaml from 'js-yaml';
|
||||||
|
|
||||||
|
export type Node = {
|
||||||
|
name?: string;
|
||||||
|
endpoint?: string;
|
||||||
|
'driver-opts'?: Array<string>;
|
||||||
|
'buildkitd-flags'?: string;
|
||||||
|
platforms?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function Parse(data: string): Node[] {
|
||||||
|
return yaml.load(data) as Node[];
|
||||||
|
}
|
@ -1,13 +1,11 @@
|
|||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
|
export const IsPost = !!process.env['STATE_isPost'];
|
||||||
export const IsDebug = !!process.env['STATE_isDebug'];
|
export const IsDebug = !!process.env['STATE_isDebug'];
|
||||||
export const standalone = /true/i.test(process.env['STATE_standalone'] || '');
|
export const standalone = process.env['STATE_standalone'] || '';
|
||||||
export const builderName = process.env['STATE_builderName'] || '';
|
export const builderName = process.env['STATE_builderName'] || '';
|
||||||
export const builderDriver = process.env['STATE_builderDriver'] || '';
|
|
||||||
export const containerName = process.env['STATE_containerName'] || '';
|
export const containerName = process.env['STATE_containerName'] || '';
|
||||||
export const certsDir = process.env['STATE_certsDir'] || '';
|
export const credsDir = process.env['STATE_credsDir'] || '';
|
||||||
export const tmpDockerContext = process.env['STATE_tmpDockerContext'] || '';
|
|
||||||
export const cleanup = /true/i.test(process.env['STATE_cleanup'] || '');
|
|
||||||
|
|
||||||
export function setDebug(debug: string) {
|
export function setDebug(debug: string) {
|
||||||
core.saveState('isDebug', debug);
|
core.saveState('isDebug', debug);
|
||||||
@ -21,22 +19,14 @@ export function setBuilderName(builderName: string) {
|
|||||||
core.saveState('builderName', builderName);
|
core.saveState('builderName', builderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setBuilderDriver(builderDriver: string) {
|
|
||||||
core.saveState('builderDriver', builderDriver);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setContainerName(containerName: string) {
|
export function setContainerName(containerName: string) {
|
||||||
core.saveState('containerName', containerName);
|
core.saveState('containerName', containerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setCertsDir(certsDir: string) {
|
export function setCredsDir(credsDir: string) {
|
||||||
core.saveState('certsDir', certsDir);
|
core.saveState('credsDir', credsDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setTmpDockerContext(tmpDockerContext: string) {
|
if (!IsPost) {
|
||||||
core.saveState('tmpDockerContext', tmpDockerContext);
|
core.saveState('isPost', 'true');
|
||||||
}
|
|
||||||
|
|
||||||
export function setCleanup(cleanup: boolean) {
|
|
||||||
core.saveState('cleanup', cleanup);
|
|
||||||
}
|
}
|
||||||
|
8
src/util.ts
Normal file
8
src/util.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export function isValidUrl(url: string): boolean {
|
||||||
|
try {
|
||||||
|
new URL(url);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
@ -1,21 +1,19 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"esModuleInterop": true,
|
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"strict": true,
|
|
||||||
"newLine": "lf",
|
"newLine": "lf",
|
||||||
"outDir": "./lib",
|
"outDir": "./lib",
|
||||||
"rootDir": "./src",
|
"rootDir": "./src",
|
||||||
|
"esModuleInterop": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
"noImplicitAny": false,
|
"noImplicitAny": false,
|
||||||
"resolveJsonModule": true,
|
|
||||||
"useUnknownInCatchVariables": false,
|
"useUnknownInCatchVariables": false,
|
||||||
},
|
},
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"./__tests__/**/*",
|
|
||||||
"./lib/**/*",
|
|
||||||
"node_modules",
|
"node_modules",
|
||||||
|
"**/*.test.ts",
|
||||||
"jest.config.ts"
|
"jest.config.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user