Skip to content

Commit eae9ab8

Browse files
committed
skopeo copy --all in the dockerhub_mirror job.
1 parent 5bdab7b commit eae9ab8

1 file changed

Lines changed: 24 additions & 24 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -274,11 +274,12 @@ jobs:
274274
path: ${{ env.MANIFEST_SUMMARY_FILE }}
275275
if-no-files-found: warn
276276

277-
# Mirror the GHCR multi-arch manifests to Docker Hub. This runs as a single
278-
# serial job (NOT inside the manifest matrix): all OS families target the same
279-
# Docker Hub repo, and concurrent blob uploads to one repo trip Docker Hub's
280-
# rate limits, so tags are copied one at a time with retries. The copy is
281-
# registry-to-registry (no pull, no rebuild). Skipped when the
277+
# Mirror the GHCR multi-arch manifests to Docker Hub. Copied with skopeo, not
278+
# `docker buildx imagetools`: the latter's blob-upload finalize is rejected by
279+
# Docker Hub's registry with "400 Bad Request", whereas skopeo's streaming
280+
# upload is accepted. The copy is registry-to-registry (no pull, no rebuild)
281+
# and `--all` carries every architecture in the manifest list. Tags are copied
282+
# one at a time (sequential) with skopeo's own retry. Skipped when the
282283
# DOCKERHUB_USERNAME secret is absent (e.g. on forks).
283284
dockerhub_mirror:
284285
name: Mirror images to Docker Hub
@@ -287,7 +288,7 @@ jobs:
287288
runs-on: ubuntu-latest
288289
env:
289290
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
290-
DOCKERHUB_REPO: ${{ vars.DOCKERHUB_REPO || 'docker.io/maureeungaro/gemc' }}
291+
DOCKERHUB_REPO: ${{ vars.DOCKERHUB_REPO || 'maureeungaro/gemc' }}
291292
steps:
292293
- name: Checkout repository
293294
uses: actions/checkout@v6
@@ -310,11 +311,13 @@ jobs:
310311
username: ${{ secrets.DOCKERHUB_USERNAME }}
311312
password: ${{ secrets.DOCKERHUB_TOKEN }}
312313

313-
- name: Set up Buildx
314+
- name: Install skopeo
314315
if: ${{ env.DOCKERHUB_USERNAME != '' }}
315-
uses: docker/setup-buildx-action@v4
316+
run: |
317+
sudo apt-get update
318+
sudo apt-get install -y skopeo
316319
317-
- name: Mirror all tags (sequential, with retry)
320+
- name: Mirror all tags (sequential)
318321
if: ${{ env.DOCKERHUB_USERNAME != '' }}
319322
shell: bash
320323
env:
@@ -323,26 +326,23 @@ jobs:
323326
set -uo pipefail
324327
source ci/tags_config.sh
325328
326-
copy_with_retry() {
327-
local src=$1 dst=$2 n=0 max=5
328-
until docker buildx imagetools create -t "$dst" "$src"; do
329-
n=$((n + 1))
330-
if [ "$n" -ge "$max" ]; then
331-
echo "::error::failed to mirror $src -> $dst after $max attempts"
332-
return 1
333-
fi
334-
echo "retry $n/$max for $dst; backing off $((n * 15))s"
335-
sleep $((n * 15))
336-
done
337-
echo "mirrored $src -> $dst"
338-
}
329+
# skopeo reads the credentials written by the docker login steps above.
330+
AUTHFILE="$HOME/.docker/config.json"
339331
340332
rc=0
341333
for gemcv in $(get_gemc_tags); do
342334
for pair in "${OS_VERSIONS[@]}"; do
343335
os="${pair%%=*}"; ver="${pair#*=}"
344336
tag="${gemcv}-${os}-${ver}"
345-
copy_with_retry "${SRC_IMAGE}:${tag}" "${DOCKERHUB_REPO}:${tag}" || rc=1
337+
echo "Mirroring ${SRC_IMAGE}:${tag} -> ${DOCKERHUB_REPO}:${tag}"
338+
if skopeo copy --all --retry-times 5 --authfile "$AUTHFILE" \
339+
"docker://${SRC_IMAGE}:${tag}" \
340+
"docker://${DOCKERHUB_REPO}:${tag}"; then
341+
echo "mirrored ${DOCKERHUB_REPO}:${tag}"
342+
else
343+
echo "::error::failed to mirror ${SRC_IMAGE}:${tag} -> ${DOCKERHUB_REPO}:${tag}"
344+
rc=1
345+
fi
346346
done
347347
done
348348
exit "$rc"
@@ -356,7 +356,7 @@ jobs:
356356
runs-on: ubuntu-latest
357357
env:
358358
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
359-
DOCKERHUB_REPO: ${{ vars.DOCKERHUB_REPO || 'docker.io/maureeungaro/gemc' }}
359+
DOCKERHUB_REPO: ${{ vars.DOCKERHUB_REPO || 'maureeungaro/gemc' }}
360360
steps:
361361
- name: Checkout repository
362362
uses: actions/checkout@v6

0 commit comments

Comments
 (0)