Skip to content

Commit 01630bf

Browse files
authored
Update docker publish
1 parent 49fe19e commit 01630bf

File tree

1 file changed

+139
-23
lines changed

1 file changed

+139
-23
lines changed

.github/workflows/docker-publish.yml

Lines changed: 139 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,57 @@ name: Docker
77

88
on:
99
push:
10-
branches: [ "master", "develop" ]
10+
branches: [ 'master', 'develop', 'feature/*' ]
1111
# Publish semver tags as releases.
12-
tags: [ 'v*.*.*', 'v*.*', 'v*.*.*-beta*' ]
12+
tags: [ 'v*.*', 'v*.*.*', 'v*.*.*-beta*' ]
1313
pull_request:
14-
branches: [ "master" ]
14+
branches: [ 'master', 'develop', 'feature/*' ]
1515

1616
env:
1717
# Use docker.io for Docker Hub if empty
1818
REGISTRY: ghcr.io
1919
# github.repository as <account>/<repo>
2020
IMAGE_NAME: ${{ github.repository }}
2121

22-
2322
jobs:
2423
build:
25-
26-
runs-on: ubuntu-latest
24+
name: Build (${{ matrix.platform }})
25+
runs-on: ${{ matrix.runner }}
26+
strategy:
27+
fail-fast: false
28+
matrix:
29+
include:
30+
- platform: linux/amd64
31+
runner: ubuntu-22.04
32+
- platform: linux/arm64
33+
runner: ubuntu-22.04-arm
2734
permissions:
2835
contents: read
2936
packages: write
30-
# This is used to complete the identity challenge
31-
# with sigstore/fulcio when running outside of PRs.
3237
id-token: write
38+
outputs:
39+
image-name: ${{ steps.meta.outputs.tags }}
40+
labels: ${{ steps.meta.outputs.labels }}
3341

3442
steps:
3543
- name: Checkout repository
3644
uses: actions/checkout@v4
45+
46+
# Ensure repository/image name is lowercase for Docker registry
47+
- name: Set lowercase image name
48+
id: image
49+
run: |
50+
image="${IMAGE_NAME}"
51+
echo "lower=${image,,}" >> "$GITHUB_OUTPUT"
52+
echo "IMAGE_NAME_LC=${image,,}" >> "$GITHUB_ENV"
53+
env:
54+
IMAGE_NAME: ${{ env.IMAGE_NAME }}
3755

