use job matrix to split build jobs #233
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json | |
name: ci | |
on: | |
push: | |
paths: | |
- '**/Dockerfile' | |
- '**/toolsets/*.json' | |
- '**/.github/workflows/ci.yml' | |
- '**/docker-bake.hcl' | |
pull_request: | |
branches: [main] | |
workflow_dispatch: | |
permissions: | |
contents: read | |
packages: write | |
pull-requests: write | |
env: | |
REGISTRY: ${{ vars.DOCKERHUB_USER && 'docker.io' || 'ghcr.io' }} | |
REGISTRY_USER: ${{ vars.DOCKERHUB_USER || github.repository_owner }} | |
SHA: ${{ github.event.pull_request.head.sha || github.event.after || github.sha }} | |
BUILDKIT_PROGRESS: plain | |
jobs: | |
test: | |
runs-on: ubuntu-latest | |
env: | |
REGISTRY: ${{ vars.DOCKERHUB_USER && 'docker.io' || 'ghcr.io' }} | |
outputs: | |
platforms: ${{ steps.platforms.outputs.matrix }} | |
targets: ${{ steps.targets.outputs.matrix }} | |
steps: | |
# kics-scan ignore-line | |
- uses: actions/checkout@v4 | |
# kics-scan ignore-line | |
- uses: docker/[email protected] | |
name: Set up QEMU | |
- name: Set up Docker Buildx | |
# kics-scan ignore-line | |
uses: docker/[email protected] | |
- name: get docker binary path | |
id: docker-binary-path | |
run: echo "DOCKER_BINARY_PATH=$(which docker)" >> "$GITHUB_OUTPUT" | |
- name: bake-file with empty env | |
id: bake-file-no-env | |
run: env -i ${{ steps.docker-binary-path.outputs.DOCKER_BINARY_PATH }} buildx bake --print | |
- name: verify tag ends on -local | |
run: | | |
BAKE_TAG="$(env -i ${{ steps.docker-binary-path.outputs.DOCKER_BINARY_PATH }} buildx bake --print | jq -r '[.target[].tags[]][0]')" | |
[[ "${BAKE_TAG}" == *"-local" ]] || exit 1 | |
# - name: bake-file with test ref | |
# id: bake-file-test-tag | |
# run: printf "BAKE_OUTPUT=%s\n" "$(env -i ${{ steps.docker-binary-path.outputs.DOCKER_BINARY_PATH }} buildx bake --print | jq -c)" >> "$GITHUB_OUTPUT" | |
# env: | |
# GITHUB_BASE_REF: 'test' | |
# - name: verify tag ends on -test | |
# run: | | |
# BAKE_TAG="$(echo '${{ steps.bake-file-test-tag.outputs.BAKE_OUTPUT }}' | jq -r '[.target[].tags[]][0]')" | |
# [[ "${BAKE_TAG}" == *"-test" ]] || exit 1 | |
- name: bake-file | |
run: docker buildx bake --print | |
env: | |
GITHUB_SHA: ${{ env.SHA }} | |
- name: validate tag | |
run: | | |
BAKE_TAG="$(docker buildx bake --print | jq -r '[.target[].tags[]][0]')" | |
[[ "${BAKE_TAG}" == *"-${{ github.ref_name}}" ]] || exit 1 | |
- name: Create platform matrix | |
id: platforms | |
run: printf "matrix=%s\n" "$(docker buildx bake linux-platforms --print | jq -cr '.target."linux-platforms".platforms')" >>"${GITHUB_OUTPUT}" | |
- name: Show platforms | |
run: echo '${{ steps.platforms.outputs.matrix }}' | jq | |
- name: Create target matrix | |
id: targets | |
run: printf "matrix=%s\n" "$(docker buildx bake --print | jq -cr ".group.ubuntu.targets")" >>"${GITHUB_OUTPUT}" | |
- name: Show targets | |
run: echo '${{ steps.targets.outputs.matrix }}' | jq | |
build: | |
needs: test | |
runs-on: ubuntu-latest | |
strategy: | |
matrix: | |
platforms: ${{ fromJson(needs.test.outputs.platforms) }} | |
targets: ${{ fromJson(needs.test.outputs.targets) }} | |
steps: | |
- uses: actions/checkout@v4 | |
# - name: Free up disk space | |
# # kics-scan ignore-line | |
# uses: ./.github/actions/free-space | |
# with: | |
# deleteDotnet: 'true' | |
# deleteAndroid: 'true' | |
# kics-scan ignore-line | |
- uses: docker/[email protected] | |
name: Set up QEMU | |
# kics-scan ignore-line | |
- uses: docker/[email protected] | |
name: Set up Docker Buildx | |
# with: | |
# buildkitd-flags: "--debug" | |
# # driver: ${{ github.event_name == 'pull_request' && 'docker' || 'docker-container' }} | |
# # driver: docker-container | |
# # driver-opts: image=moby/buildkit:v0.12.2 | |
# Login against a container registry | |
# https://github.com/docker/login-action | |
# kics-scan ignore-line | |
- uses: docker/[email protected] | |
name: Login to ${{ env.REGISTRY }} | |
with: | |
registry: ${{ env.REGISTRY }} | |
username: ${{ vars.DOCKERHUB_USER || github.repository_owner }} | |
password: ${{ secrets.DOCKERHUB_TOKEN || secrets.GITHUB_TOKEN }} | |
logout: true | |
# Get the distro version to use for the cache tag | |
- name: get distro version | |
id: get_version | |
run: | | |
distro_version="${{ matrix.targets }}" | |
echo "distro_version=${distro_version/ubuntu-act-/}" >> "$GITHUB_OUTPUT" | |
# Get the architecture to use for the cache tag | |
- name: get arch | |
id: cache-arch | |
run: >- | |
printf "cache_arch=%s\n" "$( | |
docker run | |
--quiet | |
--platform ${{ matrix.platforms }} | |
--rm | |
"${PULL_IMAGE}" | |
/bin/bash -c "dpkg --print-architecture" | |
)" >> "$GITHUB_OUTPUT" | |
env: | |
PULL_IMAGE: ubuntu:${{ steps.get_version.outputs.distro_version }} | |
# Bake the image | |
# kics-scan ignore-line | |
- uses: docker/[email protected] | |
name: Build and Push | |
id: bake | |
with: | |
files: docker-bake.hcl | |
targets: ${{ matrix.targets }} | |
set: | | |
*.tags= | |
*.platform=${{ matrix.platforms }} | |
*.cache-from=type=registry,ref=${{ env.REGISTRY_IMAGE }}:cache-${{ steps.get_version.outputs.distro_version }}-${{ steps.cache-arch.outputs.cache_arch }} | |
*.cache-to=type=registry,ref=${{ env.REGISTRY_IMAGE }}:cache-${{ steps.get_version.outputs.distro_version }}-${{ steps.cache-arch.outputs.cache_arch }},mode=max | |
*.output=type=image,"name=${{ env.REGISTRY_IMAGE }}",push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }} | |
env: | |
REGISTRY_IMAGE: ${{ format('{0}/{1}/ubuntu-act', env.REGISTRY, env.REGISTRY_USER) }} | |
TARGET_PLATFORM_PAIR: ${{ format('{0}-{1}', matrix.targets, steps.cache-arch.outputs.cache_arch) }} | |
- name: Export digest | |
run: | | |
mkdir -p /tmp/digests/${{ matrix.targets }} | |
digest="$(echo '${{ steps.bake.outputs.metadata }}' | jq -r '."${{ matrix.targets }}"["containerimage.digest"]')" | |
touch "/tmp/digests/${{ matrix.targets }}/${digest#sha256:}" | |
- name: Upload digest | |
uses: actions/upload-artifact@v3 | |
with: | |
name: digests | |
path: /tmp/digests/${{ matrix.targets }}/* | |
if-no-files-found: error | |
retention-days: 1 | |
# # vulnerability scanning to verify PRs | |
# - name: Docker Scout | |
# id: docker-scout | |
# uses: docker/[email protected] | |
# if: github.event_name == 'pull_request' | |
# with: | |
# platform: ${{ matrix.platforms }} | |
# command: quickview | |
# image: ${{ env.FROM_IMAGE_PATH }} | |
# type: archive | |
# to: ${{ env.TO_TAG }} | |
# ignore-unchanged: true | |
# only-severities: critical | |
# write-comment: ${{ github.actor != 'nektos/act' }} | |
# summary: ${{ github.actor != 'nektos/act' }} | |
# github-token: ${{ secrets.GITHUB_TOKEN }} | |
# organization: ${{ vars.DOCKERHUB_USER || github.repository_owner }} | |
merge: | |
runs-on: ubuntu-latest | |
if: github.event_name != 'pull_request' | |
strategy: | |
matrix: | |
targets: ${{ fromJson(needs.test.outputs.targets) }} | |
needs: | |
- test | |
- build | |
steps: | |
# - name: Download meta bake definition | |
# uses: actions/download-artifact@v3 | |
# with: | |
# name: bake-meta | |
# path: /tmp | |
- uses: actions/checkout@v4 | |
- name: Download digests | |
uses: actions/download-artifact@v3 | |
with: | |
name: digests | |
path: /tmp/digests/${{ matrix.targets }} | |
- name: Set up Docker Buildx | |
# kics-scan ignore-line | |
uses: docker/[email protected] | |
# with: | |
# driver: ${{ github.event_name == 'pull_request' && 'docker' || 'docker-container' }} | |
# driver: docker-container | |
# driver-opts: image=moby/buildkit:v0.12.2 | |
# install: true | |
# use: true | |
# cleanup: true | |
# Login against a container registry | |
# https://github.com/docker/login-action | |
# kics-scan ignore-line | |
- uses: docker/[email protected] | |
name: Login to ${{ env.REGISTRY }} | |
with: | |
registry: ${{ env.REGISTRY }} | |
username: ${{ vars.DOCKERHUB_USER || github.repository_owner }} | |
password: ${{ secrets.DOCKERHUB_TOKEN || secrets.GITHUB_TOKEN }} | |
logout: true | |
- name: bake metadata | |
id: bake-meta | |
run: docker buildx bake ${{ matrix.targets }} --print > /tmp/${{ matrix.targets }}.json | |
- name: Create manifest list and push | |
working-directory: /tmp/digests/${{ matrix.targets }} | |
run: | | |
docker buildx imagetools create \ | |
$(jq -cr '.target[].tags | map(select(startswith("${{ env.REGISTRY}}")) | "-t " + .) | join(" ")' </tmp/${{ matrix.targets }}.json) \ | |
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *) | |
env: | |
REGISTRY_IMAGE: ${{ format('{0}/{1}/ubuntu-act', env.REGISTRY, env.REGISTRY_USER) }} | |
- name: Inspect image | |
run: docker buildx imagetools inspect "$(jq -r '.target."${{ matrix.targets }}".tags[0]' < /tmp/${{ matrix.targets }}.json)" | |
approve-pr: | |
name: Approve PR | |
runs-on: ubuntu-latest | |
needs: [build] | |
if: github.actor != 'nektos/act' && contains(fromJson('["mauwii","dependabot[bot]"]'), github.triggering_actor) && github.event_name == 'pull_request' && needs.build.result == 'success' | |
permissions: | |
contents: read | |
pull-requests: write | |
actions: write | |
steps: | |
# approve the PR (there is still a code-owner review necessary) | |
- name: Approve PR | |
run: gh pr review --approve "$PR_URL" | |
env: | |
PR_URL: ${{github.event.pull_request.html_url}} | |
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} | |
# auto merge dependabot PRs | |
- name: Merge DependaBot | |
if: github.actor == 'dependabot[bot]' && needs.build.result == 'success' | |
run: gh pr merge --auto --merge "$PR_URL" | |
env: | |
PR_URL: ${{github.event.pull_request.html_url}} | |
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} |