Compare commits
No commits in common. 'master' and 'v3.1.1' 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,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
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
* @crazy-max
|
@ -1,3 +0,0 @@
|
|||||||
# Code of conduct
|
|
||||||
|
|
||||||
- [Moby community guidelines](https://github.com/moby/moby/blob/master/CONTRIBUTING.md#moby-community-guidelines)
|
|
@ -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).
|
|
||||||
Before submitting a bug report, check out the [Troubleshooting doc](https://github.com/docker/build-push-action/blob/master/TROUBLESHOOTING.md).
|
|
||||||
|
|
||||||
- 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/build-push-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.
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: YAML workflow
|
|
||||||
description: |
|
|
||||||
Provide the YAML of the workflow that's causing the issue.
|
|
||||||
Make sure to remove any sensitive information.
|
|
||||||
render: yaml
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Workflow logs
|
|
||||||
description: >
|
|
||||||
[Attach](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/attaching-files)
|
|
||||||
the [log file of your workflow run](https://docs.github.com/en/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs)
|
|
||||||
and make sure to remove any sensitive information.
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: BuildKit logs
|
|
||||||
description: >
|
|
||||||
If applicable, provide the [BuildKit container logs](https://docs.docker.com/build/ci/github-actions/configure-builder/#buildkit-container-logs)
|
|
||||||
render: text
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Additional info
|
|
||||||
description: |
|
|
||||||
Provide any additional information that could be useful.
|
|
@ -0,0 +1,37 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
---
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
Before submitting a bug report please read the [Troubleshooting doc](https://github.com/docker/build-push-action/blob/master/TROUBLESHOOTING.md).
|
||||||
|
|
||||||
|
### Behaviour
|
||||||
|
|
||||||
|
#### Steps to reproduce this issue
|
||||||
|
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
|
||||||
|
#### Expected behaviour
|
||||||
|
|
||||||
|
> Tell us what should happen
|
||||||
|
|
||||||
|
#### Actual behaviour
|
||||||
|
|
||||||
|
> Tell us what happens instead
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
* Repository URL (if public):
|
||||||
|
* Build URL (if public):
|
||||||
|
|
||||||
|
```yml
|
||||||
|
# paste your YAML workflow file here and remove sensitive data
|
||||||
|
```
|
||||||
|
|
||||||
|
### Logs
|
||||||
|
|
||||||
|
> Download the [log file of your build](https://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.
|
@ -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/build-push-action/discussions/new
|
|
||||||
about: Use Github Discussions to ask questions and/or open discussion topics.
|
|
||||||
- name: Documentation
|
|
||||||
url: https://docs.docker.com/build/ci/github-actions/
|
|
||||||
about: Read the documentation.
|
|
@ -1,15 +0,0 @@
|
|||||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
|
||||||
name: Feature request
|
|
||||||
description: Missing functionality? Come tell us about it!
|
|
||||||
labels:
|
|
||||||
- kind/enhancement
|
|
||||||
- status/triage
|
|
||||||
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: Description
|
|
||||||
description: What is the feature you want to see?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
@ -1,12 +0,0 @@
|
|||||||
# Reporting security issues
|
|
||||||
|
|
||||||
The project maintainers take security seriously. If you discover a security
|
|
||||||
issue, please bring it to their attention right away!
|
|
||||||
|
|
||||||
**Please _DO NOT_ file a public issue**, instead send your report privately to
|
|
||||||
[security@docker.com](mailto:security@docker.com).
|
|
||||||
|
|
||||||
Security reports are greatly appreciated, and we will publicly thank you for it.
|
|
||||||
We also like to send gifts—if you'd like Docker swag, make sure to let
|
|
||||||
us know. We currently do not offer a paid security bounty program, but are not
|
|
||||||
ruling it out in the future.
|
|
@ -0,0 +1,31 @@
|
|||||||
|
# Support [](https://isitmaintained.com/project/docker/build-push-action)
|
||||||
|
|
||||||
|
First, [be a good guy](https://github.com/kossnocorp/etiquette/blob/master/README.md).
|
||||||
|
|
||||||
|
## Reporting an issue
|
||||||
|
|
||||||
|
Please do a search in [open issues](https://github.com/docker/build-push-action/issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed.
|
||||||
|
|
||||||
|
If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment.
|
||||||
|
|
||||||
|
:+1: - upvote
|
||||||
|
|
||||||
|
:-1: - downvote
|
||||||
|
|
||||||
|
If you cannot find an existing issue that describes your bug or feature, submit an issue using the guidelines below.
|
||||||
|
|
||||||
|
## Writing good bug reports and feature requests
|
||||||
|
|
||||||
|
File a single issue per problem and feature request.
|
||||||
|
|
||||||
|
* Do not enumerate multiple bugs or feature requests in the same issue.
|
||||||
|
* Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes.
|
||||||
|
|
||||||
|
The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix.
|
||||||
|
|
||||||
|
You are now ready to [create a new issue](https://github.com/docker/build-push-action/issues/new/choose)!
|
||||||
|
|
||||||
|
## Closure policy
|
||||||
|
|
||||||
|
* Issues that don't have the information requested above (when applicable) will be closed immediately and the poster directed to the support guidelines.
|
||||||
|
* Issues that go a week without a response from original poster are subject to closure at our discretion.
|
Binary file not shown.
Before Width: | Height: | Size: 81 KiB |
@ -1,5 +0,0 @@
|
|||||||
REGISTRY_FQDN=localhost:8080
|
|
||||||
REGISTRY_SLUG=localhost:8080/test-docker-action
|
|
||||||
|
|
||||||
DISTRIBUTION_HOST=localhost
|
|
||||||
DISTRIBUTION_PORT=8080
|
|
@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
: "${DISTRIBUTION_VERSION:=2}"
|
|
||||||
: "${DISTRIBUTION_HOST:=localhost}"
|
|
||||||
: "${DISTRIBUTION_PORT:=8080}"
|
|
||||||
|
|
||||||
echo "::group::Starting registry:${DISTRIBUTION_VERSION}"
|
|
||||||
(
|
|
||||||
set -x
|
|
||||||
docker run -d --name registry -p "${DISTRIBUTION_PORT}:5000" "registry:${DISTRIBUTION_VERSION}"
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
@ -1,8 +0,0 @@
|
|||||||
REGISTRY_FQDN=localhost:8081
|
|
||||||
REGISTRY_USER=admin
|
|
||||||
REGISTRY_PASSWORD=Harbor12345
|
|
||||||
REGISTRY_SLUG=localhost:8081/test-docker-action/test-docker-action
|
|
||||||
|
|
||||||
HARBOR_HOST=localhost
|
|
||||||
HARBOR_PORT=8081
|
|
||||||
HARBOR_PROJECT=test-docker-action
|
|
@ -1,79 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
: "${HARBOR_VERSION:=v2.7.0}"
|
|
||||||
: "${HARBOR_HOST:=localhost}"
|
|
||||||
: "${HARBOR_PORT:=49154}"
|
|
||||||
: "${REGISTRY_USER:=admin}"
|
|
||||||
: "${REGISTRY_PASSWORD:=Harbor12345}"
|
|
||||||
|
|
||||||
: "${HARBOR_PROJECT:=test-docker-action}"
|
|
||||||
|
|
||||||
project_post_data() {
|
|
||||||
cat <<EOF
|
|
||||||
{
|
|
||||||
"project_name": "$HARBOR_PROJECT",
|
|
||||||
"public": true
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
export TERM=xterm
|
|
||||||
|
|
||||||
# download
|
|
||||||
echo "::group::Downloading Harbor $HARBOR_VERSION"
|
|
||||||
(
|
|
||||||
cd /tmp
|
|
||||||
set -x
|
|
||||||
wget -q "https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-offline-installer-${HARBOR_VERSION}.tgz" -O harbor-online-installer.tgz
|
|
||||||
tar xvf harbor-online-installer.tgz
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
# config
|
|
||||||
echo "::group::Configuring Harbor"
|
|
||||||
(
|
|
||||||
cd /tmp/harbor
|
|
||||||
set -x
|
|
||||||
cp harbor.yml.tmpl harbor.yml
|
|
||||||
harborConfig="$(harborHost="$HARBOR_HOST" harborPort="$HARBOR_PORT" harborPwd="$REGISTRY_PASSWORD" yq --no-colors '.hostname = env(harborHost) | .http.port = env(harborPort) | .harbor_admin_password = env(harborPwd) | del(.https)' harbor.yml)"
|
|
||||||
tee harbor.yml <<<"$harborConfig" >/dev/null
|
|
||||||
yq --no-colors harbor.yml
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
# install and start
|
|
||||||
echo "::group::Installing Harbor"
|
|
||||||
(
|
|
||||||
cd /tmp/harbor
|
|
||||||
set -x
|
|
||||||
./install.sh
|
|
||||||
sleep 10
|
|
||||||
netstat -aptn
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
# compose config
|
|
||||||
echo "::group::Compose config"
|
|
||||||
(
|
|
||||||
cd /tmp/harbor
|
|
||||||
set -x
|
|
||||||
docker compose config
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
# create project
|
|
||||||
echo "::group::Creating project"
|
|
||||||
(
|
|
||||||
set -x
|
|
||||||
curl --fail -v -k --max-time 10 -u "$REGISTRY_USER:$REGISTRY_PASSWORD" -X POST -H "Content-Type: application/json" -d "$(project_post_data)" "http://$HARBOR_HOST:$HARBOR_PORT/api/v2.0/projects"
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
# list projects
|
|
||||||
echo "::group::List projects"
|
|
||||||
(
|
|
||||||
set -x
|
|
||||||
curl --fail -s -k --max-time 10 -u "$REGISTRY_USER:$REGISTRY_PASSWORD" -H "Content-Type: application/json" "http://$HARBOR_HOST:$HARBOR_PORT/api/v2.0/projects" | jq
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
@ -1,8 +0,0 @@
|
|||||||
services:
|
|
||||||
nexus:
|
|
||||||
image: sonatype/nexus3:${NEXUS_VERSION:-latest}
|
|
||||||
volumes:
|
|
||||||
- "./data:/nexus-data"
|
|
||||||
ports:
|
|
||||||
- "8081:8081"
|
|
||||||
- "8082:8082"
|
|
@ -1,9 +0,0 @@
|
|||||||
REGISTRY_FQDN=localhost:8082
|
|
||||||
REGISTRY_USER=admin
|
|
||||||
REGISTRY_PASSWORD=Nexus12345
|
|
||||||
REGISTRY_SLUG=localhost:8082/test-docker-action
|
|
||||||
|
|
||||||
NEXUS_HOST=localhost
|
|
||||||
NEXUS_PORT=8081
|
|
||||||
NEXUS_REGISTRY_PORT=8082
|
|
||||||
NEXUS_REPO=test-docker-action
|
|
@ -1,94 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
SCRIPT_DIR=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd)
|
|
||||||
|
|
||||||
: "${NEXUS_VERSION:=3.47.1}"
|
|
||||||
: "${NEXUS_HOST:=localhost}"
|
|
||||||
: "${NEXUS_PORT:=8081}"
|
|
||||||
: "${NEXUS_REGISTRY_PORT:=8082}"
|
|
||||||
: "${REGISTRY_USER:=admin}"
|
|
||||||
: "${REGISTRY_PASSWORD:=Nexus12345}"
|
|
||||||
|
|
||||||
: "${NEXUS_REPO:=test-docker-action}"
|
|
||||||
|
|
||||||
createrepo_post_data() {
|
|
||||||
cat <<EOF
|
|
||||||
{
|
|
||||||
"name": "${NEXUS_REPO}",
|
|
||||||
"online": true,
|
|
||||||
"storage": {
|
|
||||||
"blobStoreName": "default",
|
|
||||||
"strictContentTypeValidation": true,
|
|
||||||
"writePolicy": "ALLOW"
|
|
||||||
},
|
|
||||||
"docker": {
|
|
||||||
"v1Enabled": false,
|
|
||||||
"forceBasicAuth": true,
|
|
||||||
"httpPort": ${NEXUS_REGISTRY_PORT},
|
|
||||||
"httpsPort": null,
|
|
||||||
"subdomain": null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
export NEXUS_VERSION
|
|
||||||
|
|
||||||
mkdir -p /tmp/nexus/data
|
|
||||||
chown 200:200 /tmp/nexus/data
|
|
||||||
cp "${SCRIPT_DIR}/docker-compose.yml" /tmp/nexus/docker-compose.yml
|
|
||||||
|
|
||||||
echo "::group::Pulling Nexus $NEXUS_VERSION"
|
|
||||||
(
|
|
||||||
cd /tmp/nexus
|
|
||||||
set -x
|
|
||||||
docker compose pull
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
echo "::group::Compose config"
|
|
||||||
(
|
|
||||||
cd /tmp/nexus
|
|
||||||
set -x
|
|
||||||
docker compose config
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
echo "::group::Running Nexus"
|
|
||||||
(
|
|
||||||
cd /tmp/nexus
|
|
||||||
set -x
|
|
||||||
docker compose up -d
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
echo "::group::Running Nexus"
|
|
||||||
(
|
|
||||||
cd /tmp/nexus
|
|
||||||
set -x
|
|
||||||
docker compose up -d
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
echo "::group::Waiting for Nexus to be ready"
|
|
||||||
until $(curl --output /dev/null --silent --head --fail "http://$NEXUS_HOST:$NEXUS_PORT"); do
|
|
||||||
printf '.'
|
|
||||||
sleep 5
|
|
||||||
done
|
|
||||||
echo "ready!"
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
echo "::group::Change user's password"
|
|
||||||
(
|
|
||||||
set -x
|
|
||||||
curl --fail -v -k --max-time 10 -u "$REGISTRY_USER:$(cat /tmp/nexus/data/admin.password)" -X PUT -H 'Content-Type: text/plain' -d "$REGISTRY_PASSWORD" "http://$NEXUS_HOST:$NEXUS_PORT/service/rest/v1/security/users/$REGISTRY_USER/change-password"
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
||||||
|
|
||||||
echo "::group::Create Docker repository"
|
|
||||||
(
|
|
||||||
set -x
|
|
||||||
curl --fail -v -k --max-time 10 -u "$REGISTRY_USER:$REGISTRY_PASSWORD" -X POST -H 'Content-Type: application/json' -d "$(createrepo_post_data)" "http://$NEXUS_HOST:$NEXUS_PORT/service/rest/v1/repositories/docker/hosted"
|
|
||||||
)
|
|
||||||
echo "::endgroup::"
|
|
@ -1,134 +0,0 @@
|
|||||||
# reusable workflow
|
|
||||||
name: .e2e-run
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
id:
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
name:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
registry:
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
slug:
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
username_secret:
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
password_secret:
|
|
||||||
required: false
|
|
||||||
type: string
|
|
||||||
|
|
||||||
env:
|
|
||||||
HARBOR_VERSION: v2.13.2
|
|
||||||
NEXUS_VERSION: 3.47.1
|
|
||||||
DISTRIBUTION_VERSION: 3.0.0
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
run:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
-
|
|
||||||
buildx_version: edge
|
|
||||||
buildkit_image: moby/buildkit:latest
|
|
||||||
-
|
|
||||||
buildx_version: latest
|
|
||||||
buildkit_image: moby/buildkit:buildx-stable-1
|
|
||||||
-
|
|
||||||
buildx_version: https://github.com/docker/buildx.git#master
|
|
||||||
buildkit_image: moby/buildkit:master
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
-
|
|
||||||
name: Set up env
|
|
||||||
if: inputs.type == 'local'
|
|
||||||
run: |
|
|
||||||
cat ./.github/e2e/${{ inputs.id }}/env >> $GITHUB_ENV
|
|
||||||
-
|
|
||||||
name: Set up BuildKit config
|
|
||||||
run: |
|
|
||||||
touch /tmp/buildkitd.toml
|
|
||||||
if [ "${{ inputs.type }}" = "local" ]; then
|
|
||||||
echo -e "[registry.\"${{ env.REGISTRY_FQDN }}\"]\nhttp = true\ninsecure = true" > /tmp/buildkitd.toml
|
|
||||||
fi
|
|
||||||
-
|
|
||||||
name: Set up Docker daemon
|
|
||||||
if: inputs.type == 'local'
|
|
||||||
run: |
|
|
||||||
if [ ! -e /etc/docker/daemon.json ]; then
|
|
||||||
echo '{}' | sudo tee /etc/docker/daemon.json >/dev/null
|
|
||||||
fi
|
|
||||||
DOCKERD_CONFIG=$(jq '.+{"insecure-registries":["http://${{ env.REGISTRY_FQDN }}"]}' /etc/docker/daemon.json)
|
|
||||||
sudo tee /etc/docker/daemon.json <<<"$DOCKERD_CONFIG" >/dev/null
|
|
||||||
cat /etc/docker/daemon.json
|
|
||||||
sudo service docker restart
|
|
||||||
-
|
|
||||||
name: Install ${{ inputs.name }}
|
|
||||||
if: inputs.type == 'local'
|
|
||||||
run: |
|
|
||||||
sudo -E bash ./.github/e2e/${{ inputs.id }}/install.sh
|
|
||||||
sudo chown $(id -u):$(id -g) -R ~/.docker
|
|
||||||
-
|
|
||||||
name: Docker meta
|
|
||||||
id: meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: ${{ env.REGISTRY_SLUG || inputs.slug }}
|
|
||||||
tags: |
|
|
||||||
type=ref,event=branch,enable=${{ matrix.buildx_version == 'latest' && matrix.buildkit_image == 'moby/buildkit:buildx-stable-1' }}
|
|
||||||
type=ref,event=tag,enable=${{ matrix.buildx_version == 'latest' && matrix.buildkit_image == 'moby/buildkit:buildx-stable-1' }}
|
|
||||||
type=raw,gh-runid-${{ github.run_id }}
|
|
||||||
-
|
|
||||||
name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
-
|
|
||||||
name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
with:
|
|
||||||
version: ${{ matrix.buildx_version }}
|
|
||||||
buildkitd-config: /tmp/buildkitd.toml
|
|
||||||
buildkitd-flags: --debug --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host
|
|
||||||
driver-opts: |
|
|
||||||
image=${{ matrix.buildkit_image }}
|
|
||||||
network=host
|
|
||||||
-
|
|
||||||
name: Login to Registry
|
|
||||||
if: github.event_name != 'pull_request' && (env.REGISTRY_USER || inputs.username_secret) != ''
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ${{ env.REGISTRY_FQDN || inputs.registry }}
|
|
||||||
username: ${{ env.REGISTRY_USER || secrets[inputs.username_secret] }}
|
|
||||||
password: ${{ env.REGISTRY_PASSWORD || secrets[inputs.password_secret] }}
|
|
||||||
-
|
|
||||||
name: Build and push
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
context: ./test
|
|
||||||
file: ./test/multi.Dockerfile
|
|
||||||
platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x
|
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
|
||||||
cache-from: type=registry,ref=${{ env.REGISTRY_SLUG || inputs.slug }}:master
|
|
||||||
cache-to: type=inline
|
|
||||||
-
|
|
||||||
name: Inspect image
|
|
||||||
run: |
|
|
||||||
docker pull ${{ env.REGISTRY_SLUG || inputs.slug }}:${{ steps.meta.outputs.version }}
|
|
||||||
docker image inspect ${{ env.REGISTRY_SLUG || inputs.slug }}:${{ steps.meta.outputs.version }}
|
|
||||||
-
|
|
||||||
name: Check manifest
|
|
||||||
run: |
|
|
||||||
docker buildx imagetools inspect ${{ env.REGISTRY_SLUG || inputs.slug }}:${{ steps.meta.outputs.version }} --format '{{json .}}'
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,78 @@
|
|||||||
|
# This workflow is provided just as an example and not for repo testing/verification
|
||||||
|
name: example
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 10 * * 0'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
tags:
|
||||||
|
- 'v*.*.*'
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOCKER_IMAGE: localhost:5000/name/app
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
services:
|
||||||
|
registry:
|
||||||
|
image: registry:2
|
||||||
|
ports:
|
||||||
|
- 5000:5000
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: ${{ env.DOCKER_IMAGE }}
|
||||||
|
tags: |
|
||||||
|
type=schedule
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
type=sha
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
with:
|
||||||
|
driver-opts: network=host
|
||||||
|
-
|
||||||
|
name: Build and export to Docker client
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
context: ./test
|
||||||
|
file: ./test/Dockerfile
|
||||||
|
load: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
-
|
||||||
|
name: Build and push to local registry
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
context: ./test
|
||||||
|
file: ./test/Dockerfile
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
-
|
||||||
|
name: Inspect image
|
||||||
|
run: |
|
||||||
|
docker image inspect ${{ env.DOCKER_IMAGE }}:${{ steps.meta.outputs.version }}
|
||||||
|
-
|
||||||
|
name: Check manifest
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools inspect ${{ env.DOCKER_IMAGE }}:${{ steps.meta.outputs.version }}
|
||||||
|
-
|
||||||
|
name: Dump context
|
||||||
|
if: always()
|
||||||
|
uses: crazy-max/ghaction-dump-context@v1
|
@ -1,17 +0,0 @@
|
|||||||
name: pr-assign-author
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request_target:
|
|
||||||
types:
|
|
||||||
- opened
|
|
||||||
- reopened
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
run:
|
|
||||||
uses: crazy-max/.github/.github/workflows/pr-assign-author.yml@1b673f36fad86812f538c1df9794904038a23cbf
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
@ -1,21 +0,0 @@
|
|||||||
name: publish
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types:
|
|
||||||
- published
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
publish:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
id-token: write
|
|
||||||
packages: write
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
-
|
|
||||||
name: Publish
|
|
||||||
uses: actions/publish-immutable-action@v0.0.4
|
|
@ -1,43 +0,0 @@
|
|||||||
name: validate
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- 'master'
|
|
||||||
- 'releases/v*'
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
prepare:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
targets: ${{ steps.generate.outputs.targets }}
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
-
|
|
||||||
name: List targets
|
|
||||||
id: generate
|
|
||||||
uses: docker/bake-action/subaction/list-targets@v6
|
|
||||||
with:
|
|
||||||
target: validate
|
|
||||||
|
|
||||||
validate:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- prepare
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
target: ${{ fromJson(needs.prepare.outputs.targets) }}
|
|
||||||
steps:
|
|
||||||
-
|
|
||||||
name: Validate
|
|
||||||
uses: docker/bake-action@v6
|
|
||||||
with:
|
|
||||||
targets: ${{ matrix.target }}
|
|
@ -0,0 +1,72 @@
|
|||||||
|
name: virtual-env
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 10 * * *'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/virtual-env.yml'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
paths:
|
||||||
|
- '.github/workflows/virtual-env.yml'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
os:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os:
|
||||||
|
- ubuntu-latest
|
||||||
|
- ubuntu-22.04
|
||||||
|
- ubuntu-20.04
|
||||||
|
- ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: File system
|
||||||
|
run: df -ah
|
||||||
|
-
|
||||||
|
name: Mounts
|
||||||
|
run: mount
|
||||||
|
-
|
||||||
|
name: Node info
|
||||||
|
run: node -p process
|
||||||
|
-
|
||||||
|
name: NPM version
|
||||||
|
run: npm version
|
||||||
|
-
|
||||||
|
name: List install packages
|
||||||
|
run: apt list --installed
|
||||||
|
-
|
||||||
|
name: Docker daemon conf
|
||||||
|
run: |
|
||||||
|
cat /etc/docker/daemon.json
|
||||||
|
-
|
||||||
|
name: Docker info
|
||||||
|
run: docker info
|
||||||
|
-
|
||||||
|
name: Docker version
|
||||||
|
run: docker version
|
||||||
|
-
|
||||||
|
name: Cgroups
|
||||||
|
run: |
|
||||||
|
sudo apt-get install -y cgroup-tools
|
||||||
|
lscgroup
|
||||||
|
-
|
||||||
|
name: buildx version
|
||||||
|
run: docker buildx version
|
||||||
|
-
|
||||||
|
name: containerd version
|
||||||
|
run: containerd --version
|
||||||
|
-
|
||||||
|
name: Docker images
|
||||||
|
run: docker image ls
|
||||||
|
-
|
||||||
|
name: Dump context
|
||||||
|
if: always()
|
||||||
|
uses: crazy-max/ghaction-dump-context@v1
|
@ -1,6 +0,0 @@
|
|||||||
# Dependency directories
|
|
||||||
node_modules/
|
|
||||||
jspm_packages/
|
|
||||||
|
|
||||||
# yarn v2
|
|
||||||
.yarn/
|
|
File diff suppressed because one or more lines are too long
@ -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"
|
|
@ -1,207 +0,0 @@
|
|||||||
import {jest} from '@jest/globals';
|
|
||||||
|
|
||||||
export const context = {
|
|
||||||
repo: {
|
|
||||||
owner: 'docker',
|
|
||||||
repo: 'build-push-action'
|
|
||||||
},
|
|
||||||
ref: 'refs/heads/master',
|
|
||||||
runId: 123456789,
|
|
||||||
payload: {
|
|
||||||
after: '860c1904a1ce19322e91ac35af1ab07466440c37',
|
|
||||||
base_ref: null,
|
|
||||||
before: '5f3331d7f7044c18ca9f12c77d961c4d7cf3276a',
|
|
||||||
commits: [
|
|
||||||
{
|
|
||||||
author: {
|
|
||||||
email: 'crazy-max@users.noreply.github.com',
|
|
||||||
name: 'CrazyMax',
|
|
||||||
username: 'crazy-max'
|
|
||||||
},
|
|
||||||
committer: {
|
|
||||||
email: 'crazy-max@users.noreply.github.com',
|
|
||||||
name: 'CrazyMax',
|
|
||||||
username: 'crazy-max'
|
|
||||||
},
|
|
||||||
distinct: true,
|
|
||||||
id: '860c1904a1ce19322e91ac35af1ab07466440c37',
|
|
||||||
message: 'hello dev',
|
|
||||||
timestamp: '2022-04-19T11:27:24+02:00',
|
|
||||||
tree_id: 'd2c60af597e863787d2d27f569e30495b0b92820',
|
|
||||||
url: 'https://github.com/docker/test-docker-action/commit/860c1904a1ce19322e91ac35af1ab07466440c37'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
compare: 'https://github.com/docker/test-docker-action/compare/5f3331d7f704...860c1904a1ce',
|
|
||||||
created: false,
|
|
||||||
deleted: false,
|
|
||||||
forced: false,
|
|
||||||
head_commit: {
|
|
||||||
author: {
|
|
||||||
email: 'crazy-max@users.noreply.github.com',
|
|
||||||
name: 'CrazyMax',
|
|
||||||
username: 'crazy-max'
|
|
||||||
},
|
|
||||||
committer: {
|
|
||||||
email: 'crazy-max@users.noreply.github.com',
|
|
||||||
name: 'CrazyMax',
|
|
||||||
username: 'crazy-max'
|
|
||||||
},
|
|
||||||
distinct: true,
|
|
||||||
id: '860c1904a1ce19322e91ac35af1ab07466440c37',
|
|
||||||
message: 'hello dev',
|
|
||||||
timestamp: '2022-04-19T11:27:24+02:00',
|
|
||||||
tree_id: 'd2c60af597e863787d2d27f569e30495b0b92820',
|
|
||||||
url: 'https://github.com/docker/test-docker-action/commit/860c1904a1ce19322e91ac35af1ab07466440c37'
|
|
||||||
},
|
|
||||||
organization: {
|
|
||||||
avatar_url: 'https://avatars.githubusercontent.com/u/5429470?v=4',
|
|
||||||
description: 'Docker helps developers bring their ideas to life by conquering the complexity of app development.',
|
|
||||||
events_url: 'https://api.github.com/orgs/docker/events',
|
|
||||||
hooks_url: 'https://api.github.com/orgs/docker/hooks',
|
|
||||||
id: 5429470,
|
|
||||||
issues_url: 'https://api.github.com/orgs/docker/issues',
|
|
||||||
login: 'docker',
|
|
||||||
members_url: 'https://api.github.com/orgs/docker/members{/member}',
|
|
||||||
node_id: 'MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=',
|
|
||||||
public_members_url: 'https://api.github.com/orgs/docker/public_members{/member}',
|
|
||||||
repos_url: 'https://api.github.com/orgs/docker/repos',
|
|
||||||
url: 'https://api.github.com/orgs/docker'
|
|
||||||
},
|
|
||||||
pusher: {
|
|
||||||
email: 'github@crazymax.dev',
|
|
||||||
name: 'crazy-max'
|
|
||||||
},
|
|
||||||
ref: 'refs/heads/dev',
|
|
||||||
repository: {
|
|
||||||
allow_forking: true,
|
|
||||||
archive_url: 'https://api.github.com/repos/docker/test-docker-action/{archive_format}{/ref}',
|
|
||||||
archived: false,
|
|
||||||
assignees_url: 'https://api.github.com/repos/docker/test-docker-action/assignees{/user}',
|
|
||||||
blobs_url: 'https://api.github.com/repos/docker/test-docker-action/git/blobs{/sha}',
|
|
||||||
branches_url: 'https://api.github.com/repos/docker/test-docker-action/branches{/branch}',
|
|
||||||
clone_url: 'https://github.com/docker/test-docker-action.git',
|
|
||||||
collaborators_url: 'https://api.github.com/repos/docker/test-docker-action/collaborators{/collaborator}',
|
|
||||||
comments_url: 'https://api.github.com/repos/docker/test-docker-action/comments{/number}',
|
|
||||||
commits_url: 'https://api.github.com/repos/docker/test-docker-action/commits{/sha}',
|
|
||||||
compare_url: 'https://api.github.com/repos/docker/test-docker-action/compare/{base}...{head}',
|
|
||||||
contents_url: 'https://api.github.com/repos/docker/test-docker-action/contents/{+path}',
|
|
||||||
contributors_url: 'https://api.github.com/repos/docker/test-docker-action/contributors',
|
|
||||||
created_at: 1596792180,
|
|
||||||
default_branch: 'master',
|
|
||||||
deployments_url: 'https://api.github.com/repos/docker/test-docker-action/deployments',
|
|
||||||
description: 'Test "Docker" Actions',
|
|
||||||
disabled: false,
|
|
||||||
downloads_url: 'https://api.github.com/repos/docker/test-docker-action/downloads',
|
|
||||||
events_url: 'https://api.github.com/repos/docker/test-docker-action/events',
|
|
||||||
fork: false,
|
|
||||||
forks: 1,
|
|
||||||
forks_count: 1,
|
|
||||||
forks_url: 'https://api.github.com/repos/docker/test-docker-action/forks',
|
|
||||||
full_name: 'docker/test-docker-action',
|
|
||||||
git_commits_url: 'https://api.github.com/repos/docker/test-docker-action/git/commits{/sha}',
|
|
||||||
git_refs_url: 'https://api.github.com/repos/docker/test-docker-action/git/refs{/sha}',
|
|
||||||
git_tags_url: 'https://api.github.com/repos/docker/test-docker-action/git/tags{/sha}',
|
|
||||||
git_url: 'git://github.com/docker/test-docker-action.git',
|
|
||||||
has_downloads: true,
|
|
||||||
has_issues: true,
|
|
||||||
has_pages: false,
|
|
||||||
has_projects: true,
|
|
||||||
has_wiki: true,
|
|
||||||
homepage: '',
|
|
||||||
hooks_url: 'https://api.github.com/repos/docker/test-docker-action/hooks',
|
|
||||||
html_url: 'https://github.com/docker/test-docker-action',
|
|
||||||
id: 285789493,
|
|
||||||
is_template: false,
|
|
||||||
issue_comment_url: 'https://api.github.com/repos/docker/test-docker-action/issues/comments{/number}',
|
|
||||||
issue_events_url: 'https://api.github.com/repos/docker/test-docker-action/issues/events{/number}',
|
|
||||||
issues_url: 'https://api.github.com/repos/docker/test-docker-action/issues{/number}',
|
|
||||||
keys_url: 'https://api.github.com/repos/docker/test-docker-action/keys{/key_id}',
|
|
||||||
labels_url: 'https://api.github.com/repos/docker/test-docker-action/labels{/name}',
|
|
||||||
language: 'JavaScript',
|
|
||||||
languages_url: 'https://api.github.com/repos/docker/test-docker-action/languages',
|
|
||||||
license: {
|
|
||||||
key: 'mit',
|
|
||||||
name: 'MIT License',
|
|
||||||
node_id: 'MDc6TGljZW5zZTEz',
|
|
||||||
spdx_id: 'MIT',
|
|
||||||
url: 'https://api.github.com/licenses/mit'
|
|
||||||
},
|
|
||||||
master_branch: 'master',
|
|
||||||
merges_url: 'https://api.github.com/repos/docker/test-docker-action/merges',
|
|
||||||
milestones_url: 'https://api.github.com/repos/docker/test-docker-action/milestones{/number}',
|
|
||||||
mirror_url: null,
|
|
||||||
name: 'test-docker-action',
|
|
||||||
node_id: 'MDEwOlJlcG9zaXRvcnkyODU3ODk0OTM=',
|
|
||||||
notifications_url: 'https://api.github.com/repos/docker/test-docker-action/notifications{?since,all,participating}',
|
|
||||||
open_issues: 6,
|
|
||||||
open_issues_count: 6,
|
|
||||||
organization: 'docker',
|
|
||||||
owner: {
|
|
||||||
avatar_url: 'https://avatars.githubusercontent.com/u/5429470?v=4',
|
|
||||||
email: 'info@docker.com',
|
|
||||||
events_url: 'https://api.github.com/users/docker/events{/privacy}',
|
|
||||||
followers_url: 'https://api.github.com/users/docker/followers',
|
|
||||||
following_url: 'https://api.github.com/users/docker/following{/other_user}',
|
|
||||||
gists_url: 'https://api.github.com/users/docker/gists{/gist_id}',
|
|
||||||
gravatar_id: '',
|
|
||||||
html_url: 'https://github.com/docker',
|
|
||||||
id: 5429470,
|
|
||||||
login: 'docker',
|
|
||||||
name: 'docker',
|
|
||||||
node_id: 'MDEyOk9yZ2FuaXphdGlvbjU0Mjk0NzA=',
|
|
||||||
organizations_url: 'https://api.github.com/users/docker/orgs',
|
|
||||||
received_events_url: 'https://api.github.com/users/docker/received_events',
|
|
||||||
repos_url: 'https://api.github.com/users/docker/repos',
|
|
||||||
site_admin: false,
|
|
||||||
starred_url: 'https://api.github.com/users/docker/starred{/owner}{/repo}',
|
|
||||||
subscriptions_url: 'https://api.github.com/users/docker/subscriptions',
|
|
||||||
type: 'Organization',
|
|
||||||
url: 'https://api.github.com/users/docker'
|
|
||||||
},
|
|
||||||
private: true,
|
|
||||||
pulls_url: 'https://api.github.com/repos/docker/test-docker-action/pulls{/number}',
|
|
||||||
pushed_at: 1650360446,
|
|
||||||
releases_url: 'https://api.github.com/repos/docker/test-docker-action/releases{/id}',
|
|
||||||
size: 796,
|
|
||||||
ssh_url: 'git@github.com:docker/test-docker-action.git',
|
|
||||||
stargazers: 0,
|
|
||||||
stargazers_count: 0,
|
|
||||||
stargazers_url: 'https://api.github.com/repos/docker/test-docker-action/stargazers',
|
|
||||||
statuses_url: 'https://api.github.com/repos/docker/test-docker-action/statuses/{sha}',
|
|
||||||
subscribers_url: 'https://api.github.com/repos/docker/test-docker-action/subscribers',
|
|
||||||
subscription_url: 'https://api.github.com/repos/docker/test-docker-action/subscription',
|
|
||||||
svn_url: 'https://github.com/docker/test-docker-action',
|
|
||||||
tags_url: 'https://api.github.com/repos/docker/test-docker-action/tags',
|
|
||||||
teams_url: 'https://api.github.com/repos/docker/test-docker-action/teams',
|
|
||||||
topics: [],
|
|
||||||
trees_url: 'https://api.github.com/repos/docker/test-docker-action/git/trees{/sha}',
|
|
||||||
updated_at: '2022-04-19T09:05:09Z',
|
|
||||||
url: 'https://github.com/docker/test-docker-action',
|
|
||||||
visibility: 'private',
|
|
||||||
watchers: 0,
|
|
||||||
watchers_count: 0
|
|
||||||
},
|
|
||||||
sender: {
|
|
||||||
avatar_url: 'https://avatars.githubusercontent.com/u/1951866?v=4',
|
|
||||||
events_url: 'https://api.github.com/users/crazy-max/events{/privacy}',
|
|
||||||
followers_url: 'https://api.github.com/users/crazy-max/followers',
|
|
||||||
following_url: 'https://api.github.com/users/crazy-max/following{/other_user}',
|
|
||||||
gists_url: 'https://api.github.com/users/crazy-max/gists{/gist_id}',
|
|
||||||
gravatar_id: '',
|
|
||||||
html_url: 'https://github.com/crazy-max',
|
|
||||||
id: 1951866,
|
|
||||||
login: 'crazy-max',
|
|
||||||
node_id: 'MDQ6VXNlcjE5NTE4NjY=',
|
|
||||||
organizations_url: 'https://api.github.com/users/crazy-max/orgs',
|
|
||||||
received_events_url: 'https://api.github.com/users/crazy-max/received_events',
|
|
||||||
repos_url: 'https://api.github.com/users/crazy-max/repos',
|
|
||||||
site_admin: false,
|
|
||||||
starred_url: 'https://api.github.com/users/crazy-max/starred{/owner}{/repo}',
|
|
||||||
subscriptions_url: 'https://api.github.com/users/crazy-max/subscriptions',
|
|
||||||
type: 'User',
|
|
||||||
url: 'https://api.github.com/users/crazy-max'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getOctokit = jest.fn();
|
|
@ -0,0 +1,147 @@
|
|||||||
|
import {describe, expect, it, jest, test} from '@jest/globals';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
import * as semver from 'semver';
|
||||||
|
import * as exec from '@actions/exec';
|
||||||
|
import * as buildx from '../src/buildx';
|
||||||
|
import * as context from '../src/context';
|
||||||
|
|
||||||
|
const tmpNameSync = path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
|
||||||
|
const imageID = 'sha256:bfb45ab72e46908183546477a08f8867fc40cebadd00af54b071b097aed127a9';
|
||||||
|
const metadata = `{
|
||||||
|
"containerimage.config.digest": "sha256:059b68a595b22564a1cbc167af369349fdc2ecc1f7bc092c2235cbf601a795fd",
|
||||||
|
"containerimage.digest": "sha256:b09b9482c72371486bb2c1d2c2a2633ed1d0b8389e12c8d52b9e052725c0c83c"
|
||||||
|
}`;
|
||||||
|
|
||||||
|
jest.spyOn(context, 'tmpDir').mockImplementation((): string => {
|
||||||
|
const tmpDir = path.join('/tmp/.docker-build-push-jest').split(path.sep).join(path.posix.sep);
|
||||||
|
if (!fs.existsSync(tmpDir)) {
|
||||||
|
fs.mkdirSync(tmpDir, {recursive: true});
|
||||||
|
}
|
||||||
|
return tmpDir;
|
||||||
|
});
|
||||||
|
|
||||||
|
jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => {
|
||||||
|
return tmpNameSync;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getImageID', () => {
|
||||||
|
it('matches', async () => {
|
||||||
|
const imageIDFile = await buildx.getImageIDFile();
|
||||||
|
await fs.writeFileSync(imageIDFile, imageID);
|
||||||
|
const expected = await buildx.getImageID();
|
||||||
|
expect(expected).toEqual(imageID);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getMetadata', () => {
|
||||||
|
it('matches', async () => {
|
||||||
|
const metadataFile = await buildx.getMetadataFile();
|
||||||
|
await fs.writeFileSync(metadataFile, metadata);
|
||||||
|
const expected = await buildx.getMetadata();
|
||||||
|
expect(expected).toEqual(metadata);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getDigest', () => {
|
||||||
|
it('matches', async () => {
|
||||||
|
const metadataFile = await buildx.getMetadataFile();
|
||||||
|
await fs.writeFileSync(metadataFile, metadata);
|
||||||
|
const expected = await buildx.getDigest(metadata);
|
||||||
|
expect(expected).toEqual('sha256:b09b9482c72371486bb2c1d2c2a2633ed1d0b8389e12c8d52b9e052725c0c83c');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isLocalOrTarExporter', () => {
|
||||||
|
test.each([
|
||||||
|
[['type=registry,ref=user/app'], false],
|
||||||
|
[['type=docker'], false],
|
||||||
|
[['type=local,dest=./release-out'], true],
|
||||||
|
[['type=tar,dest=/tmp/image.tar'], true],
|
||||||
|
[['type=docker', 'type=tar,dest=/tmp/image.tar'], true],
|
||||||
|
[['"type=tar","dest=/tmp/image.tar"'], true],
|
||||||
|
[['" type= local" , dest=./release-out'], true],
|
||||||
|
[['.'], true]
|
||||||
|
])('given %p returns %p', async (outputs: Array<string>, expected: boolean) => {
|
||||||
|
expect(buildx.isLocalOrTarExporter(outputs)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('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('getSecret', () => {
|
||||||
|
test.each([
|
||||||
|
['A_SECRET=abcdef0123456789', false, 'A_SECRET', 'abcdef0123456789', false],
|
||||||
|
['GIT_AUTH_TOKEN=abcdefghijklmno=0123456789', false, 'GIT_AUTH_TOKEN', 'abcdefghijklmno=0123456789', false],
|
||||||
|
['MY_KEY=c3RyaW5nLXdpdGgtZXF1YWxzCg==', false, 'MY_KEY', 'c3RyaW5nLXdpdGgtZXF1YWxzCg==', false],
|
||||||
|
['aaaaaaaa', false, '', '', true],
|
||||||
|
['aaaaaaaa=', false, '', '', true],
|
||||||
|
['=bbbbbbb', false, '', '', true],
|
||||||
|
[`foo=${path.join(__dirname, 'fixtures', 'secret.txt').split(path.sep).join(path.posix.sep)}`, true, 'foo', 'bar', false],
|
||||||
|
[`notfound=secret`, true, '', '', true]
|
||||||
|
])('given %p key and %p secret', async (kvp, file, exKey, exValue, invalid) => {
|
||||||
|
try {
|
||||||
|
let secret: string;
|
||||||
|
if (file) {
|
||||||
|
secret = await buildx.getSecretFile(kvp);
|
||||||
|
} else {
|
||||||
|
secret = await buildx.getSecretString(kvp);
|
||||||
|
}
|
||||||
|
expect(true).toBe(!invalid);
|
||||||
|
expect(secret).toEqual(`id=${exKey},src=${tmpNameSync}`);
|
||||||
|
const secretValue = await fs.readFileSync(tmpNameSync, 'utf-8');
|
||||||
|
expect(secretValue).toEqual(exValue);
|
||||||
|
} catch (err) {
|
||||||
|
// eslint-disable-next-line jest/no-conditional-expect
|
||||||
|
expect(true).toBe(invalid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
File diff suppressed because it is too large
Load Diff
@ -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,362 +0,0 @@
|
|||||||
{
|
|
||||||
"id": 1296269,
|
|
||||||
"node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
|
|
||||||
"name": "Hello-World",
|
|
||||||
"full_name": "octocat/Hello-World",
|
|
||||||
"owner": {
|
|
||||||
"login": "octocat",
|
|
||||||
"id": 1,
|
|
||||||
"node_id": "MDQ6VXNlcjE=",
|
|
||||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
|
||||||
"gravatar_id": "",
|
|
||||||
"url": "https://api.github.com/users/octocat",
|
|
||||||
"html_url": "https://github.com/octocat",
|
|
||||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
|
||||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
|
||||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
|
||||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
|
||||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
|
||||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
|
||||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
|
||||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
|
||||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
|
||||||
"type": "User",
|
|
||||||
"site_admin": false
|
|
||||||
},
|
|
||||||
"private": false,
|
|
||||||
"html_url": "https://github.com/octocat/Hello-World",
|
|
||||||
"description": "This your first repo!",
|
|
||||||
"fork": false,
|
|
||||||
"url": "https://api.github.com/repos/octocat/Hello-World",
|
|
||||||
"archive_url": "http://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}",
|
|
||||||
"assignees_url": "http://api.github.com/repos/octocat/Hello-World/assignees{/user}",
|
|
||||||
"blobs_url": "http://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}",
|
|
||||||
"branches_url": "http://api.github.com/repos/octocat/Hello-World/branches{/branch}",
|
|
||||||
"collaborators_url": "http://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}",
|
|
||||||
"comments_url": "http://api.github.com/repos/octocat/Hello-World/comments{/number}",
|
|
||||||
"commits_url": "http://api.github.com/repos/octocat/Hello-World/commits{/sha}",
|
|
||||||
"compare_url": "http://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}",
|
|
||||||
"contents_url": "http://api.github.com/repos/octocat/Hello-World/contents/{+path}",
|
|
||||||
"contributors_url": "http://api.github.com/repos/octocat/Hello-World/contributors",
|
|
||||||
"deployments_url": "http://api.github.com/repos/octocat/Hello-World/deployments",
|
|
||||||
"downloads_url": "http://api.github.com/repos/octocat/Hello-World/downloads",
|
|
||||||
"events_url": "http://api.github.com/repos/octocat/Hello-World/events",
|
|
||||||
"forks_url": "http://api.github.com/repos/octocat/Hello-World/forks",
|
|
||||||
"git_commits_url": "http://api.github.com/repos/octocat/Hello-World/git/commits{/sha}",
|
|
||||||
"git_refs_url": "http://api.github.com/repos/octocat/Hello-World/git/refs{/sha}",
|
|
||||||
"git_tags_url": "http://api.github.com/repos/octocat/Hello-World/git/tags{/sha}",
|
|
||||||
"git_url": "git:github.com/octocat/Hello-World.git",
|
|
||||||
"issue_comment_url": "http://api.github.com/repos/octocat/Hello-World/issues/comments{/number}",
|
|
||||||
"issue_events_url": "http://api.github.com/repos/octocat/Hello-World/issues/events{/number}",
|
|
||||||
"issues_url": "http://api.github.com/repos/octocat/Hello-World/issues{/number}",
|
|
||||||
"keys_url": "http://api.github.com/repos/octocat/Hello-World/keys{/key_id}",
|
|
||||||
"labels_url": "http://api.github.com/repos/octocat/Hello-World/labels{/name}",
|
|
||||||
"languages_url": "http://api.github.com/repos/octocat/Hello-World/languages",
|
|
||||||
"merges_url": "http://api.github.com/repos/octocat/Hello-World/merges",
|
|
||||||
"milestones_url": "http://api.github.com/repos/octocat/Hello-World/milestones{/number}",
|
|
||||||
"notifications_url": "http://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}",
|
|
||||||
"pulls_url": "http://api.github.com/repos/octocat/Hello-World/pulls{/number}",
|
|
||||||
"releases_url": "http://api.github.com/repos/octocat/Hello-World/releases{/id}",
|
|
||||||
"ssh_url": "git@github.com:octocat/Hello-World.git",
|
|
||||||
"stargazers_url": "http://api.github.com/repos/octocat/Hello-World/stargazers",
|
|
||||||
"statuses_url": "http://api.github.com/repos/octocat/Hello-World/statuses/{sha}",
|
|
||||||
"subscribers_url": "http://api.github.com/repos/octocat/Hello-World/subscribers",
|
|
||||||
"subscription_url": "http://api.github.com/repos/octocat/Hello-World/subscription",
|
|
||||||
"tags_url": "http://api.github.com/repos/octocat/Hello-World/tags",
|
|
||||||
"teams_url": "http://api.github.com/repos/octocat/Hello-World/teams",
|
|
||||||
"trees_url": "http://api.github.com/repos/octocat/Hello-World/git/trees{/sha}",
|
|
||||||
"clone_url": "https://github.com/octocat/Hello-World.git",
|
|
||||||
"mirror_url": "git:git.example.com/octocat/Hello-World",
|
|
||||||
"hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks",
|
|
||||||
"svn_url": "https://svn.github.com/octocat/Hello-World",
|
|
||||||
"homepage": "https://github.com",
|
|
||||||
"language": null,
|
|
||||||
"forks_count": 9,
|
|
||||||
"stargazers_count": 80,
|
|
||||||
"watchers_count": 80,
|
|
||||||
"size": 108,
|
|
||||||
"default_branch": "master",
|
|
||||||
"open_issues_count": 0,
|
|
||||||
"is_template": true,
|
|
||||||
"topics": [
|
|
||||||
"octocat",
|
|
||||||
"atom",
|
|
||||||
"electron",
|
|
||||||
"api"
|
|
||||||
],
|
|
||||||
"has_issues": true,
|
|
||||||
"has_projects": true,
|
|
||||||
"has_wiki": true,
|
|
||||||
"has_pages": false,
|
|
||||||
"has_downloads": true,
|
|
||||||
"archived": false,
|
|
||||||
"disabled": false,
|
|
||||||
"visibility": "public",
|
|
||||||
"pushed_at": "2011-01-26T19:06:43Z",
|
|
||||||
"created_at": "2011-01-26T19:01:12Z",
|
|
||||||
"updated_at": "2011-01-26T19:14:43Z",
|
|
||||||
"permissions": {
|
|
||||||
"pull": true,
|
|
||||||
"triage": true,
|
|
||||||
"push": false,
|
|
||||||
"maintain": false,
|
|
||||||
"admin": false
|
|
||||||
},
|
|
||||||
"allow_rebase_merge": true,
|
|
||||||
"template_repository": null,
|
|
||||||
"temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O",
|
|
||||||
"allow_squash_merge": true,
|
|
||||||
"delete_branch_on_merge": true,
|
|
||||||
"allow_merge_commit": true,
|
|
||||||
"subscribers_count": 42,
|
|
||||||
"network_count": 0,
|
|
||||||
"license": {
|
|
||||||
"key": "mit",
|
|
||||||
"name": "MIT License",
|
|
||||||
"spdx_id": "MIT",
|
|
||||||
"url": "https://api.github.com/licenses/mit",
|
|
||||||
"node_id": "MDc6TGljZW5zZW1pdA=="
|
|
||||||
},
|
|
||||||
"organization": {
|
|
||||||
"login": "octocat",
|
|
||||||
"id": 1,
|
|
||||||
"node_id": "MDQ6VXNlcjE=",
|
|
||||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
|
||||||
"gravatar_id": "",
|
|
||||||
"url": "https://api.github.com/users/octocat",
|
|
||||||
"html_url": "https://github.com/octocat",
|
|
||||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
|
||||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
|
||||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
|
||||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
|
||||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
|
||||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
|
||||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
|
||||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
|
||||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
|
||||||
"type": "Organization",
|
|
||||||
"site_admin": false
|
|
||||||
},
|
|
||||||
"parent": {
|
|
||||||
"id": 1296269,
|
|
||||||
"node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
|
|
||||||
"name": "Hello-World",
|
|
||||||
"full_name": "octocat/Hello-World",
|
|
||||||
"owner": {
|
|
||||||
"login": "octocat",
|
|
||||||
"id": 1,
|
|
||||||
"node_id": "MDQ6VXNlcjE=",
|
|
||||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
|
||||||
"gravatar_id": "",
|
|
||||||
"url": "https://api.github.com/users/octocat",
|
|
||||||
"html_url": "https://github.com/octocat",
|
|
||||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
|
||||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
|
||||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
|
||||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
|
||||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
|
||||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
|
||||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
|
||||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
|
||||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
|
||||||
"type": "User",
|
|
||||||
"site_admin": false
|
|
||||||
},
|
|
||||||
"private": false,
|
|
||||||
"html_url": "https://github.com/octocat/Hello-World",
|
|
||||||
"description": "This your first repo!",
|
|
||||||
"fork": false,
|
|
||||||
"url": "https://api.github.com/repos/octocat/Hello-World",
|
|
||||||
"archive_url": "http://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}",
|
|
||||||
"assignees_url": "http://api.github.com/repos/octocat/Hello-World/assignees{/user}",
|
|
||||||
"blobs_url": "http://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}",
|
|
||||||
"branches_url": "http://api.github.com/repos/octocat/Hello-World/branches{/branch}",
|
|
||||||
"collaborators_url": "http://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}",
|
|
||||||
"comments_url": "http://api.github.com/repos/octocat/Hello-World/comments{/number}",
|
|
||||||
"commits_url": "http://api.github.com/repos/octocat/Hello-World/commits{/sha}",
|
|
||||||
"compare_url": "http://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}",
|
|
||||||
"contents_url": "http://api.github.com/repos/octocat/Hello-World/contents/{+path}",
|
|
||||||
"contributors_url": "http://api.github.com/repos/octocat/Hello-World/contributors",
|
|
||||||
"deployments_url": "http://api.github.com/repos/octocat/Hello-World/deployments",
|
|
||||||
"downloads_url": "http://api.github.com/repos/octocat/Hello-World/downloads",
|
|
||||||
"events_url": "http://api.github.com/repos/octocat/Hello-World/events",
|
|
||||||
"forks_url": "http://api.github.com/repos/octocat/Hello-World/forks",
|
|
||||||
"git_commits_url": "http://api.github.com/repos/octocat/Hello-World/git/commits{/sha}",
|
|
||||||
"git_refs_url": "http://api.github.com/repos/octocat/Hello-World/git/refs{/sha}",
|
|
||||||
"git_tags_url": "http://api.github.com/repos/octocat/Hello-World/git/tags{/sha}",
|
|
||||||
"git_url": "git:github.com/octocat/Hello-World.git",
|
|
||||||
"issue_comment_url": "http://api.github.com/repos/octocat/Hello-World/issues/comments{/number}",
|
|
||||||
"issue_events_url": "http://api.github.com/repos/octocat/Hello-World/issues/events{/number}",
|
|
||||||
"issues_url": "http://api.github.com/repos/octocat/Hello-World/issues{/number}",
|
|
||||||
"keys_url": "http://api.github.com/repos/octocat/Hello-World/keys{/key_id}",
|
|
||||||
"labels_url": "http://api.github.com/repos/octocat/Hello-World/labels{/name}",
|
|
||||||
"languages_url": "http://api.github.com/repos/octocat/Hello-World/languages",
|
|
||||||
"merges_url": "http://api.github.com/repos/octocat/Hello-World/merges",
|
|
||||||
"milestones_url": "http://api.github.com/repos/octocat/Hello-World/milestones{/number}",
|
|
||||||
"notifications_url": "http://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}",
|
|
||||||
"pulls_url": "http://api.github.com/repos/octocat/Hello-World/pulls{/number}",
|
|
||||||
"releases_url": "http://api.github.com/repos/octocat/Hello-World/releases{/id}",
|
|
||||||
"ssh_url": "git@github.com:octocat/Hello-World.git",
|
|
||||||
"stargazers_url": "http://api.github.com/repos/octocat/Hello-World/stargazers",
|
|
||||||
"statuses_url": "http://api.github.com/repos/octocat/Hello-World/statuses/{sha}",
|
|
||||||
"subscribers_url": "http://api.github.com/repos/octocat/Hello-World/subscribers",
|
|
||||||
"subscription_url": "http://api.github.com/repos/octocat/Hello-World/subscription",
|
|
||||||
"tags_url": "http://api.github.com/repos/octocat/Hello-World/tags",
|
|
||||||
"teams_url": "http://api.github.com/repos/octocat/Hello-World/teams",
|
|
||||||
"trees_url": "http://api.github.com/repos/octocat/Hello-World/git/trees{/sha}",
|
|
||||||
"clone_url": "https://github.com/octocat/Hello-World.git",
|
|
||||||
"mirror_url": "git:git.example.com/octocat/Hello-World",
|
|
||||||
"hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks",
|
|
||||||
"svn_url": "https://svn.github.com/octocat/Hello-World",
|
|
||||||
"homepage": "https://github.com",
|
|
||||||
"language": null,
|
|
||||||
"forks_count": 9,
|
|
||||||
"stargazers_count": 80,
|
|
||||||
"watchers_count": 80,
|
|
||||||
"size": 108,
|
|
||||||
"default_branch": "master",
|
|
||||||
"open_issues_count": 0,
|
|
||||||
"is_template": true,
|
|
||||||
"topics": [
|
|
||||||
"octocat",
|
|
||||||
"atom",
|
|
||||||
"electron",
|
|
||||||
"api"
|
|
||||||
],
|
|
||||||
"has_issues": true,
|
|
||||||
"has_projects": true,
|
|
||||||
"has_wiki": true,
|
|
||||||
"has_pages": false,
|
|
||||||
"has_downloads": true,
|
|
||||||
"archived": false,
|
|
||||||
"disabled": false,
|
|
||||||
"visibility": "public",
|
|
||||||
"pushed_at": "2011-01-26T19:06:43Z",
|
|
||||||
"created_at": "2011-01-26T19:01:12Z",
|
|
||||||
"updated_at": "2011-01-26T19:14:43Z",
|
|
||||||
"permissions": {
|
|
||||||
"admin": false,
|
|
||||||
"push": false,
|
|
||||||
"pull": true
|
|
||||||
},
|
|
||||||
"allow_rebase_merge": true,
|
|
||||||
"template_repository": null,
|
|
||||||
"temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O",
|
|
||||||
"allow_squash_merge": true,
|
|
||||||
"delete_branch_on_merge": true,
|
|
||||||
"allow_merge_commit": true,
|
|
||||||
"subscribers_count": 42,
|
|
||||||
"network_count": 0
|
|
||||||
},
|
|
||||||
"source": {
|
|
||||||
"id": 1296269,
|
|
||||||
"node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
|
|
||||||
"name": "Hello-World",
|
|
||||||
"full_name": "octocat/Hello-World",
|
|
||||||
"owner": {
|
|
||||||
"login": "octocat",
|
|
||||||
"id": 1,
|
|
||||||
"node_id": "MDQ6VXNlcjE=",
|
|
||||||
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
|
|
||||||
"gravatar_id": "",
|
|
||||||
"url": "https://api.github.com/users/octocat",
|
|
||||||
"html_url": "https://github.com/octocat",
|
|
||||||
"followers_url": "https://api.github.com/users/octocat/followers",
|
|
||||||
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
|
|
||||||
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
|
|
||||||
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
|
|
||||||
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
|
|
||||||
"organizations_url": "https://api.github.com/users/octocat/orgs",
|
|
||||||
"repos_url": "https://api.github.com/users/octocat/repos",
|
|
||||||
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
|
|
||||||
"received_events_url": "https://api.github.com/users/octocat/received_events",
|
|
||||||
"type": "User",
|
|
||||||
"site_admin": false
|
|
||||||
},
|
|
||||||
"private": false,
|
|
||||||
"html_url": "https://github.com/octocat/Hello-World",
|
|
||||||
"description": "This your first repo!",
|
|
||||||
"fork": false,
|
|
||||||
"url": "https://api.github.com/repos/octocat/Hello-World",
|
|
||||||
"archive_url": "http://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}",
|
|
||||||
"assignees_url": "http://api.github.com/repos/octocat/Hello-World/assignees{/user}",
|
|
||||||
"blobs_url": "http://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}",
|
|
||||||
"branches_url": "http://api.github.com/repos/octocat/Hello-World/branches{/branch}",
|
|
||||||
"collaborators_url": "http://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}",
|
|
||||||
"comments_url": "http://api.github.com/repos/octocat/Hello-World/comments{/number}",
|
|
||||||
"commits_url": "http://api.github.com/repos/octocat/Hello-World/commits{/sha}",
|
|
||||||
"compare_url": "http://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}",
|
|
||||||
"contents_url": "http://api.github.com/repos/octocat/Hello-World/contents/{+path}",
|
|
||||||
"contributors_url": "http://api.github.com/repos/octocat/Hello-World/contributors",
|
|
||||||
"deployments_url": "http://api.github.com/repos/octocat/Hello-World/deployments",
|
|
||||||
"downloads_url": "http://api.github.com/repos/octocat/Hello-World/downloads",
|
|
||||||
"events_url": "http://api.github.com/repos/octocat/Hello-World/events",
|
|
||||||
"forks_url": "http://api.github.com/repos/octocat/Hello-World/forks",
|
|
||||||
"git_commits_url": "http://api.github.com/repos/octocat/Hello-World/git/commits{/sha}",
|
|
||||||
"git_refs_url": "http://api.github.com/repos/octocat/Hello-World/git/refs{/sha}",
|
|
||||||
"git_tags_url": "http://api.github.com/repos/octocat/Hello-World/git/tags{/sha}",
|
|
||||||
"git_url": "git:github.com/octocat/Hello-World.git",
|
|
||||||
"issue_comment_url": "http://api.github.com/repos/octocat/Hello-World/issues/comments{/number}",
|
|
||||||
"issue_events_url": "http://api.github.com/repos/octocat/Hello-World/issues/events{/number}",
|
|
||||||
"issues_url": "http://api.github.com/repos/octocat/Hello-World/issues{/number}",
|
|
||||||
"keys_url": "http://api.github.com/repos/octocat/Hello-World/keys{/key_id}",
|
|
||||||
"labels_url": "http://api.github.com/repos/octocat/Hello-World/labels{/name}",
|
|
||||||
"languages_url": "http://api.github.com/repos/octocat/Hello-World/languages",
|
|
||||||
"merges_url": "http://api.github.com/repos/octocat/Hello-World/merges",
|
|
||||||
"milestones_url": "http://api.github.com/repos/octocat/Hello-World/milestones{/number}",
|
|
||||||
"notifications_url": "http://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}",
|
|
||||||
"pulls_url": "http://api.github.com/repos/octocat/Hello-World/pulls{/number}",
|
|
||||||
"releases_url": "http://api.github.com/repos/octocat/Hello-World/releases{/id}",
|
|
||||||
"ssh_url": "git@github.com:octocat/Hello-World.git",
|
|
||||||
"stargazers_url": "http://api.github.com/repos/octocat/Hello-World/stargazers",
|
|
||||||
"statuses_url": "http://api.github.com/repos/octocat/Hello-World/statuses/{sha}",
|
|
||||||
"subscribers_url": "http://api.github.com/repos/octocat/Hello-World/subscribers",
|
|
||||||
"subscription_url": "http://api.github.com/repos/octocat/Hello-World/subscription",
|
|
||||||
"tags_url": "http://api.github.com/repos/octocat/Hello-World/tags",
|
|
||||||
"teams_url": "http://api.github.com/repos/octocat/Hello-World/teams",
|
|
||||||
"trees_url": "http://api.github.com/repos/octocat/Hello-World/git/trees{/sha}",
|
|
||||||
"clone_url": "https://github.com/octocat/Hello-World.git",
|
|
||||||
"mirror_url": "git:git.example.com/octocat/Hello-World",
|
|
||||||
"hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks",
|
|
||||||
"svn_url": "https://svn.github.com/octocat/Hello-World",
|
|
||||||
"homepage": "https://github.com",
|
|
||||||
"language": null,
|
|
||||||
"forks_count": 9,
|
|
||||||
"stargazers_count": 80,
|
|
||||||
"watchers_count": 80,
|
|
||||||
"size": 108,
|
|
||||||
"default_branch": "master",
|
|
||||||
"open_issues_count": 0,
|
|
||||||
"is_template": true,
|
|
||||||
"topics": [
|
|
||||||
"octocat",
|
|
||||||
"atom",
|
|
||||||
"electron",
|
|
||||||
"api"
|
|
||||||
],
|
|
||||||
"has_issues": true,
|
|
||||||
"has_projects": true,
|
|
||||||
"has_wiki": true,
|
|
||||||
"has_pages": false,
|
|
||||||
"has_downloads": true,
|
|
||||||
"archived": false,
|
|
||||||
"disabled": false,
|
|
||||||
"visibility": "public",
|
|
||||||
"pushed_at": "2011-01-26T19:06:43Z",
|
|
||||||
"created_at": "2011-01-26T19:01:12Z",
|
|
||||||
"updated_at": "2011-01-26T19:14:43Z",
|
|
||||||
"permissions": {
|
|
||||||
"admin": false,
|
|
||||||
"push": false,
|
|
||||||
"pull": true
|
|
||||||
},
|
|
||||||
"allow_rebase_merge": true,
|
|
||||||
"template_repository": null,
|
|
||||||
"temp_clone_token": "ABTLWHOULUVAXGTRYU7OC2876QJ2O",
|
|
||||||
"allow_squash_merge": true,
|
|
||||||
"delete_branch_on_merge": true,
|
|
||||||
"allow_merge_commit": true,
|
|
||||||
"subscribers_count": 42,
|
|
||||||
"network_count": 0
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +1 @@
|
|||||||
bar
|
bar
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -0,0 +1,200 @@
|
|||||||
|
# Cache
|
||||||
|
|
||||||
|
* [Inline cache](#inline-cache)
|
||||||
|
* [Registry cache](#registry-cache)
|
||||||
|
* [GitHub cache](#github-cache)
|
||||||
|
* [Cache backend API](#cache-backend-api)
|
||||||
|
* [Local cache](#local-cache)
|
||||||
|
|
||||||
|
> More info about cache on [BuildKit](https://github.com/moby/buildkit#export-cache) and [Buildx](https://github.com/docker/buildx/blob/master/docs/reference/buildx_build.md#cache-from) repositories.
|
||||||
|
|
||||||
|
## Inline cache
|
||||||
|
|
||||||
|
In most cases you want to use the [`type=inline` cache exporter](https://github.com/moby/buildkit#inline-push-image-and-cache-together).
|
||||||
|
However, note that the `inline` cache exporter only supports `min` cache mode. To enable `max` cache mode, push the
|
||||||
|
image and the cache separately by using the `registry` cache exporter as shown in the [next example](#registry-cache).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: user/app:latest
|
||||||
|
cache-from: type=registry,ref=user/app:latest
|
||||||
|
cache-to: type=inline
|
||||||
|
```
|
||||||
|
|
||||||
|
## Registry cache
|
||||||
|
|
||||||
|
You can import/export cache from a cache manifest or (special) image configuration on the registry with the
|
||||||
|
[`type=registry` cache exporter](https://github.com/moby/buildkit/tree/master#registry-push-image-and-cache-separately).
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: user/app:latest
|
||||||
|
cache-from: type=registry,ref=user/app:buildcache
|
||||||
|
cache-to: type=registry,ref=user/app:buildcache,mode=max
|
||||||
|
```
|
||||||
|
|
||||||
|
## GitHub cache
|
||||||
|
|
||||||
|
### Cache backend API
|
||||||
|
|
||||||
|
> :test_tube: This cache exporter is considered EXPERIMENTAL until further notice. Please provide feedback on
|
||||||
|
> [BuildKit repository](https://github.com/moby/buildkit) if you encounter any issues.
|
||||||
|
|
||||||
|
Since [buildx 0.6.0](https://github.com/docker/buildx/releases/tag/v0.6.0) and [BuildKit 0.9.0](https://github.com/moby/buildkit/releases/tag/v0.9.0),
|
||||||
|
you can use the [`type=gha` cache exporter](https://github.com/moby/buildkit/tree/master#github-actions-cache-experimental).
|
||||||
|
|
||||||
|
GitHub Actions cache exporter backend uses the [GitHub Cache API](https://github.com/tonistiigi/go-actions-cache/blob/master/api.md)
|
||||||
|
to fetch and upload cache blobs. That's why this type of cache should be exclusively used in a GitHub Action workflow
|
||||||
|
as the `url` (`$ACTIONS_CACHE_URL`) and `token` (`$ACTIONS_RUNTIME_TOKEN`) attributes are populated when a workflow
|
||||||
|
is started.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: user/app:latest
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
```
|
||||||
|
|
||||||
|
### Local cache
|
||||||
|
|
||||||
|
> :warning: At the moment caches are copied over the existing cache so it [keeps growing](https://github.com/docker/build-push-action/issues/252).
|
||||||
|
> The `Move cache` step is used as a temporary fix (see https://github.com/moby/buildkit/issues/1896).
|
||||||
|
|
||||||
|
You can also leverage [GitHub cache](https://docs.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows)
|
||||||
|
using [actions/cache](https://github.com/actions/cache) and [`type=local` cache exporter](https://github.com/moby/buildkit#local-directory-1)
|
||||||
|
with this action:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Cache Docker layers
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: /tmp/.buildx-cache
|
||||||
|
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-buildx-
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: user/app:latest
|
||||||
|
cache-from: type=local,src=/tmp/.buildx-cache
|
||||||
|
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max
|
||||||
|
-
|
||||||
|
# Temp fix
|
||||||
|
# https://github.com/docker/build-push-action/issues/252
|
||||||
|
# https://github.com/moby/buildkit/issues/1896
|
||||||
|
name: Move cache
|
||||||
|
run: |
|
||||||
|
rm -rf /tmp/.buildx-cache
|
||||||
|
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
|
||||||
|
```
|
@ -0,0 +1,73 @@
|
|||||||
|
# Copy images between registries
|
||||||
|
|
||||||
|
Multi-platform images built using buildx can be copied from one registry to another without
|
||||||
|
changing the image SHA using the [tag-push-action](https://github.com/akhilerm/tag-push-action).
|
||||||
|
|
||||||
|
The following workflow will first push the image to dockerhub, run some tests using the images
|
||||||
|
and then push to quay and ghcr
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- # quay and ghcr logins for pushing image after testing
|
||||||
|
name: Login to Quay Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: quay.io
|
||||||
|
username: ${{ secrets.QUAY_USERNAME }}
|
||||||
|
password: ${{ secrets.QUAY_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
user/app:latest
|
||||||
|
user/app:1.0.0
|
||||||
|
- # run tests using image from docker hub
|
||||||
|
name: Run Tests
|
||||||
|
run: make tests
|
||||||
|
- # copy multiplatform image from dockerhub to quay and ghcr
|
||||||
|
name: Push Image to multiple registries
|
||||||
|
uses: akhilerm/tag-push-action@v2.0.0
|
||||||
|
with:
|
||||||
|
src: docker.io/user/app:1.0.0
|
||||||
|
dst: |
|
||||||
|
quay.io/user/app:latest
|
||||||
|
quay.io/user/app:1.0.0
|
||||||
|
ghcr.io/user/app:latest
|
||||||
|
ghcr.io/user/app:1.0.0
|
||||||
|
```
|
@ -0,0 +1,48 @@
|
|||||||
|
# Update DockerHub repo description
|
||||||
|
|
||||||
|
You can update the [DockerHub repository description](https://docs.docker.com/docker-hub/repos/) using
|
||||||
|
a third party action called [DockerHub Description](https://github.com/peter-evans/dockerhub-description)
|
||||||
|
with this action:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: user/app:latest
|
||||||
|
-
|
||||||
|
name: Update repo description
|
||||||
|
uses: peter-evans/dockerhub-description@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_PASSWORD }}
|
||||||
|
repository: user/app
|
||||||
|
```
|
@ -0,0 +1,35 @@
|
|||||||
|
# Export image to Docker
|
||||||
|
|
||||||
|
You may want your build result to be available in the Docker client through `docker images` to be able to use it
|
||||||
|
in another step of your workflow:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Build
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
load: true
|
||||||
|
tags: myimage:latest
|
||||||
|
-
|
||||||
|
name: Inspect
|
||||||
|
run: |
|
||||||
|
docker image inspect myimage:latest
|
||||||
|
```
|
@ -0,0 +1,44 @@
|
|||||||
|
# Isolated builders
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
id: builder1
|
||||||
|
-
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
id: builder2
|
||||||
|
-
|
||||||
|
name: Builder 1 name
|
||||||
|
run: echo ${{ steps.builder1.outputs.name }}
|
||||||
|
-
|
||||||
|
name: Builder 2 name
|
||||||
|
run: echo ${{ steps.builder2.outputs.name }}
|
||||||
|
-
|
||||||
|
name: Build against builder1
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
builder: ${{ steps.builder1.outputs.name }}
|
||||||
|
context: .
|
||||||
|
target: mytarget1
|
||||||
|
-
|
||||||
|
name: Build against builder2
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
builder: ${{ steps.builder2.outputs.name }}
|
||||||
|
context: .
|
||||||
|
target: mytarget2
|
||||||
|
```
|
@ -0,0 +1,44 @@
|
|||||||
|
# Local registry
|
||||||
|
|
||||||
|
For testing purposes you may need to create a [local registry](https://hub.docker.com/_/registry) to push images into:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
services:
|
||||||
|
registry:
|
||||||
|
image: registry:2
|
||||||
|
ports:
|
||||||
|
- 5000:5000
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
with:
|
||||||
|
driver-opts: network=host
|
||||||
|
-
|
||||||
|
name: Build and push to local registry
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: localhost:5000/name/app:latest
|
||||||
|
-
|
||||||
|
name: Inspect
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools inspect localhost:5000/name/app:latest
|
||||||
|
```
|
@ -0,0 +1,44 @@
|
|||||||
|
# Multi-platform image
|
||||||
|
|
||||||
|
You can build multi-platform images using the [`platforms` input](../../README.md#inputs) as described below.
|
||||||
|
|
||||||
|
> :bulb: List of available platforms will be displayed and available through our [setup-buildx](https://github.com/docker/setup-buildx-action#about) action.
|
||||||
|
|
||||||
|
> :bulb: If you want support for more platforms, you can use QEMU with our [setup-qemu](https://github.com/docker/setup-qemu-action) action.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: user/app:latest
|
||||||
|
```
|
@ -0,0 +1,57 @@
|
|||||||
|
# Push to multi-registries
|
||||||
|
|
||||||
|
* [Docker Hub and GHCR](#docker-hub-and-ghcr)
|
||||||
|
|
||||||
|
## Docker Hub and GHCR
|
||||||
|
|
||||||
|
The following workflow will connect you to [DockerHub](https://github.com/docker/login-action#dockerhub)
|
||||||
|
and [GitHub Container Registry](https://github.com/docker/login-action#github-container-registry) and push the
|
||||||
|
image to these registries.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
user/app:latest
|
||||||
|
user/app:1.0.0
|
||||||
|
ghcr.io/user/app:latest
|
||||||
|
ghcr.io/user/app:1.0.0
|
||||||
|
```
|
@ -0,0 +1,84 @@
|
|||||||
|
# Secrets
|
||||||
|
|
||||||
|
In the following example we will expose and use the [GITHUB_TOKEN secret](https://docs.github.com/en/actions/reference/authentication-in-a-workflow#about-the-github_token-secret)
|
||||||
|
as provided by GitHub in your workflow.
|
||||||
|
|
||||||
|
First let's create our `Dockerfile` to use our secret:
|
||||||
|
|
||||||
|
```Dockerfile
|
||||||
|
#syntax=docker/dockerfile:1.2
|
||||||
|
|
||||||
|
FROM alpine
|
||||||
|
RUN --mount=type=secret,id=github_token \
|
||||||
|
cat /run/secrets/github_token
|
||||||
|
```
|
||||||
|
|
||||||
|
As you can see we have named our secret `github_token`. Here is the workflow you can use to expose this secret using
|
||||||
|
the [`secrets` input](../../README.md#inputs):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Build
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
tags: user/app:latest
|
||||||
|
secrets: |
|
||||||
|
"github_token=${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
> :bulb: You can also expose a secret file to the build with [`secret-files`](../../README.md#inputs) input:
|
||||||
|
> ```yaml
|
||||||
|
> secret-files: |
|
||||||
|
> "MY_SECRET=./secret.txt"
|
||||||
|
> ```
|
||||||
|
|
||||||
|
If you're using [GitHub secrets](https://docs.github.com/en/actions/reference/encrypted-secrets) and need to handle
|
||||||
|
multi-line value, you will need to place the key-value pair between quotes:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
secrets: |
|
||||||
|
"MYSECRET=${{ secrets.GPG_KEY }}"
|
||||||
|
GIT_AUTH_TOKEN=abcdefghi,jklmno=0123456789
|
||||||
|
"MYSECRET=aaaaaaaa
|
||||||
|
bbbbbbb
|
||||||
|
ccccccccc"
|
||||||
|
FOO=bar
|
||||||
|
"EMPTYLINE=aaaa
|
||||||
|
|
||||||
|
bbbb
|
||||||
|
ccc"
|
||||||
|
"JSON_SECRET={""key1"":""value1"",""key2"":""value2""}"
|
||||||
|
```
|
||||||
|
|
||||||
|
| Key | Value |
|
||||||
|
|--------------------|--------------------------------------------------|
|
||||||
|
| `MYSECRET` | `***********************` |
|
||||||
|
| `GIT_AUTH_TOKEN` | `abcdefghi,jklmno=0123456789` |
|
||||||
|
| `MYSECRET` | `aaaaaaaa\nbbbbbbb\nccccccccc` |
|
||||||
|
| `FOO` | `bar` |
|
||||||
|
| `EMPTYLINE` | `aaaa\n\nbbbb\nccc` |
|
||||||
|
| `JSON_SECRET` | `{"key1":"value1","key2":"value2"}` |
|
||||||
|
|
||||||
|
> :bulb: All quote signs need to be doubled for escaping.
|
@ -0,0 +1,58 @@
|
|||||||
|
# Share built image between jobs
|
||||||
|
|
||||||
|
As each job is isolated in its own runner you cannot use your built image between jobs (except for [self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners)).
|
||||||
|
However, you can [pass data between jobs in a workflow](https://docs.github.com/en/actions/guides/storing-workflow-data-as-artifacts#passing-data-between-jobs-in-a-workflow)
|
||||||
|
using the [actions/upload-artifact](https://github.com/actions/upload-artifact) and [actions/download-artifact](https://github.com/actions/download-artifact)
|
||||||
|
actions:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Build and export
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
tags: myimage:latest
|
||||||
|
outputs: type=docker,dest=/tmp/myimage.tar
|
||||||
|
-
|
||||||
|
name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: myimage
|
||||||
|
path: /tmp/myimage.tar
|
||||||
|
|
||||||
|
use:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Download artifact
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: myimage
|
||||||
|
path: /tmp
|
||||||
|
-
|
||||||
|
name: Load image
|
||||||
|
run: |
|
||||||
|
docker load --input /tmp/myimage.tar
|
||||||
|
docker image ls -a
|
||||||
|
```
|
@ -0,0 +1,76 @@
|
|||||||
|
# Handle tags and labels
|
||||||
|
|
||||||
|
If you want an "automatic" tag management and [OCI Image Format Specification](https://github.com/opencontainers/image-spec/blob/master/annotations.md)
|
||||||
|
for labels, you can do it in a dedicated step. The following workflow will use the [Docker metadata action](https://github.com/docker/metadata-action)
|
||||||
|
to handle tags and labels based on GitHub actions events and Git metadata.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 10 * * *'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
tags:
|
||||||
|
- 'v*.*.*'
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
# list of Docker images to use as base name for tags
|
||||||
|
images: |
|
||||||
|
name/app
|
||||||
|
ghcr.io/username/app
|
||||||
|
# generate Docker tags based on the following events/attributes
|
||||||
|
tags: |
|
||||||
|
type=schedule
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
type=semver,pattern={{major}}
|
||||||
|
type=sha
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Login to GHCR
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
```
|
@ -0,0 +1,64 @@
|
|||||||
|
# Test your image before pushing it
|
||||||
|
|
||||||
|
In some cases, you might want to validate that the image works as expected
|
||||||
|
before pushing it.
|
||||||
|
|
||||||
|
The workflow below will be composed of several steps to achieve this:
|
||||||
|
* Build and export the image to Docker
|
||||||
|
* Test your image
|
||||||
|
* Multi-platform build and push the image
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ci
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'main'
|
||||||
|
|
||||||
|
env:
|
||||||
|
TEST_TAG: user/myapp:test
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
-
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
-
|
||||||
|
name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Build and export to Docker
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
load: true
|
||||||
|
tags: ${{ env.TEST_TAG }}
|
||||||
|
-
|
||||||
|
name: Test
|
||||||
|
run: |
|
||||||
|
docker run --rm ${{ env.TEST_TAG }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: user/app:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
> :bulb: Build time will not be increased with this workflow because internal
|
||||||
|
> cache for `linux/amd64` will be used from previous step on `Build and push`
|
||||||
|
> step so only `linux/arm64` will be actually built.
|
@ -0,0 +1,161 @@
|
|||||||
|
import {parse} from 'csv-parse/sync';
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import * as semver from 'semver';
|
||||||
|
import * as exec from '@actions/exec';
|
||||||
|
|
||||||
|
import * as context from './context';
|
||||||
|
|
||||||
|
export async function getImageIDFile(): Promise<string> {
|
||||||
|
return path.join(context.tmpDir(), 'iidfile').split(path.sep).join(path.posix.sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getImageID(): Promise<string | undefined> {
|
||||||
|
const iidFile = await getImageIDFile();
|
||||||
|
if (!fs.existsSync(iidFile)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return fs.readFileSync(iidFile, {encoding: 'utf-8'}).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getMetadataFile(): Promise<string> {
|
||||||
|
return path.join(context.tmpDir(), 'metadata-file').split(path.sep).join(path.posix.sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getMetadata(): Promise<string | undefined> {
|
||||||
|
const metadataFile = await getMetadataFile();
|
||||||
|
if (!fs.existsSync(metadataFile)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const content = fs.readFileSync(metadataFile, {encoding: 'utf-8'}).trim();
|
||||||
|
if (content === 'null') {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getDigest(metadata: string | undefined): Promise<string | undefined> {
|
||||||
|
if (metadata === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const metadataJSON = JSON.parse(metadata);
|
||||||
|
if (metadataJSON['containerimage.digest']) {
|
||||||
|
return metadataJSON['containerimage.digest'];
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getSecretString(kvp: string): Promise<string> {
|
||||||
|
return getSecret(kvp, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getSecretFile(kvp: string): Promise<string> {
|
||||||
|
return getSecret(kvp, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getSecret(kvp: string, file: boolean): Promise<string> {
|
||||||
|
const delimiterIndex = kvp.indexOf('=');
|
||||||
|
const key = kvp.substring(0, delimiterIndex);
|
||||||
|
let value = kvp.substring(delimiterIndex + 1);
|
||||||
|
if (key.length == 0 || value.length == 0) {
|
||||||
|
throw new Error(`${kvp} is not a valid secret`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
if (!fs.existsSync(value)) {
|
||||||
|
throw new Error(`secret file ${value} not found`);
|
||||||
|
}
|
||||||
|
value = fs.readFileSync(value, {encoding: 'utf-8'});
|
||||||
|
}
|
||||||
|
|
||||||
|
const secretFile = context.tmpNameSync({
|
||||||
|
tmpdir: context.tmpDir()
|
||||||
|
});
|
||||||
|
fs.writeFileSync(secretFile, value);
|
||||||
|
|
||||||
|
return `id=${key},src=${secretFile}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isLocalOrTarExporter(outputs: string[]): boolean {
|
||||||
|
const records = parse(outputs.join(`\n`), {
|
||||||
|
delimiter: ',',
|
||||||
|
trim: true,
|
||||||
|
columns: false,
|
||||||
|
relaxColumnCount: true
|
||||||
|
});
|
||||||
|
for (const record of records) {
|
||||||
|
// Local if no type is defined
|
||||||
|
// https://github.com/docker/buildx/blob/d2bf42f8b4784d83fde17acb3ed84703ddc2156b/build/output.go#L29-L43
|
||||||
|
if (record.length == 1 && !record[0].startsWith('type=')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (const [key, value] of record.map(chunk => chunk.split('=').map(item => item.trim()))) {
|
||||||
|
if (key == 'type' && (value == 'local' || value == 'tar')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hasGitAuthToken(secrets: string[]): boolean {
|
||||||
|
for (const secret of secrets) {
|
||||||
|
if (secret.startsWith('GIT_AUTH_TOKEN=')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function isAvailable(standalone?: boolean): Promise<boolean> {
|
||||||
|
const cmd = getCommand([], standalone);
|
||||||
|
return await exec
|
||||||
|
.getExecOutput(cmd.command, 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.command, 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 function getCommand(args: Array<string>, standalone?: boolean) {
|
||||||
|
return {
|
||||||
|
command: standalone ? 'buildx' : 'docker',
|
||||||
|
args: standalone ? args : ['buildx', ...args]
|
||||||
|
};
|
||||||
|
}
|
@ -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;
|
||||||
|
});
|
||||||
|
}
|
@ -1,306 +1,95 @@
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as buildx from './buildx';
|
||||||
|
import * as context from './context';
|
||||||
|
import * as docker from './docker';
|
||||||
import * as stateHelper from './state-helper';
|
import * as stateHelper from './state-helper';
|
||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
import * as actionsToolkit from '@docker/actions-toolkit';
|
import * as exec from '@actions/exec';
|
||||||
|
|
||||||
import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx';
|
async function run(): Promise<void> {
|
||||||
import {History as BuildxHistory} from '@docker/actions-toolkit/lib/buildx/history';
|
try {
|
||||||
import {Context} from '@docker/actions-toolkit/lib/context';
|
const defContext = context.defaultContext();
|
||||||
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
|
const inputs: context.Inputs = await context.getInputs(defContext);
|
||||||
import {Exec} from '@docker/actions-toolkit/lib/exec';
|
|
||||||
import {GitHub} from '@docker/actions-toolkit/lib/github';
|
// standalone if docker cli not available
|
||||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
|
const standalone = !(await docker.isAvailable());
|
||||||
import {Util} from '@docker/actions-toolkit/lib/util';
|
|
||||||
|
core.startGroup(`Docker info`);
|
||||||
import {BuilderInfo} from '@docker/actions-toolkit/lib/types/buildx/builder';
|
if (standalone) {
|
||||||
import {ConfigFile} from '@docker/actions-toolkit/lib/types/docker/docker';
|
core.info(`Docker info skipped in standalone mode`);
|
||||||
import {UploadArtifactResponse} from '@docker/actions-toolkit/lib/types/github';
|
} else {
|
||||||
|
await exec.exec('docker', ['version'], {
|
||||||
import * as context from './context';
|
failOnStdErr: false
|
||||||
|
});
|
||||||
actionsToolkit.run(
|
await exec.exec('docker', ['info'], {
|
||||||
// main
|
failOnStdErr: false
|
||||||
async () => {
|
});
|
||||||
const startedTime = new Date();
|
}
|
||||||
const inputs: context.Inputs = await context.getInputs();
|
core.endGroup();
|
||||||
stateHelper.setSummaryInputs(inputs);
|
|
||||||
core.debug(`inputs: ${JSON.stringify(inputs)}`);
|
|
||||||
|
|
||||||
const toolkit = new Toolkit();
|
|
||||||
|
|
||||||
await core.group(`GitHub Actions runtime token ACs`, async () => {
|
|
||||||
try {
|
|
||||||
await GitHub.printActionsRuntimeTokenACs();
|
|
||||||
} catch (e) {
|
|
||||||
core.warning(e.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await core.group(`Docker info`, async () => {
|
|
||||||
try {
|
|
||||||
await Docker.printVersion();
|
|
||||||
await Docker.printInfo();
|
|
||||||
} catch (e) {
|
|
||||||
core.info(e.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await core.group(`Proxy configuration`, async () => {
|
|
||||||
let dockerConfig: ConfigFile | undefined;
|
|
||||||
let dockerConfigMalformed = false;
|
|
||||||
try {
|
|
||||||
dockerConfig = await Docker.configFile();
|
|
||||||
} catch (e) {
|
|
||||||
dockerConfigMalformed = true;
|
|
||||||
core.warning(`Unable to parse config file ${path.join(Docker.configDir, 'config.json')}: ${e}`);
|
|
||||||
}
|
|
||||||
if (dockerConfig && dockerConfig.proxies) {
|
|
||||||
for (const host in dockerConfig.proxies) {
|
|
||||||
let prefix = '';
|
|
||||||
if (Object.keys(dockerConfig.proxies).length > 1) {
|
|
||||||
prefix = ' ';
|
|
||||||
core.info(host);
|
|
||||||
}
|
|
||||||
for (const key in dockerConfig.proxies[host]) {
|
|
||||||
core.info(`${prefix}${key}: ${dockerConfig.proxies[host][key]}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (!dockerConfigMalformed) {
|
|
||||||
core.info('No proxy configuration found');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!(await toolkit.buildx.isAvailable())) {
|
if (!(await buildx.isAvailable(standalone))) {
|
||||||
core.setFailed(`Docker buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
|
core.setFailed(`Docker buildx is required. See https://github.com/docker/setup-buildx-action to set up buildx.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
stateHelper.setTmpDir(context.tmpDir());
|
||||||
|
|
||||||
stateHelper.setTmpDir(Context.tmpDir());
|
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.command, versionCmd.args, {
|
||||||
|
failOnStdErr: false
|
||||||
let builder: BuilderInfo;
|
});
|
||||||
await core.group(`Builder info`, async () => {
|
|
||||||
builder = await toolkit.builder.inspect(inputs.builder);
|
|
||||||
stateHelper.setBuilderDriver(builder.driver ?? '');
|
|
||||||
stateHelper.setBuilderEndpoint(builder.nodes?.[0]?.endpoint ?? '');
|
|
||||||
core.info(JSON.stringify(builder, null, 2));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const args: string[] = await context.getArgs(inputs, toolkit);
|
const args: string[] = await context.getArgs(inputs, defContext, buildxVersion);
|
||||||
core.debug(`context.getArgs: ${JSON.stringify(args)}`);
|
const buildCmd = buildx.getCommand(args, standalone);
|
||||||
|
await exec
|
||||||
const buildCmd = await toolkit.buildx.getCommand(args);
|
.getExecOutput(buildCmd.command, buildCmd.args, {
|
||||||
core.debug(`buildCmd.command: ${buildCmd.command}`);
|
ignoreReturnCode: true
|
||||||
core.debug(`buildCmd.args: ${JSON.stringify(buildCmd.args)}`);
|
})
|
||||||
|
.then(res => {
|
||||||
let err: Error | undefined;
|
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||||
await Exec.getExecOutput(buildCmd.command, buildCmd.args, {
|
throw new Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
||||||
ignoreReturnCode: true,
|
|
||||||
env: Object.assign({}, process.env, {
|
|
||||||
BUILDX_METADATA_WARNINGS: 'true'
|
|
||||||
}) as {
|
|
||||||
[key: string]: string;
|
|
||||||
}
|
|
||||||
}).then(res => {
|
|
||||||
if (res.exitCode != 0) {
|
|
||||||
if (inputs.call && inputs.call === 'check' && res.stdout.length > 0) {
|
|
||||||
// checks warnings are printed to stdout: https://github.com/docker/buildx/pull/2647
|
|
||||||
// take the first line with the message summaryzing the warnings
|
|
||||||
err = new Error(res.stdout.split('\n')[0]?.trim());
|
|
||||||
} else if (res.stderr.length > 0) {
|
|
||||||
err = new Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
const imageID = await buildx.getImageID();
|
||||||
|
const metadata = await buildx.getMetadata();
|
||||||
|
const digest = await buildx.getDigest(metadata);
|
||||||
|
|
||||||
const imageID = toolkit.buildxBuild.resolveImageID();
|
|
||||||
const metadata = toolkit.buildxBuild.resolveMetadata();
|
|
||||||
const digest = toolkit.buildxBuild.resolveDigest(metadata);
|
|
||||||
if (imageID) {
|
if (imageID) {
|
||||||
await core.group(`ImageID`, async () => {
|
await core.group(`ImageID`, async () => {
|
||||||
core.info(imageID);
|
core.info(imageID);
|
||||||
core.setOutput('imageid', imageID);
|
context.setOutput('imageid', imageID);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (digest) {
|
if (digest) {
|
||||||
await core.group(`Digest`, async () => {
|
await core.group(`Digest`, async () => {
|
||||||
core.info(digest);
|
core.info(digest);
|
||||||
core.setOutput('digest', digest);
|
context.setOutput('digest', digest);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (metadata) {
|
if (metadata) {
|
||||||
await core.group(`Metadata`, async () => {
|
await core.group(`Metadata`, async () => {
|
||||||
const metadatadt = JSON.stringify(metadata, null, 2);
|
core.info(metadata);
|
||||||
core.info(metadatadt);
|
context.setOutput('metadata', metadata);
|
||||||
core.setOutput('metadata', metadatadt);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let ref: string | undefined;
|
|
||||||
await core.group(`Reference`, async () => {
|
|
||||||
ref = await buildRef(toolkit, startedTime, inputs.builder);
|
|
||||||
if (ref) {
|
|
||||||
core.info(ref);
|
|
||||||
stateHelper.setBuildRef(ref);
|
|
||||||
} else {
|
|
||||||
core.info('No build reference found');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (buildChecksAnnotationsEnabled()) {
|
|
||||||
const warnings = toolkit.buildxBuild.resolveWarnings(metadata);
|
|
||||||
if (ref && warnings && warnings.length > 0) {
|
|
||||||
const annotations = await Buildx.convertWarningsToGitHubAnnotations(warnings, [ref]);
|
|
||||||
core.debug(`annotations: ${JSON.stringify(annotations, null, 2)}`);
|
|
||||||
if (annotations && annotations.length > 0) {
|
|
||||||
await core.group(`Generating GitHub annotations (${annotations.length} build checks found)`, async () => {
|
|
||||||
for (const annotation of annotations) {
|
|
||||||
core.warning(annotation.message, annotation);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await core.group(`Check build summary support`, async () => {
|
|
||||||
if (!buildSummaryEnabled()) {
|
|
||||||
core.info('Build summary disabled');
|
|
||||||
} else if (inputs.call && inputs.call !== 'build') {
|
|
||||||
core.info(`Build summary skipped for ${inputs.call} subrequest`);
|
|
||||||
} else if (GitHub.isGHES) {
|
|
||||||
core.info('Build summary is not yet supported on GHES');
|
|
||||||
} else if (!(await toolkit.buildx.versionSatisfies('>=0.13.0'))) {
|
|
||||||
core.info('Build summary requires Buildx >= 0.13.0');
|
|
||||||
} else if (!ref) {
|
|
||||||
core.info('Build summary requires a build reference');
|
|
||||||
} else {
|
|
||||||
core.info('Build summary supported!');
|
|
||||||
stateHelper.setSummarySupported();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// post
|
|
||||||
async () => {
|
|
||||||
if (stateHelper.isSummarySupported) {
|
|
||||||
await core.group(`Generating build summary`, async () => {
|
|
||||||
try {
|
|
||||||
const recordUploadEnabled = buildRecordUploadEnabled();
|
|
||||||
let recordRetentionDays: number | undefined;
|
|
||||||
if (recordUploadEnabled) {
|
|
||||||
recordRetentionDays = buildRecordRetentionDays();
|
|
||||||
}
|
|
||||||
|
|
||||||
const buildxHistory = new BuildxHistory();
|
|
||||||
const exportRes = await buildxHistory.export({
|
|
||||||
refs: stateHelper.buildRef ? [stateHelper.buildRef] : [],
|
|
||||||
useContainer: buildExportLegacy()
|
|
||||||
});
|
|
||||||
core.info(`Build record written to ${exportRes.dockerbuildFilename} (${Util.formatFileSize(exportRes.dockerbuildSize)})`);
|
|
||||||
|
|
||||||
let uploadRes: UploadArtifactResponse | undefined;
|
|
||||||
if (recordUploadEnabled) {
|
|
||||||
uploadRes = await GitHub.uploadArtifact({
|
|
||||||
filename: exportRes.dockerbuildFilename,
|
|
||||||
mimeType: 'application/gzip',
|
|
||||||
retentionDays: recordRetentionDays
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await GitHub.writeBuildSummary({
|
|
||||||
exportRes: exportRes,
|
|
||||||
uploadRes: uploadRes,
|
|
||||||
inputs: stateHelper.summaryInputs,
|
|
||||||
driver: stateHelper.builderDriver,
|
|
||||||
endpoint: stateHelper.builderEndpoint
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
core.warning(e.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (stateHelper.tmpDir.length > 0) {
|
|
||||||
await core.group(`Removing temp folder ${stateHelper.tmpDir}`, async () => {
|
|
||||||
try {
|
|
||||||
fs.rmSync(stateHelper.tmpDir, {recursive: true});
|
|
||||||
} catch (e) {
|
|
||||||
core.warning(`Failed to remove temp folder ${stateHelper.tmpDir}`);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(error.message);
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
async function buildRef(toolkit: Toolkit, since: Date, builder?: string): Promise<string> {
|
|
||||||
// get ref from metadata file
|
|
||||||
const ref = toolkit.buildxBuild.resolveRef();
|
|
||||||
if (ref) {
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
// otherwise, look for the very first build ref since the build has started
|
|
||||||
if (!builder) {
|
|
||||||
const currentBuilder = await toolkit.builder.inspect();
|
|
||||||
builder = currentBuilder.name;
|
|
||||||
}
|
|
||||||
const refs = Buildx.refs({
|
|
||||||
dir: Buildx.refsDir,
|
|
||||||
builderName: builder,
|
|
||||||
since: since
|
|
||||||
});
|
|
||||||
return Object.keys(refs).length > 0 ? Object.keys(refs)[0] : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildChecksAnnotationsEnabled(): boolean {
|
|
||||||
if (process.env.DOCKER_BUILD_CHECKS_ANNOTATIONS) {
|
|
||||||
return Util.parseBool(process.env.DOCKER_BUILD_CHECKS_ANNOTATIONS);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildSummaryEnabled(): boolean {
|
|
||||||
if (process.env.DOCKER_BUILD_NO_SUMMARY) {
|
|
||||||
core.warning('DOCKER_BUILD_NO_SUMMARY is deprecated. Set DOCKER_BUILD_SUMMARY to false instead.');
|
|
||||||
return !Util.parseBool(process.env.DOCKER_BUILD_NO_SUMMARY);
|
|
||||||
} else if (process.env.DOCKER_BUILD_SUMMARY) {
|
|
||||||
return Util.parseBool(process.env.DOCKER_BUILD_SUMMARY);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildRecordUploadEnabled(): boolean {
|
async function cleanup(): Promise<void> {
|
||||||
if (process.env.DOCKER_BUILD_RECORD_UPLOAD) {
|
if (stateHelper.tmpDir.length > 0) {
|
||||||
return Util.parseBool(process.env.DOCKER_BUILD_RECORD_UPLOAD);
|
core.startGroup(`Removing temp folder ${stateHelper.tmpDir}`);
|
||||||
|
fs.rmSync(stateHelper.tmpDir, {recursive: true});
|
||||||
|
core.endGroup();
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildRecordRetentionDays(): number | undefined {
|
if (!stateHelper.IsPost) {
|
||||||
let val: string | undefined;
|
run();
|
||||||
if (process.env.DOCKER_BUILD_EXPORT_RETENTION_DAYS) {
|
} else {
|
||||||
core.warning('DOCKER_BUILD_EXPORT_RETENTION_DAYS is deprecated. Use DOCKER_BUILD_RECORD_RETENTION_DAYS instead.');
|
cleanup();
|
||||||
val = process.env.DOCKER_BUILD_EXPORT_RETENTION_DAYS;
|
|
||||||
} else if (process.env.DOCKER_BUILD_RECORD_RETENTION_DAYS) {
|
|
||||||
val = process.env.DOCKER_BUILD_RECORD_RETENTION_DAYS;
|
|
||||||
}
|
|
||||||
if (val) {
|
|
||||||
const res = parseInt(val);
|
|
||||||
if (isNaN(res)) {
|
|
||||||
throw new Error(`Invalid build record retention days: ${val}`);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildExportLegacy(): boolean {
|
|
||||||
if (process.env.DOCKER_BUILD_EXPORT_LEGACY) {
|
|
||||||
return Util.parseBool(process.env.DOCKER_BUILD_EXPORT_LEGACY);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
@ -1,70 +1,12 @@
|
|||||||
import * as core from '@actions/core';
|
import * as core from '@actions/core';
|
||||||
|
|
||||||
import {Build} from '@docker/actions-toolkit/lib/buildx/build';
|
export const IsPost = !!process.env['STATE_isPost'];
|
||||||
|
|
||||||
import {Inputs} from './context';
|
|
||||||
|
|
||||||
export const tmpDir = process.env['STATE_tmpDir'] || '';
|
export const tmpDir = process.env['STATE_tmpDir'] || '';
|
||||||
|
|
||||||
export const builderDriver = process.env['STATE_builderDriver'] || '';
|
|
||||||
export const builderEndpoint = process.env['STATE_builderEndpoint'] || '';
|
|
||||||
export const summaryInputs = process.env['STATE_summaryInputs'] ? JSON.parse(process.env['STATE_summaryInputs']) : undefined;
|
|
||||||
|
|
||||||
export const buildRef = process.env['STATE_buildRef'] || '';
|
|
||||||
export const isSummarySupported = !!process.env['STATE_isSummarySupported'];
|
|
||||||
|
|
||||||
export function setTmpDir(tmpDir: string) {
|
export function setTmpDir(tmpDir: string) {
|
||||||
core.saveState('tmpDir', tmpDir);
|
core.saveState('tmpDir', tmpDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setBuilderDriver(builderDriver: string) {
|
if (!IsPost) {
|
||||||
core.saveState('builderDriver', builderDriver);
|
core.saveState('isPost', 'true');
|
||||||
}
|
|
||||||
|
|
||||||
export function setBuilderEndpoint(builderEndpoint: string) {
|
|
||||||
core.saveState('builderEndpoint', builderEndpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setBuildRef(buildRef: string) {
|
|
||||||
core.saveState('buildRef', buildRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setSummarySupported() {
|
|
||||||
core.saveState('isSummarySupported', 'true');
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setSummaryInputs(inputs: Inputs) {
|
|
||||||
const res = {};
|
|
||||||
for (const key of Object.keys(inputs)) {
|
|
||||||
if (key === 'github-token') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const value: string | string[] | boolean = inputs[key];
|
|
||||||
if (typeof value === 'boolean' && !value) {
|
|
||||||
continue;
|
|
||||||
} else if (Array.isArray(value)) {
|
|
||||||
if (value.length === 0) {
|
|
||||||
continue;
|
|
||||||
} else if (key === 'secrets' && value.length > 0) {
|
|
||||||
const secretKeys: string[] = [];
|
|
||||||
for (const secret of value) {
|
|
||||||
try {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const [skey, _] = Build.parseSecretKvp(secret, true);
|
|
||||||
secretKeys.push(skey);
|
|
||||||
} catch (err) {
|
|
||||||
// ignore invalid secret
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (secretKeys.length > 0) {
|
|
||||||
res[key] = secretKeys;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else if (!value) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
res[key] = value;
|
|
||||||
}
|
|
||||||
core.saveState('summaryInputs', JSON.stringify(res));
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
FROM alpine
|
FROM alpine
|
||||||
|
|
||||||
RUN echo "Hello world!"
|
RUN echo "Hello world!"
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
FROM busybox
|
FROM busybox
|
||||||
RUN cat /etc/hosts
|
RUN cat /etc/hosts
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
# syntax=docker/dockerfile-upstream:master
|
||||||
|
FROM alpine
|
||||||
|
RUN cat /etc/*release
|
@ -1,3 +1,2 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
FROM alpine
|
FROM alpine
|
||||||
RUN cat /proc/self/cgroup
|
RUN cat /proc/self/cgroup
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
|
|
||||||
FROM golang:alpine AS base
|
|
||||||
ENV CGO_ENABLED=0
|
|
||||||
RUN apk add --no-cache file git
|
|
||||||
WORKDIR /src
|
|
||||||
|
|
||||||
FROM base AS build
|
|
||||||
RUN --mount=type=bind,target=/src \
|
|
||||||
--mount=type=cache,target=/root/.cache/go-build \
|
|
||||||
go build -ldflags "-s -w" -o /usr/bin/app .
|
|
||||||
|
|
||||||
FROM scratch AS binary
|
|
||||||
COPY --from=build /usr/bin/app /bin/app
|
|
||||||
|
|
||||||
FROM alpine AS image
|
|
||||||
COPY --from=build /usr/bin/app /bin/app
|
|
||||||
EXPOSE 8080
|
|
||||||
ENTRYPOINT ["/bin/app"]
|
|
@ -1,3 +0,0 @@
|
|||||||
module github.com/docker/build-push-action/test/go
|
|
||||||
|
|
||||||
go 1.18
|
|
@ -1,14 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
fmt.Fprintf(w, "Hello, Go!")
|
|
||||||
})
|
|
||||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
frOM busybox as base
|
|
||||||
cOpy lint.Dockerfile .
|
|
||||||
|
|
||||||
from scratch
|
|
||||||
MAINTAINER moby@example.com
|
|
||||||
COPy --from=base \
|
|
||||||
/lint.Dockerfile \
|
|
||||||
/
|
|
||||||
|
|
||||||
CMD [ "echo", "Hello, Norway!" ]
|
|
||||||
CMD [ "echo", "Hello, Sweden!" ]
|
|
||||||
ENTRYPOINT my-program start
|
|
@ -1,4 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
|
|
||||||
FROM debian
|
|
||||||
RUN echo "Hello debian!"
|
|
@ -1,4 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
|
|
||||||
FROM alpine
|
|
||||||
RUN cat /etc/*release
|
|
@ -1,9 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
FROM alpine
|
|
||||||
RUN apk add --no-cache curl net-tools
|
|
||||||
ARG HTTP_PROXY
|
|
||||||
ARG HTTPS_PROXY
|
|
||||||
RUN printenv HTTP_PROXY
|
|
||||||
RUN printenv HTTPS_PROXY
|
|
||||||
RUN netstat -aptn
|
|
||||||
RUN curl --retry 5 --retry-all-errors --retry-delay 0 --connect-timeout 5 --proxy $HTTP_PROXY -v --insecure --head https://www.google.com
|
|
@ -1,4 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
FROM busybox
|
|
||||||
RUN --mount=type=secret,id=MYSECRET \
|
|
||||||
echo "MYSECRET=$(cat /run/secrets/MYSECRET)"
|
|
@ -1,3 +1,2 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
FROM busybox
|
FROM busybox
|
||||||
RUN mount | grep /dev/shm
|
RUN mount | grep /dev/shm
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
# syntax=docker/dockerfile:1
|
|
||||||
FROM busybox
|
FROM busybox
|
||||||
RUN ulimit -a
|
RUN ulimit -a
|
||||||
|
@ -1,22 +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": [
|
||||||
"./__mocks__/**/*",
|
|
||||||
"./__tests__/**/*",
|
|
||||||
"./lib/**/*",
|
|
||||||
"node_modules",
|
"node_modules",
|
||||||
|
"**/*.test.ts",
|
||||||
"jest.config.ts"
|
"jest.config.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue