Skip to content

Add Workflow for Multi-Architecture Docker Image Build, Push, and Manifest Management #133

Add Workflow for Multi-Architecture Docker Image Build, Push, and Manifest Management

Add Workflow for Multi-Architecture Docker Image Build, Push, and Manifest Management #133

name: Build and Push Docker Image for Multiple Architectures
on:
pull_request:
push:
branches:
- master
- develop
- multiArchitectureFeature
tags:
- 'v*.*.*'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
DOCKER_REGISTRY: docker.io
DOCKER_USERNAME: metacall
IMAGE_NAME: core
BUILDKIT_VERSION: 0.13.0
jobs:
build:
name: Build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
- linux/riscv64
- linux/ppc64le
- linux/s390x
- linux/386
- linux/arm/v7
- linux/arm/v6
# - linux/mips64le
# - linux/mips64
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker BuildX
uses: docker/setup-buildx-action@v3
with:
version: v${{ env.BUILDKIT_VERSION }}
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Build MetaCall Docker Images
env:
METACALL_PLATFORM: ${{ matrix.platform }}
run: |
./docker-compose.sh platform
- name: Push Platform Images
run: |
platform_tag=$(echo "${{ matrix.platform }}" | tr '/' '-')
echo "Platform Tag: ${platform_tag}"
for tag in "deps" "dev" "runtime" "cli"; do
echo "Pushing image for tag: ${tag} with platform: ${platform_tag}"
docker tag ${DOCKER_USERNAME}/${IMAGE_NAME}:${tag} \
${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}-${platform_tag}
docker push ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}-${platform_tag}
done
manifest:
name: Create and Push Manifest Lists
needs: build
runs-on: ubuntu-latest
steps:
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Create and Push Manifest Lists
run: |
for tag in "deps" "dev" "runtime" "cli"; do
echo "Creating manifest for tag: $tag"
platform_tags=""
platforms=("linux-amd64" "linux-arm64" "linux-riscv64" "linux-ppc64le" "linux-s390x" "linux-386" "linux-arm-v7" "linux-arm-v6")
for platform in "${platforms[@]}"; do
platform_tags="${platform_tags} ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}-${platform}"
done
docker manifest create ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag} ${platform_tags} --amend
docker manifest push ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}
done
- name: Create Version-Specific Tags
if: startsWith(github.ref, 'refs/tags/')
run: |
VERSION=${GITHUB_REF#refs/tags/v}
tags=("deps" "dev" "runtime" "cli")
platforms=("linux-amd64" "linux-arm64" "linux-riscv64" "linux-ppc64le" "linux-s390x" "linux-386" "linux-arm-v7" "linux-arm-v6")
for tag in "${tags[@]}"; do
platform_tags=""
for platform in "${platforms[@]}"; do
platform_tags="${platform_tags} ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}-${platform}"
done
docker manifest create ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${VERSION}-${tag} ${platform_tags} --amend
docker manifest push ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${VERSION}-${tag}
done
# Create and push the 'latest' tag for CLI
cli_platform_tags=""
for platform in ${{ matrix.platform }}; do
cli_platform_tags="${cli_platform_tags} ${DOCKER_USERNAME}/${IMAGE_NAME}:cli-${platform}"
done
docker manifest create ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:latest ${cli_platform_tags} --amend
docker manifest push ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:latest
test:
name: Test CLI Image
needs: manifest
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
- linux/riscv64
- linux/ppc64le
- linux/s390x
- linux/386
- linux/arm/v7
- linux/arm/v6
# - linux/mips64le
# - linux/mips64
steps:
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Create Test Dockerfile
run: |
cat <<EOF > Dockerfile
FROM ${DOCKER_USERNAME}/${IMAGE_NAME}:cli
RUN echo "console.log('abcde')" > script.js
RUN metacallcli script.js
EOF
- name: Build and Test Image
run: |
platform_tag=$(echo "${{ matrix.platform }}" | tr '/' '-')
docker pull ${DOCKER_USERNAME}/${IMAGE_NAME}:cli
docker build --platform ${{ matrix.platform }} -t test-image .
docker run --rm --platform=${{ matrix.platform }} test-image
cleanup:
name: Cleanup Platform Specific Tags
needs: [build, manifest, test]
runs-on: ubuntu-latest
if: always()
steps:
- name: Remove Platform-Specific Tags
run: |
platforms=("linux-amd64" "linux-arm64" "linux-riscv64" "linux-ppc64le" "linux-s390x" "linux-386" "linux-arm-v7" "linux-arm-v6")
tags=("deps" "dev" "runtime" "cli")
for platform in "${platforms[@]}"; do
for tag in "${tags[@]}"; do
tag_to_delete="${tag}-${platform}"
echo "Deleting tag: ${tag_to_delete}"
curl -X DELETE \
-H "Authorization: Bearer ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}" \
"https://hub.docker.com/v2/repositories/${DOCKER_USERNAME}/${IMAGE_NAME}/tags/${tag_to_delete}/"
done
done