Skip to content

Feat: Allows multi platform builds for both linux/amd64 & linux/arm64 #1486

Feat: Allows multi platform builds for both linux/amd64 & linux/arm64

Feat: Allows multi platform builds for both linux/amd64 & linux/arm64 #1486

name: Build and Publish Docker Image
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on:
schedule:
- cron: '0 10 * * *'
# If any commit message in your push or the HEAD commit of your PR contains the strings
# [skip ci], [ci skip], [no ci], [skip actions], or [actions skip]
# workflows triggered on the push or pull_request events will be skipped.
# https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/
push:
branches: [ master ]
# Publish semver tags as releases.
tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ]
# If any commit message in your push or the HEAD commit of your PR contains the strings
# [skip ci], [ci skip], [no ci], [skip actions], or [actions skip]
# workflows triggered on the push or pull_request events will be skipped.
# https://github.blog/changelog/2021-02-08-github-actions-skip-pull-request-and-push-workflows-with-skip-ci/
pull_request:
branches: [ master ]
env:
# https://hub.docker.com/r/athenz/authorization-proxy/tags
DOCKER_REGISTRY_URL: docker.io
DOCKER_REGISTRY_ORG: athenz
DOCKER_REGISTRY_IMAGE: authorization-proxy
# DOCKER_REGISTRY_USER: values for docker login is stored in repository variables
# DOCKER_REGISTRY_TOKEN_NAME: values for docker login is stored in repository variables
TAGS_CONFIG: |
# If branch is master, main or default branch, push the latest tag image:
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'master') }}
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
# If the event is a tag release following the semver regex, push the latest tag image:
# Semver official regex: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
type=match,value=latest,group=0,pattern=^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$
# If it is PR version, push the pr-<pr-number> tag image:
type=ref,event=pr
type=semver,pattern=v{{version}}
# Any cron builds (scheduled workflows) push the nightly tag image:
type=schedule,pattern=nightly
jobs:
set_matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set.outputs.matrix }}
suffixes: ${{ steps.set.outputs.suffixes }}
steps:
- id: set
run: |
# We define BUILD_MATRIX so that we have multiple platform supported,
# maybe Windows as well in the future:
MATRIX_JSON='{
"include": [
{ "platform": "linux/amd64", "runner": "ubuntu-latest", "suffix": "-amd64" },
{ "platform": "linux/arm64", "runner": "ubuntu-24.04-arm", "suffix": "-arm64" }
]
}'
# Store JSON data:
echo "matrix=$(echo "$MATRIX_JSON" | jq -c .)" >> $GITHUB_OUTPUT
# Store Suffix list:
echo "suffixes=$(echo "$MATRIX_JSON" | jq -r '.include[].suffix' | xargs)" >> $GITHUB_OUTPUT
build:
needs: set_matrix
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.set_matrix.outputs.matrix) }}
permissions:
actions: none
checks: none
contents: read
deployments: none
issues: none
discussions: none
packages: none
pull-requests: none
repository-projects: none
security-events: none
statuses: none
steps:
# A GitHub Action to expose useful environment variables.
# https://github.com/FranzDiebold/github-env-vars-action
-
name: GitHub Environment Variables Action
id: env
# uses: https://github.com/FranzDiebold/github-env-vars-action/tags
uses: FranzDiebold/github-env-vars-action@v2
# This action checks-out your repository under $GITHUB_WORKSPACE, so your workflow can access it.
# https://github.com/actions/checkout
-
name: Checkout repository
id: checkout
# You may pin to the exact commit or the version.
# uses: https://github.com/actions/checkout/tags
uses: actions/checkout@v4
# This action sets up a go environment for use in actions by:
# - Optionally downloading and caching a version of Go by version and adding to PATH.
# - Registering problem matchers for error output.
# https://github.com/actions/setup-go
-
name: Setup Golang
id: setup-go
# You may pin to the exact commit or the version.
# uses: https://github.com/actions/setup-go/tags
uses: actions/setup-go@v4
with:
# Fix the following warning: Both go-version and go-version-file inputs are specified, only go-version will be used
go-version: "stable"
# go-version-file: './go.mod'
cache: true
# A GitHub Action for golang tests
-
name: Golang Tests
id: go-tests
run: |
go version
rm -rf example
go test -v -race -covermode=atomic -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
# https://github.com/apache/skywalking-eyes
# issue: go version hard-coded: https://github.com/apache/skywalking-eyes/blob/5dfa68f93380a5e57259faaf95088b7f133b5778/header/action.yml#L47-L51
- name: Check License Header
if: matrix.platform == 'linux/amd64' # Only required once for any platform, and will do the most general amd64
uses: apache/skywalking-eyes/header@main
with:
log: "info" # optional: set the log level. The default value is `info`.
config: ".licenserc.yaml" # optional: set the config file. The default value is `.licenserc.yaml`.
token: "" # optional: the token that license eye uses when it needs to comment on the pull request. Set to empty ("") to disable commenting on pull request. The default value is ${{ github.token }}
mode: "check" # optional: Which mode License-Eye should be run in. Choices are `check` or `fix`. The default value is `check`.
# The Github action runs CIS Dockerfile benchmark against dockerfiles in repository (CIS 4.1, 4.2, 4.3, 4.6, 4.7, 4.9, 4.10)
# https://github.com/sysdiglabs/benchmark-dockerfile
-
name: Sysdig Benchmark Dockerfile
id: sysdig
if: matrix.platform == 'linux/amd64' # Only required once for any platform, and will do the most general amd64
# You may pin to the exact commit or the version.
# uses: https://github.com/sysdiglabs/benchmark-dockerfile/tags
uses: sysdiglabs/benchmark-dockerfile@v1.0.0
with:
# Directory of dockerfiles (default "./")
directory: "./"
# list of disallowed packages separated by comma (default ")
#disallowedPackages: ''
# list of trusted base images separated by comma (default "", meaning trust any base image)
trustedBaseImages: ""
# The Github action runs CIS Dockerfile benchmark against dockerfiles in repository (CIS 4.1, 4.2, 4.3, 4.6, 4.7, 4.9, 4.10)
# https://github.com/sysdiglabs/benchmark-dockerfile
# TODO: Skipping CIS 4.1 check until https://github.com/yahoojapan/authorization-proxy/pull/95 is fixed.
-
name: Post Sysdig Benchmark Dockerfile
id: postsysdig
if: matrix.platform == 'linux/amd64' # Only required once for any platform, and will do the most general amd64
run: |
echo ${{ toJSON(steps.sysdig.outputs.violation_report) }} | \
jq -r .
echo ${{ toJSON(steps.sysdig.outputs.violation_report) }} | \
jq -r '.cis_docker_benchmark_violation_report[] | select(.rule!="CIS 4.1 Create a user for the container") | .violations[]' | \
wc -l | \
xargs -I% test 0 -eq %
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
-
name: Extract Docker metadata
id: meta
# You may pin to the exact commit or the version.
# uses: https://github.com/docker/metadata-action/tags
uses: docker/metadata-action@v5
with:
images: ${{ env.DOCKER_REGISTRY_URL }}/${{ env.DOCKER_REGISTRY_ORG }}/${{ env.DOCKER_REGISTRY_IMAGE }}
# for latest tag
# latest=auto for tagging latest only for "master" branch
flavor: |
latest=false # we want to make sure we only push latest tag from conditions defined ourselves
suffix=${{ matrix.suffix }} # make sure that every platform has its own suffix (we will merge them in later phase)
# eg. refs/heads/master
# eg. refs/pull/318/merge
# shorthand for {{major}}.{{minor}}.{{patch}} (can include pre-release)
tags: ${{ env.TAGS_CONFIG }}
# GitHub Action to login against a Docker registry.
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
-
name: Docker Login to registry ${{ env.DOCKER_REGISTRY_URL }}
id: login
# You may pin to the exact commit or the version.
# uses: https://github.com/docker/login-action/tags
uses: docker/login-action@v3
with:
# Server address of Docker registry. If not set then will default to Docker Hub
registry: ${{ env.DOCKER_REGISTRY_URL }} # optional
# Username used to log against the Docker registry
username: ${{ vars.DOCKER_REGISTRY_USER }} # optional
# Password or personal access token used to log against the Docker registry
password: ${{ secrets[vars.DOCKER_REGISTRY_TOKEN_NAME] }} # optional
# Log out from the Docker registry at the end of a job
logout: true # optional, default is true
# GitHub Action to install QEMU static binaries.
# https://github.com/docker/setup-qemu-action
-
name: Set up QEMU
id: qemu
# You may pin to the exact commit or the version.
# uses: https://github.com/docker/setup-qemu-action/tags
uses: docker/setup-qemu-action@v3
# GitHub Action to set up Docker Buildx.
# https://github.com/docker/setup-buildx-action
-
name: Set up Docker Buildx
id: buildx
# You may pin to the exact commit or the version.
# uses: https://github.com/docker/setup-buildx-action/tags
uses: docker/setup-buildx-action@v3
# Build and push Docker image with Buildx
# https://github.com/docker/build-push-action
-
name: Build and push Docker image
id: build_and_push
# You may pin to the exact commit or the version.
# uses: https://github.com/docker/build-push-action/tags
# TODO: Migrate me to v6!
uses: docker/build-push-action@v4
with:
context: .
# We will push images in the job "merge" section. All we need to do
push: false
load: true
tags: ${{ steps.meta.outputs.tags }} # tags defined here will have its platform suffix
# tags: ${{ env.DOCKER_REGISTRY_URL }}/${{ env.DOCKER_REGISTRY_ORG }}/${{ env.DOCKER_REGISTRY_IMAGE }}:nightly
labels: ${{ steps.meta.outputs.labels }}
platforms: ${{ matrix.platform }}
build-args: |
APP_VERSION=${{ steps.meta.outputs.version }}
# Test Docker image
-
name: Test Docker image
id: test_docker
run: |
docker run --rm ${{ fromJSON(steps.meta.outputs.json).tags[0] }} --version
merge:
needs:
- set_matrix
- build # Make sure each build of every platform defined in matrix is completed
runs-on: ubuntu-latest
steps:
- uses: docker/login-action@v3
with:
# Server address of Docker registry. If not set then will default to Docker Hub
registry: ${{ env.DOCKER_REGISTRY_URL }} # optional
# Username used to log against the Docker registry
username: ${{ vars.DOCKER_REGISTRY_USER }} # optional
# Password or personal access token used to log against the Docker registry
password: ${{ secrets[vars.DOCKER_REGISTRY_TOKEN_NAME] }} # optional
# Log out from the Docker registry at the end of a job
logout: true # optional, default is true
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.DOCKER_REGISTRY_URL }}/${{ env.DOCKER_REGISTRY_ORG }}/${{ env.DOCKER_REGISTRY_IMAGE }}
flavor: |
latest=false
# No suffix defined as this will be the merged one!
tags: ${{ env.TAGS_CONFIG }}
- name: Create Manifest List
env:
PLATFORM_SUFFIXES: ${{ needs.set_matrix.outputs.suffixes }}
run: |
# i.e) PLATFORM_SUFFIXES=["-amd64", "-arm64"]
echo "Target Suffixes: $PLATFORM_SUFFIXES"
# Handle all tags required:
echo "${{ steps.meta.outputs.tags }}" | while read -r tag; do
echo "Merging manifest for tag: $tag"
# List sources to merge as one tag:
sources=""
for suffix in $PLATFORM_SUFFIXES; do
sources="$sources ${tag}${suffix}"
done
# Finally merge:
docker buildx imagetools create -t "$tag" $sources
done