Build, Test, Push #28
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
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/solr | |
#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: "8.11" | |
- | |
arch: arm64 | |
version: "8.11" | |
- | |
arch: amd64 | |
version: "9.4" | |
- | |
arch: arm64 | |
version: "9.4" | |
- | |
arch: amd64 | |
version: "9.5" | |
- | |
arch: arm64 | |
version: "9.5" | |
env: | |
ARCH: ${{ matrix.arch }} | |
VERSION_PREFIX: "" | |
VERSION: ${{ matrix.version }} | |
UPSTREAM_IMAGE: solr:${{ matrix.version }}-slim | |
BUILD_DIR: "." | |
SOLR_DEFAULT_CONFIG_SET: "search_api_solr_4.3.3" | |
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 }} | |
- | |
name: Build Configset | |
run: VERSION=${{ env.VERSION }} scripts/prepare_configsets.sh | |
- | |
# 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: | | |
FROM=${{ env.UPSTREAM_IMAGE }} | |
VERSION=${{ env.VERSION }} | |
SOLR_DEFAULT_CONFIG_SET=${{ env.SOLR_DEFAULT_CONFIG_SET }} | |
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: | |
- | |
arch: amd64 | |
version: "8.11" | |
- | |
arch: amd64 | |
version: "9.4" | |
- | |
arch: amd64 | |
version: "9.5" | |
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} | |
- | |
# Switch docker context to a remote arm64 host | |
# Used for building heavy images that take too long to build using QEMU + for native arm64 testing. | |
name: Switch to arm64 builder host | |
if: ${{ env.ARCH == 'arm64' }} | |
uses: arwynfr/actions-docker-context@v2 | |
with: | |
docker_host: "ssh://ubuntu@${{ secrets.ARM64_HOST }}" | |
context_name: arm64-host | |
ssh_key: "${{ secrets.ARM64_HOST_SSH_KEY }}" | |
ssh_cert: "${{ env.ARM64_HOST_SSH_CERT }}" | |
use_context: true | |
- | |
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: | |
- "8.11" | |
- "9.4" | |
- "9.5" | |
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} | |
# 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} | |
- | |
# 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" |