Compare commits
No commits in common. "master" and "releases/v3" have entirely different histories.
master
...
releases/v
|
@ -1,12 +1,2 @@
|
|||
/coverage
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
/node_modules
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
/dist/**
|
||||
/coverage/**
|
||||
/node_modules/**
|
|
@ -1,19 +1,18 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jest": true
|
||||
"es2021": true,
|
||||
"jest/globals": true
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:jest/recommended",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2023,
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": [
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
/.yarn/releases/** binary
|
||||
/.yarn/plugins/** binary
|
||||
/dist/** linguist-generated=true
|
||||
/lib/** linguist-generated=true
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
* @crazy-max
|
|
@ -1,3 +0,0 @@
|
|||
# Code of conduct
|
||||
|
||||
- [Moby community guidelines](https://github.com/moby/moby/blob/master/CONTRIBUTING.md#moby-community-guidelines)
|
|
@ -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/badge/resolution/docker/build-push-action.svg)](https://isitmaintained.com/project/docker/build-push-action)
|
||||
|
||||
First, [be a good guy](https://github.com/kossnocorp/etiquette/blob/master/README.md).
|
||||
|
||||
## Reporting an issue
|
||||
|
||||
Please do a search in [open issues](https://github.com/docker/build-push-action/issues?utf8=%E2%9C%93&q=) to see if the issue or feature request has already been filed.
|
||||
|
||||
If you find your issue already exists, make relevant comments and add your [reaction](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments). Use a reaction in place of a "+1" comment.
|
||||
|
||||
:+1: - upvote
|
||||
|
||||
:-1: - downvote
|
||||
|
||||
If you cannot find an existing issue that describes your bug or feature, submit an issue using the guidelines below.
|
||||
|
||||
## Writing good bug reports and feature requests
|
||||
|
||||
File a single issue per problem and feature request.
|
||||
|
||||
* Do not enumerate multiple bugs or feature requests in the same issue.
|
||||
* Do not add your issue as a comment to an existing issue unless it's for the identical input. Many issues look similar, but have different causes.
|
||||
|
||||
The more information you can provide, the more likely someone will be successful reproducing the issue and finding a fix.
|
||||
|
||||
You are now ready to [create a new issue](https://github.com/docker/build-push-action/issues/new/choose)!
|
||||
|
||||
## Closure policy
|
||||
|
||||
* Issues that don't have the information requested above (when applicable) will be closed immediately and the poster directed to the support guidelines.
|
||||
* Issues that go a week without a response from original poster are subject to closure at our discretion.
|
Binary file not shown.
Before Width: | Height: | Size: 81 KiB |
|
@ -11,7 +11,6 @@ updates:
|
|||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
versioning-strategy: "increase"
|
||||
allow:
|
||||
- dependency-type: "production"
|
||||
labels:
|
||||
|
|
|
@ -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,93 +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 "::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,130 +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.7.0
|
||||
NEXUS_VERSION: 3.47.1
|
||||
DISTRIBUTION_VERSION: 2.8.1
|
||||
|
||||
jobs:
|
||||
run:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
-
|
||||
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@v4
|
||||
-
|
||||
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 '{}' | 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
|
||||
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
|
@ -1,114 +1,123 @@
|
|||
name: e2e
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
buildx-version:
|
||||
description: 'Buildx version or Git context'
|
||||
default: 'latest'
|
||||
required: false
|
||||
buildkit-image:
|
||||
description: 'BuildKit image'
|
||||
default: 'moby/buildkit:buildx-stable-1'
|
||||
required: false
|
||||
schedule:
|
||||
- cron: '0 10 * * *'
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
tags:
|
||||
- 'v*'
|
||||
- v*
|
||||
|
||||
env:
|
||||
BUILDX_VERSION: latest
|
||||
BUILDKIT_IMAGE: moby/buildkit:buildx-stable-1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
uses: ./.github/workflows/.e2e-run.yml
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
-
|
||||
name: Distribution
|
||||
id: distribution
|
||||
type: local
|
||||
-
|
||||
name: Docker Hub
|
||||
registry: ''
|
||||
slug: ghactionstest/ghactionstest
|
||||
username_secret: DOCKERHUB_USERNAME
|
||||
password_secret: DOCKERHUB_TOKEN
|
||||
type: remote
|
||||
-
|
||||
name: GitHub
|
||||
registry: ghcr.io
|
||||
slug: ghcr.io/docker-ghactiontest/test
|
||||
username_secret: GHCR_USERNAME
|
||||
password_secret: GHCR_PAT
|
||||
type: remote
|
||||
-
|
||||
name: GitLab
|
||||
registry: registry.gitlab.com
|
||||
slug: registry.gitlab.com/test1716/test
|
||||
username_secret: GITLAB_USERNAME
|
||||
password_secret: GITLAB_TOKEN
|
||||
type: remote
|
||||
-
|
||||
name: AWS ECR
|
||||
registry: 175142243308.dkr.ecr.us-east-2.amazonaws.com
|
||||
slug: 175142243308.dkr.ecr.us-east-2.amazonaws.com/sandbox/test-docker-action
|
||||
username_secret: AWS_ACCESS_KEY_ID
|
||||
password_secret: AWS_SECRET_ACCESS_KEY
|
||||
type: remote
|
||||
-
|
||||
name: AWS ECR Public
|
||||
registry: public.ecr.aws
|
||||
slug: public.ecr.aws/q3b5f1u4/test-docker-action
|
||||
username_secret: AWS_ACCESS_KEY_ID
|
||||
password_secret: AWS_SECRET_ACCESS_KEY
|
||||
type: remote
|
||||
-
|
||||
name: Google Artifact Registry
|
||||
registry: us-east4-docker.pkg.dev
|
||||
slug: us-east4-docker.pkg.dev/sandbox-298914/docker-official-github-actions/test-docker-action
|
||||
username_secret: GAR_USERNAME
|
||||
password_secret: GAR_JSON_KEY
|
||||
type: remote
|
||||
-
|
||||
name: Google Container Registry
|
||||
registry: gcr.io
|
||||
slug: gcr.io/sandbox-298914/test-docker-action
|
||||
username_secret: GCR_USERNAME
|
||||
password_secret: GCR_JSON_KEY
|
||||
type: remote
|
||||
-
|
||||
name: Azure Container Registry
|
||||
registry: officialgithubactions.azurecr.io
|
||||
slug: officialgithubactions.azurecr.io/test-docker-action
|
||||
username_secret: AZURE_CLIENT_ID
|
||||
password_secret: AZURE_CLIENT_SECRET
|
||||
type: remote
|
||||
steps:
|
||||
-
|
||||
name: Quay
|
||||
registry: quay.io
|
||||
slug: quay.io/docker_build_team/ghactiontest
|
||||
username_secret: QUAY_USERNAME
|
||||
password_secret: QUAY_TOKEN
|
||||
type: remote
|
||||
name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Artifactory
|
||||
registry: infradock.jfrog.io
|
||||
slug: infradock.jfrog.io/test-ghaction/build-push-action
|
||||
username_secret: ARTIFACTORY_USERNAME
|
||||
password_secret: ARTIFACTORY_TOKEN
|
||||
type: remote
|
||||
-
|
||||
name: Harbor
|
||||
id: harbor
|
||||
type: local
|
||||
-
|
||||
name: Nexus
|
||||
id: nexus
|
||||
type: local
|
||||
name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ matrix.slug }}
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
version: ${{ inputs.buildx-version || env.BUILDX_VERSION }}
|
||||
driver-opts: |
|
||||
image=${{ inputs.buildkit-image || env.BUILDKIT_IMAGE }}
|
||||
-
|
||||
name: Login to Registry
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
id: ${{ matrix.id }}
|
||||
type: ${{ matrix.type }}
|
||||
name: ${{ matrix.name }}
|
||||
registry: ${{ matrix.registry }}
|
||||
slug: ${{ matrix.slug }}
|
||||
username_secret: ${{ matrix.username_secret }}
|
||||
password_secret: ${{ matrix.password_secret }}
|
||||
secrets: inherit
|
||||
username: ${{ secrets[matrix.username_secret] }}
|
||||
password: ${{ secrets[matrix.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=${{ matrix.slug }}:master
|
||||
cache-to: type=inline
|
||||
-
|
||||
name: Inspect image
|
||||
if: github.event_name != 'pull_request'
|
||||
run: |
|
||||
docker pull ${{ matrix.slug }}:${{ steps.meta.outputs.version }}
|
||||
docker image inspect ${{ matrix.slug }}:${{ steps.meta.outputs.version }}
|
||||
-
|
||||
name: Check manifest
|
||||
if: github.event_name != 'pull_request'
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ matrix.slug }}:${{ steps.meta.outputs.version }} --format '{{json .}}'
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
# 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 }} --format '{{json .}}'
|
|
@ -1,15 +1,12 @@
|
|||
name: test
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'releases/v*'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
|
@ -17,15 +14,19 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Validate
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: validate
|
||||
-
|
||||
name: Test
|
||||
uses: docker/bake-action@v5
|
||||
uses: docker/bake-action@v2
|
||||
with:
|
||||
targets: test
|
||||
-
|
||||
name: Upload coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: ./coverage/clover.xml
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
|
|
@ -1,45 +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.targets.outputs.matrix }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Targets matrix
|
||||
id: targets
|
||||
run: |
|
||||
echo "matrix=$(docker buildx bake validate --print | jq -cr '.group.validate.targets')" >> $GITHUB_OUTPUT
|
||||
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- prepare
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
target: ${{ fromJson(needs.prepare.outputs.targets) }}
|
||||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
-
|
||||
name: Validate
|
||||
uses: docker/bake-action@v5
|
||||
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,5 +1,11 @@
|
|||
# https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
|
||||
node_modules
|
||||
lib
|
||||
|
||||
# Jetbrains
|
||||
/.idea
|
||||
/*.iml
|
||||
|
||||
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
@ -7,7 +13,6 @@ npm-debug.log*
|
|||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
@ -18,14 +23,34 @@ pids
|
|||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
|
@ -35,19 +60,36 @@ jspm_packages/
|
|||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
.env.test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# yarn v2
|
||||
.yarn/
|
File diff suppressed because one or more lines are too long
13
.yarnrc.yml
13
.yarnrc.yml
|
@ -1,13 +0,0 @@
|
|||
logFilters:
|
||||
- code: YN0013
|
||||
level: discard
|
||||
- code: YN0019
|
||||
level: discard
|
||||
- code: YN0076
|
||||
level: discard
|
||||
|
||||
nodeLinker: node-modules
|
||||
|
||||
plugins:
|
||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
||||
spec: "@yarnpkg/plugin-interactive-tools"
|
100
README.md
100
README.md
|
@ -19,11 +19,9 @@ ___
|
|||
* [Git context](#git-context)
|
||||
* [Path context](#path-context)
|
||||
* [Examples](#examples)
|
||||
* [Summaries](#summaries)
|
||||
* [Customizing](#customizing)
|
||||
* [inputs](#inputs)
|
||||
* [outputs](#outputs)
|
||||
* [environment variables](#environment-variables)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
* [Contributing](#contributing)
|
||||
|
||||
|
@ -55,6 +53,8 @@ name: ci
|
|||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
|
@ -62,19 +62,19 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
push: true
|
||||
tags: user/app:latest
|
||||
|
@ -92,24 +92,37 @@ expression `{{defaultContext}}`. Here we can use it to provide a subdirectory
|
|||
to the default Git context:
|
||||
|
||||
```yaml
|
||||
-
|
||||
# Setting up Docker Buildx with docker-container driver is required
|
||||
# at the moment to be able to use a subdirectory with Git context
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: "{{defaultContext}}:mysubdir"
|
||||
push: true
|
||||
tags: user/app:latest
|
||||
```
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> Subdirectory for Git context is available from [BuildKit v0.9.0](https://github.com/moby/buildkit/releases/tag/v0.9.0).
|
||||
> If you're using the `docker` builder (default if `setup-buildx-action` not used),
|
||||
> then BuildKit in Docker Engine will be used. As Docker Engine < v22.x.x embeds
|
||||
> Buildkit 0.8.2 at the moment, it does not support this feature. It's therefore
|
||||
> required to use the `setup-buildx-action` at the moment.
|
||||
|
||||
Building from the current repository automatically uses the [GitHub Token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication),
|
||||
so it does not need to be passed. If you want to authenticate against another
|
||||
private repository, you have to use a [secret](https://docs.docker.com/build/ci/github-actions/secrets)
|
||||
private repository, you have to use a [secret](https://docs.docker.com/build/ci/github-actions/examples/#secrets)
|
||||
named `GIT_AUTH_TOKEN` to be able to authenticate against it with Buildx:
|
||||
|
||||
```yaml
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
push: true
|
||||
tags: user/app:latest
|
||||
|
@ -124,6 +137,8 @@ name: ci
|
|||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
|
@ -131,22 +146,22 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v2
|
||||
-
|
||||
name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
-
|
||||
name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
@ -155,47 +170,13 @@ jobs:
|
|||
|
||||
## Examples
|
||||
|
||||
* [Multi-platform image](https://docs.docker.com/build/ci/github-actions/multi-platform/)
|
||||
* [Secrets](https://docs.docker.com/build/ci/github-actions/secrets/)
|
||||
* [Push to multi-registries](https://docs.docker.com/build/ci/github-actions/push-multi-registries/)
|
||||
* [Manage tags and labels](https://docs.docker.com/build/ci/github-actions/manage-tags-labels/)
|
||||
* [Cache management](https://docs.docker.com/build/ci/github-actions/cache/)
|
||||
* [Export to Docker](https://docs.docker.com/build/ci/github-actions/export-docker/)
|
||||
* [Test before push](https://docs.docker.com/build/ci/github-actions/test-before-push/)
|
||||
* [Local registry](https://docs.docker.com/build/ci/github-actions/local-registry/)
|
||||
* [Share built image between jobs](https://docs.docker.com/build/ci/github-actions/share-image-jobs/)
|
||||
* [Named contexts](https://docs.docker.com/build/ci/github-actions/named-contexts/)
|
||||
* [Copy image between registries](https://docs.docker.com/build/ci/github-actions/copy-image-registries/)
|
||||
* [Update Docker Hub repo description](https://docs.docker.com/build/ci/github-actions/update-dockerhub-desc/)
|
||||
* [SBOM and provenance attestations](https://docs.docker.com/build/ci/github-actions/attestations/)
|
||||
* [Annotations](https://docs.docker.com/build/ci/github-actions/annotations/)
|
||||
* [Reproducible builds](https://docs.docker.com/build/ci/github-actions/reproducible-builds/)
|
||||
|
||||
## Summaries
|
||||
|
||||
This action generates a [job summary](https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/)
|
||||
that provides a detailed overview of the build execution. The summary shows an
|
||||
overview of all the steps executed during the build, including the build inputs
|
||||
and eventual errors.
|
||||
|
||||
![build-push-action job summary](./.github/build-push-summary.png)
|
||||
|
||||
The summary also includes a link for downloading the build record with
|
||||
additional details about the build, including build stats, logs, outputs, and
|
||||
more. The build record can be imported to Docker Desktop for inspecting the
|
||||
build in greater detail.
|
||||
|
||||
Summaries are enabled by default, but can be disabled with the
|
||||
`DOCKER_BUILD_SUMMARY` [environment variable](#environment-variables).
|
||||
|
||||
For more information about summaries, refer to the
|
||||
[documentation](https://docs.docker.com/go/build-summary/).
|
||||
See https://docs.docker.com/build/ci/github-actions/examples/.
|
||||
|
||||
## Customizing
|
||||
|
||||
### inputs
|
||||
|
||||
The following inputs can be used as `step.with` keys:
|
||||
Following inputs can be used as `step.with` keys
|
||||
|
||||
> `List` type is a newline-delimited string
|
||||
> ```yaml
|
||||
|
@ -213,7 +194,6 @@ The following inputs can be used as `step.with` keys:
|
|||
|--------------------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `add-hosts` | List/CSV | List of [customs host-to-IP mapping](https://docs.docker.com/engine/reference/commandline/build/#add-entries-to-container-hosts-file---add-host) (e.g., `docker:10.180.0.1`) |
|
||||
| `allow` | List/CSV | List of [extra privileged entitlement](https://docs.docker.com/engine/reference/commandline/buildx_build/#allow) (e.g., `network.host,security.insecure`) |
|
||||
| `annotations` | List | List of annotation to set to the image |
|
||||
| `attests` | List | List of [attestation](https://docs.docker.com/build/attestations/) parameters (e.g., `type=sbom,generator=image`) |
|
||||
| `builder` | String | Builder instance (see [setup-buildx](https://github.com/docker/setup-buildx-action) action) |
|
||||
| `build-args` | List | List of [build-time variables](https://docs.docker.com/engine/reference/commandline/buildx_build/#build-arg) |
|
||||
|
@ -228,14 +208,13 @@ The following inputs can be used as `step.with` keys:
|
|||
| `network` | String | Set the networking mode for the `RUN` instructions during build |
|
||||
| `no-cache` | Bool | Do not use cache when building the image (default `false`) |
|
||||
| `no-cache-filters` | List/CSV | Do not cache specified stages |
|
||||
| `outputs` | List | List of [output destinations](https://docs.docker.com/engine/reference/commandline/buildx_build/#output) (format: `type=local,dest=path`) |
|
||||
| `outputs`¹ | List | List of [output destinations](https://docs.docker.com/engine/reference/commandline/buildx_build/#output) (format: `type=local,dest=path`) |
|
||||
| `platforms` | List/CSV | List of [target platforms](https://docs.docker.com/engine/reference/commandline/buildx_build/#platform) for build |
|
||||
| `provenance` | Bool/String | Generate [provenance](https://docs.docker.com/build/attestations/slsa-provenance/) attestation for the build (shorthand for `--attest=type=provenance`) |
|
||||
| `pull` | Bool | Always attempt to pull all referenced images (default `false`) |
|
||||
| `push` | Bool | [Push](https://docs.docker.com/engine/reference/commandline/buildx_build/#push) is a shorthand for `--output=type=registry` (default `false`) |
|
||||
| `sbom` | Bool/String | Generate [SBOM](https://docs.docker.com/build/attestations/sbom/) attestation for the build (shorthand for `--attest=type=sbom`) |
|
||||
| `secrets` | List | List of [secrets](https://docs.docker.com/engine/reference/commandline/buildx_build/#secret) to expose to the build (e.g., `key=string`, `GIT_AUTH_TOKEN=mytoken`) |
|
||||
| `secret-envs` | List/CSV | List of [secret env vars](https://docs.docker.com/engine/reference/commandline/buildx_build/#secret) to expose to the build (e.g., `key=envname`, `MY_SECRET=MY_ENV_VAR`) |
|
||||
| `secret-files` | List | List of [secret files](https://docs.docker.com/engine/reference/commandline/buildx_build/#secret) to expose to the build (e.g., `key=filename`, `MY_SECRET=./secret.txt`) |
|
||||
| `shm-size` | String | Size of [`/dev/shm`](https://docs.docker.com/engine/reference/commandline/buildx_build/#shm-size) (e.g., `2g`) |
|
||||
| `ssh` | List | List of [SSH agent socket or keys](https://docs.docker.com/engine/reference/commandline/buildx_build/#ssh) to expose to the build |
|
||||
|
@ -244,9 +223,13 @@ The following inputs can be used as `step.with` keys:
|
|||
| `ulimit` | List | [Ulimit](https://docs.docker.com/engine/reference/commandline/buildx_build/#ulimit) options (e.g., `nofile=1024:1024`) |
|
||||
| `github-token` | String | GitHub Token used to authenticate against a repository for [Git context](#git-context) (default `${{ github.token }}`) |
|
||||
|
||||
> **Note**
|
||||
>
|
||||
> * ¹ multiple `outputs` are [not yet supported](https://github.com/moby/buildkit/issues/1555)
|
||||
|
||||
### outputs
|
||||
|
||||
The following outputs are available:
|
||||
Following outputs are available
|
||||
|
||||
| Name | Type | Description |
|
||||
|------------|---------|-----------------------|
|
||||
|
@ -254,15 +237,6 @@ The following outputs are available:
|
|||
| `digest` | String | Image digest |
|
||||
| `metadata` | JSON | Build result metadata |
|
||||
|
||||
### environment variables
|
||||
|
||||
| Name | Type | Default | Description |
|
||||
|--------------------------------------|--------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `DOCKER_BUILD_CHECKS_ANNOTATIONS` | Bool | `true` | If `false`, GitHub annotations are not generated for [build checks](https://docs.docker.com/build/checks/) |
|
||||
| `DOCKER_BUILD_SUMMARY` | Bool | `true` | If `false`, [build summary](https://docs.docker.com/build/ci/github-actions/build-summary/) generation is disabled |
|
||||
| `DOCKER_BUILD_RECORD_UPLOAD` | Bool | `true` | If `false`, build record upload as [GitHub artifact](https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts) is disabled |
|
||||
| `DOCKER_BUILD_RECORD_RETENTION_DAYS` | Number | | Duration after which build record artifact will expire in days. Defaults to repository/org [retention settings](https://docs.github.com/en/actions/learn-github-actions/usage-limits-billing-and-administration#artifact-and-log-retention-policy) if unset or `0` |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
See [TROUBLESHOOTING.md](TROUBLESHOOTING.md)
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
* [BuildKit container logs](#buildkit-container-logs)
|
||||
* [With containerd](#with-containerd)
|
||||
* [`repository name must be lowercase`](#repository-name-must-be-lowercase)
|
||||
* [Image not loaded](#image-not-loaded)
|
||||
|
||||
## Cannot push to a registry
|
||||
|
||||
|
@ -45,13 +44,13 @@ jobs:
|
|||
steps:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v3
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v2
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
buildkitd-flags: --debug
|
||||
-
|
||||
|
@ -59,7 +58,7 @@ jobs:
|
|||
uses: crazy-max/ghaction-setup-containerd@v2
|
||||
-
|
||||
name: Build Docker image
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
@ -112,7 +111,7 @@ to generate sanitized tags:
|
|||
tags: latest
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
|
@ -130,35 +129,9 @@ Or a dedicated step to sanitize the slug:
|
|||
script: return 'ghcr.io/${{ github.repository }}'.toLowerCase()
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.repo_slug.outputs.result }}:latest
|
||||
```
|
||||
|
||||
## Image not loaded
|
||||
|
||||
Sometimes when your workflows are heavy consumers of disk storage, it can happen that build-push-action declares that the built image is loaded, but then not found in the following workflow steps.
|
||||
|
||||
- You can use the following solution as workaround, to free space on disk before building docker image using the following workflow step
|
||||
|
||||
```yaml
|
||||
# Free disk space
|
||||
- name: Free Disk space
|
||||
shell: bash
|
||||
run: |
|
||||
sudo rm -rf /usr/local/lib/android # will release about 10 GB if you don't need Android
|
||||
sudo rm -rf /usr/share/dotnet # will release about 20GB if you don't need .NET
|
||||
```
|
||||
|
||||
- Another workaround can be to call `docker/setup-buildx-action` with docker driver
|
||||
|
||||
```yaml
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
driver: docker
|
||||
```
|
||||
|
||||
More details in the [related issue](https://github.com/docker/build-push-action/issues/321)
|
||||
|
|
|
@ -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,146 @@
|
|||
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}`);
|
||||
expect(fs.readFileSync(tmpNameSync, 'utf-8')).toEqual(exValue);
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line jest/no-conditional-expect
|
||||
expect(true).toBe(invalid);
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,71 +1,134 @@
|
|||
import {beforeEach, describe, expect, jest, test} from '@jest/globals';
|
||||
import {beforeEach, describe, expect, it, jest, test} from '@jest/globals';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import {Builder} from '@docker/actions-toolkit/lib/buildx/builder';
|
||||
import {Buildx} from '@docker/actions-toolkit/lib/buildx/buildx';
|
||||
import {Build} from '@docker/actions-toolkit/lib/buildx/build';
|
||||
import {Context} from '@docker/actions-toolkit/lib/context';
|
||||
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
|
||||
import {GitHub} from '@docker/actions-toolkit/lib/github';
|
||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
|
||||
|
||||
import {BuilderInfo} from '@docker/actions-toolkit/lib/types/buildx/builder';
|
||||
import {GitHubRepo} from '@docker/actions-toolkit/lib/types/github';
|
||||
|
||||
import * as buildx from '../src/buildx';
|
||||
import * as context from '../src/context';
|
||||
|
||||
const tmpDir = path.join('/tmp', '.docker-build-push-jest');
|
||||
const tmpName = path.join(tmpDir, '.tmpname-jest');
|
||||
const pgp = `-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
import repoFixture from './fixtures/github-repo.json';
|
||||
jest.spyOn(GitHub.prototype, 'repoData').mockImplementation((): Promise<GitHubRepo> => {
|
||||
return <Promise<GitHubRepo>>(repoFixture as unknown);
|
||||
lQdGBF6tzaABEACjFbX7PFEG6vDPN2MPyxYW7/3o/sonORj4HXUFjFxxJxktJ3x3
|
||||
N1ayHPJ1lqIeoiY7jVbq0ZdEVGkd3YsKG9ZMdZkzGzY6PQPC/+M8OnzOiOPwUdWc
|
||||
+Tdhh115LvVz0MMKYiab6Sn9cgxj9On3LCQKpjvMDpPo9Ttf6v2GQIw8h2ACvdzQ
|
||||
71LtIELS/I+dLbfZiwpUu2fhQT13EJkEnYMOYwM5jNUd66P9itUc7MrOWjkicrKP
|
||||
oF1dQaCM+tuKuxvD8WLdiwU5x60NoGkJHHUehKQXl2dVzjpqEqHKEBJt9tfJ9lpE
|
||||
YIisgwB8o3pes0fgCehjW2zI95/o9+ayJ6nl4g5+mSvWRXEu66h71nwM0Yuvquk8
|
||||
3me7qhYfDrDdCwcxS5BS1hwakTgUQLD99FZjbx1j8sq96I65O0GRdyU2PR8KIjwu
|
||||
JrkTH4ZlKxK3FQghUhFoA5GkiDb+eClmRMSni5qg+81T4XChmUkEprA3eWCHL+Ma
|
||||
xRNNxLS+r6hH9HG5JBxpV3iaTI9HHpnQKhEeaLXqsUTDZliN9hP7Ywo8bpUB8j2d
|
||||
oWYwDV4dPyMKr6Fb8RDCh2q5gJGbVp8w/NmmBTeL+IP2fFggJkRfyumv3Ul7x66L
|
||||
tBFQ4rYo4JUUrGweSTneG6REIgxH66hIrNl6Vo/D1ZyknTe1dMOu/BTkkQARAQAB
|
||||
/gcDAqra8KO+h3bfyu90vxTL1ro4x/x9il7VBcWlIR4cBP7Imgxv+T4hwPIu8P1x
|
||||
lOlxLNWegFOV0idoTy1o3VLLBev/F+IlspX4A+2XEIddR6nZnKFi0Lv2L4TKgE9E
|
||||
VJJTszmviDIRLMLN9dWzDfA8hj5tR5Inot92CHRF414AS22JHvlhbFSLQnjqsN+C
|
||||
n1cQpNOJhkxsSfZsxjnFa/70y/u8v0o8mzyLZmk9HpzRHGzoz8IfpLp8OTqBR9u6
|
||||
zzoKLy16zZO55OKbj7h8uVZvDUq9l8iDICpqWMdZqBJIl56MBexYKgYxh3YO/8v2
|
||||
oXli+8Xuaq5QLiCN3yT7IbKoYzplnFfaJwFiMh7R1iPLXaYAZ0qdRijlbtseTK1m
|
||||
oHNkwUbxVzjkh4LfE8UpmMwZn5ZjWni3230SoiXuKy0OHkGvwGvWWAL1mEuoYuUI
|
||||
mFMcH5MnixP8oQYZKDj2IR/yEeOpdU6B/tr3Tk1NidLf7pUMqG7Ff1NU6dAUeBpa
|
||||
9xahITMjHvrhgMISY4IYZep5cEnVw8lQTpUJtW/ePMzrFhu3sA7oNdj9joW/VMfz
|
||||
H7MHwwavtICsYqoqV3lnjX4EC9dW6o8PTUg2u956dmtK7KAyUK/+w2aLNGT28ChN
|
||||
jhRYHvHzB9Kw5asqI/lTM49eqslBqYQMTTjdBphkYuSZQzNMf291j/ZmoLhD1A1a
|
||||
S8tUnNygKV4D1cJYgSXfzhFoU8ib/0SPo+KqQ+CzGS+wxXg6WNBA6wepTjpnVVx3
|
||||
4JADP8IJcDC3P0iwAreWjSy15F1cvemFFB0SLNUkyZGzsxtKzbM1+8khl68+eazC
|
||||
LzRj0rxfIF5znWjX1QFhKxCk6eF0IWDY0+b3DBkmChME9YDXJ3TthcqA7JgcX4JI
|
||||
M4/wdqhgerJYOmj+i2Q0M+Bu02icOJYMwTMMsDVl7XGHkaCuRgZ54eZAUH7JFwUm
|
||||
1Ct3tcaqiTMmz0ngHVqBTauzgqKDvzwdVqdfg05H364nJMay/3omR6GayIb5CwSo
|
||||
xdNVwG3myPPradT9MP09mDr4ys2zcnQmCkvTVBF6cMZ1Eh6PQQ8CyQWv0zkaBnqj
|
||||
JrM1hRpgW4ZlRosSIjCaaJjolN5QDcXBM9TbW9ww+ZYstazN2bV1ZQ7BEjlHQPa1
|
||||
BhzMsvqkbETHsIpDNF52gZKn3Q9eIX05BeadzpHUb5/XOheIHVIdhSaTlgl/qQW5
|
||||
hQgPGSzSV6KhXEY7aevTdvOgq++WiELkjfz2f2lQFesTjFoQWEvxVDUmLxHtEhaN
|
||||
DOuh4H3mX5Opn3pLQmqWVhJTbFdx+g5qQd0NCW4mDaTFWTRLFLZQsSJxDSeg9xrY
|
||||
gmaii8NhMZRwquADW+6iU6KfraBhngi7HRz4TfqPr9ma/KUY464cqim1fnwXejyx
|
||||
jsb5YHR9R66i+F6P/ysF5w+QuVdDt1fnf9GLay0r6qxpA8ft2vGPcDs4806Huj+7
|
||||
Aq5VeJaNkCuh3GR3xVnCFAz/7AtkO6xKuZm8B3q904UuMdSmkhWbaobIuF/B2B6S
|
||||
eawIXQHEOplK3ic26d8Ckf4gbjeORfELcMAEi5nGXpTThCdmxQApCLxAYYnTfQT1
|
||||
xhlDwT9xPEabo98mIwJJsAU5VsTDYW+qfo4qIx8gYoSKc9Xu3yVh3n+9k43Gcm5V
|
||||
9lvK1slijf+TzODZt/jsmkF8mPjXyP5KOI+xQp/m4PxW3pp57YrYj/Rnwga+8DKX
|
||||
jMsW7mLAAZ/e+PY6z/s3x1Krfk+Bb5Ph4mI0zjw5weQdtyEToRgveda0GEpvZSBU
|
||||
ZXN0ZXIgPGpvZUBmb28uYmFyPokCNgQQAQgAIAUCXq3NoAYLCQcIAwIEFQgKAgQW
|
||||
AgEAAhkBAhsDAh4BAAoJEH2FHrctc72gxtQP/AulaClIcn/kDt43mhYnyLglPfbo
|
||||
AqPlU26chXolBg0Wo0frFY3aIs5SrcWEf8aR4XLwCFGyi3vya0CUxjghN5tZBYqo
|
||||
vswbT00zP3ohxxlJFCRRR9bc7OZXCgTddtfVf6EKrUAzIkbWyAhaJnwJy/1UGpSw
|
||||
SEO/KpastrVKf3sv1wqOeFQ4DFyjaNda+xv3dVWS8db7KogqJiPFZXrQK3FKVIxS
|
||||
fxRSmKaYN7//d+xwVAEY++RrnL/o8B2kV6N68cCpQWJELyYnJzis9LBcWd/3wiYh
|
||||
efTyY+ePKUjcB+kEZnyJfLc7C2hll2e7UJ0fxv+k8vHReRhrNWmGRXsjNRxiw3U0
|
||||
hfvxD/C8nyqAbeTHp4XDX78Tc3XCysAqIYboIL+RyewDMjjLj5vzUYAdUdtyNaD7
|
||||
C6M2R6pN1GAt52CJmC/Z6F7W7GFGoYOdEkVdMQDsjCwScyEUNlGj9Zagw5M2EgSe
|
||||
6gaHgMgTzsMzCc4W6WV5RcS55cfDNOXtxPsMJTt4FmXrjl11prBzpMfpU5a9zxDZ
|
||||
oi54ZZ8VPE6jsT4Lzw3sni3c83wm28ArM20AzZ1vh7fk3Sfd0u4Yaz7s9JlEm5+D
|
||||
34tEyli28+QjCQc18EfQUiJqiYEJRxJXJ3esvMHfYi45pV/Eh5DgRW1305fUJV/6
|
||||
+rGpg0NejsHoZdZPnQdGBF6tzaABEAC4mVXTkVk6Kdfa4r5zlzsoIrR27laUlMkb
|
||||
OBMt+aokqS+BEbmTnMg6xIAmcUT5uvGAc8S/WhrPoYfc15fTUyHIz8ZbDoAg0LO6
|
||||
0Io4VkAvNJNEnsSV9VdLBh/XYlc4K49JqKyWTL4/FJFAGbsmHY3b+QU90AS6FYRv
|
||||
KeBAoiyebrjx0vmzb8E8h3xthVLN+AfMlR1ickY62zvnpkbncSMY/skur1D2KfbF
|
||||
3sFprty2pEtjFcyB5+18l2IyyHGOlEUw1PZdOAV4/Myh1EZRgYBPs80lYTJALCVF
|
||||
IdOakH33WJCImtNZB0AbDTABG+JtMjQGscOa0qzf1Y/7tlhgCrynBBdaIJTx95TD
|
||||
21BUHcHOu5yTIS6Ulysxfkv611+BiOKHgdq7DVGP78VuzA7bCjlP1+vHqIt3cnIa
|
||||
t2tEyuZ/XF4uc3/i4g0uP9r7AmtET7Z6SKECWjpVv+UEgLx5Cv+ql+LSKYQMvU9a
|
||||
i3B1F9fatn3FSLVYrL4aRxu4TSw9POb0/lgDNmN3lGQOsjGCZPibkHjgPEVxKuiq
|
||||
9Oi38/VTQ0ZKAmHwBTq1WTZIrPrCW0/YMQ6yIJZulwQ9Yx1cgzYzEfg04fPXlXMi
|
||||
vkvNpKbYIICzqj0/DVztz9wgpW6mnd0A2VX2dqbMM0fJUCHA6pj8AvXY4R+9Q4rj
|
||||
eWRK9ycInQARAQAB/gcDApjt7biRO0PEyrrAiUwDMsJL4/CVMu11qUWEPjKe2Grh
|
||||
ZTW3N+m3neKPRULu+LUtndUcEdVWUCoDzAJ7MwihZtV5vKST/5Scd2inonOaJqoA
|
||||
nS3wnEMN/Sc93HAZiZnFx3NKjQVNCwbuEs45mXkkcjLm2iadrTL8fL4acsu5IsvD
|
||||
LbDwVOPeNnHKl6Hr20e39fK0FuJEyH49JM6U3B1/8385sJB8+E24+hvSF81aMddh
|
||||
Ne4Bc3ZYiYaKxe1quPNKC0CQhAZiT7LsMfkInXr0hY1I+kISNXEJ1dPYOEWiv0Ze
|
||||
jD5Pupn34okKNEeBCx+dK8BmUCi6Jgs7McUA7hN0D/YUS++5fuR55UQq2j8Ui0tS
|
||||
P8GDr86upH3PgEL0STh9fYfJ7TesxurwonWjlmmT62Myl4Pr+RmpS6PXOnhtcADm
|
||||
eGLpzhTveFj4JBLMpyYHgBTqcs12zfprATOpsI/89kmQoGCZpG6+AbfSHqNNPdy2
|
||||
eqUCBhOZlIIda1z/cexmU3f/gBqyflFf8fkvmlO4AvI8aMH3OpgHdWnzh+AB51xj
|
||||
kmdD/oWel9v7Dz4HoZUfwFaLZ0fE3P9voD8e+sCwqQwVqRY4L/BOYPD5noVOKgOj
|
||||
ABNKu5uKrobj6rFUi6DTUCjFGcmoF1Sc06xFNaagUNggRbmlC/dz22RWdDUYv5ra
|
||||
N6TxIDkGC0cK6ujyK0nes3DN0aHjgwWuMXDYkN3UckiebI4Cv/eF9jvUKOSiIcy1
|
||||
RtxdazZS4dYg2LBMeJKVkPi5elsNyw2812nEY3du/nEkQYXfYgWOF27OR+g4Y9Yw
|
||||
1BiqJ1TTjbQnd/khOCrrbzDH1mw00+1XVsT6wjObuYqqxPPS87UrqmMf6OdoYfPm
|
||||
zEOnNLBnsJ5VQM3A3pcT40RfdBrZRO8LjGhzKTreyq3C+jz0RLa5HNE8GgOhGyck
|
||||
ME4h+RhXlE8KGM+tTo6PA1NJSrEt+8kZzxjP4rIEn0aVthCkNXK12inuXtnHm0ao
|
||||
iLUlQOsfPFEnzl0TUPd7+z7j/wB+XiKU/AyEUuB0mvdxdKtqXvajahOyhLjzHQhz
|
||||
ZnNlgANGtiqcSoJmkJ8yAvhrtQX51fQLftxbArRW1RYk/5l+Gy3azR+gUC17M6JN
|
||||
jrUYxn0zlAxDGFH7gACHUONwVekcuEffHzgu2lk7MyO1Y+lPnwabqjG0eWWHuU00
|
||||
hskJlXyhj7DeR12bwjYkyyjG62GvOH02g3OMvUgNGH+K321Dz539csCh/xwtg7Wt
|
||||
U3YAphU7htQ1dPDfk1IRs7DQo2L+ZTE57vmL5m0l6fTataEWBPUXkygfQFUJOM6Q
|
||||
yY76UEZww1OSDujNeY171NSTzXCVkUeAdAMXgjaHXWLK2QUQUoXbYX/Kr7Vvt9Fu
|
||||
Jh6eGjjp7dSjQ9+DW8CAB8vxd93gsQQGWYjmGu8khkEmx6OdZhmSbDbe915LQTb9
|
||||
sPhk2s5/Szsvr5W2JJ2321JI6KXBJMZvPC5jEBWmRzOYkRd2vloft+CSMfXF+Zfd
|
||||
nYtc6R3dvb9vcjo+a9wFtfcoDsO0MaPSM+9GB25MamdatmGX6iLOy9Re1UABwUi/
|
||||
VhTWNkP5uzqx0sDwHEIa2rYOwxpIZDwwjM3oOASCW1DDBQ0BI9KNjfIeL3ubx2mS
|
||||
2x8hFU9qSK4umoDNbzOqGPSlkdbiPcNjF2ZcSN1qQZiYdwLL5dw6APNyBVjxTN1J
|
||||
gkCdJ/HwAY+r93Lbl5g8gz8d0vJEyfn//34sn9u+toSTw55GcG9Ks1kSKIeDNh0h
|
||||
MiPm3HmJAh8EGAEIAAkFAl6tzaACGwwACgkQfYUety1zvaBV9hAAgliX36pXJ59g
|
||||
3I9/4R68e/fGg0FMM6D+01yCeiKApOYRrJ0cYKn7ITDYmHhlGGpBAie90UsqX12h
|
||||
hdLP7LoQx7sjTyzQt6JmpA8krIwi2ON7FKBkdYb8IYx4mE/5vKnYT4/SFnwTmnZY
|
||||
+m+NzK2U/qmhq8JyO8gozdAKJUcgz49IVv2Ij0tQ4qaPbyPwQxIDyKnT758nJhB1
|
||||
jTqo+oWtER8q3okzIlqcArqn5rDaNJx+DRYL4E/IddyHQAiUWUka8usIUqeW5reu
|
||||
zoPUE2CCfOJSGArkqHQQqMx0WEzjQTwAPaHrQbera4SbiV/o4CLCV/u5p1Qnig+Q
|
||||
iUsakmlD299t//125LIQEa5qzd9hRC7u1uJS7VdW8eGIEcZ0/XT/sr+z23z0kpZH
|
||||
D3dXPX0BwM4IP9xu31CNg10x0rKwjbxy8VaskFEelpqpu+gpAnxqMd1evpeUHcOd
|
||||
r5RgPgkNFfba9Nbxf7uEX+HOmsOM+kdtSmdGIvsBZjVnW31nnoDMp49jG4OynjrH
|
||||
cRuoM9sxdr6UDqb22CZ3/e0YN4UaZM3YDWMVaP/QBVgvIFcdByqNWezpd9T4ZUII
|
||||
MZlaV1uRnHg6B/zTzhIdMM80AXz6Uv6kw4S+Lt7HlbrnMT7uKLuvzH7cle0hcIUa
|
||||
PejgXO0uIRolYQ3sz2tMGhx1MfBqH64=
|
||||
=WbwB
|
||||
-----END PGP PRIVATE KEY BLOCK-----`;
|
||||
|
||||
jest.spyOn(context, 'defaultContext').mockImplementation((): string => {
|
||||
return 'https://github.com/docker/build-push-action.git#refs/heads/test-jest';
|
||||
});
|
||||
|
||||
jest.spyOn(Context, 'tmpDir').mockImplementation((): string => {
|
||||
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, 'tmpName').mockImplementation((): string => {
|
||||
return tmpName;
|
||||
jest.spyOn(context, 'tmpNameSync').mockImplementation((): string => {
|
||||
return path.join('/tmp/.docker-build-push-jest', '.tmpname-jest').split(path.sep).join(path.posix.sep);
|
||||
});
|
||||
|
||||
jest.spyOn(Docker, 'isAvailable').mockImplementation(async (): Promise<boolean> => {
|
||||
return true;
|
||||
});
|
||||
|
||||
const metadataJson = path.join(tmpDir, 'metadata.json');
|
||||
jest.spyOn(Build.prototype, 'getMetadataFilePath').mockImplementation((): string => {
|
||||
return metadataJson;
|
||||
});
|
||||
|
||||
const imageIDFilePath = path.join(tmpDir, 'iidfile.txt');
|
||||
jest.spyOn(Build.prototype, 'getImageIDFilePath').mockImplementation((): string => {
|
||||
return imageIDFilePath;
|
||||
});
|
||||
|
||||
jest.spyOn(Builder.prototype, 'inspect').mockImplementation(async (): Promise<BuilderInfo> => {
|
||||
return {
|
||||
name: 'builder2',
|
||||
driver: 'docker-container',
|
||||
lastActivity: new Date('2023-01-16 09:45:23 +0000 UTC'),
|
||||
nodes: [
|
||||
{
|
||||
buildkit: 'v0.11.0',
|
||||
'buildkitd-flags': '--debug --allow-insecure-entitlement security.insecure --allow-insecure-entitlement network.host',
|
||||
'driver-opts': ['BUILDKIT_STEP_LOG_MAX_SIZE=10485760', 'BUILDKIT_STEP_LOG_MAX_SPEED=10485760', 'JAEGER_TRACE=localhost:6831', 'image=moby/buildkit:latest', 'network=host'],
|
||||
endpoint: 'unix:///var/run/docker.sock',
|
||||
name: 'builder20',
|
||||
platforms: 'linux/amd64,linux/amd64/v2,linux/amd64/v3,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6',
|
||||
status: 'running'
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
jest.spyOn(buildx, 'satisfiesBuildKitVersion').mockResolvedValueOnce(true);
|
||||
|
||||
describe('getArgs', () => {
|
||||
beforeEach(() => {
|
||||
|
@ -91,7 +154,7 @@ describe('getArgs', () => {
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -114,8 +177,8 @@ ccc"`],
|
|||
'--build-arg', 'MY_ARG=val1,val2,val3',
|
||||
'--build-arg', 'ARG=val',
|
||||
'--build-arg', `MULTILINE=aaaa\nbbbb\nccc`,
|
||||
'--iidfile', imageIDFilePath,
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/master'
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/test-jest'
|
||||
]
|
||||
],
|
||||
[
|
||||
|
@ -130,10 +193,10 @@ ccc"`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--tag', 'name/app:7.4',
|
||||
'--tag', 'name/app:latest',
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/master'
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/test-jest'
|
||||
]
|
||||
],
|
||||
[
|
||||
|
@ -185,7 +248,7 @@ ccc"`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -202,8 +265,8 @@ ccc"`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--secret', `id=GIT_AUTH_TOKEN,src=${tmpName}`,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -221,8 +284,8 @@ ccc"`],
|
|||
[
|
||||
'build',
|
||||
'--output', '.',
|
||||
'--secret', `id=GIT_AUTH_TOKEN,src=${tmpName}`,
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/master'
|
||||
'--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/test-jest'
|
||||
]
|
||||
],
|
||||
[
|
||||
|
@ -243,9 +306,9 @@ ccc"`],
|
|||
[
|
||||
'build',
|
||||
'--file', './test/Dockerfile',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--platform', 'linux/amd64,linux/arm64',
|
||||
'--secret', `id=GIT_AUTH_TOKEN,src=${tmpName}`,
|
||||
'--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--builder', 'builder-git-context-2',
|
||||
'--push',
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/master'
|
||||
|
@ -277,12 +340,12 @@ ccc"`],
|
|||
[
|
||||
'build',
|
||||
'--file', './test/Dockerfile',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--platform', 'linux/amd64,linux/arm64',
|
||||
'--secret', `id=GIT_AUTH_TOKEN,src=${tmpName}`,
|
||||
'--secret', `id=MYSECRET,src=${tmpName}`,
|
||||
'--secret', `id=FOO,src=${tmpName}`,
|
||||
'--secret', `id=EMPTYLINE,src=${tmpName}`,
|
||||
'--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--secret', 'id=MYSECRET,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--secret', 'id=FOO,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--secret', 'id=EMPTYLINE,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--builder', 'builder-git-context-2',
|
||||
'--push',
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/master'
|
||||
|
@ -314,12 +377,12 @@ ccc`],
|
|||
[
|
||||
'build',
|
||||
'--file', './test/Dockerfile',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--platform', 'linux/amd64,linux/arm64',
|
||||
'--secret', `id=GIT_AUTH_TOKEN,src=${tmpName}`,
|
||||
'--secret', `id=MYSECRET,src=${tmpName}`,
|
||||
'--secret', `id=FOO,src=${tmpName}`,
|
||||
'--secret', `id=EMPTYLINE,src=${tmpName}`,
|
||||
'--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--secret', 'id=MYSECRET,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--secret', 'id=FOO,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--secret', 'id=EMPTYLINE,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--builder', 'builder-git-context-2',
|
||||
'--push',
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/master'
|
||||
|
@ -331,7 +394,7 @@ ccc`],
|
|||
new Map<string, string>([
|
||||
['context', 'https://github.com/docker/build-push-action.git#refs/heads/master'],
|
||||
['tag', 'localhost:5000/name/app:latest'],
|
||||
['secret-files', `MY_SECRET=${path.join(__dirname, 'fixtures', 'secret.txt')}`],
|
||||
['secret-files', `MY_SECRET=${path.join(__dirname, 'fixtures', 'secret.txt').split(path.sep).join(path.posix.sep)}`],
|
||||
['file', './test/Dockerfile'],
|
||||
['builder', 'builder-git-context-2'],
|
||||
['network', 'host'],
|
||||
|
@ -343,8 +406,8 @@ ccc`],
|
|||
[
|
||||
'build',
|
||||
'--file', './test/Dockerfile',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--secret', `id=MY_SECRET,src=${tmpName}`,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--secret', 'id=MY_SECRET,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--builder', 'builder-git-context-2',
|
||||
'--network', 'host',
|
||||
'--push',
|
||||
|
@ -390,8 +453,8 @@ ccc`],
|
|||
'--add-host', 'docker:10.180.0.1',
|
||||
'--add-host', 'foo:10.0.0.1',
|
||||
'--file', './test/Dockerfile',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--metadata-file', metadataJson,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'--network', 'host',
|
||||
'--push',
|
||||
'.'
|
||||
|
@ -419,11 +482,11 @@ nproc=3`],
|
|||
'--add-host', 'foo:10.0.0.1',
|
||||
'--cgroup-parent', 'foo',
|
||||
'--file', './test/Dockerfile',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--shm-size', '2g',
|
||||
'--ulimit', 'nofile=1024:1024',
|
||||
'--ulimit', 'nproc=3',
|
||||
'--metadata-file', metadataJson,
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -439,9 +502,9 @@ nproc=3`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--metadata-file', metadataJson,
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/master:docker'
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/test-jest:docker'
|
||||
]
|
||||
],
|
||||
[
|
||||
|
@ -457,10 +520,10 @@ nproc=3`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--secret', `id=GIT_AUTH_TOKEN,src=${tmpName}`,
|
||||
'--metadata-file', metadataJson,
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/master:subdir'
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--secret', 'id=GIT_AUTH_TOKEN,src=/tmp/.docker-build-push-jest/.tmpname-jest',
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'https://github.com/docker/build-push-action.git#refs/heads/test-jest:subdir'
|
||||
]
|
||||
],
|
||||
[
|
||||
|
@ -476,8 +539,8 @@ nproc=3`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--metadata-file', metadataJson,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -493,9 +556,9 @@ nproc=3`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--attest', `type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--metadata-file', metadataJson,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
"--provenance", 'false',
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -512,9 +575,9 @@ nproc=3`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--attest', `type=provenance,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--metadata-file', metadataJson,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
"--provenance", `builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`,
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -531,9 +594,9 @@ nproc=3`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--attest', `type=provenance,mode=max,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--metadata-file', metadataJson,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
"--provenance", `mode=max,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789`,
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -550,9 +613,9 @@ nproc=3`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--attest', 'type=provenance,disabled=true',
|
||||
'--metadata-file', metadataJson,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
"--provenance", 'false',
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -569,9 +632,9 @@ nproc=3`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--attest', 'type=provenance,builder-id=foo',
|
||||
'--metadata-file', metadataJson,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
"--provenance", 'builder-id=foo',
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -588,9 +651,9 @@ nproc=3`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
"--output", 'type=docker',
|
||||
'--metadata-file', metadataJson,
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -606,196 +669,9 @@ nproc=3`],
|
|||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--load',
|
||||
'--metadata-file', metadataJson,
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
25,
|
||||
'0.10.0',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['build-args', `FOO=bar#baz`],
|
||||
['load', 'true'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
]),
|
||||
[
|
||||
'build',
|
||||
'--build-arg', 'FOO=bar#baz',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--load',
|
||||
'--metadata-file', metadataJson,
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
26,
|
||||
'0.10.0',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['no-cache', 'false'],
|
||||
['load', 'true'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['secret-envs', `MY_SECRET=MY_SECRET_ENV
|
||||
ANOTHER_SECRET=ANOTHER_SECRET_ENV`]
|
||||
]),
|
||||
[
|
||||
'build',
|
||||
'--secret', 'id=MY_SECRET,env=MY_SECRET_ENV',
|
||||
'--secret', 'id=ANOTHER_SECRET,env=ANOTHER_SECRET_ENV',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--load',
|
||||
'--metadata-file', metadataJson,
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
27,
|
||||
'0.10.0',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['no-cache', 'false'],
|
||||
['load', 'true'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['secret-envs', 'MY_SECRET=MY_SECRET_ENV,ANOTHER_SECRET=ANOTHER_SECRET_ENV']
|
||||
]),
|
||||
[
|
||||
'build',
|
||||
'--secret', 'id=MY_SECRET,env=MY_SECRET_ENV',
|
||||
'--secret', 'id=ANOTHER_SECRET,env=ANOTHER_SECRET_ENV',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--load',
|
||||
'--metadata-file', metadataJson,
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
28,
|
||||
'0.11.0',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['annotations', 'example1=www\nindex:example2=xxx\nmanifest:example3=yyy\nmanifest-descriptor[linux/amd64]:example4=zzz'],
|
||||
['outputs', 'type=local,dest=./release-out'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
]),
|
||||
[
|
||||
'build',
|
||||
'--output', 'type=local,dest=./release-out',
|
||||
'--attest', `type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--metadata-file', metadataJson,
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
29,
|
||||
'0.12.0',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['annotations', 'example1=www\nindex:example2=xxx\nmanifest:example3=yyy\nmanifest-descriptor[linux/amd64]:example4=zzz'],
|
||||
['outputs', 'type=local,dest=./release-out'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
]),
|
||||
[
|
||||
'build',
|
||||
'--annotation', 'example1=www',
|
||||
'--annotation', 'index:example2=xxx',
|
||||
'--annotation', 'manifest:example3=yyy',
|
||||
'--annotation', 'manifest-descriptor[linux/amd64]:example4=zzz',
|
||||
'--output', 'type=local,dest=./release-out',
|
||||
'--attest', `type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--metadata-file', metadataJson,
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
30,
|
||||
'0.12.0',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['outputs', `type=image,"name=localhost:5000/name/app:latest,localhost:5000/name/app:foo",push-by-digest=true,name-canonical=true,push=true`],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
"--output", `type=image,"name=localhost:5000/name/app:latest,localhost:5000/name/app:foo",push-by-digest=true,name-canonical=true,push=true`,
|
||||
'--attest', `type=provenance,mode=min,inline-only=true,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--metadata-file', metadataJson,
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
31,
|
||||
'0.13.1',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['provenance', 'mode=max'],
|
||||
['sbom', 'true'],
|
||||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--attest', `type=provenance,mode=max,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--attest', `type=sbom,disabled=false`,
|
||||
'--metadata-file', metadataJson,
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
32,
|
||||
'0.13.1',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['attests', 'type=provenance,mode=min'],
|
||||
['provenance', 'mode=max'],
|
||||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--attest', `type=provenance,mode=max,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--metadata-file', metadataJson,
|
||||
'.'
|
||||
]
|
||||
],
|
||||
[
|
||||
33,
|
||||
'0.13.1',
|
||||
new Map<string, string>([
|
||||
['context', '.'],
|
||||
['load', 'false'],
|
||||
['no-cache', 'false'],
|
||||
['push', 'false'],
|
||||
['pull', 'false'],
|
||||
['attests', 'type=provenance,mode=min'],
|
||||
]),
|
||||
[
|
||||
'build',
|
||||
'--iidfile', imageIDFilePath,
|
||||
'--attest', `type=provenance,mode=min,builder-id=https://github.com/docker/build-push-action/actions/runs/123456789/attempts/1`,
|
||||
'--metadata-file', metadataJson,
|
||||
'--iidfile', '/tmp/.docker-build-push-jest/iidfile',
|
||||
"--load",
|
||||
'--metadata-file', '/tmp/.docker-build-push-jest/metadata-file',
|
||||
'.'
|
||||
]
|
||||
],
|
||||
|
@ -805,17 +681,171 @@ ANOTHER_SECRET=ANOTHER_SECRET_ENV`]
|
|||
inputs.forEach((value: string, name: string) => {
|
||||
setInput(name, value);
|
||||
});
|
||||
const toolkit = new Toolkit();
|
||||
jest.spyOn(Buildx.prototype, 'version').mockImplementation(async (): Promise<string> => {
|
||||
return buildxVersion;
|
||||
});
|
||||
const inp = await context.getInputs();
|
||||
const res = await context.getArgs(inp, toolkit);
|
||||
const defContext = context.defaultContext();
|
||||
const inp = await context.getInputs(defContext);
|
||||
const res = await context.getArgs(inp, defContext, buildxVersion);
|
||||
expect(res).toEqual(expected);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('getInputList', () => {
|
||||
it('single line correctly', async () => {
|
||||
await setInput('foo', 'bar');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar']);
|
||||
});
|
||||
|
||||
it('multiline correctly', async () => {
|
||||
setInput('foo', 'bar\nbaz');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('empty lines correctly', async () => {
|
||||
setInput('foo', 'bar\n\nbaz');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('comma correctly', async () => {
|
||||
setInput('foo', 'bar,baz');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('empty result correctly', async () => {
|
||||
setInput('foo', 'bar,baz,');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('different new lines correctly', async () => {
|
||||
setInput('foo', 'bar\r\nbaz');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz']);
|
||||
});
|
||||
|
||||
it('different new lines and comma correctly', async () => {
|
||||
setInput('foo', 'bar\r\nbaz,bat');
|
||||
const res = await context.getInputList('foo');
|
||||
expect(res).toEqual(['bar', 'baz', 'bat']);
|
||||
});
|
||||
|
||||
it('multiline and ignoring comma correctly', async () => {
|
||||
setInput('cache-from', 'user/app:cache\ntype=local,src=path/to/dir');
|
||||
const res = await context.getInputList('cache-from', true);
|
||||
expect(res).toEqual(['user/app:cache', 'type=local,src=path/to/dir']);
|
||||
});
|
||||
|
||||
it('different new lines and ignoring comma correctly', async () => {
|
||||
setInput('cache-from', 'user/app:cache\r\ntype=local,src=path/to/dir');
|
||||
const res = await context.getInputList('cache-from', true);
|
||||
expect(res).toEqual(['user/app:cache', 'type=local,src=path/to/dir']);
|
||||
});
|
||||
|
||||
it('multiline values', async () => {
|
||||
setInput(
|
||||
'secrets',
|
||||
`GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789
|
||||
"MYSECRET=aaaaaaaa
|
||||
bbbbbbb
|
||||
ccccccccc"
|
||||
FOO=bar`
|
||||
);
|
||||
const res = await context.getInputList('secrets', true);
|
||||
expect(res).toEqual([
|
||||
'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789',
|
||||
`MYSECRET=aaaaaaaa
|
||||
bbbbbbb
|
||||
ccccccccc`,
|
||||
'FOO=bar'
|
||||
]);
|
||||
});
|
||||
|
||||
it('multiline values with empty lines', async () => {
|
||||
setInput(
|
||||
'secrets',
|
||||
`GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789
|
||||
"MYSECRET=aaaaaaaa
|
||||
bbbbbbb
|
||||
ccccccccc"
|
||||
FOO=bar
|
||||
"EMPTYLINE=aaaa
|
||||
|
||||
bbbb
|
||||
ccc"`
|
||||
);
|
||||
const res = await context.getInputList('secrets', true);
|
||||
expect(res).toEqual([
|
||||
'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789',
|
||||
`MYSECRET=aaaaaaaa
|
||||
bbbbbbb
|
||||
ccccccccc`,
|
||||
'FOO=bar',
|
||||
`EMPTYLINE=aaaa
|
||||
|
||||
bbbb
|
||||
ccc`
|
||||
]);
|
||||
});
|
||||
|
||||
it('multiline values without quotes', async () => {
|
||||
setInput(
|
||||
'secrets',
|
||||
`GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789
|
||||
MYSECRET=aaaaaaaa
|
||||
bbbbbbb
|
||||
ccccccccc
|
||||
FOO=bar`
|
||||
);
|
||||
const res = await context.getInputList('secrets', true);
|
||||
expect(res).toEqual(['GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789', 'MYSECRET=aaaaaaaa', 'bbbbbbb', 'ccccccccc', 'FOO=bar']);
|
||||
});
|
||||
|
||||
it('large multiline values', async () => {
|
||||
setInput(
|
||||
'secrets',
|
||||
`"GPG_KEY=${pgp}"
|
||||
FOO=bar`
|
||||
);
|
||||
const res = await context.getInputList('secrets', true);
|
||||
expect(res).toEqual([`GPG_KEY=${pgp}`, 'FOO=bar']);
|
||||
});
|
||||
|
||||
it('multiline values escape quotes', async () => {
|
||||
setInput(
|
||||
'secrets',
|
||||
`GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789
|
||||
"MYSECRET=aaaaaaaa
|
||||
bbbb""bbb
|
||||
ccccccccc"
|
||||
FOO=bar`
|
||||
);
|
||||
const res = await context.getInputList('secrets', true);
|
||||
expect(res).toEqual([
|
||||
'GIT_AUTH_TOKEN=abcdefgh,ijklmno=0123456789',
|
||||
`MYSECRET=aaaaaaaa
|
||||
bbbb"bbb
|
||||
ccccccccc`,
|
||||
'FOO=bar'
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('asyncForEach', () => {
|
||||
it('executes async tasks sequentially', async () => {
|
||||
const testValues = [1, 2, 3, 4, 5];
|
||||
const results: number[] = [];
|
||||
|
||||
await context.asyncForEach(testValues, async value => {
|
||||
results.push(value);
|
||||
});
|
||||
|
||||
expect(results).toEqual(testValues);
|
||||
});
|
||||
});
|
||||
|
||||
// See: https://github.com/actions/toolkit/blob/a1b068ec31a042ff1e10a522d8fdf0b8869d53ca/packages/core/src/core.ts#L89
|
||||
function getInputName(name: string): string {
|
||||
return `INPUT_${name.replace(/ /g, '_').toUpperCase()}`;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -13,9 +13,6 @@ inputs:
|
|||
allow:
|
||||
description: "List of extra privileged entitlement (e.g., network.host,security.insecure)"
|
||||
required: false
|
||||
annotations:
|
||||
description: "List of annotation to set to the image"
|
||||
required: false
|
||||
attests:
|
||||
description: "List of attestation parameters (e.g., type=sbom,generator=image)"
|
||||
required: false
|
||||
|
@ -83,9 +80,6 @@ inputs:
|
|||
secrets:
|
||||
description: "List of secrets to expose to the build (e.g., key=string, GIT_AUTH_TOKEN=mytoken)"
|
||||
required: false
|
||||
secret-envs:
|
||||
description: "List of secret env vars to expose to the build (e.g., key=envname, MY_SECRET=MY_ENV_VAR)"
|
||||
required: false
|
||||
secret-files:
|
||||
description: "List of secret files to expose to the build (e.g., key=filename, MY_SECRET=./secret.txt)"
|
||||
required: false
|
||||
|
@ -118,6 +112,6 @@ outputs:
|
|||
description: 'Build result metadata'
|
||||
|
||||
runs:
|
||||
using: 'node20'
|
||||
using: 'node16'
|
||||
main: 'dist/index.js'
|
||||
post: 'dist/index.js'
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG NODE_VERSION=20
|
||||
ARG NODE_VERSION=16
|
||||
ARG DOCKER_VERSION=20.10.13
|
||||
ARG BUILDX_VERSION=0.8.0
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine AS base
|
||||
RUN apk add --no-cache cpio findutils git
|
||||
WORKDIR /src
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache <<EOT
|
||||
corepack enable
|
||||
yarn --version
|
||||
yarn config set --home enableTelemetry 0
|
||||
EOT
|
||||
|
||||
FROM base AS deps
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn install && mkdir /vendor && cp yarn.lock /vendor
|
||||
|
||||
|
@ -23,19 +18,18 @@ COPY --from=deps /vendor /
|
|||
|
||||
FROM deps AS vendor-validate
|
||||
RUN --mount=type=bind,target=.,rw <<EOT
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /vendor/* .
|
||||
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /vendor/* .
|
||||
if [ -n "$(git status --porcelain -- yarn.lock)" ]; then
|
||||
echo >&2 'ERROR: Vendor result differs. Please vendor your package with "docker buildx bake vendor-update"'
|
||||
git status --porcelain -- yarn.lock
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM deps AS build
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run build && mkdir /out && cp -Rf dist /out/
|
||||
|
||||
|
@ -44,37 +38,39 @@ COPY --from=build /out /
|
|||
|
||||
FROM build AS build-validate
|
||||
RUN --mount=type=bind,target=.,rw <<EOT
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /out/* .
|
||||
if [ -n "$(git status --porcelain -- dist)" ]; then
|
||||
set -e
|
||||
git add -A
|
||||
cp -rf /out/* .
|
||||
if [ -n "$(git status --porcelain -- dist)" ]; then
|
||||
echo >&2 'ERROR: Build result differs. Please build first with "docker buildx bake build"'
|
||||
git status --porcelain -- dist
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
EOT
|
||||
|
||||
FROM deps AS format
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run format \
|
||||
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' -not -path './.yarn/*' | cpio -pdm /out
|
||||
&& mkdir /out && find . -name '*.ts' -not -path './node_modules/*' | cpio -pdm /out
|
||||
|
||||
FROM scratch AS format-update
|
||||
COPY --from=format /out /
|
||||
|
||||
FROM deps AS lint
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run lint
|
||||
|
||||
FROM docker:${DOCKER_VERSION} as docker
|
||||
FROM docker/buildx-bin:${BUILDX_VERSION} as buildx
|
||||
|
||||
FROM deps AS test
|
||||
RUN --mount=type=bind,target=.,rw \
|
||||
--mount=type=cache,target=/src/.yarn/cache \
|
||||
--mount=type=cache,target=/src/node_modules \
|
||||
yarn run test --coverage --coverageDirectory=/tmp/coverage
|
||||
--mount=type=bind,from=docker,source=/usr/local/bin/docker,target=/usr/bin/docker \
|
||||
--mount=type=bind,from=buildx,source=/buildx,target=/usr/libexec/docker/cli-plugins/docker-buildx \
|
||||
yarn run test --coverageDirectory=/tmp/coverage
|
||||
|
||||
FROM scratch AS test-coverage
|
||||
COPY --from=test /tmp/coverage /
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -3,7 +3,7 @@ group "default" {
|
|||
}
|
||||
|
||||
group "pre-checkin" {
|
||||
targets = ["vendor", "format", "build"]
|
||||
targets = ["vendor-update", "format", "build"]
|
||||
}
|
||||
|
||||
group "validate" {
|
||||
|
@ -34,7 +34,7 @@ target "lint" {
|
|||
output = ["type=cacheonly"]
|
||||
}
|
||||
|
||||
target "vendor" {
|
||||
target "vendor-update" {
|
||||
dockerfile = "dev.Dockerfile"
|
||||
target = "vendor-update"
|
||||
output = ["."]
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# Cache
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#cache)
|
|
@ -0,0 +1,3 @@
|
|||
# Copy images between registries
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#copy-images-between-registries)
|
|
@ -0,0 +1,3 @@
|
|||
# Update Docker Hub repo description
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#update-docker-hub-repository-description)
|
|
@ -0,0 +1,3 @@
|
|||
# Export image to Docker
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#export-image-to-docker)
|
|
@ -0,0 +1,3 @@
|
|||
# Isolated builders
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/configure-builder/#isolated-builders)
|
|
@ -0,0 +1,3 @@
|
|||
# Local registry
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#local-registry)
|
|
@ -0,0 +1,3 @@
|
|||
# Multi-platform image
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#multi-platform-images)
|
|
@ -0,0 +1,3 @@
|
|||
# Named contexts
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#named-contexts)
|
|
@ -0,0 +1,3 @@
|
|||
# Push to multi-registries
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#push-to-multi-registries)
|
|
@ -0,0 +1,3 @@
|
|||
# Secrets
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#secrets)
|
|
@ -0,0 +1,3 @@
|
|||
# Share built image between jobs
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#share-built-image-between-jobs)
|
|
@ -0,0 +1,3 @@
|
|||
# Handle tags and labels
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#manage-tags-and-labels)
|
|
@ -0,0 +1,3 @@
|
|||
# Test your image before pushing it
|
||||
|
||||
This page has moved to [Docker Docs website](https://docs.docker.com/build/ci/github-actions/examples/#test-your-image-before-pushing-it)
|
|
@ -1,14 +1,8 @@
|
|||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-build-push-action-'));
|
||||
|
||||
process.env = Object.assign({}, process.env, {
|
||||
TEMP: tmpDir,
|
||||
RUNNER_TEMP: '/tmp/github_runner',
|
||||
RUNNER_TOOL_CACHE: '/tmp/github_tool_cache',
|
||||
GITHUB_REPOSITORY: 'docker/build-push-action',
|
||||
RUNNER_TEMP: path.join(tmpDir, 'runner-temp'),
|
||||
RUNNER_TOOL_CACHE: path.join(tmpDir, 'runner-tool-cache')
|
||||
GITHUB_RUN_ID: '123456789'
|
||||
}) as {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
@ -17,6 +11,7 @@ module.exports = {
|
|||
clearMocks: false,
|
||||
testEnvironment: 'node',
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
setupFiles: ['dotenv/config'],
|
||||
testMatch: ['**/*.test.ts'],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
|
@ -24,7 +19,5 @@ module.exports = {
|
|||
moduleNameMapper: {
|
||||
'^csv-parse/sync': '<rootDir>/node_modules/csv-parse/dist/cjs/sync.cjs'
|
||||
},
|
||||
collectCoverageFrom: ['src/**/{!(main.ts),}.ts'],
|
||||
coveragePathIgnorePatterns: ['lib/', 'node_modules/', '__mocks__/', '__tests__/'],
|
||||
verbose: true
|
||||
};
|
||||
|
|
65
package.json
65
package.json
|
@ -1,16 +1,13 @@
|
|||
{
|
||||
"name": "docker-build-push",
|
||||
"description": "Build and push Docker images",
|
||||
"main": "src/main.ts",
|
||||
"main": "lib/main.js",
|
||||
"scripts": {
|
||||
"build": "ncc build --source-map --minify --license licenses.txt",
|
||||
"lint": "yarn run prettier && yarn run eslint",
|
||||
"format": "yarn run prettier:fix && yarn run eslint:fix",
|
||||
"eslint": "eslint --max-warnings=0 .",
|
||||
"eslint:fix": "eslint --fix .",
|
||||
"prettier": "prettier --check \"./**/*.ts\"",
|
||||
"prettier:fix": "prettier --write \"./**/*.ts\"",
|
||||
"test": "jest"
|
||||
"build": "ncc build src/main.ts --source-map --minify --license licenses.txt",
|
||||
"lint": "eslint src/**/*.ts __tests__/**/*.ts",
|
||||
"format": "eslint --fix src/**/*.ts __tests__/**/*.ts",
|
||||
"test": "jest --coverage",
|
||||
"all": "yarn run build && yarn run format && yarn test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -22,27 +19,41 @@
|
|||
"build",
|
||||
"push"
|
||||
],
|
||||
"author": "Docker Inc.",
|
||||
"author": "Docker",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "CrazyMax",
|
||||
"url": "https://crazymax.dev"
|
||||
}
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"packageManager": "yarn@3.6.3",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.1",
|
||||
"@docker/actions-toolkit": "0.37.1",
|
||||
"handlebars": "^4.7.7"
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/github": "^5.1.1",
|
||||
"csv-parse": "^5.3.3",
|
||||
"handlebars": "^4.7.7",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"semver": "^7.3.7",
|
||||
"tmp": "^0.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.12.12",
|
||||
"@typescript-eslint/eslint-plugin": "^7.9.0",
|
||||
"@typescript-eslint/parser": "^7.9.0",
|
||||
"@vercel/ncc": "^0.38.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-jest": "^28.5.0",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"jest": "^29.7.0",
|
||||
"prettier": "^3.2.5",
|
||||
"ts-jest": "^29.1.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.5"
|
||||
"@types/csv-parse": "^1.2.2",
|
||||
"@types/node": "^16.11.26",
|
||||
"@types/semver": "^7.3.9",
|
||||
"@types/tmp": "^0.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.14.0",
|
||||
"@typescript-eslint/parser": "^5.14.0",
|
||||
"@vercel/ncc": "^0.33.3",
|
||||
"dotenv": "^16.0.0",
|
||||
"eslint": "^8.11.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-jest": "^26.1.1",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"jest": "^27.2.5",
|
||||
"prettier": "^2.3.1",
|
||||
"ts-jest": "^27.1.2",
|
||||
"ts-node": "^10.7.0",
|
||||
"typescript": "^4.4.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
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 type Builder = {
|
||||
name?: string;
|
||||
driver?: string;
|
||||
nodes: Node[];
|
||||
};
|
||||
|
||||
export type Node = {
|
||||
name?: string;
|
||||
endpoint?: string;
|
||||
'driver-opts'?: Array<string>;
|
||||
status?: string;
|
||||
'buildkitd-flags'?: string;
|
||||
buildkit?: string;
|
||||
platforms?: string;
|
||||
};
|
||||
|
||||
export async function 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 satisfiesBuildKitVersion(builderName: string, range: string, standalone?: boolean): Promise<boolean> {
|
||||
const builderInspect = await inspect(builderName, standalone);
|
||||
for (const node of builderInspect.nodes) {
|
||||
if (!node.buildkit) {
|
||||
return false;
|
||||
}
|
||||
// BuildKit version reported by moby is in the format of `v0.11.0-moby`
|
||||
if (builderInspect.driver == 'docker' && !node.buildkit.endsWith('-moby')) {
|
||||
return false;
|
||||
}
|
||||
const version = node.buildkit.replace(/-moby$/, '');
|
||||
if (!semver.satisfies(version, range)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
async function inspect(name: string, standalone?: boolean): Promise<Builder> {
|
||||
const cmd = getCommand(['inspect', name], 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 parseInspect(res.stdout);
|
||||
});
|
||||
}
|
||||
|
||||
async function parseInspect(data: string): Promise<Builder> {
|
||||
const builder: Builder = {
|
||||
nodes: []
|
||||
};
|
||||
let node: Node = {};
|
||||
for (const line of data.trim().split(`\n`)) {
|
||||
const [key, ...rest] = line.split(':');
|
||||
const value = rest.map(v => v.trim()).join(':');
|
||||
if (key.length == 0 || value.length == 0) {
|
||||
continue;
|
||||
}
|
||||
switch (key.toLowerCase()) {
|
||||
case 'name': {
|
||||
if (builder.name == undefined) {
|
||||
builder.name = value;
|
||||
} else {
|
||||
if (Object.keys(node).length > 0) {
|
||||
builder.nodes.push(node);
|
||||
node = {};
|
||||
}
|
||||
node.name = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'driver': {
|
||||
builder.driver = value;
|
||||
break;
|
||||
}
|
||||
case 'endpoint': {
|
||||
node.endpoint = value;
|
||||
break;
|
||||
}
|
||||
case 'driver options': {
|
||||
node['driver-opts'] = (value.match(/(\w+)="([^"]*)"/g) || []).map(v => v.replace(/^(.*)="(.*)"$/g, '$1=$2'));
|
||||
break;
|
||||
}
|
||||
case 'status': {
|
||||
node.status = value;
|
||||
break;
|
||||
}
|
||||
case 'flags': {
|
||||
node['buildkitd-flags'] = value;
|
||||
break;
|
||||
}
|
||||
case 'buildkit': {
|
||||
node.buildkit = value;
|
||||
break;
|
||||
}
|
||||
case 'platforms': {
|
||||
let platforms: Array<string> = [];
|
||||
// if a preferred platform is being set then use only these
|
||||
// https://docs.docker.com/engine/reference/commandline/buildx_inspect/#get-information-about-a-builder-instance
|
||||
if (value.includes('*')) {
|
||||
for (const platform of value.split(', ')) {
|
||||
if (platform.includes('*')) {
|
||||
platforms.push(platform.replace('*', ''));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// otherwise set all platforms available
|
||||
platforms = value.split(', ');
|
||||
}
|
||||
node.platforms = platforms.join(',');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Object.keys(node).length > 0) {
|
||||
builder.nodes.push(node);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
export async function 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]
|
||||
};
|
||||
}
|
365
src/context.ts
365
src/context.ts
|
@ -1,30 +1,32 @@
|
|||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as tmp from 'tmp';
|
||||
import * as buildx from './buildx';
|
||||
import * as core from '@actions/core';
|
||||
import * as github from '@actions/github';
|
||||
import {parse} from 'csv-parse/sync';
|
||||
import * as handlebars from 'handlebars';
|
||||
|
||||
import {Build} from '@docker/actions-toolkit/lib/buildx/build';
|
||||
import {Context} from '@docker/actions-toolkit/lib/context';
|
||||
import {GitHub} from '@docker/actions-toolkit/lib/github';
|
||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
|
||||
import {Util} from '@docker/actions-toolkit/lib/util';
|
||||
let _defaultContext, _tmpDir: string;
|
||||
|
||||
export interface Inputs {
|
||||
'add-hosts': string[];
|
||||
addHosts: string[];
|
||||
allow: string[];
|
||||
annotations: string[];
|
||||
attests: string[];
|
||||
'build-args': string[];
|
||||
'build-contexts': string[];
|
||||
buildArgs: string[];
|
||||
buildContexts: string[];
|
||||
builder: string;
|
||||
'cache-from': string[];
|
||||
'cache-to': string[];
|
||||
'cgroup-parent': string;
|
||||
cacheFrom: string[];
|
||||
cacheTo: string[];
|
||||
cgroupParent: string;
|
||||
context: string;
|
||||
file: string;
|
||||
labels: string[];
|
||||
load: boolean;
|
||||
network: string;
|
||||
'no-cache': boolean;
|
||||
'no-cache-filters': string[];
|
||||
noCache: boolean;
|
||||
noCacheFilters: string[];
|
||||
outputs: string[];
|
||||
platforms: string[];
|
||||
provenance: string;
|
||||
|
@ -32,184 +34,190 @@ export interface Inputs {
|
|||
push: boolean;
|
||||
sbom: string;
|
||||
secrets: string[];
|
||||
'secret-envs': string[];
|
||||
'secret-files': string[];
|
||||
'shm-size': string;
|
||||
secretFiles: string[];
|
||||
shmSize: string;
|
||||
ssh: string[];
|
||||
tags: string[];
|
||||
target: string;
|
||||
ulimit: string[];
|
||||
'github-token': string;
|
||||
githubToken: string;
|
||||
}
|
||||
|
||||
export async function getInputs(): Promise<Inputs> {
|
||||
export function defaultContext(): string {
|
||||
if (!_defaultContext) {
|
||||
let ref = github.context.ref;
|
||||
if (github.context.sha && ref && !ref.startsWith('refs/')) {
|
||||
ref = `refs/heads/${github.context.ref}`;
|
||||
}
|
||||
if (github.context.sha && !ref.startsWith(`refs/pull/`)) {
|
||||
ref = github.context.sha;
|
||||
}
|
||||
_defaultContext = `${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${github.context.repo.repo}.git#${ref}`;
|
||||
}
|
||||
return _defaultContext;
|
||||
}
|
||||
|
||||
export function tmpDir(): string {
|
||||
if (!_tmpDir) {
|
||||
_tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'docker-build-push-')).split(path.sep).join(path.posix.sep);
|
||||
}
|
||||
return _tmpDir;
|
||||
}
|
||||
|
||||
export function tmpNameSync(options?: tmp.TmpNameOptions): string {
|
||||
return tmp.tmpNameSync(options);
|
||||
}
|
||||
|
||||
export function provenanceBuilderID(): string {
|
||||
return `${process.env.GITHUB_SERVER_URL || 'https://github.com'}/${github.context.repo.owner}/${github.context.repo.repo}/actions/runs/${github.context.runId}`;
|
||||
}
|
||||
|
||||
export async function getInputs(defaultContext: string): Promise<Inputs> {
|
||||
return {
|
||||
'add-hosts': Util.getInputList('add-hosts'),
|
||||
allow: Util.getInputList('allow'),
|
||||
annotations: Util.getInputList('annotations', {ignoreComma: true}),
|
||||
attests: Util.getInputList('attests', {ignoreComma: true}),
|
||||
'build-args': Util.getInputList('build-args', {ignoreComma: true}),
|
||||
'build-contexts': Util.getInputList('build-contexts', {ignoreComma: true}),
|
||||
addHosts: await getInputList('add-hosts'),
|
||||
allow: await getInputList('allow'),
|
||||
attests: await getInputList('attests', true),
|
||||
buildArgs: await getInputList('build-args', true),
|
||||
buildContexts: await getInputList('build-contexts', true),
|
||||
builder: core.getInput('builder'),
|
||||
'cache-from': Util.getInputList('cache-from', {ignoreComma: true}),
|
||||
'cache-to': Util.getInputList('cache-to', {ignoreComma: true}),
|
||||
'cgroup-parent': core.getInput('cgroup-parent'),
|
||||
context: core.getInput('context') || Context.gitContext(),
|
||||
cacheFrom: await getInputList('cache-from', true),
|
||||
cacheTo: await getInputList('cache-to', true),
|
||||
cgroupParent: core.getInput('cgroup-parent'),
|
||||
context: core.getInput('context') || defaultContext,
|
||||
file: core.getInput('file'),
|
||||
labels: Util.getInputList('labels', {ignoreComma: true}),
|
||||
labels: await getInputList('labels', true),
|
||||
load: core.getBooleanInput('load'),
|
||||
network: core.getInput('network'),
|
||||
'no-cache': core.getBooleanInput('no-cache'),
|
||||
'no-cache-filters': Util.getInputList('no-cache-filters'),
|
||||
outputs: Util.getInputList('outputs', {ignoreComma: true, quote: false}),
|
||||
platforms: Util.getInputList('platforms'),
|
||||
provenance: Build.getProvenanceInput('provenance'),
|
||||
noCache: core.getBooleanInput('no-cache'),
|
||||
noCacheFilters: await getInputList('no-cache-filters'),
|
||||
outputs: await getInputList('outputs', true),
|
||||
platforms: await getInputList('platforms'),
|
||||
provenance: getProvenanceInput('provenance'),
|
||||
pull: core.getBooleanInput('pull'),
|
||||
push: core.getBooleanInput('push'),
|
||||
sbom: core.getInput('sbom'),
|
||||
secrets: Util.getInputList('secrets', {ignoreComma: true}),
|
||||
'secret-envs': Util.getInputList('secret-envs'),
|
||||
'secret-files': Util.getInputList('secret-files', {ignoreComma: true}),
|
||||
'shm-size': core.getInput('shm-size'),
|
||||
ssh: Util.getInputList('ssh'),
|
||||
tags: Util.getInputList('tags'),
|
||||
secrets: await getInputList('secrets', true),
|
||||
secretFiles: await getInputList('secret-files', true),
|
||||
shmSize: core.getInput('shm-size'),
|
||||
ssh: await getInputList('ssh'),
|
||||
tags: await getInputList('tags'),
|
||||
target: core.getInput('target'),
|
||||
ulimit: Util.getInputList('ulimit', {ignoreComma: true}),
|
||||
'github-token': core.getInput('github-token')
|
||||
ulimit: await getInputList('ulimit', true),
|
||||
githubToken: core.getInput('github-token')
|
||||
};
|
||||
}
|
||||
|
||||
export function sanitizeInputs(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 === false) {
|
||||
continue;
|
||||
} else if (Array.isArray(value) && value.length === 0) {
|
||||
continue;
|
||||
} else if (!value) {
|
||||
continue;
|
||||
}
|
||||
res[key] = value;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
export async function getArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> {
|
||||
const context = handlebars.compile(inputs.context)({
|
||||
defaultContext: Context.gitContext()
|
||||
});
|
||||
export async function getArgs(inputs: Inputs, defaultContext: string, buildxVersion: string, standalone?: boolean): Promise<Array<string>> {
|
||||
const context = handlebars.compile(inputs.context)({defaultContext});
|
||||
// prettier-ignore
|
||||
return [
|
||||
...await getBuildArgs(inputs, context, toolkit),
|
||||
...await getCommonArgs(inputs, toolkit),
|
||||
...await getBuildArgs(inputs, defaultContext, context, buildxVersion, standalone),
|
||||
...await getCommonArgs(inputs, buildxVersion),
|
||||
context
|
||||
];
|
||||
}
|
||||
|
||||
async function getBuildArgs(inputs: Inputs, context: string, toolkit: Toolkit): Promise<Array<string>> {
|
||||
async function getBuildArgs(inputs: Inputs, defaultContext: string, context: string, buildxVersion: string, standalone?: boolean): Promise<Array<string>> {
|
||||
const args: Array<string> = ['build'];
|
||||
await Util.asyncForEach(inputs['add-hosts'], async addHost => {
|
||||
await asyncForEach(inputs.addHosts, async addHost => {
|
||||
args.push('--add-host', addHost);
|
||||
});
|
||||
if (inputs.allow.length > 0) {
|
||||
args.push('--allow', inputs.allow.join(','));
|
||||
}
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.12.0')) {
|
||||
await Util.asyncForEach(inputs.annotations, async annotation => {
|
||||
args.push('--annotation', annotation);
|
||||
if (buildx.satisfies(buildxVersion, '>=0.10.0')) {
|
||||
await asyncForEach(inputs.attests, async attest => {
|
||||
args.push('--attest', attest);
|
||||
});
|
||||
} else if (inputs.annotations.length > 0) {
|
||||
core.warning("Annotations are only supported by buildx >= 0.12.0; the input 'annotations' is ignored.");
|
||||
}
|
||||
await Util.asyncForEach(inputs['build-args'], async buildArg => {
|
||||
await asyncForEach(inputs.buildArgs, async buildArg => {
|
||||
args.push('--build-arg', buildArg);
|
||||
});
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.8.0')) {
|
||||
await Util.asyncForEach(inputs['build-contexts'], async buildContext => {
|
||||
if (buildx.satisfies(buildxVersion, '>=0.8.0')) {
|
||||
await asyncForEach(inputs.buildContexts, async buildContext => {
|
||||
args.push('--build-context', buildContext);
|
||||
});
|
||||
} else if (inputs['build-contexts'].length > 0) {
|
||||
core.warning("Build contexts are only supported by buildx >= 0.8.0; the input 'build-contexts' is ignored.");
|
||||
}
|
||||
await Util.asyncForEach(inputs['cache-from'], async cacheFrom => {
|
||||
await asyncForEach(inputs.cacheFrom, async cacheFrom => {
|
||||
args.push('--cache-from', cacheFrom);
|
||||
});
|
||||
await Util.asyncForEach(inputs['cache-to'], async cacheTo => {
|
||||
await asyncForEach(inputs.cacheTo, async cacheTo => {
|
||||
args.push('--cache-to', cacheTo);
|
||||
});
|
||||
if (inputs['cgroup-parent']) {
|
||||
args.push('--cgroup-parent', inputs['cgroup-parent']);
|
||||
if (inputs.cgroupParent) {
|
||||
args.push('--cgroup-parent', inputs.cgroupParent);
|
||||
}
|
||||
await Util.asyncForEach(inputs['secret-envs'], async secretEnv => {
|
||||
try {
|
||||
args.push('--secret', Build.resolveSecretEnv(secretEnv));
|
||||
} catch (err) {
|
||||
core.warning(err.message);
|
||||
}
|
||||
});
|
||||
if (inputs.file) {
|
||||
args.push('--file', inputs.file);
|
||||
}
|
||||
if (!Build.hasLocalExporter(inputs.outputs) && !Build.hasTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || (await toolkit.buildx.versionSatisfies('>=0.4.2')))) {
|
||||
args.push('--iidfile', toolkit.buildxBuild.getImageIDFilePath());
|
||||
if (!buildx.isLocalOrTarExporter(inputs.outputs) && (inputs.platforms.length == 0 || buildx.satisfies(buildxVersion, '>=0.4.2'))) {
|
||||
args.push('--iidfile', await buildx.getImageIDFile());
|
||||
}
|
||||
await Util.asyncForEach(inputs.labels, async label => {
|
||||
await asyncForEach(inputs.labels, async label => {
|
||||
args.push('--label', label);
|
||||
});
|
||||
await Util.asyncForEach(inputs['no-cache-filters'], async noCacheFilter => {
|
||||
await asyncForEach(inputs.noCacheFilters, async noCacheFilter => {
|
||||
args.push('--no-cache-filter', noCacheFilter);
|
||||
});
|
||||
await Util.asyncForEach(inputs.outputs, async output => {
|
||||
await asyncForEach(inputs.outputs, async output => {
|
||||
args.push('--output', output);
|
||||
});
|
||||
if (inputs.platforms.length > 0) {
|
||||
args.push('--platform', inputs.platforms.join(','));
|
||||
}
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.10.0')) {
|
||||
args.push(...(await getAttestArgs(inputs, toolkit)));
|
||||
} else {
|
||||
core.warning("Attestations are only supported by buildx >= 0.10.0; the inputs 'attests', 'provenance' and 'sbom' are ignored.");
|
||||
if (buildx.satisfies(buildxVersion, '>=0.10.0')) {
|
||||
if (inputs.provenance) {
|
||||
args.push('--provenance', inputs.provenance);
|
||||
} else if ((await buildx.satisfiesBuildKitVersion(inputs.builder, '>=0.11.0', standalone)) && !hasDockerExport(inputs)) {
|
||||
// If provenance not specified but BuildKit version compatible for
|
||||
// attestation, disable provenance anyway. Also needs to make sure user
|
||||
// doesn't want to explicitly load the image to docker.
|
||||
// While this action successfully pushes OCI compliant images to
|
||||
// well-known registries, some runtimes (e.g. Google Cloud Run and AWS
|
||||
// Lambda) are not able to pull resulting image from their own registry...
|
||||
// See also https://github.com/docker/buildx/issues/1533
|
||||
args.push('--provenance', 'false');
|
||||
}
|
||||
await Util.asyncForEach(inputs.secrets, async secret => {
|
||||
if (inputs.sbom) {
|
||||
args.push('--sbom', inputs.sbom);
|
||||
}
|
||||
}
|
||||
await asyncForEach(inputs.secrets, async secret => {
|
||||
try {
|
||||
args.push('--secret', Build.resolveSecretString(secret));
|
||||
args.push('--secret', await buildx.getSecretString(secret));
|
||||
} catch (err) {
|
||||
core.warning(err.message);
|
||||
}
|
||||
});
|
||||
await Util.asyncForEach(inputs['secret-files'], async secretFile => {
|
||||
await asyncForEach(inputs.secretFiles, async secretFile => {
|
||||
try {
|
||||
args.push('--secret', Build.resolveSecretFile(secretFile));
|
||||
args.push('--secret', await buildx.getSecretFile(secretFile));
|
||||
} catch (err) {
|
||||
core.warning(err.message);
|
||||
}
|
||||
});
|
||||
if (inputs['github-token'] && !Build.hasGitAuthTokenSecret(inputs.secrets) && context.startsWith(Context.gitContext())) {
|
||||
args.push('--secret', Build.resolveSecretString(`GIT_AUTH_TOKEN=${inputs['github-token']}`));
|
||||
if (inputs.githubToken && !buildx.hasGitAuthToken(inputs.secrets) && context.startsWith(defaultContext)) {
|
||||
args.push('--secret', await buildx.getSecretString(`GIT_AUTH_TOKEN=${inputs.githubToken}`));
|
||||
}
|
||||
if (inputs['shm-size']) {
|
||||
args.push('--shm-size', inputs['shm-size']);
|
||||
if (inputs.shmSize) {
|
||||
args.push('--shm-size', inputs.shmSize);
|
||||
}
|
||||
await Util.asyncForEach(inputs.ssh, async ssh => {
|
||||
await asyncForEach(inputs.ssh, async ssh => {
|
||||
args.push('--ssh', ssh);
|
||||
});
|
||||
await Util.asyncForEach(inputs.tags, async tag => {
|
||||
await asyncForEach(inputs.tags, async tag => {
|
||||
args.push('--tag', tag);
|
||||
});
|
||||
if (inputs.target) {
|
||||
args.push('--target', inputs.target);
|
||||
}
|
||||
await Util.asyncForEach(inputs.ulimit, async ulimit => {
|
||||
await asyncForEach(inputs.ulimit, async ulimit => {
|
||||
args.push('--ulimit', ulimit);
|
||||
});
|
||||
return args;
|
||||
}
|
||||
|
||||
async function getCommonArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> {
|
||||
async function getCommonArgs(inputs: Inputs, buildxVersion: string): Promise<Array<string>> {
|
||||
const args: Array<string> = [];
|
||||
if (inputs.builder) {
|
||||
args.push('--builder', inputs.builder);
|
||||
|
@ -217,13 +225,13 @@ async function getCommonArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<st
|
|||
if (inputs.load) {
|
||||
args.push('--load');
|
||||
}
|
||||
if (await toolkit.buildx.versionSatisfies('>=0.6.0')) {
|
||||
args.push('--metadata-file', toolkit.buildxBuild.getMetadataFilePath());
|
||||
if (buildx.satisfies(buildxVersion, '>=0.6.0')) {
|
||||
args.push('--metadata-file', await buildx.getMetadataFile());
|
||||
}
|
||||
if (inputs.network) {
|
||||
args.push('--network', inputs.network);
|
||||
}
|
||||
if (inputs['no-cache']) {
|
||||
if (inputs.noCache) {
|
||||
args.push('--no-cache');
|
||||
}
|
||||
if (inputs.pull) {
|
||||
|
@ -235,51 +243,98 @@ async function getCommonArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<st
|
|||
return args;
|
||||
}
|
||||
|
||||
async function getAttestArgs(inputs: Inputs, toolkit: Toolkit): Promise<Array<string>> {
|
||||
const args: Array<string> = [];
|
||||
export async function getInputList(name: string, ignoreComma?: boolean): Promise<string[]> {
|
||||
const res: Array<string> = [];
|
||||
|
||||
// check if provenance attestation is set in attests input
|
||||
let hasAttestProvenance = false;
|
||||
await Util.asyncForEach(inputs.attests, async (attest: string) => {
|
||||
if (Build.hasAttestationType('provenance', attest)) {
|
||||
hasAttestProvenance = true;
|
||||
const items = core.getInput(name);
|
||||
if (items == '') {
|
||||
return res;
|
||||
}
|
||||
|
||||
const records = await parse(items, {
|
||||
columns: false,
|
||||
relaxQuotes: true,
|
||||
relaxColumnCount: true,
|
||||
skipEmptyLines: true
|
||||
});
|
||||
|
||||
let provenanceSet = false;
|
||||
let sbomSet = false;
|
||||
if (inputs.provenance) {
|
||||
args.push('--attest', Build.resolveAttestationAttrs(`type=provenance,${inputs.provenance}`));
|
||||
provenanceSet = true;
|
||||
} else if (!hasAttestProvenance && (await toolkit.buildkit.versionSatisfies(inputs.builder, '>=0.11.0')) && !Build.hasDockerExporter(inputs.outputs, inputs.load)) {
|
||||
// if provenance not specified in provenance or attests inputs and BuildKit
|
||||
// version compatible for attestation, set default provenance. Also needs
|
||||
// to make sure user doesn't want to explicitly load the image to docker.
|
||||
if (GitHub.context.payload.repository?.private ?? false) {
|
||||
// if this is a private repository, we set the default provenance
|
||||
// attributes being set in buildx: https://github.com/docker/buildx/blob/fb27e3f919dcbf614d7126b10c2bc2d0b1927eb6/build/build.go#L603
|
||||
args.push('--attest', `type=provenance,${Build.resolveProvenanceAttrs(`mode=min,inline-only=true`)}`);
|
||||
} else {
|
||||
// for a public repository, we set max provenance mode.
|
||||
args.push('--attest', `type=provenance,${Build.resolveProvenanceAttrs(`mode=max`)}`);
|
||||
for (const record of records as Array<string[]>) {
|
||||
if (record.length == 1) {
|
||||
res.push(record[0]);
|
||||
continue;
|
||||
} else if (!ignoreComma) {
|
||||
res.push(...record);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (inputs.sbom) {
|
||||
args.push('--attest', Build.resolveAttestationAttrs(`type=sbom,${inputs.sbom}`));
|
||||
sbomSet = true;
|
||||
res.push(record.join(','));
|
||||
}
|
||||
|
||||
// set attests but check if provenance or sbom types already set as
|
||||
// provenance and sbom inputs take precedence over attests input.
|
||||
await Util.asyncForEach(inputs.attests, async (attest: string) => {
|
||||
if (!Build.hasAttestationType('provenance', attest) && !Build.hasAttestationType('sbom', attest)) {
|
||||
args.push('--attest', Build.resolveAttestationAttrs(attest));
|
||||
} else if (!provenanceSet && Build.hasAttestationType('provenance', attest)) {
|
||||
args.push('--attest', Build.resolveProvenanceAttrs(attest));
|
||||
} else if (!sbomSet && Build.hasAttestationType('sbom', attest)) {
|
||||
args.push('--attest', attest);
|
||||
}
|
||||
});
|
||||
|
||||
return args;
|
||||
return res.filter(item => item).map(pat => pat.trim());
|
||||
}
|
||||
|
||||
export const asyncForEach = async (array, callback) => {
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
await callback(array[index], index, array);
|
||||
}
|
||||
};
|
||||
|
||||
function getProvenanceInput(name: string): string {
|
||||
const input = core.getInput(name);
|
||||
if (!input) {
|
||||
// if input is not set, default values will be set later.
|
||||
return input;
|
||||
}
|
||||
const builderID = provenanceBuilderID();
|
||||
try {
|
||||
return core.getBooleanInput(name) ? `builder-id=${builderID}` : 'false';
|
||||
} catch (err) {
|
||||
// not a valid boolean, so we assume it's a string
|
||||
return getProvenanceAttrs(input);
|
||||
}
|
||||
}
|
||||
|
||||
function getProvenanceAttrs(input: string): string {
|
||||
const builderID = provenanceBuilderID();
|
||||
// parse attributes from input
|
||||
const fields = parse(input, {
|
||||
relaxColumnCount: true,
|
||||
skipEmptyLines: true
|
||||
})[0];
|
||||
// check if builder-id attribute exists in the input
|
||||
for (const field of fields) {
|
||||
const parts = field
|
||||
.toString()
|
||||
.split(/(?<=^[^=]+?)=/)
|
||||
.map(item => item.trim());
|
||||
if (parts[0] == 'builder-id') {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
// if not add builder-id attribute
|
||||
return `${input},builder-id=${builderID}`;
|
||||
}
|
||||
|
||||
function hasDockerExport(inputs: Inputs): boolean {
|
||||
if (inputs.load) {
|
||||
return true;
|
||||
}
|
||||
for (const output of inputs.outputs) {
|
||||
const fields = parse(output, {
|
||||
relaxColumnCount: true,
|
||||
skipEmptyLines: true
|
||||
})[0];
|
||||
for (const field of fields) {
|
||||
const parts = field
|
||||
.toString()
|
||||
.split(/(?<=^[^=]+?)=/)
|
||||
.map(item => item.trim());
|
||||
if (parts.length != 2) {
|
||||
continue;
|
||||
}
|
||||
if (parts[0] == 'type' && parts[1] == 'docker') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import jwt_decode, {JwtPayload} from 'jwt-decode';
|
||||
|
||||
interface Jwt extends JwtPayload {
|
||||
ac?: string;
|
||||
}
|
||||
|
||||
export const parseRuntimeToken = (token: string): Jwt => {
|
||||
return jwt_decode<Jwt>(token);
|
||||
};
|
303
src/main.ts
303
src/main.ts
|
@ -1,117 +1,72 @@
|
|||
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 github from './github';
|
||||
import * as stateHelper from './state-helper';
|
||||
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';
|
||||
import {History as BuildxHistory} from '@docker/actions-toolkit/lib/buildx/history';
|
||||
import {Context} from '@docker/actions-toolkit/lib/context';
|
||||
import {Docker} from '@docker/actions-toolkit/lib/docker/docker';
|
||||
import {Exec} from '@docker/actions-toolkit/lib/exec';
|
||||
import {GitHub} from '@docker/actions-toolkit/lib/github';
|
||||
import {Toolkit} from '@docker/actions-toolkit/lib/toolkit';
|
||||
import {Util} from '@docker/actions-toolkit/lib/util';
|
||||
|
||||
import {BuilderInfo} from '@docker/actions-toolkit/lib/types/buildx/builder';
|
||||
import {ConfigFile} from '@docker/actions-toolkit/lib/types/docker/docker';
|
||||
import {UploadArtifactResponse} from '@docker/actions-toolkit/lib/types/github';
|
||||
|
||||
import * as context from './context';
|
||||
|
||||
actionsToolkit.run(
|
||||
// main
|
||||
async () => {
|
||||
const startedTime = new Date();
|
||||
const inputs: context.Inputs = await context.getInputs();
|
||||
core.debug(`inputs: ${JSON.stringify(inputs)}`);
|
||||
stateHelper.setInputs(inputs);
|
||||
|
||||
const toolkit = new Toolkit();
|
||||
|
||||
await core.group(`GitHub Actions runtime token ACs`, async () => {
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
await GitHub.printActionsRuntimeTokenACs();
|
||||
} catch (e) {
|
||||
core.warning(e.message);
|
||||
const defContext = context.defaultContext();
|
||||
const inputs: context.Inputs = await context.getInputs(defContext);
|
||||
|
||||
// standalone if docker cli not available
|
||||
const standalone = !(await docker.isAvailable());
|
||||
|
||||
await core.group(`GitHub Actions runtime token access controls`, async () => {
|
||||
const actionsRuntimeToken = process.env['ACTIONS_RUNTIME_TOKEN'];
|
||||
if (actionsRuntimeToken) {
|
||||
core.info(JSON.stringify(JSON.parse(github.parseRuntimeToken(actionsRuntimeToken).ac as string), undefined, 2));
|
||||
} else {
|
||||
core.info(`ACTIONS_RUNTIME_TOKEN not set`);
|
||||
}
|
||||
});
|
||||
|
||||
await core.group(`Docker info`, async () => {
|
||||
try {
|
||||
await Docker.printVersion();
|
||||
await Docker.printInfo();
|
||||
} catch (e) {
|
||||
core.info(e.message);
|
||||
}
|
||||
core.startGroup(`Docker info`);
|
||||
if (standalone) {
|
||||
core.info(`Docker info skipped in standalone mode`);
|
||||
} else {
|
||||
await exec.exec('docker', ['version'], {
|
||||
failOnStdErr: false
|
||||
});
|
||||
|
||||
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');
|
||||
}
|
||||
await exec.exec('docker', ['info'], {
|
||||
failOnStdErr: false
|
||||
});
|
||||
}
|
||||
core.endGroup();
|
||||
|
||||
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.`);
|
||||
return;
|
||||
}
|
||||
stateHelper.setTmpDir(context.tmpDir());
|
||||
|
||||
stateHelper.setTmpDir(Context.tmpDir());
|
||||
|
||||
const buildxVersion = await buildx.getVersion(standalone);
|
||||
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);
|
||||
core.info(JSON.stringify(builder, null, 2));
|
||||
});
|
||||
|
||||
const args: string[] = await context.getArgs(inputs, toolkit);
|
||||
core.debug(`context.getArgs: ${JSON.stringify(args)}`);
|
||||
|
||||
const buildCmd = await toolkit.buildx.getCommand(args);
|
||||
core.debug(`buildCmd.command: ${buildCmd.command}`);
|
||||
core.debug(`buildCmd.args: ${JSON.stringify(buildCmd.args)}`);
|
||||
|
||||
let err: Error | undefined;
|
||||
await Exec.getExecOutput(buildCmd.command, buildCmd.args, {
|
||||
ignoreReturnCode: true,
|
||||
env: Object.assign({}, process.env, {
|
||||
BUILDX_METADATA_WARNINGS: 'true'
|
||||
}) as {
|
||||
[key: string]: string;
|
||||
}
|
||||
}).then(res => {
|
||||
const args: string[] = await context.getArgs(inputs, defContext, buildxVersion, standalone);
|
||||
const buildCmd = buildx.getCommand(args, standalone);
|
||||
await exec
|
||||
.getExecOutput(buildCmd.command, buildCmd.args, {
|
||||
ignoreReturnCode: true
|
||||
})
|
||||
.then(res => {
|
||||
if (res.stderr.length > 0 && res.exitCode != 0) {
|
||||
err = Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
||||
throw new Error(`buildx failed with: ${res.stderr.match(/(.*)\s*$/)?.[0]?.trim() ?? 'unknown error'}`);
|
||||
}
|
||||
});
|
||||
|
||||
const imageID = toolkit.buildxBuild.resolveImageID();
|
||||
const metadata = toolkit.buildxBuild.resolveMetadata();
|
||||
const digest = toolkit.buildxBuild.resolveDigest(metadata);
|
||||
const imageID = await buildx.getImageID();
|
||||
const metadata = await buildx.getMetadata();
|
||||
const digest = await buildx.getDigest(metadata);
|
||||
|
||||
if (imageID) {
|
||||
await core.group(`ImageID`, async () => {
|
||||
core.info(imageID);
|
||||
|
@ -126,159 +81,25 @@ actionsToolkit.run(
|
|||
}
|
||||
if (metadata) {
|
||||
await core.group(`Metadata`, async () => {
|
||||
const metadatadt = JSON.stringify(metadata, null, 2);
|
||||
core.info(metadatadt);
|
||||
core.setOutput('metadata', metadatadt);
|
||||
core.info(metadata);
|
||||
core.setOutput('metadata', metadata);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
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 (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 (builder && builder.driver === 'cloud') {
|
||||
core.info('Build summary is not yet supported with Docker Build Cloud');
|
||||
} 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] : []
|
||||
});
|
||||
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.inputs
|
||||
});
|
||||
} catch (e) {
|
||||
core.warning(e.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
async function cleanup(): Promise<void> {
|
||||
if (stateHelper.tmpDir.length > 0) {
|
||||
await core.group(`Removing temp folder ${stateHelper.tmpDir}`, async () => {
|
||||
core.startGroup(`Removing temp folder ${stateHelper.tmpDir}`);
|
||||
fs.rmSync(stateHelper.tmpDir, {recursive: true});
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
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 {
|
||||
if (process.env.DOCKER_BUILD_RECORD_UPLOAD) {
|
||||
return Util.parseBool(process.env.DOCKER_BUILD_RECORD_UPLOAD);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function buildRecordRetentionDays(): number | undefined {
|
||||
let val: string | undefined;
|
||||
if (process.env.DOCKER_BUILD_EXPORT_RETENTION_DAYS) {
|
||||
core.warning('DOCKER_BUILD_EXPORT_RETENTION_DAYS is deprecated. Use DOCKER_BUILD_RECORD_RETENTION_DAYS instead.');
|
||||
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 Error(`Invalid build record retention days: ${val}`);
|
||||
}
|
||||
return res;
|
||||
core.endGroup();
|
||||
}
|
||||
}
|
||||
|
||||
if (!stateHelper.IsPost) {
|
||||
run();
|
||||
} else {
|
||||
cleanup();
|
||||
}
|
||||
|
|
|
@ -1,24 +1,12 @@
|
|||
import * as core from '@actions/core';
|
||||
|
||||
import {Inputs, sanitizeInputs} from './context';
|
||||
|
||||
export const IsPost = !!process.env['STATE_isPost'];
|
||||
export const tmpDir = process.env['STATE_tmpDir'] || '';
|
||||
export const inputs = process.env['STATE_inputs'] ? JSON.parse(process.env['STATE_inputs']) : undefined;
|
||||
export const buildRef = process.env['STATE_buildRef'] || '';
|
||||
export const isSummarySupported = !!process.env['STATE_isSummarySupported'];
|
||||
|
||||
export function setTmpDir(tmpDir: string) {
|
||||
core.saveState('tmpDir', tmpDir);
|
||||
}
|
||||
|
||||
export function setInputs(inputs: Inputs) {
|
||||
core.saveState('inputs', JSON.stringify(sanitizeInputs(inputs)));
|
||||
}
|
||||
|
||||
export function setBuildRef(buildRef: string) {
|
||||
core.saveState('buildRef', buildRef);
|
||||
}
|
||||
|
||||
export function setSummarySupported() {
|
||||
core.saveState('isSummarySupported', 'true');
|
||||
if (!IsPost) {
|
||||
core.saveState('isPost', 'true');
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM alpine
|
||||
RUN cat /etc/*release
|
|
@ -1,19 +1,16 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM golang:alpine AS base
|
||||
FROM golang:1.19-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 base as build
|
||||
COPY go.mod go.sum ./
|
||||
RUN go mod download -x
|
||||
COPY . .
|
||||
RUN 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
|
||||
FROM alpine:3.17 AS image
|
||||
COPY --from=build /usr/bin/app /bin/app
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["/bin/app"]
|
||||
|
|
|
@ -1,3 +1,19 @@
|
|||
module github.com/docker/build-push-action/test/go
|
||||
|
||||
go 1.18
|
||||
|
||||
require github.com/labstack/echo/v4 v4.9.1
|
||||
|
||||
require (
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/labstack/gommon v0.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.11 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 // indirect
|
||||
)
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+Y=
|
||||
github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo=
|
||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||
github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs=
|
||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4=
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
|
||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
@ -1,14 +1,31 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Hello, Go!")
|
||||
e := echo.New()
|
||||
|
||||
e.Use(middleware.Logger())
|
||||
e.Use(middleware.Recover())
|
||||
|
||||
e.GET("/", func(c echo.Context) error {
|
||||
return c.HTML(http.StatusOK, "Hello World")
|
||||
})
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
|
||||
e.GET("/ping", func(c echo.Context) error {
|
||||
return c.JSON(http.StatusOK, struct{ Status string }{Status: "OK"})
|
||||
})
|
||||
|
||||
httpPort := os.Getenv("HTTP_PORT")
|
||||
if httpPort == "" {
|
||||
httpPort = "8080"
|
||||
}
|
||||
|
||||
e.Logger.Fatal(e.Start(":" + httpPort))
|
||||
}
|
||||
|
|
|
@ -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,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,22 +1,19 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"esModuleInterop": true,
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"strict": true,
|
||||
"newLine": "lf",
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": false,
|
||||
"resolveJsonModule": true,
|
||||
"useUnknownInCatchVariables": false,
|
||||
},
|
||||
"exclude": [
|
||||
"./__mocks__/**/*",
|
||||
"./__tests__/**/*",
|
||||
"./lib/**/*",
|
||||
"node_modules",
|
||||
"**/*.test.ts",
|
||||
"jest.config.ts"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue