build multi-arch images #1051
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
--- | |
# Please see contrib/<reponame>image/README.md for details on the intentions | |
# of this workflow. | |
# | |
# BIG FAT WARNING: This workflow is duplicated across containers/skopeo, | |
# containers/buildah, and containers/podman. ANY AND | |
# ALL CHANGES MADE HERE MUST BE MANUALLY DUPLICATED | |
# TO THE OTHER REPOS. | |
name: build multi-arch images | |
on: | |
# Upstream tends to be very active, with many merges per day. | |
# Only run this daily via cron schedule, or manually, not by branch push. | |
schedule: | |
- cron: '0 8 * * *' | |
# allows to run this workflow manually from the Actions tab | |
workflow_dispatch: | |
permissions: | |
contents: read | |
jobs: | |
multi: | |
name: multi-arch image build | |
env: | |
REPONAME: buildah # No easy way to parse this out of $GITHUB_REPOSITORY | |
# Server/namespace value used to format FQIN | |
REPONAME_QUAY_REGISTRY: quay.io/buildah | |
CONTAINERS_QUAY_REGISTRY: quay.io/containers | |
# list of architectures for build | |
PLATFORMS: linux/amd64,linux/s390x,linux/ppc64le,linux/arm64 | |
# Command to execute in container to obtain project version number | |
VERSION_CMD: "buildah --version" | |
# build several images (upstream, testing, stable) in parallel | |
strategy: | |
# By default, failure of one matrix item cancels all others | |
fail-fast: false | |
matrix: | |
# Builds are located under contrib/<reponame>image/<source> directory | |
source: | |
- upstream | |
- testing | |
- stable | |
runs-on: ubuntu-latest | |
# internal registry caches build for inspection before push | |
services: | |
registry: | |
image: quay.io/libpod/registry:2 | |
ports: | |
- 5000:5000 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v2 | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@27d0a4f181a40b142cce983c5393082c365d1480 # v1 | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@94ab11c41e45d028884a99163086648e898eed25 # v1 | |
with: | |
driver-opts: network=host | |
install: true | |
- name: Build and locally push image | |
uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a # v2 | |
with: | |
context: contrib/${{ env.REPONAME }}image/${{ matrix.source }} | |
file: ./contrib/${{ env.REPONAME }}image/${{ matrix.source }}/Dockerfile | |
platforms: ${{ env.PLATFORMS }} | |
push: true | |
tags: localhost:5000/${{ env.REPONAME }}/${{ matrix.source }} | |
# Simple verification that stable images work, and | |
# also grab version number use in forming the FQIN. | |
- name: amd64 container sniff test | |
if: matrix.source == 'stable' | |
id: sniff_test | |
run: | | |
podman pull --tls-verify=false \ | |
localhost:5000/$REPONAME/${{ matrix.source }} | |
VERSION_OUTPUT=$(podman run \ | |
localhost:5000/$REPONAME/${{ matrix.source }} \ | |
$VERSION_CMD) | |
echo "$VERSION_OUTPUT" | |
VERSION=$(awk -r -e "/^${REPONAME} version /"'{print $3}' <<<"$VERSION_OUTPUT") | |
test -n "$VERSION" | |
echo "::set-output name=version::$VERSION" | |
- name: Generate image FQIN(s) to push | |
id: reponame_reg | |
run: | | |
if [[ "${{ matrix.source }}" == 'stable' ]]; then | |
# The command version in image just built | |
VERSION='v${{ steps.sniff_test.outputs.version }}' | |
# workaround vim syntax-highlight bug: ' | |
# Push both new|updated version-tag and latest-tag FQINs | |
FQIN="$REPONAME_QUAY_REGISTRY/stable:$VERSION,$REPONAME_QUAY_REGISTRY/stable:latest" | |
elif [[ "${{ matrix.source }}" == 'testing' ]]; then | |
# Assume some contents changed, always push latest testing. | |
FQIN="$REPONAME_QUAY_REGISTRY/testing:latest" | |
elif [[ "${{ matrix.source }}" == 'upstream' ]]; then | |
# Assume some contents changed, always push latest upstream. | |
FQIN="$REPONAME_QUAY_REGISTRY/upstream:latest" | |
else | |
echo "::error::Unknown matrix item '${{ matrix.source }}'" | |
exit 1 | |
fi | |
echo "::warning::Pushing $FQIN" | |
echo "::set-output name=fqin::${FQIN}" | |
echo '::set-output name=push::true' | |
# This is substantially similar to the above logic, | |
# but only handles $CONTAINERS_QUAY_REGISTRY for | |
# the stable "latest" and named-version tagged images. | |
- name: Generate containers reg. image FQIN(s) | |
if: matrix.source == 'stable' | |
id: containers_reg | |
run: | | |
VERSION='v${{ steps.sniff_test.outputs.version }}' | |
# workaround vim syntax-highlight bug: ' | |
# Push both new|updated version-tag and latest-tag FQINs | |
FQIN="$CONTAINERS_QUAY_REGISTRY/$REPONAME:$VERSION,$CONTAINERS_QUAY_REGISTRY/$REPONAME:latest" | |
echo "::warning::Pushing $FQIN" | |
echo "::set-output name=fqin::${FQIN}" | |
echo '::set-output name=push::true' | |
- name: Define LABELS multi-line env. var. value | |
run: | | |
# This is a really hacky/strange workflow idiom, required | |
# for setting multi-line $LABELS value for consumption in | |
# a future step. There is literally no cleaner way to do this :< | |
# https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#multiline-strings | |
function set_labels() { | |
echo 'LABELS<<DELIMITER' >> "$GITHUB_ENV" | |
for line; do | |
echo "$line" | tee -a "$GITHUB_ENV" | |
done | |
echo "DELIMITER" >> "$GITHUB_ENV" | |
} | |
declare -a lines | |
lines=(\ | |
"org.opencontainers.image.source=https://github.com/${GITHUB_REPOSITORY}.git" | |
"org.opencontainers.image.revision=${GITHUB_SHA}" | |
"org.opencontainers.image.created=$(date -u --iso-8601=seconds)" | |
) | |
# Only the 'stable' matrix source obtains $VERSION | |
if [[ "${{ matrix.source }}" == "stable" ]]; then | |
lines+=(\ | |
"org.opencontainers.image.version=${{ steps.sniff_test.outputs.version }}" | |
) | |
fi | |
set_labels "${lines[@]}" | |
# Separate steps to login and push for $REPONAME_QUAY_REGISTRY and | |
# $CONTAINERS_QUAY_REGISTRY are required, because 2 sets of credentials | |
# are used and namespaced within the registry. At the same time, reuse | |
# of non-shell steps is not supported by Github Actions nor are YAML | |
# anchors/aliases, nor composite actions. | |
# Push to $REPONAME_QUAY_REGISTRY for stable, testing. and upstream | |
- name: Login to ${{ env.REPONAME_QUAY_REGISTRY }} | |
uses: docker/login-action@dd4fa0671be5250ee6f50aedf4cb05514abda2c7 # v1 | |
if: steps.reponame_reg.outputs.push == 'true' | |
with: | |
registry: ${{ env.REPONAME_QUAY_REGISTRY }} | |
# N/B: Secrets are not passed to workflows that are triggered | |
# by a pull request from a fork | |
username: ${{ secrets.REPONAME_QUAY_USERNAME }} | |
password: ${{ secrets.REPONAME_QUAY_PASSWORD }} | |
- name: Push images to ${{ steps.reponame_reg.outputs.fqin }} | |
uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a # v2 | |
if: steps.reponame_reg.outputs.push == 'true' | |
with: | |
cache-from: type=registry,ref=localhost:5000/${{ env.REPONAME }}/${{ matrix.source }} | |
cache-to: type=inline | |
context: contrib/${{ env.REPONAME }}image/${{ matrix.source }} | |
file: ./contrib/${{ env.REPONAME }}image/${{ matrix.source }}/Dockerfile | |
platforms: ${{ env.PLATFORMS }} | |
push: true | |
tags: ${{ steps.reponame_reg.outputs.fqin }} | |
labels: | | |
${{ env.LABELS }} | |
# Push to $CONTAINERS_QUAY_REGISTRY only stable | |
- name: Login to ${{ env.CONTAINERS_QUAY_REGISTRY }} | |
if: steps.containers_reg.outputs.push == 'true' | |
uses: docker/login-action@dd4fa0671be5250ee6f50aedf4cb05514abda2c7 # v1 | |
with: | |
registry: ${{ env.CONTAINERS_QUAY_REGISTRY}} | |
username: ${{ secrets.CONTAINERS_QUAY_USERNAME }} | |
password: ${{ secrets.CONTAINERS_QUAY_PASSWORD }} | |
- name: Push images to ${{ steps.containers_reg.outputs.fqin }} | |
if: steps.containers_reg.outputs.push == 'true' | |
uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a # v2 | |
with: | |
cache-from: type=registry,ref=localhost:5000/${{ env.REPONAME }}/${{ matrix.source }} | |
cache-to: type=inline | |
context: contrib/${{ env.REPONAME }}image/${{ matrix.source }} | |
file: ./contrib/${{ env.REPONAME }}image/${{ matrix.source }}/Dockerfile | |
platforms: ${{ env.PLATFORMS }} | |
push: true | |
tags: ${{ steps.containers_reg.outputs.fqin }} | |
labels: | | |
${{ env.LABELS }} |