Skip to content

Build, Test, Push

Build, Test, Push #59

Workflow file for this run

name: Build, Test, Push
on:
schedule:
- cron: "0 10 * * 0" # Every Sunday at 10AM
push:
branches:
- master
- develop
- feature/*
tags:
- "v*.*.*"
workflow_dispatch: # Allow manually triggering a build
defaults:
run:
shell: bash
env:
IMAGE: docksal/mariadb
LATEST_VERSION: "10.11"
#DOCKSAL_VERSION: develop
jobs:
build:
name: "Build: ${{ matrix.version }}/${{ matrix.arch }}"
runs-on: ubuntu-22.04
strategy:
fail-fast: false # Don't cancel other jobs if one fails
matrix:
include:
-
arch: amd64
version: "10.4"
-
arch: arm64
version: "10.4"
-
arch: amd64
version: "10.5"
-
arch: arm64
version: "10.5"
-
arch: amd64
version: "10.6"
-
arch: arm64
version: "10.6"
-
arch: amd64
version: "10.11"
-
arch: arm64
version: "10.11"
env:
ARCH: ${{ matrix.arch }}
VERSION_PREFIX: ""
VERSION: ${{ matrix.version }}
UPSTREAM_IMAGE: mariadb:${{ matrix.version }}
BUILD_DIR: "."
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Environment variables
run: |
# Export variables for further steps
echo GIT_SHA7="${GITHUB_SHA:0:7}" | tee -a ${GITHUB_ENV}
echo BUILD_IMAGE_TAG="${IMAGE}:${VERSION_PREFIX}${VERSION}-build" | tee -a ${GITHUB_ENV}
# Pull the host public SSH key at runtime instead of relying on a static value stored in secrets.
echo ARM64_HOST_SSH_CERT="$(ssh-keyscan -t rsa ${{ secrets.ARM64_HOST }} 2>/dev/null)" | tee -a ${GITHUB_ENV}
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Check Docker
run: |
docker version
docker info
-
name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
# Build and cache image in the registry
name: Build image
uses: docker/build-push-action@v5
with:
context: ${{ env.BUILD_DIR }}
file: ${{ env.BUILD_DIR }}/Dockerfile
build-args: |
UPSTREAM_IMAGE=${{ env.UPSTREAM_IMAGE }}
VERSION=${{ env.VERSION }}
platforms: linux/${{ env.ARCH }}
# Push intermediate arch-specific build tag to repo
tags: ${{ env.BUILD_IMAGE_TAG }}-${{ env.GIT_SHA7 }}-${{ env.ARCH }}
push: ${{ github.event_name != 'pull_request' }} # Don't push for PRs
# Disable automatic image attestations
# With image attestations enabled, the image tag pushed to the registry is a manifest list.
# That makes it impossible to stitch different platform images together in a manifest list, since you
# cannot have a manifest list of manifest lists.
# See https://docs.docker.com/build/attestations/attestation-storage/
# TODO: Refactor to allow for image attestations
provenance: false
sbom: false
# BUILD_IMAGE_TAG - persistent multi-arch tag, updated at the end of the build (success or failure)
# Use registry cache with max mode to cahce all image layers in the registry
cache-from: type=registry,ref=${{ env.BUILD_IMAGE_TAG }}-cache-${{ env.ARCH }}
cache-to: type=registry,ref=${{ env.BUILD_IMAGE_TAG }}-cache-${{ env.ARCH }},mode=max
test:
name: "Test: ${{ matrix.version }}/${{ matrix.arch }}"
runs-on: ubuntu-22.04
needs: build
strategy:
fail-fast: false # Don't cancel other jobs if one fails
matrix:
include:
# Disabled arm64 tests.
# TODO: Refactor tests to be compatible with a remote host test runner.
# TODO: Remember to re-enabled the test results check in "push".
-
arch: amd64
version: "10.4"
# -
# arch: arm64
# version: "10.4"
-
arch: amd64
version: "10.5"
# -
# arch: arm64
# version: "10.5"
-
arch: amd64
version: "10.6"
# -
# arch: arm64
# version: "10.6"
-
arch: amd64
version: "10.11"
# -
# arch: arm64
# version: "10.11"
env:
ARCH: ${{ matrix.arch }}
VERSION_PREFIX: ""
VERSION: ${{ matrix.version }}
steps:
-
name: Setup Bats
uses: bats-core/[email protected]
-
name: Checkout
uses: actions/checkout@v4
-
name: Environment variables
run: |
# Export variables for further steps
echo GIT_SHA7="${GITHUB_SHA:0:7}" | tee -a ${GITHUB_ENV}
echo BUILD_IMAGE_TAG="${IMAGE}:${VERSION_PREFIX}${VERSION}-build" | tee -a ${GITHUB_ENV}
# Pull the host public SSH key at runtime instead of relying on a static value stored in secrets.
echo ARM64_HOST_SSH_CERT="$(ssh-keyscan -t rsa ${{ secrets.ARM64_HOST }} 2>/dev/null)" | tee -a ${GITHUB_ENV}
-
name: Check Docker
run: |
docker version
docker info
-
# Run tests
name: Test
id: tests
working-directory: ${{ env.BUILD_DIR }}
env:
BUILD_IMAGE_TAG: ${{ env.BUILD_IMAGE_TAG }}-${{ env.GIT_SHA7 }}-${{ env.ARCH }}
VERSION: ${{ env.VERSION }}
run: |
make test
([[ $? == 0 ]] && echo "pass" || echo "fail") | tee ${{ github.workspace }}/test-results-${VERSION_PREFIX}${VERSION}-${ARCH}.txt
# Store tests results as an artifact (used by downstream jobs)
# Note: Cannot use "::set-output name=var_name::var_value" as var_name would need to be dynamic here.
# Dynamic variable names cannot be used when mapping step outputs to job outputs.
# Step outputs cannot be accessed directly from other jobs. Dead end.
- name: Store test results
uses: actions/upload-artifact@v4
with:
name: test-results-${{ env.GIT_SHA7 }}-${{ env.VERSION_PREFIX }}${{ env.VERSION }}-${{ env.ARCH }}
path: ${{ github.workspace }}/test-results-*.txt
if-no-files-found: error
overwrite: true
push:
name: "Push: ${{ matrix.version }}/multi"
runs-on: ubuntu-22.04
# Wait for test to either succeed or fail
needs: test
if: always()
strategy:
matrix:
version:
- "10.4"
- "10.5"
- "10.6"
- "10.11"
env:
VERSION_PREFIX: ""
VERSION: ${{ matrix.version }}
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Environment variables
run: |
# Export variables for further steps
echo GIT_SHA7="${GITHUB_SHA:0:7}" | tee -a ${GITHUB_ENV}
echo BUILD_IMAGE_TAG="${IMAGE}:${VERSION_PREFIX}${VERSION}-build" | tee -a ${GITHUB_ENV}
-
# Login to Docker Hub
name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Retrieve test results
uses: actions/download-artifact@v4
with:
pattern: test-results-${{ env.GIT_SHA7 }}-*
merge-multiple: true
-
# Generate persistent tags (edge, stable, release)
name: Docker image tags
id: docker_tags
# Don't push broken builds to persistent tags (both amd64 and arm64 tests must pass)
# TODO: re-enable the arm64 test results check once those tests are re-enabled
run: |
amd64_tests=$(cat test-results-${VERSION_PREFIX}${VERSION}-amd64.txt)
#arm64_tests=$(cat test-results-${VERSION_PREFIX}${VERSION}-arm64.txt)
# && [[ "${arm64_tests}" == "pass" ]]
if [[ "${amd64_tests}" == "pass" ]]; then
.github/scripts/docker-tags.sh
fi
-
# Create and push multi-arch image manifests
name: Push multi-arch images
env:
# build tags are always pushed (build caching, debugging needs)
# edge, stage, release are only pushed if tests were successful (see docker_tags step)
TAGS: |
${{ env.BUILD_IMAGE_TAG }}
${{ steps.docker_tags.outputs.tags }}
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} # Needed for docker-tag-delete.sh
DOCKERHUB_PASSWORD: ${{ secrets.DOCKERHUB_PASSWORD }} # Needed for docker-tag-delete.sh
run: |
set -xeuo pipefail
IFS="${IFS}," # Also split strings by comma (in case list of tag is comma-separated)
for tag in ${TAGS}; do
if [[ "${tag}" == "" ]]; then continue; fi
docker manifest create --amend ${tag} \
${{ env.BUILD_IMAGE_TAG }}-${{ env.GIT_SHA7 }}-amd64 \
${{ env.BUILD_IMAGE_TAG }}-${{ env.GIT_SHA7 }}-arm64
docker manifest inspect ${tag}
docker manifest push ${tag}
done
# Clean up intermediate arch-specific image tags (DockerHub only)
.github/scripts/docker-tag-delete.sh "${{ env.BUILD_IMAGE_TAG }}-${{ env.GIT_SHA7 }}-amd64"
.github/scripts/docker-tag-delete.sh "${{ env.BUILD_IMAGE_TAG }}-${{ env.GIT_SHA7 }}-arm64"