38-
# Install the cosign tool except on PR
39-
# https://github.com/sigstore/cosign-installer
40-
- name: Install cosign
41-
if: github.event_name != 'pull_request'
42-
uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 #v3.1.1
43-
with:
44-
cosign-release: 'v2.1.1'
56+
- name: Prepare platform name
57+
id: platform
58+
run: |
59+
platform=${{ matrix.platform }}
60+
echo "name=${platform//\//-}" >> $GITHUB_OUTPUT
4561
4662
# Set up BuildKit Docker container builder to be able to build
4763
# multi-platform images and export cache
@@ -65,18 +81,118 @@ jobs:
6581
id: meta
6682
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
6783
with:
68-
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
84+
images: ${{ env.REGISTRY }}/${{ steps.image.outputs.lower }}
85+
flavor: |
86+
latest=false
87+
tags: |
88+
type=raw,value=${{ github.sha }}-${{ steps.platform.outputs.name }}
6989
7090
# Build and push Docker image with Buildx (don't push on PR)
7191
# https://github.com/docker/build-push-action
72-
- name: Build and push Docker image
73-
id: build-and-push
92+
- name: Build and push Docker image by digest
93+
id: build
7494
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0
7595
with:
7696
context: .
77-
push: ${{ github.event_name != 'pull_request' }}
78-
tags: ${{ steps.meta.outputs.tags }}
97+
platforms: ${{ matrix.platform }}
7998
labels: ${{ steps.meta.outputs.labels }}
80-
cache-from: type=gha
81-
cache-to: type=gha,mode=max
82-
platforms: linux/amd64,linux/arm64
99+
outputs: type=image,name=${{ env.REGISTRY }}/${{ steps.image.outputs.lower }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
100+
cache-from: type=gha,scope=build-${{ steps.platform.outputs.name }}
101+
cache-to: type=gha,mode=max,scope=build-${{ steps.platform.outputs.name }}
102+
provenance: false
103+
sbom: false
104+
105+
- name: Export digest
106+
if: github.event_name != 'pull_request'
107+
run: |
108+
mkdir -p /tmp/digests
109+
digest="${{ steps.build.outputs.digest }}"
110+
touch "/tmp/digests/${digest#sha256:}"
111+
112+
- name: Upload digest
113+
if: github.event_name != 'pull_request'
114+
uses: actions/upload-artifact@v4
115+
with:
116+
name: digests-${{ steps.platform.outputs.name }}
117+
path: /tmp/digests/*
118+
if-no-files-found: error
119+
retention-days: 1
120+
121+
merge:
122+
name: Create multi-arch manifest
123+
runs-on: ubuntu-22.04
124+
needs: build
125+
if: github.event_name != 'pull_request'
126+
permissions:
127+
contents: read
128+
packages: write
129+
id-token: write
130+
131+
steps:
132+
- name: Download digests
133+
uses: actions/download-artifact@v4
134+
with:
135+
pattern: digests-*
136+
path: /tmp/digests
137+
merge-multiple: true
138+
139+
- name: Set up Docker Buildx
140+
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
141+
142+
- name: Log into registry ${{ env.REGISTRY }}
143+
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
144+
with:
145+
registry: ${{ env.REGISTRY }}
146+
username: ${{ github.actor }}
147+
password: ${{ secrets.GITHUB_TOKEN }}
148+
149+
# Ensure repository/image name is lowercase for Docker registry
150+
- name: Set lowercase image name
151+
id: image
152+
run: |
153+
image="${IMAGE_NAME}"
154+
echo "lower=${image,,}" >> "$GITHUB_OUTPUT"
155+
echo "IMAGE_NAME_LC=${image,,}" >> "$GITHUB_ENV"
156+
env:
157+
IMAGE_NAME: ${{ env.IMAGE_NAME }}
158+
159+
# Extract metadata (tags, labels) for Docker
160+
# https://github.com/docker/metadata-action
161+
- name: Extract Docker metadata
162+
id: meta
163+
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0
164+
with:
165+
images: ${{ env.REGISTRY }}/${{ steps.image.outputs.lower }}
166+
167+
- name: Create manifest list and push
168+
id: create-manifest
169+
working-directory: /tmp/digests
170+
run: |
171+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
172+
$(printf '${{ env.REGISTRY }}/${{ steps.image.outputs.lower }}@sha256:%s ' *)
173+
174+
# Get the digest of the manifest
175+
manifest_digest=$(docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ steps.image.outputs.lower }}:${{ steps.meta.outputs.version }} --format '{{json .Manifest}}' | jq -r '.digest // .Digest // empty')
176+
if [ -z "$manifest_digest" ]; then
177+
manifest_digest=$(docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ steps.image.outputs.lower }}:${{ steps.meta.outputs.version }} --format '{{.Digest}}')
178+
fi
179+
echo "digest=${manifest_digest}" >> $GITHUB_OUTPUT
180+
181+
- name: Inspect image
182+
run: |
183+
docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ steps.image.outputs.lower }}:${{ steps.meta.outputs.version }}
184+
185+
# Install cosign (before using it)
186+
- name: Install cosign
187+
uses: sigstore/[email protected]
188+
with:
189+
cosign-release: 'v2.2.4'
190+
191+
# Sign the pushed image by digest (skip on PRs)
192+
- name: Sign image with cosign
193+
if: github.event_name != 'pull_request'
194+
env:
195+
DIGEST: ${{ steps.create-manifest.outputs.digest }}
196+
TAGS: ${{ steps.meta.outputs.tags }}
197+
run: |
198+
echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}

0 commit comments

Comments
 (0)