Skip to content

Commit c0467ed

Browse files
hjmjohnsonclaude
andcommitted
ENH: Mirror dockcross images to GHCR for reliable Python wheel builds
Python wheel CI builds pull large dockcross/manylinux container images (~1-2 GB) from Docker Hub and Quay.io on every run. These pulls intermittently fail with "unexpected EOF" or Docker Hub rate limiting (401/429), causing wheel builds to fail across all remote modules. Add a scheduled workflow that mirrors the pinned dockcross images to GHCR (ghcr.io/insightsoftwareconsortium/), which has much better connectivity from GitHub Actions runners (same network). Add pre-pull steps to the Linux x64 and ARM build jobs that: 1. Try pulling from the GHCR mirror first 2. Fall back to the original Docker Hub / Quay.io source 3. Retry up to 3 times with backoff 4. Tag the GHCR image with the original name so the downstream ITKPythonPackage build scripts find it already cached This eliminates transient Docker image pull failures that have been causing sporadic Python wheel build failures across ~55 remote modules. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6f39107 commit c0467ed

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

.github/workflows/build-test-package-python.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,38 @@ jobs:
8484
large-packages: "false" # Takes too long to remove apt-get packages
8585
mandb: "true" # Speeds up future apt-get installs (disables man page generation), this CI does not use apt-get
8686

87+
- name: 'Pre-pull dockcross image'
88+
run: |
89+
MANYLINUX_PLATFORM=${{ matrix.manylinux-platform }}
90+
MANYLINUX_VERSION=$(echo ${MANYLINUX_PLATFORM} | cut -d '-' -f 1)
91+
TARGET_ARCH=$(echo ${MANYLINUX_PLATFORM} | cut -d '-' -f 2)
92+
if [[ ${MANYLINUX_VERSION} == _2_28 && ${TARGET_ARCH} == x64 ]]; then
93+
IMAGE_TAG="20240304-9e57d2b"
94+
elif [[ ${MANYLINUX_VERSION} == 2014 ]]; then
95+
IMAGE_TAG="20240304-9e57d2b"
96+
else
97+
echo "Unknown manylinux platform ${MANYLINUX_PLATFORM}, skipping pre-pull"
98+
exit 0
99+
fi
100+
IMAGE="dockcross/manylinux${MANYLINUX_VERSION}-${TARGET_ARCH}:${IMAGE_TAG}"
101+
GHCR_IMAGE="ghcr.io/insightsoftwareconsortium/dockcross-manylinux${MANYLINUX_VERSION}-${TARGET_ARCH}:${IMAGE_TAG}"
102+
echo "Pre-pulling ${GHCR_IMAGE} (mirror of docker.io/${IMAGE})"
103+
for attempt in 1 2 3; do
104+
if docker pull "${GHCR_IMAGE}" 2>/dev/null; then
105+
docker tag "${GHCR_IMAGE}" "docker.io/${IMAGE}"
106+
echo "Successfully pulled from GHCR mirror"
107+
exit 0
108+
fi
109+
echo "GHCR pull attempt ${attempt} failed, trying Docker Hub..."
110+
if docker pull "docker.io/${IMAGE}"; then
111+
echo "Successfully pulled from Docker Hub"
112+
exit 0
113+
fi
114+
echo "Docker Hub pull attempt ${attempt} failed, retrying in 15s..."
115+
sleep 15
116+
done
117+
echo "WARNING: All pull attempts failed, build script will retry"
118+
87119
- name: 'Fetch build script'
88120
run: |
89121
IPP_DOWNLOAD_GIT_TAG=${{ inputs.itk-python-package-tag }}
@@ -180,6 +212,28 @@ jobs:
180212
large-packages: "false" # Takes too long to remove apt-get packages
181213
mandb: "true" # Speeds up future apt-get installs (disables man page generation), this CI does not use apt-get
182214

215+
- name: 'Pre-pull manylinux aarch64 image'
216+
run: |
217+
IMAGE_TAG="2024-03-25-9206bd9"
218+
IMAGE="quay.io/pypa/manylinux_2_28_aarch64:${IMAGE_TAG}"
219+
GHCR_IMAGE="ghcr.io/insightsoftwareconsortium/dockcross-manylinux_2_28-aarch64:${IMAGE_TAG}"
220+
echo "Pre-pulling ${GHCR_IMAGE} (mirror of ${IMAGE})"
221+
for attempt in 1 2 3; do
222+
if docker pull "${GHCR_IMAGE}" 2>/dev/null; then
223+
docker tag "${GHCR_IMAGE}" "${IMAGE}"
224+
echo "Successfully pulled from GHCR mirror"
225+
exit 0
226+
fi
227+
echo "GHCR pull attempt ${attempt} failed, trying upstream..."
228+
if docker pull "${IMAGE}"; then
229+
echo "Successfully pulled from upstream"
230+
exit 0
231+
fi
232+
echo "Upstream pull attempt ${attempt} failed, retrying in 15s..."
233+
sleep 15
234+
done
235+
echo "WARNING: All pull attempts failed, build script will retry"
236+
183237
- name: 'Fetch build script'
184238
run: |
185239
IPP_DOWNLOAD_GIT_TAG=${{ inputs.itk-python-package-tag }}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: Mirror dockcross images to GHCR
2+
3+
on:
4+
schedule:
5+
# Run weekly on Monday at 06:00 UTC
6+
- cron: '0 6 * * 1'
7+
workflow_dispatch:
8+
9+
env:
10+
GHCR_ORG: ghcr.io/insightsoftwareconsortium
11+
12+
jobs:
13+
mirror:
14+
runs-on: ubuntu-22.04
15+
permissions:
16+
packages: write
17+
strategy:
18+
matrix:
19+
include:
20+
- source: docker.io/dockcross/manylinux_2_28-x64:20240304-9e57d2b
21+
target: dockcross-manylinux_2_28-x64:20240304-9e57d2b
22+
- source: docker.io/dockcross/manylinux2014-x64:20240304-9e57d2b
23+
target: dockcross-manylinux2014-x64:20240304-9e57d2b
24+
- source: quay.io/pypa/manylinux_2_28_aarch64:2024-03-25-9206bd9
25+
target: dockcross-manylinux_2_28-aarch64:2024-03-25-9206bd9
26+
27+
steps:
28+
- name: Log in to GHCR
29+
uses: docker/login-action@v3
30+
with:
31+
registry: ghcr.io
32+
username: ${{ github.actor }}
33+
password: ${{ secrets.GITHUB_TOKEN }}
34+
35+
- name: Pull source image
36+
run: |
37+
for attempt in 1 2 3; do
38+
docker pull ${{ matrix.source }} && break
39+
echo "Pull attempt $attempt failed, retrying in 15s..."
40+
sleep 15
41+
done
42+
43+
- name: Tag and push to GHCR
44+
run: |
45+
docker tag ${{ matrix.source }} ${{ env.GHCR_ORG }}/${{ matrix.target }}
46+
docker push ${{ env.GHCR_ORG }}/${{ matrix.target }}

0 commit comments

Comments
 (0)