sync-gpustack-images #220
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: sync-gpustack-images | |
| on: | |
| schedule: | |
| # Weekly: sync new dev images (diff against the latest release) | |
| - cron: "25 18 * * 0" | |
| # Every 4 hours: sync only gpustack/gpustack:dev | |
| - cron: "45 */4 * * *" | |
| workflow_dispatch: | |
| inputs: | |
| dev: | |
| description: "Whether to sync dev images instead of release images (default: false)" | |
| required: false | |
| default: false | |
| type: boolean | |
| docker_login: | |
| description: "Log in to Docker Hub to raise the pull rate limit (default: false)" | |
| required: false | |
| default: false | |
| type: boolean | |
| full_sync: | |
| description: "Sync all images of the target tag instead of only the diff (default: false)" | |
| required: false | |
| default: false | |
| type: boolean | |
| force_sync: | |
| description: "Comma-separated images to force sync, e.g. gpustack:dev,mirrored-node-feature-discovery:v0.18.3 (gpustack/ namespace is prepended automatically)" | |
| required: false | |
| default: "" | |
| type: string | |
| concurrency: | |
| group: ${{ github.workflow }} | |
| cancel-in-progress: false | |
| jobs: | |
| sync-images: | |
| name: Compare and Sync Images | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 🏷️ Fetch Latest Tags | |
| id: get_tags | |
| run: | | |
| # Fetch the latest two release tags from the repository | |
| TAGS=$(curl -s -H "Authorization: Bearer ${{ github.token }}" "https://api.github.com/repos/gpustack/gpustack/releases?page=1&per_page=2" | grep '"tag_name":' | awk -F'"' '{print $4}') | |
| LATEST_TAG=$(echo "$TAGS" | head -n 1) | |
| SECOND_LATEST_TAG=$(echo "$TAGS" | sed -n '2p') | |
| if [[ "${{ inputs.dev }}" == 'true' || "${{ github.event_name }}" == 'schedule' ]]; then | |
| SECOND_LATEST_TAG=$LATEST_TAG | |
| LATEST_TAG=dev | |
| fi | |
| echo "🚀 Latest tag: $LATEST_TAG" | |
| echo "⏮️ Second latest tag: $SECOND_LATEST_TAG" | |
| echo "LATEST_TAG=$LATEST_TAG" >> "$GITHUB_ENV" | |
| echo "SECOND_LATEST_TAG=$SECOND_LATEST_TAG" >> "$GITHUB_ENV" | |
| - name: 🔍 Determine Images to Sync | |
| id: get_images | |
| run: | | |
| # Build the list of images to sync based on the trigger and inputs | |
| if [[ "${{ github.event_name }}" == 'schedule' && "${{ github.event.schedule }}" == '45 */4 * * *' ]]; then | |
| # Every-4-hours schedule: only sync gpustack/gpustack:dev | |
| IMAGES_TO_SYNC="gpustack/gpustack:dev" | |
| elif [ -n "${{ inputs.force_sync }}" ]; then | |
| # Force sync: only the specified images (comma-separated name:tag, gpustack/ namespace prepended) | |
| IMAGES_TO_SYNC=$(echo "${{ inputs.force_sync }}" | tr ',' '\n' | \ | |
| sed 's/^[[:space:]]*//; s/[[:space:]]*$//' | sed '/^$/d' | sed 's#^#gpustack/#' | awk '!seen[$0]++') | |
| echo "🔧 Force-sync images requested:" | |
| echo "$IMAGES_TO_SYNC" | |
| elif [[ "${{ inputs.full_sync }}" == 'true' ]]; then | |
| # Full sync: all images of the target tag | |
| IMAGES_TO_SYNC=$(docker run -q --rm --entrypoint gpustack gpustack/gpustack:"$LATEST_TAG" list-images | uniq || true) | |
| else | |
| # Default: diff between the two tags | |
| IMAGES_TO_SYNC=$(grep -Fvf \ | |
| <(docker run -q --rm --entrypoint gpustack gpustack/gpustack:"$SECOND_LATEST_TAG" list-images) \ | |
| <(docker run -q --rm --entrypoint gpustack gpustack/gpustack:"$LATEST_TAG" list-images) | \ | |
| uniq || true) | |
| fi | |
| # On release syncs (manual dispatch with dev=false), also sync gpustack/gpustack:latest. | |
| # Schedules set LATEST_TAG=dev, so they are excluded; force_sync uses an explicit list. | |
| if [[ "$LATEST_TAG" != 'dev' && -z "${{ inputs.force_sync }}" ]]; then | |
| echo "🏷️ Release sync: including gpustack/gpustack:latest" | |
| IMAGES_TO_SYNC=$(printf '%s\n' "$IMAGES_TO_SYNC" "gpustack/gpustack:latest" | sed '/^$/d' | awk '!seen[$0]++') | |
| fi | |
| if [ -z "$IMAGES_TO_SYNC" ]; then | |
| echo "✅ No new images found for synchronization." | |
| echo "HAS_NEW_IMAGES=false" >> "$GITHUB_ENV" | |
| else | |
| echo "📦 Images identified for synchronization:" | |
| echo "$IMAGES_TO_SYNC" | |
| echo "HAS_NEW_IMAGES=true" >> "$GITHUB_ENV" | |
| { | |
| echo "IMAGES_TO_SYNC<<EOF" | |
| echo "$IMAGES_TO_SYNC" | |
| echo "EOF" | |
| } >> "$GITHUB_ENV" | |
| # Initialize the Job Summary header | |
| echo "### 🔄 Image Synchronization Report" >> "$GITHUB_STEP_SUMMARY" | |
| echo "The following images were identified and synced:" >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| - name: 🔑 Login to Docker Hub (Improve API Limits) | |
| if: env.HAS_NEW_IMAGES == 'true' && inputs.docker_login == 'true' | |
| run: | | |
| # Log in to Docker Hub to raise the pull rate limit | |
| echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USER }}" docker.io --password-stdin | |
| - name: 🔄 Sync to Quay.io | |
| if: env.HAS_NEW_IMAGES == 'true' | |
| run: | | |
| # Sync each identified image to Quay.io | |
| echo "${{ secrets.DOCKER_QUAY_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_QUAY_USER }}" quay.io --password-stdin | |
| echo "#### 🟢 Quay.io" >> "$GITHUB_STEP_SUMMARY" | |
| echo "$IMAGES_TO_SYNC" | while read -r image; do | |
| if [ -z "$image" ]; then continue; fi | |
| echo "➡️ Syncing: $image" | |
| skopeo copy --all --retry-times 3 "docker://${image}" "docker://quay.io/${image}" | |
| # Append success status to Job Summary | |
| echo "- ✅ \`$image\`" >> "$GITHUB_STEP_SUMMARY" | |
| done | |
| - name: 🔄 Sync to SWR | |
| if: env.HAS_NEW_IMAGES == 'true' | |
| run: | | |
| # Sync each identified image to SWR | |
| echo "${{ secrets.DOCKER_SWR_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_SWR_USER }}" "${{ secrets.DOCKER_SWR_REGISTRY }}" --password-stdin | |
| echo "#### 🔵 SWR" >> "$GITHUB_STEP_SUMMARY" | |
| echo "$IMAGES_TO_SYNC" | while read -r image; do | |
| if [ -z "$image" ]; then continue; fi | |
| echo "➡️ Syncing: $image" | |
| skopeo copy --all --retry-times 3 "docker://${image}" "docker://${{ secrets.DOCKER_SWR_REGISTRY }}/${image}" | |
| echo "- ✅ \`$image\`" >> "$GITHUB_STEP_SUMMARY" | |
| done |