@@ -19,14 +19,13 @@ concurrency:
1919
2020env :
2121 REPO_SLUG : centralized-logging
22- DOCKERHUB_NAMESPACE : " " # set to mirror to Docker Hub or leave empty
22+ DOCKERHUB_NAMESPACE : " " # optional mirroring
2323 PLATFORMS : linux/amd64,linux/arm64
2424
2525jobs :
2626 images :
2727 name : Build and Push Images (GHCR)
2828 runs-on : ubuntu-latest
29- # Push images only on master, tags, or manual dispatch (PRs still build if you press Run)
3029 if : >
3130 github.event_name == 'workflow_dispatch' ||
3231 startsWith(github.ref, 'refs/heads/master') ||
@@ -37,51 +36,47 @@ jobs:
3736 steps :
3837 - name : Checkout
3938 uses : actions/checkout@v4
40- with :
41- fetch-depth : 0
39+ with : { fetch-depth: 0 }
4240
4341 - name : Set up QEMU
4442 uses : docker/setup-qemu-action@v3
4543
4644 - name : Set up Docker Buildx
4745 uses : docker/setup-buildx-action@v3
4846
49- # Build a single-line, comma-separated tag list per service
50- - name : Compute tags
47+ # Build JSON arrays of tags for each service
48+ - name : Compute tags (JSON arrays)
5149 id : tags
5250 shell : bash
5351 run : |
5452 set -euo pipefail
55- OWNER_LC="${GITHUB_REPOSITORY_OWNER,,}" # force lowercase for GHCR
53+ OWNER_LC="${GITHUB_REPOSITORY_OWNER,,}"
5654 REPO_SLUG="${REPO_SLUG}"
57-
58- # Always push :edge
59- user_tags="ghcr.io/${OWNER_LC}/${REPO_SLUG}/userapi:edge"
60- api_tags="ghcr.io/${OWNER_LC}/${REPO_SLUG}/api:edge"
61- web_tags="ghcr.io/${OWNER_LC}/${REPO_SLUG}/web:edge"
62-
6355 REF="${GITHUB_REF}"
6456
65- # On master, also push :latest
57+ user_tags=( "ghcr.io/${OWNER_LC}/${REPO_SLUG}/userapi:edge" )
58+ api_tags=( "ghcr.io/${OWNER_LC}/${REPO_SLUG}/api:edge" )
59+ web_tags=( "ghcr.io/${OWNER_LC}/${REPO_SLUG}/web:edge" )
60+
6661 if [[ "$REF" == "refs/heads/master" ]]; then
67- user_tags+=", ghcr.io/${OWNER_LC}/${REPO_SLUG}/userapi:latest"
68- api_tags+=", ghcr.io/${OWNER_LC}/${REPO_SLUG}/api:latest"
69- web_tags+=", ghcr.io/${OWNER_LC}/${REPO_SLUG}/web:latest"
62+ user_tags+=( " ghcr.io/${OWNER_LC}/${REPO_SLUG}/userapi:latest" )
63+ api_tags+=( " ghcr.io/${OWNER_LC}/${REPO_SLUG}/api:latest" )
64+ web_tags+=( " ghcr.io/${OWNER_LC}/${REPO_SLUG}/web:latest" )
7065 fi
7166
72- # On tag vX.Y.Z, also push :vX.Y.Z and :X.Y
7367 if [[ "$REF" == refs/tags/v* ]]; then
74- ver="${REF#refs/tags/}" # vX.Y.Z
75- short="${ver#v}" # X.Y.Z
76- minor="${short%.*}" # X.Y
77- user_tags+=", ghcr.io/${OWNER_LC}/${REPO_SLUG}/userapi:${ver}, ghcr.io/${OWNER_LC}/${REPO_SLUG}/userapi:${minor}"
78- api_tags+=", ghcr.io/${OWNER_LC}/${REPO_SLUG}/api:${ver}, ghcr.io/${OWNER_LC}/${REPO_SLUG}/api:${minor}"
79- web_tags+=", ghcr.io/${OWNER_LC}/${REPO_SLUG}/web:${ver}, ghcr.io/${OWNER_LC}/${REPO_SLUG}/web:${minor}"
68+ ver="${REF#refs/tags/}" # vX.Y.Z
69+ short="${ver#v}" # X.Y.Z
70+ minor="${short%.*}" # X.Y
71+ user_tags+=( " ghcr.io/${OWNER_LC}/${REPO_SLUG}/userapi:${ver}" " ghcr.io/${OWNER_LC}/${REPO_SLUG}/userapi:${minor}" )
72+ api_tags+=( " ghcr.io/${OWNER_LC}/${REPO_SLUG}/api:${ver}" " ghcr.io/${OWNER_LC}/${REPO_SLUG}/api:${minor}" )
73+ web_tags+=( " ghcr.io/${OWNER_LC}/${REPO_SLUG}/web:${ver}" " ghcr.io/${OWNER_LC}/${REPO_SLUG}/web:${minor}" )
8074 fi
8175
82- echo "user_tags=$user_tags" >> "$GITHUB_OUTPUT"
83- echo "api_tags=$api_tags" >> "$GITHUB_OUTPUT"
84- echo "web_tags=$web_tags" >> "$GITHUB_OUTPUT"
76+ # emit JSON arrays
77+ printf 'user_tags_json=%s\n' "$(printf '%s\n' "${user_tags[@]}" | jq -R . | jq -s .)" >> "$GITHUB_OUTPUT"
78+ printf 'api_tags_json=%s\n' "$(printf '%s\n' "${api_tags[@]}" | jq -R . | jq -s .)" >> "$GITHUB_OUTPUT"
79+ printf 'web_tags_json=%s\n' "$(printf '%s\n' "${web_tags[@]}" | jq -R . | jq -s .)" >> "$GITHUB_OUTPUT"
8580
8681 - name : Login to GHCR
8782 uses : docker/login-action@v3
@@ -102,25 +97,21 @@ jobs:
10297 with :
10398 path : /tmp/.buildx-cache
10499 key : ${{ runner.os }}-buildx-${{ github.sha }}
105- restore-keys : |
106- ${{ runner.os }}-buildx-
100+ restore-keys : ${{ runner.os }}-buildx-
107101
108102 - name : Bake and Push (multi-arch)
109103 uses : docker/bake-action@v5
110104 with :
111105 files : ./docker-bake.hcl
112106 push : true
113- variables : |
114- OWNER=${{ github.repository_owner }}
115- REPO_SLUG=${{ env.REPO_SLUG }}
116107 set : |
117108 *.platform=${{ env.PLATFORMS }}
118109 *.cache-from=type=local,src=/tmp/.buildx-cache
119110 *.cache-to=type=local,dest=/tmp/.buildx-cache-new,mode=max
120111 *.labels.org.opencontainers.image.revision=${{ github.sha }}
121- userapi.tags=${{ steps.tags.outputs.user_tags }}
122- api.tags=${{ steps.tags.outputs.api_tags }}
123- web.tags=${{ steps.tags.outputs.web_tags }}
112+ userapi.tags=${{ steps.tags.outputs.user_tags_json }}
113+ api.tags=${{ steps.tags.outputs.api_tags_json }}
114+ web.tags=${{ steps.tags.outputs.web_tags_json }}
124115
125116 - name : Save build cache
126117 if : always()
@@ -132,7 +123,8 @@ jobs:
132123 if : ${{ env.DOCKERHUB_NAMESPACE != '' && env.DOCKERHUB_USERNAME != '' && env.DOCKERHUB_TOKEN != '' }}
133124 run : |
134125 set -euo pipefail
135- mirror() { local svc="$1"; local list="$2"; IFS=',' read -ra arr <<< "$list"; \
126+ mirror() { local svc="$1"; local json="$2"; \
127+ mapfile -t arr < <(jq -r '.[]' <<<"$json"); \
136128 for img in "${arr[@]}"; do
137129 tag="${img##*:}"
138130 hub="${DOCKERHUB_NAMESPACE}/${REPO_SLUG}-${svc}:${tag}"
@@ -142,6 +134,6 @@ jobs:
142134 docker push "$hub"
143135 done
144136 }
145- mirror userapi " ${{ steps.tags.outputs.user_tags }}"
146- mirror api " ${{ steps.tags.outputs.api_tags }}"
147- mirror web " ${{ steps.tags.outputs.web_tags }}"
137+ mirror userapi ' ${{ steps.tags.outputs.user_tags_json }}'
138+ mirror api ' ${{ steps.tags.outputs.api_tags_json }}'
139+ mirror web ' ${{ steps.tags.outputs.web_tags_json }}'
0 commit comments