Skip to content

Update All Images [15] #15

Update All Images [15]

Update All Images [15] #15

name: Update Latest Images
run-name: ${{ github.event_name == 'schedule' && format('Daily Update [{0}]', github.run_number) || github.event.inputs.specific_image != '' && format('Update {0} [{1}]', github.event.inputs.specific_image, github.run_number) || format('Update All Images [{0}]', github.run_number) }}
on:
schedule:
# Run daily at midnight UTC
- cron: '0 0 * * *'
workflow_dispatch:
inputs:
force_update_all:
description: 'Force update all latest images'
required: false
default: false
type: boolean
specific_image:
description: 'Specific image to update (leave empty for all). No need to include dockerhub- prefix'
required: false
type: string
jobs:
find-and-update-images:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Find latest images
id: find_images
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "::group::Finding Latest Images"
# Get all images with 'latest' tag
PACKAGE_NAME="dockerhub-"
ORG="${{ github.repository_owner }}"
if [[ -n "${{ github.event.inputs.specific_image }}" ]]; then
# If a specific image was requested
SPECIFIC_IMAGE="${{ github.event.inputs.specific_image }}"
# Strip dockerhub- prefix if user accidentally included it
SPECIFIC_IMAGE="${SPECIFIC_IMAGE#dockerhub-}"
echo "Processing specific image: ${SPECIFIC_IMAGE}"
API_URL="/orgs/${ORG}/packages/container/${PACKAGE_NAME}${SPECIFIC_IMAGE}"
echo "Querying: $API_URL"
# Check if specific image exists in the registry
gh api \
-H "Accept: application/vnd.github+json" \
"${API_URL}" > image_info.json
if [[ $? -eq 0 ]]; then
# Image exists
IMAGE_DIGEST=$(jq -r '.metadata.container.digest' image_info.json)
echo "Image ${SPECIFIC_IMAGE} found in registry, will update."
export IMAGES="${SPECIFIC_IMAGE}"
else
echo "Image ${SPECIFIC_IMAGE} not found in registry. Skipping update."
mkdir -p /tmp/libertyhub
echo "[]" > /tmp/libertyhub/images_to_update.txt
exit 0
fi
else
# Get only existing dockerhub-* packages from GitHub Container Registry
echo "Fetching existing mirrored images from ghcr.io/${ORG}..."
# Use GitHub CLI to list all packages starting with 'dockerhub-'
API_URL="/orgs/${ORG}/packages?package_type=container"
echo "Querying: $API_URL"
gh status
gh api "${API_URL}" > all_images.json
# Initialize IMAGES array
IMAGES=()
# Extract all dockerhub packages in one jq command
mapfile -t IMAGES < <(jq -r '.packages[] | .name | select(startswith("dockerhub-")) | sub("^dockerhub-"; "")' all_images.json)
# Verify we found images
echo "Found ${#IMAGES[@]} mirrored images to check for updates"
if [[ -z "$IMAGES" ]]; then
echo "No existing mirrored images found in GitHub Container Registry."
echo "No images to update."
mkdir -p /tmp/libertyhub
echo "[]" > /tmp/libertyhub/images_to_update.txt
exit 0
fi
fi
# Save images to a file for next step
mkdir -p /tmp/libertyhub
printf "%s\n" "${IMAGES[@]}" > /tmp/libertyhub/images_to_update.txt
echo "Found images to update: ${IMAGES[@]}"
echo "::endgroup::"
- name: Update latest images
run: |
echo "::group::Updating Images"
mkdir -p /tmp/libertyhub
IMAGES=$(cat /tmp/libertyhub/images_to_update.txt)
ORG="${{ github.repository_owner }}"
UPDATED=0
SKIPPED=0
FAILED=0
for IMAGE_NAME in $IMAGES; do
echo "Processing: $IMAGE_NAME"
# Source image will be from Docker Hub
SOURCE_IMAGE="${IMAGE_NAME}:latest"
TARGET_IMAGE="ghcr.io/${ORG}/dockerhub-${IMAGE_NAME}:latest"
echo "Pulling latest from Docker Hub: ${SOURCE_IMAGE}"
if docker pull "${SOURCE_IMAGE}"; then
# Get source digest
SOURCE_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "${SOURCE_IMAGE}" | cut -d '@' -f 2)
# Tag for GitHub packages
docker tag "${SOURCE_IMAGE}" "${TARGET_IMAGE}"
echo "Pushing to GitHub Packages as ${TARGET_IMAGE}"
if docker push "${TARGET_IMAGE}"; then
UPDATED=$((UPDATED+1))
TARGET_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "${TARGET_IMAGE}" | cut -d '@' -f 2)
echo "✅ Updated ${IMAGE_NAME}:latest"
echo " Source Digest: ${SOURCE_DIGEST}"
echo " Target Digest: ${TARGET_DIGEST}"
else
FAILED=$((FAILED+1))
echo "❌ Failed to push ${TARGET_IMAGE}"
fi
else
SKIPPED=$((SKIPPED+1))
echo "⚠️ Could not pull ${SOURCE_IMAGE}, skipping"
fi
echo "-----------------------"
done
echo "::endgroup::"
echo "Update Summary:"
echo "- Updated: $UPDATED"
echo "- Skipped: $SKIPPED"
echo "- Failed: $FAILED"
# Set job status based on results
if [[ $FAILED -gt 0 ]]; then
exit 1
fi