name: 🧊 Warm Docker Build Cache run-name: Warm Cache - ${{ inputs.branch || 'main' }} on: schedule: - cron: '0 4 * * 0' workflow_dispatch: inputs: branch: description: 'Branch to use for warming caches' required: false default: 'main' env: REGISTRY: registry.michaelschiemer.de IMAGE_NAME: framework RUNTIME_IMAGE_NAME: framework-runtime jobs: warm: name: Refresh Buildx Caches runs-on: docker-build steps: - name: Install git and tooling shell: sh run: | if ! command -v bash >/dev/null 2>&1 || ! command -v git >/dev/null 2>&1; then apk add --no-cache git bash curl fi bash --version git --version - name: Determine target ref id: target shell: bash run: | TARGET="${{ inputs.branch }}" if [ -z "$TARGET" ]; then TARGET="main" fi echo "target_ref=$TARGET" >> "$GITHUB_OUTPUT" echo "TARGET_REF=$TARGET" >> $GITHUB_ENV echo "BRANCH_NAME=$TARGET" >> $GITHUB_ENV - name: Download CI helpers shell: bash env: CI_TOKEN: ${{ secrets.CI_TOKEN }} run: | set -euo pipefail REF="${{ steps.target.outputs.target_ref }}" URL="https://git.michaelschiemer.de/${{ github.repository }}/raw/${REF}/scripts/ci/clone_repo.sh" mkdir -p /tmp/ci-tools if [ -n "$CI_TOKEN" ]; then curl -sfL -u "$CI_TOKEN:x-oauth-basic" "$URL" -o /tmp/ci-tools/clone_repo.sh else curl -sfL "$URL" -o /tmp/ci-tools/clone_repo.sh fi chmod +x /tmp/ci-tools/clone_repo.sh - name: Checkout repository shell: bash env: TARGET_REF: ${{ steps.target.outputs.target_ref }} run: | export CI_REPOSITORY="${{ github.repository }}" export CI_TOKEN="${{ secrets.CI_TOKEN }}" export CI_REF_NAME="$TARGET_REF" export CI_INPUT_BRANCH="$TARGET_REF" export CI_DEFAULT_BRANCH="main" export CI_TARGET_DIR="/workspace/repo" export CI_FETCH_DEPTH="1" /tmp/ci-tools/clone_repo.sh cd /workspace/repo git rev-parse HEAD - name: Setup Docker Buildx shell: bash run: | docker buildx version || echo "Buildx nicht gefunden" if ! docker buildx ls 2>/dev/null | grep -q builder; then docker buildx create --name builder --use --driver docker-container else docker buildx use builder fi docker buildx inspect --bootstrap - name: Login to registry id: login shell: bash run: | REGISTRY_USER="${{ secrets.REGISTRY_USER }}" REGISTRY_PASSWORD="${{ secrets.REGISTRY_PASSWORD }}" REGISTRY_URL="${{ env.REGISTRY }}" DEPLOYMENT_HOST="94.16.110.151" if [ -z "$REGISTRY_USER" ] || [ -z "$REGISTRY_PASSWORD" ]; then echo "❌ Error: Registry credentials missing" exit 1 fi echo "🔐 Logging in to registry..." HOST_IP=$(ip route | grep default | awk '{print $3}' 2>/dev/null | head -1 || echo "$DEPLOYMENT_HOST") REGISTRY_URLS=( "registry.michaelschiemer.de" "$REGISTRY_URL" "$DEPLOYMENT_HOST" "$DEPLOYMENT_HOST:5000" "${HOST_IP}:5000" ) LOGIN_SUCCESS=false for TEST_URL in "${REGISTRY_URLS[@]}"; do echo "🔍 Testing registry: $TEST_URL" if [[ "$TEST_URL" == *":5000" ]]; then HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "http://$TEST_URL/v2/" 2>&1 || echo "000") if [ "$HTTP_CODE" = "401" ] || [ "$HTTP_CODE" = "200" ]; then set +e LOGIN_OUTPUT=$(echo "$REGISTRY_PASSWORD" | docker login "$TEST_URL" -u "$REGISTRY_USER" --password-stdin 2>&1) LOGIN_EXIT_CODE=$? set -e if [ $LOGIN_EXIT_CODE -eq 0 ]; then REGISTRY_URL="$TEST_URL" LOGIN_SUCCESS=true break fi fi else HTTPS_CODE=$(curl -k -s -o /dev/null -w "%{http_code}" "https://$TEST_URL/v2/" 2>&1 || echo "000") if [ "$HTTPS_CODE" = "401" ] || [ "$HTTPS_CODE" = "200" ]; then set +e LOGIN_OUTPUT=$(echo "$REGISTRY_PASSWORD" | docker login "$TEST_URL" -u "$REGISTRY_USER" --password-stdin 2>&1) LOGIN_EXIT_CODE=$? set -e if [ $LOGIN_EXIT_CODE -eq 0 ]; then REGISTRY_URL="$TEST_URL" LOGIN_SUCCESS=true break fi fi fi done if [ "$LOGIN_SUCCESS" = false ]; then echo "❌ Registry login failed" exit 1 fi echo "✅ Registry login successful: $REGISTRY_URL" echo "REGISTRY_URL=$REGISTRY_URL" >> $GITHUB_ENV echo "CACHE_REGISTRY=${{ env.REGISTRY }}" >> $GITHUB_ENV - name: Warm runtime base cache shell: bash env: REGISTRY_URL: ${{ env.REGISTRY_URL }} CACHE_REGISTRY: ${{ env.CACHE_REGISTRY }} run: | cd /workspace/repo TARGET_REGISTRY="$CACHE_REGISTRY" if [ -z "$TARGET_REGISTRY" ]; then TARGET_REGISTRY="$REGISTRY_URL" fi IMAGE_NAME="${{ env.RUNTIME_IMAGE_NAME }}" DATE_TAG="warm-$(date -u +%Y%m%d%H%M)" BRANCH_NAME="${{ env.BRANCH_NAME || 'main' }}" # Build cache sources - multiple sources for better cache hit rate CACHE_SOURCES=( "type=registry,ref=${TARGET_REGISTRY}/${IMAGE_NAME}:buildcache" "type=registry,ref=${TARGET_REGISTRY}/${IMAGE_NAME}:${BRANCH_NAME}-cache" "type=registry,ref=${TARGET_REGISTRY}/${IMAGE_NAME}:latest" ) CACHE_FROM_ARGS="" for CACHE_SRC in "${CACHE_SOURCES[@]}"; do CACHE_FROM_ARGS="${CACHE_FROM_ARGS} --cache-from ${CACHE_SRC}" done docker buildx build \ --platform linux/amd64 \ --file ./Dockerfile.production \ --target runtime-base \ --build-arg RUNTIME_IMAGE=runtime-base \ ${CACHE_FROM_ARGS} \ --cache-to type=registry,ref="${TARGET_REGISTRY}/${IMAGE_NAME}:buildcache",mode=max \ --cache-to type=registry,ref="${TARGET_REGISTRY}/${IMAGE_NAME}:${BRANCH_NAME}-cache",mode=max \ --tag "$TARGET_REGISTRY/$IMAGE_NAME:$DATE_TAG" \ --push \ . - name: Warm production cache shell: bash env: REGISTRY_URL: ${{ env.REGISTRY_URL }} CACHE_REGISTRY: ${{ env.CACHE_REGISTRY }} run: | cd /workspace/repo REGISTRY_TO_USE="$REGISTRY_URL" CACHE_TARGET="$CACHE_REGISTRY" if [ -z "$CACHE_TARGET" ]; then CACHE_TARGET="$REGISTRY_TO_USE" fi IMAGE_NAME="${{ env.IMAGE_NAME }}" DATE_TAG="warm-$(date -u +%Y%m%d%H%M)" BRANCH_NAME="${{ env.BRANCH_NAME || 'main' }}" DEFAULT_RUNTIME="$CACHE_TARGET/${{ env.RUNTIME_IMAGE_NAME }}:latest" RUNTIME_ARG="runtime-base" if docker pull "$DEFAULT_RUNTIME" >/dev/null 2>&1; then RUNTIME_ARG="$DEFAULT_RUNTIME" fi # Build cache sources - multiple sources for better cache hit rate CACHE_SOURCES=( "type=registry,ref=${CACHE_TARGET}/${IMAGE_NAME}:buildcache" "type=registry,ref=${REGISTRY_TO_USE}/${IMAGE_NAME}:${BRANCH_NAME}-cache" "type=registry,ref=${REGISTRY_TO_USE}/${IMAGE_NAME}:latest" ) CACHE_FROM_ARGS="" for CACHE_SRC in "${CACHE_SOURCES[@]}"; do CACHE_FROM_ARGS="${CACHE_FROM_ARGS} --cache-from ${CACHE_SRC}" done docker buildx build \ --platform linux/amd64 \ --file ./Dockerfile.production \ --build-arg RUNTIME_IMAGE="$RUNTIME_ARG" \ ${CACHE_FROM_ARGS} \ --cache-to type=registry,ref="${CACHE_TARGET}/${IMAGE_NAME}:buildcache",mode=max \ --cache-to type=registry,ref="${REGISTRY_TO_USE}/${IMAGE_NAME}:${BRANCH_NAME}-cache",mode=max \ --tag "$REGISTRY_TO_USE/$IMAGE_NAME:$DATE_TAG" \ --push \ . - name: Cleanup warm tags shell: bash env: REGISTRY_URL: ${{ env.REGISTRY_URL }} CACHE_REGISTRY: ${{ env.CACHE_REGISTRY }} run: | echo "â„šī¸ Cleanup of warm tags deferred to registry retention policy"