11
11
env :
12
12
REGISTRY : ghcr.io
13
13
IMAGE_NAME : ${{ github.repository }}
14
-
14
+
15
+ concurrency :
16
+ # This concurrency group ensures that only one job in the group runs at a time.
17
+ # If a new job is triggered, the previous one will be canceled.
18
+ group : ${{ github.workflow }}-${{ github.ref }}
19
+ cancel-in-progress : true
20
+
15
21
jobs :
16
22
build-and-push :
17
23
strategy :
18
24
matrix :
19
25
include :
20
26
- os : ubuntu-latest
27
+ platform : linux/amd64
21
28
- os : ubuntu-24.04-arm
29
+ platform : linux/arm64
22
30
runs-on : ${{ matrix.os }}
23
31
permissions :
24
32
contents : read
25
33
packages : write
26
34
27
35
steps :
36
+ - name : Prepare environment for current platform
37
+ id : prepare
38
+ run : |
39
+ platform=${{ matrix.platform }}
40
+ echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
41
+ echo "GHCR_IMAGE=ghcr.io/${GITHUB_REPOSITORY@L}" >> $GITHUB_ENV
42
+
28
43
- name : Checkout repository
29
44
uses : actions/checkout@v4
30
45
43
58
id : meta
44
59
uses : docker/metadata-action@v5
45
60
with :
46
- images : ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
61
+ images : ${{ env.GHCR_IMAGE }}
62
+
63
+ - name : Create empty .env file for build
64
+ run : touch .env
65
+
66
+ - name : Build and push Docker image
67
+ uses : docker/build-push-action@v6
68
+ id : build
69
+ with :
70
+ context : .
71
+ platforms : ${{ matrix.platform }}
72
+ push : ${{ github.event_name != 'pull_request' }}
73
+ annotations : ${{ steps.meta.outputs.annotations }}
74
+ labels : ${{ steps.meta.outputs.labels }}
75
+ outputs : type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }},oci-mediatypes=true
76
+ cache-from : type=gha,scope=${{ github.repository }}-${{ github.ref_name }}-${{ matrix.platform }}
77
+ cache-to : type=gha,mode=max,scope=${{ github.repository }}-${{ github.ref_name }}-${{ matrix.platform }}
78
+
79
+ - name : Export digest
80
+ run : |
81
+ mkdir -p /tmp/digests
82
+ digest="${{ steps.build.outputs.digest }}"
83
+ touch "/tmp/digests/${digest#sha256:}"
84
+
85
+ - name : Upload digest
86
+ uses : actions/upload-artifact@v4
87
+ with :
88
+ name : digests-${{ env.PLATFORM_PAIR }}
89
+ path : /tmp/digests/*
90
+ if-no-files-found : error
91
+ retention-days : 1
92
+
93
+ merge :
94
+ name : merge Docker manifests
95
+ runs-on : ubuntu-latest
96
+ if : github.event_name != 'pull_request'
97
+ permissions :
98
+ contents : read
99
+ packages : write
100
+
101
+ needs :
102
+ - build-and-push
103
+ steps :
104
+ - name : Prepare environment
105
+ id : prepare
106
+ run : |
107
+ echo "GHCR_IMAGE=ghcr.io/${GITHUB_REPOSITORY@L}" >> $GITHUB_ENV
108
+
109
+ - name : Download digests
110
+ uses : actions/download-artifact@v4
111
+ with :
112
+ path : /tmp/digests
113
+ pattern : digests-*
114
+ merge-multiple : true
115
+
116
+
117
+ - name : Docker meta
118
+ id : meta
119
+ uses : docker/metadata-action@v5
120
+ with :
121
+ images : ${{ env.GHCR_IMAGE }}
122
+ annotations : |
123
+ type=org.opencontainers.image.description,value=${{ github.event.repository.description || 'No description provided' }}
47
124
tags : |
48
125
type=semver,pattern={{version}}
49
126
type=semver,pattern={{major}}.{{minor}}
@@ -52,15 +129,45 @@ jobs:
52
129
type=ref,event=pr
53
130
latest
54
131
55
- - name : Create empty .env file for build
56
- run : touch .env
132
+ - name : Set up Docker Buildx
133
+ uses : docker/setup-buildx-action@v3
134
+ with :
135
+ driver-opts : |
136
+ network=host
57
137
58
- - name : Build and push Docker image
59
- uses : docker/build-push- action@v5
138
+ - name : Login to GitHub Container Registry
139
+ uses : docker/login- action@v3
60
140
with :
61
- context : .
62
- push : ${{ github.event_name != 'pull_request' }}
63
- tags : ${{ steps.meta.outputs.tags }}
64
- labels : ${{ steps.meta.outputs.labels }}
65
- cache-from : type=gha
66
- cache-to : type=gha,mode=max
141
+ registry : ${{ env.REGISTRY }}
142
+ username : ${{ github.actor }}
143
+ password : ${{ secrets.GITHUB_TOKEN }}
144
+
145
+ - name : Get execution timestamp with RFC3339 format
146
+ id : timestamp
147
+ run : |
148
+ echo "timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> $GITHUB_OUTPUT
149
+
150
+ - name : Create manifest list and pushs
151
+ working-directory : /tmp/digests
152
+ id : manifest-annotate
153
+ continue-on-error : true
154
+ run : |
155
+ docker buildx imagetools create \
156
+ $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
157
+ --annotation='index:org.opencontainers.image.description=${{ github.event.repository.description }}' \
158
+ --annotation='index:org.opencontainers.image.created=${{ steps.timestamp.outputs.timestamp }}' \
159
+ --annotation='index:org.opencontainers.image.url=${{ github.event.repository.url }}' \
160
+ --annotation='index:org.opencontainers.image.source=${{ github.event.repository.url }}' \
161
+ $(printf '${{ env.GHCR_IMAGE }}@sha256:%s ' *)
162
+
163
+ - name : Create manifest list and push without annotations
164
+ if : steps.manifest-annotate.outcome == 'failure'
165
+ working-directory : /tmp/digests
166
+ run : |
167
+ docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
168
+ $(printf '${{ env.GHCR_IMAGE }}@sha256:%s ' *)
169
+
170
+ - name : Inspect image
171
+ id : inspect
172
+ run : |
173
+ docker buildx imagetools inspect '${{ env.GHCR_IMAGE }}:${{ steps.meta.outputs.version }}'
0 commit comments