Skip to content

Commit 00614d6

Browse files
committed
ci: Add docker image publish workflow
1 parent 9651e01 commit 00614d6

1 file changed

Lines changed: 227 additions & 0 deletions

File tree

.github/workflows/publishImage.yml

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
# Based on https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
2+
3+
name: Publish Docker image to Dockerhub
4+
5+
concurrency:
6+
group: ${{ github.workflow }}-${{ github.ref }}
7+
cancel-in-progress: true
8+
9+
on:
10+
workflow_dispatch:
11+
push:
12+
branches:
13+
- 'main'
14+
tags:
15+
- '*.*.*'
16+
# don't trigger if just updating docs
17+
paths-ignore:
18+
- 'README.md'
19+
- '.github/**'
20+
- '.vscode/**'
21+
- '.devcontainer/**'
22+
# use release instead of tags once version is correctly parsed
23+
# https://github.com/docker/metadata-action/issues/422
24+
# https://github.com/docker/metadata-action/issues/240
25+
# release:
26+
# types: [ published ]
27+
28+
# define in GH Repository -> Actions -> Variables (or act .variables) to enable pushing to registries
29+
# -- will only push to registries that are defined
30+
# EX
31+
# DOCKERHUB_SLUG=foxxmd/multi-scrobbler
32+
# GHCR_SLUG=ghcr.io/foxxmd/multi-scrobbler
33+
34+
jobs:
35+
36+
build:
37+
name: Build OCI Images
38+
if: ${{ github.event_name != 'pull_request' && (vars.DOCKERHUB_SLUG != '' || vars.GHCR_SLUG != '') }}
39+
runs-on: ${{ matrix.os }}
40+
permissions:
41+
packages: write
42+
contents: read
43+
strategy:
44+
fail-fast: false
45+
matrix:
46+
include:
47+
- os: ubuntu-latest
48+
arch: amd64
49+
platform: linux/amd64
50+
- os: ubuntu-24.04-arm
51+
arch: arm64
52+
platform: linux/arm64
53+
steps:
54+
- name: Prepare
55+
run: |
56+
platform=${{ matrix.platform }}
57+
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
58+
59+
# list all registries to push to and join all non-empty with comma
60+
# https://unix.stackexchange.com/a/693165/116849
61+
# https://stackoverflow.com/a/9429887/1469797
62+
strings=("${{vars.DOCKERHUB_SLUG}}" "${{vars.GHCR_SLUG}}")
63+
for i in ${!strings[@]}; do [[ -z ${strings[i]} ]] && unset strings[i]; done
64+
joined_string=$(IFS=, ; echo "${strings[*]}")
65+
echo "REGISTRIES_JOINED=$joined_string" >> $GITHUB_ENV
66+
67+
- name: Check out the repo
68+
uses: actions/checkout@v4
69+
70+
- name: Set short git commit SHA
71+
id: appvars
72+
# https://dev.to/hectorleiva/github-actions-and-creating-a-short-sha-hash-8b7
73+
# short sha available under env.COMMIT_SHORT_SHA
74+
run: |
75+
calculatedSha=$(git rev-parse --short HEAD)
76+
branchName=$(git rev-parse --abbrev-ref HEAD)
77+
echo "COMMIT_SHORT_SHA=$calculatedSha" >> $GITHUB_ENV
78+
echo "COMMIT_BRANCH=$branchName" >> $GITHUB_ENV
79+
80+
- name: Get App Version
81+
id: appversion
82+
env:
83+
# use release instead of tags once version is correctly parsed
84+
#APP_VERSION: ${{ github.event.release.tag_name }}
85+
86+
# https://github.com/actions/runner/issues/409#issuecomment-752775072
87+
# https://stackoverflow.com/a/69919067/1469797
88+
APP_VERSION: ${{ contains(github.ref, 'refs/tags/') && github.ref_name || format('{0}-{1}', env.COMMIT_BRANCH, env.COMMIT_SHORT_SHA ) }}
89+
run: |
90+
echo appversion=$APP_VERSION >>${GITHUB_OUTPUT}
91+
92+
- name: Login to Docker Hub
93+
if: ${{ github.event_name != 'pull_request' && vars.DOCKERHUB_SLUG != '' }}
94+
uses: docker/login-action@v3
95+
with:
96+
username: ${{ secrets.DOCKER_USERNAME }}
97+
password: ${{ secrets.DOCKER_PASSWORD }}
98+
99+
- name: Login to GitHub Container Registry
100+
if: ${{ github.event_name != 'pull_request' && vars.GHCR_SLUG != '' }}
101+
uses: docker/login-action@v3
102+
with:
103+
registry: ghcr.io
104+
username: ${{ github.repository_owner }}
105+
password: ${{ secrets.GITHUB_TOKEN }}
106+
107+
# metadata extract for docker labels/image names is done in merge job
108+
109+
- name: Set up Docker Buildx
110+
uses: docker/setup-buildx-action@v3
111+
112+
# https://github.com/docker/build-push-action/issues/671#issuecomment-1619353328
113+
# for caching
114+
- name: Build and push by digest
115+
id: build
116+
uses: docker/build-push-action@v6
117+
with:
118+
context: .
119+
file: ./docker/Dockerfile
120+
build-args: |
121+
APP_BUILD_VERSION=${{steps.appversion.outputs.appversion}}
122+
SOURCE=${{inputs.pip_source}}
123+
platforms: ${{ matrix.platform }}
124+
labels: ${{ steps.meta.outputs.labels }}
125+
outputs: type=image,"name=${{ env.REGISTRIES_JOINED }}",push-by-digest=true,name-canonical=true,push=true
126+
#cache-from: type=gha,scope=build-${{ env.PLATFORM_PAIR }}
127+
#cache-to: type=gha,scope=build-${{ env.PLATFORM_PAIR }}
128+
129+
- name: Export digest
130+
run: |
131+
mkdir -p /tmp/digests
132+
digest="${{ steps.build.outputs.digest }}"
133+
touch "/tmp/digests/${digest#sha256:}"
134+
135+
- name: Upload digest
136+
uses: actions/upload-artifact@v4
137+
with:
138+
name: digests-${{ env.PLATFORM_PAIR }}
139+
path: /tmp/digests/*
140+
if-no-files-found: error
141+
retention-days: 1
142+
143+
merge:
144+
name: Merge OCI Images and Push
145+
if: ${{ github.event_name != 'pull_request' && (vars.DOCKERHUB_SLUG != '' || vars.GHCR_SLUG != '') }}
146+
runs-on: ubuntu-latest
147+
permissions:
148+
packages: write
149+
contents: read
150+
needs:
151+
- build
152+
steps:
153+
- name: Download digests
154+
uses: actions/download-artifact@v4
155+
with:
156+
path: /tmp/digests
157+
pattern: digests-*
158+
merge-multiple: true
159+
160+
- name: Login to Docker Hub
161+
if: ${{ github.event_name != 'pull_request' && vars.DOCKERHUB_SLUG != '' }}
162+
uses: docker/login-action@v3
163+
with:
164+
username: ${{ secrets.DOCKER_USERNAME }}
165+
password: ${{ secrets.DOCKER_PASSWORD }}
166+
167+
- name: Login to GitHub Container Registry
168+
if: ${{ github.event_name != 'pull_request' && vars.GHCR_SLUG != '' }}
169+
uses: docker/login-action@v3
170+
with:
171+
registry: ghcr.io
172+
username: ${{ github.repository_owner }}
173+
password: ${{ secrets.GITHUB_TOKEN }}
174+
175+
- name: Set up Docker Buildx
176+
uses: docker/setup-buildx-action@v3
177+
178+
- name: Extract metadata (tags, labels)
179+
id: meta
180+
uses: docker/metadata-action@v5
181+
with:
182+
images: |
183+
${{ vars.DOCKERHUB_SLUG }}
184+
${{ vars.GHCR_SLUG }}
185+
# generate Docker tags based on the following events/attributes
186+
# https://github.com/docker/metadata-action/issues/247#issuecomment-1511259674 for NOT is default branch, eventually
187+
tags: |
188+
type=edge
189+
190+
# push with branch name as tag if not master/main
191+
type=ref,event=branch,enable=${{ !endsWith(github.ref, 'main') }}
192+
193+
# tag non-prelease as latest -- has a higher priority than regular tag so it shows first in registries
194+
type=match,pattern=\d.\d.\d$,priority=901
195+
196+
# tag all semver (include pre-release)
197+
type=semver,pattern={{version}}
198+
# flavor: |
199+
# latest=false
200+
labels: |
201+
org.opencontainers.image.title=Docker Proxy Filter
202+
org.opencontainers.image.description=Filter respones and content from Docker API through an http socket
203+
org.opencontainers.image.vendor=FoxxMD
204+
205+
- name: Create manifest list and push dockerhub
206+
if: ${{ vars.DOCKERHUB_SLUG != '' }}
207+
working-directory: /tmp/digests
208+
run: |
209+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
210+
$(printf '${{ vars.DOCKERHUB_SLUG }}@sha256:%s ' *)
211+
212+
- name: Create manifest list and push gchr
213+
if: ${{ vars.GHCR_SLUG != '' }}
214+
working-directory: /tmp/digests
215+
run: |
216+
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
217+
$(printf '${{ vars.GHCR_SLUG }}@sha256:%s ' *)
218+
219+
- name: Inspect image dockerhub
220+
if: ${{ vars.DOCKERHUB_SLUG != '' }}
221+
run: |
222+
docker buildx imagetools inspect ${{ vars.DOCKERHUB_SLUG }}:${{ steps.meta.outputs.version }}
223+
224+
- name: Inspect image ghcr
225+
if: ${{ vars.GHCR_SLUG != '' }}
226+
run: |
227+
docker buildx imagetools inspect ${{ vars.GHCR_SLUG }}:${{ steps.meta.outputs.version }}

0 commit comments

Comments
 (0)