This repository was archived by the owner on Apr 4, 2026. It is now read-only.
ci: add multi-arch build workflow for ARM64 support #1
Workflow file for this run
This file contains hidden or 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: Multi-arch Build and Push | |
| on: | |
| push: | |
| branches: [multi-arch-arm64] | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'PostgreSQL-PostGIS version (e.g., 17-3.5)' | |
| required: false | |
| default: '17-3.5' | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # Debian variant | |
| - runner: ubuntu-24.04 | |
| platform: linux/amd64 | |
| version: '17-3.5' | |
| variant: default | |
| - runner: ubuntu-24.04-arm | |
| platform: linux/arm64 | |
| version: '17-3.5' | |
| variant: default | |
| # Alpine variant | |
| - runner: ubuntu-24.04 | |
| platform: linux/amd64 | |
| version: '17-3.5' | |
| variant: alpine | |
| - runner: ubuntu-24.04-arm | |
| platform: linux/arm64 | |
| version: '17-3.5' | |
| variant: alpine | |
| name: ${{ matrix.version }}-${{ matrix.variant }} (${{ matrix.platform }}) | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| outputs: | |
| # We use artifact exchange for digests instead of outputs | |
| # because matrix jobs can't cleanly merge outputs | |
| image-name: ${{ steps.meta.outputs.image-name }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Determine image metadata | |
| id: meta | |
| run: | | |
| VERSION="${{ matrix.version }}" | |
| VARIANT="${{ matrix.variant }}" | |
| REPO="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" | |
| # Lowercase the image name (GHCR requirement) | |
| REPO=$(echo "$REPO" | tr '[:upper:]' '[:lower:]') | |
| if [ "$VARIANT" = "alpine" ]; then | |
| TAG="${VERSION}-alpine" | |
| else | |
| TAG="${VERSION}" | |
| fi | |
| echo "tag=${TAG}" >> "$GITHUB_OUTPUT" | |
| echo "repo=${REPO}" >> "$GITHUB_OUTPUT" | |
| echo "image-name=${REPO}:${TAG}" >> "$GITHUB_OUTPUT" | |
| echo "dockerfile-dir=${VERSION}$([ "$VARIANT" = "alpine" ] && echo "/alpine" || echo "")" >> "$GITHUB_OUTPUT" | |
| - name: Build and push by digest | |
| id: build | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: ${{ steps.meta.outputs.dockerfile-dir }} | |
| platforms: ${{ matrix.platform }} | |
| push: true | |
| outputs: type=image,name=${{ steps.meta.outputs.repo }},push-by-digest=true,name-canonical=true | |
| cache-from: type=gha,scope=${{ matrix.version }}-${{ matrix.variant }}-${{ matrix.platform }} | |
| cache-to: type=gha,mode=max,scope=${{ matrix.version }}-${{ matrix.variant }}-${{ matrix.platform }} | |
| - name: Export digest | |
| run: | | |
| mkdir -p /tmp/digests/${{ matrix.variant }} | |
| digest="${{ steps.build.outputs.digest }}" | |
| touch "/tmp/digests/${{ matrix.variant }}/${digest#sha256:}" | |
| echo "Exported digest: ${digest}" | |
| - name: Upload digest | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: digests-${{ matrix.version }}-${{ matrix.variant }}-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }} | |
| path: /tmp/digests/${{ matrix.variant }}/ | |
| if-no-files-found: error | |
| retention-days: 1 | |
| # Create and push multi-arch manifests | |
| manifest: | |
| needs: build | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| packages: write | |
| strategy: | |
| matrix: | |
| include: | |
| - version: '17-3.5' | |
| variant: default | |
| tag: '17-3.5' | |
| - version: '17-3.5' | |
| variant: alpine | |
| tag: '17-3.5-alpine' | |
| name: Manifest ${{ matrix.tag }} | |
| steps: | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Download amd64 digest | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: digests-${{ matrix.version }}-${{ matrix.variant }}-amd64 | |
| path: /tmp/digests/ | |
| - name: Download arm64 digest | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: digests-${{ matrix.version }}-${{ matrix.variant }}-arm64 | |
| path: /tmp/digests/ | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Create and push manifest | |
| run: | | |
| REPO="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" | |
| REPO=$(echo "$REPO" | tr '[:upper:]' '[:lower:]') | |
| TAG="${{ matrix.tag }}" | |
| # Collect all digests | |
| DIGESTS="" | |
| for digest_file in /tmp/digests/*; do | |
| digest="sha256:$(basename $digest_file)" | |
| DIGESTS="${DIGESTS} ${REPO}@${digest}" | |
| done | |
| echo "Creating manifest for ${REPO}:${TAG} from digests:${DIGESTS}" | |
| docker buildx imagetools create \ | |
| --tag "${REPO}:${TAG}" \ | |
| ${DIGESTS} | |
| - name: Inspect manifest | |
| run: | | |
| REPO="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" | |
| REPO=$(echo "$REPO" | tr '[:upper:]' '[:lower:]') | |
| docker buildx imagetools inspect "${REPO}:${{ matrix.tag }}" |