Skip to content

use job matrix to split build jobs #233

use job matrix to split build jobs

use job matrix to split build jobs #233

Workflow file for this run

---
# 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}}