11---
22name : Docker build and push to quay
3- permissions : read-all
43
54on :
65 push :
7- branches : ['main']
8- tags : ['v*.*.*']
6+ branches : ["main"]
7+ # Publish semver tags as releases.
8+ tags : ["v*.*.*"]
9+ pull_request :
10+ branches : ["main"]
11+
12+ workflow_dispatch :
13+
14+ repository_dispatch :
15+ types : [dependency-updated]
916
1017env :
18+ # Use docker.io for Docker Hub if empty
1119 REGISTRY : quay.io
20+ # Generic image name for build artifacts, will be retagged for specific repos
21+ QUAY_IMAGE_NAME : localhost/utility-container
1222
1323jobs :
14- build-container-and-push :
15- runs-on : ubuntu-latest
24+ test :
25+ uses : ./.github/workflows/container-test.yml
26+
27+ build-container :
28+ needs : [test]
1629 strategy :
1730 matrix :
18- image :
19- - name : hybridcloudpatterns/utility-container
20- username_secret : LEGACY_QUAY_USERNAME
21- password_secret : LEGACY_QUAY_PASSWORD
22- - name : validatedpatterns/utility-container
31+ include :
32+ - targetarch : amd64
33+ runner : ubuntu-latest
34+ platform : linux/amd64
35+ alttargetarch : x86_64
36+ opttargetarch : " "
37+ extrarpms : " "
38+ - targetarch : arm64
39+ runner : ubuntu-24.04-arm
40+ platform : linux/arm64
41+ alttargetarch : aarch64
42+ opttargetarch : " arm64-"
43+ extrarpms : " gcc python3-devel glibc-devel libxcrypt-devel"
44+
45+ runs-on : ${{ matrix.runner }}
46+ permissions :
47+ contents : read
48+
49+ steps :
50+ - name : Checkout repository
51+ uses : actions/checkout@v5
52+
53+ # Set up BuildKit Docker container builder for docker save functionality
54+ # https://github.com/docker/setup-buildx-action
55+ - name : Set up Docker Buildx
56+ uses : docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
57+
58+ # https://github.com/docker/build-push-action
59+ # Build Docker image with Buildx. We always disable the cache as
60+ # it sometimes would not pull the new git changes for the cluster_utils,v1
61+ - name : Build Docker image
62+ id : build-and-push
63+ uses : docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
64+ with :
65+ context : .
66+ file : Containerfile
67+ platforms : ${{ matrix.platform }}
68+ push : false
69+ tags : ${{ env.REGISTRY }}/${{ env.QUAY_IMAGE_NAME }}:build-${{ github.run_id }}-${{ matrix.targetarch }}
70+ no-cache : true
71+ outputs : type=docker,dest=/tmp/image-${{ matrix.targetarch }}.tar
72+ build-args : |
73+ TARGETARCH=${{ matrix.targetarch }}
74+ ALTTARGETARCH=${{ matrix.alttargetarch }}
75+ OPTTARGETARCH=${{ matrix.opttargetarch }}
76+ EXTRARPMS=${{ matrix.extrarpms }}
77+
78+ # Upload image as artifact
79+ - name : Upload image artifact
80+ if : github.event_name != 'pull_request'
81+ uses : actions/upload-artifact@v4
82+ with :
83+ name : image-${{ matrix.targetarch }}-${{ github.run_id }}
84+ path : /tmp/image-${{ matrix.targetarch }}.tar
85+ retention-days : 1
86+
87+ create-multiarch-manifest :
88+ needs : [build-container]
89+ if : github.event_name != 'pull_request'
90+ strategy :
91+ matrix :
92+ include :
93+ - image_name : validatedpatterns/utility-container
2394 username_secret : QUAY_USERNAME
2495 password_secret : QUAY_PASSWORD
96+ - image_name : hybridcloudpatterns/utility-container
97+ username_secret : LEGACY_QUAY_USERNAME
98+ password_secret : LEGACY_QUAY_PASSWORD
99+
100+ runs-on : ubuntu-latest
25101 permissions :
26102 contents : read
27- packages : write
28103 # This is used to complete the identity challenge
29104 # with sigstore/fulcio when running outside of PRs.
30105 id-token : write
31106
32107 steps :
33- - name : Checkout repository
34- uses : actions/checkout@v5
108+ # Download image artifacts
109+ - name : Download AMD64 image
110+ uses : actions/download-artifact@v4
111+ with :
112+ name : image-amd64-${{ github.run_id }}
113+ path : /tmp/
114+
115+ - name : Download ARM64 image
116+ uses : actions/download-artifact@v4
117+ with :
118+ name : image-arm64-${{ github.run_id }}
119+ path : /tmp/
35120
36- - name : Set up QEMU
37- uses : docker/setup-qemu-action@v3
121+ # Load images into Docker and retag for this repo
122+ - name : Load and retag images
123+ run : |
124+ docker load --input /tmp/image-amd64.tar
125+ docker load --input /tmp/image-arm64.tar
126+
127+ # Retag loaded images for this specific repo
128+ OLD_IMAGE_BASE="${{ env.REGISTRY }}/${{ env.QUAY_IMAGE_NAME }}"
129+ NEW_IMAGE_BASE="${{ env.REGISTRY }}/${{ matrix.image_name }}"
130+
131+ docker tag "${OLD_IMAGE_BASE}:build-${{ github.run_id }}-amd64" "${NEW_IMAGE_BASE}:build-${{ github.run_id }}-amd64"
132+ docker tag "${OLD_IMAGE_BASE}:build-${{ github.run_id }}-arm64" "${NEW_IMAGE_BASE}:build-${{ github.run_id }}-arm64"
38133
39134 # Install the cosign tool
40135 # https://github.com/sigstore/cosign-installer
41136 - name : Install cosign
42137 uses : sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
43138 with :
44- cosign-release : ' v2.2.4'
139+ cosign-release : " v2.2.4"
45140
46- # Set up BuildKit Docker container builder to be able to build
47- # multi-platform images and export cache
48- # https://github.com/docker/setup-buildx-action
49- - name : Set up Docker Buildx
50- uses : docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
51-
52- # Login against a Docker registry
53- # https://github.com/docker/login-action
54141 - name : Log into registry ${{ env.REGISTRY }}
55142 uses : docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
56143 with :
57144 registry : ${{ env.REGISTRY }}
58- username : ${{ secrets[matrix.image.username_secret] }}
59- password : ${{ secrets[matrix.image.password_secret] }}
145+ username : ${{ secrets[matrix.username_secret] }}
146+ password : ${{ secrets[matrix.password_secret] }}
147+
148+ # Push individual architecture images to registry
149+ - name : Push architecture-specific images
150+ run : |
151+ IMAGE_BASE="${{ env.REGISTRY }}/${{ matrix.image_name }}"
152+ docker push "${IMAGE_BASE}:build-${{ github.run_id }}-amd64"
153+ docker push "${IMAGE_BASE}:build-${{ github.run_id }}-arm64"
60154
61- # Extract metadata (tags, labels) for Docker
62- # https://github.com/docker/metadata-action
63- - name : Extract Docker metadata
155+ # Extract metadata for multi-arch manifest
156+ - name : Extract Docker metadata for manifest
64157 id : meta
65158 uses : docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
66159 with :
67- images : ${{ env.REGISTRY }}/${{ matrix.image.name }}
160+ images : ${{ env.REGISTRY }}/${{ matrix.image_name }}
161+ flavor : |
162+ latest=${{ github.ref == 'refs/heads/main' }}
68163
69- # Build and push Docker image with Buildx
70- # https://github.com/docker/build-push-action
71- - name : Build and push Docker image
72- id : build-and-push
73- uses : docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
74- with :
75- context : .
76- file : Containerfile
77- platforms : linux/amd64,linux/arm64
78- push : true
79- tags : ${{ steps.meta.outputs.tags }}
80- labels : ${{ steps.meta.outputs.labels }}
81- cache-from : type=gha
82- cache-to : type=gha,mode=max
83-
84- # Sign the resulting Docker image digest.
164+ # Create and push multi-arch manifest
165+ - name : Create and push multi-arch manifest
166+ id : push-manifest
167+ run : |
168+ IMAGE_BASE="${{ env.REGISTRY }}/${{ matrix.image_name }}"
169+
170+ # Get the tags from metadata
171+ TAGS="${{ steps.meta.outputs.tags }}"
172+
173+ for TAG in $TAGS; do
174+ echo "Creating manifest for: $TAG"
175+
176+ # Use docker buildx imagetools to create multi-arch manifest
177+ docker buildx imagetools create -t "$TAG" \
178+ "${IMAGE_BASE}:build-${{ github.run_id }}-amd64" \
179+ "${IMAGE_BASE}:build-${{ github.run_id }}-arm64"
180+ done
181+
182+ # Get the digest of the first tag for signing
183+ FIRST_TAG=$(echo "$TAGS" | head -n1)
184+ DIGEST=$(docker buildx imagetools inspect "$FIRST_TAG" --format '{{json .}}' | jq -r '.manifest.digest')
185+ echo "digest=$DIGEST" >> "$GITHUB_OUTPUT"
186+
187+ # Sign the resulting Docker image digest
85188 # This will only write to the public Rekor transparency log when the Docker
86189 # repository is public to avoid leaking data. If you would like to publish
87190 # transparency data even for private images, pass --force to cosign below.
@@ -90,7 +193,22 @@ jobs:
90193 env :
91194 # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
92195 TAGS : ${{ steps.meta.outputs.tags }}
93- DIGEST : ${{ steps.build-and- push.outputs.digest }}
196+ DIGEST : ${{ steps.push-manifest .outputs.digest }}
94197 # This step uses the identity token to provision an ephemeral certificate
95198 # against the sigstore community Fulcio instance.
96199 run : echo "${TAGS}" | xargs -I "{}" cosign sign --yes "{}@${DIGEST}"
200+
201+ # Clean up temporary architecture-specific images
202+ - name : Clean up temporary images
203+ if : always()
204+ run : |
205+ IMAGE_BASE="${{ env.REGISTRY }}/${{ matrix.image_name }}"
206+
207+ # Try to delete temporary images, ignore errors if they don't exist
208+ docker run --rm quay.io/skopeo/stable delete \
209+ --creds "${{ secrets[matrix.username_secret] }}:${{ secrets[matrix.password_secret] }}" \
210+ docker://"${IMAGE_BASE}:build-${{ github.run_id }}-amd64" || true
211+
212+ docker run --rm quay.io/skopeo/stable delete \
213+ --creds "${{ secrets[matrix.username_secret] }}:${{ secrets[matrix.password_secret] }}" \
214+ docker://"${IMAGE_BASE}:build-${{ github.run_id }}-arm64" || true
0 commit comments