Re-enable validation with Docker image pull retry logic

Added exponential backoff retry logic to handle Docker Hub CDN
propagation delays (2-5 minutes after push).

Validation workflow now:
- Retries Docker image pull up to 10 times
- Uses exponential backoff: 30s, 60s, 120s, 120s...
- Total timeout: ~10 minutes max
- Continues with asset-only validation if image unavailable

This keeps validation enabled (important for quality) while
fixing the race condition that caused consistent failures.

Related to #695
This commit is contained in:
rcourtman 2025-11-12 13:24:54 +00:00
parent 0ab0309be0
commit c89f5ae773
2 changed files with 44 additions and 27 deletions

View file

@ -436,20 +436,13 @@ jobs:
echo "Review the draft release and publish when ready." echo "Review the draft release and publish when ready."
echo "" echo ""
# Validation disabled - was causing race conditions with Docker image propagation validate-release-assets:
# The release workflow already has comprehensive checks: needs: create-release
# - Version guard uses: ./.github/workflows/validate-release-assets.yml
# - Preflight tests (backend + frontend + linting) secrets: inherit
# - Docker image builds with:
# - Release asset creation with checksums tag: ${{ needs.create-release.outputs.tag }}
# Manual validation can be done after draft release creation if needed version: ${{ inputs.version }}
# validate-release-assets: release_id: ${{ needs.create-release.outputs.release_id }}
# needs: create-release draft: true
# uses: ./.github/workflows/validate-release-assets.yml target_commitish: ${{ needs.create-release.outputs.target_commitish }}
# secrets: inherit
# with:
# tag: ${{ needs.create-release.outputs.tag }}
# version: ${{ inputs.version }}
# release_id: ${{ needs.create-release.outputs.release_id }}
# draft: true
# target_commitish: ${{ needs.create-release.outputs.target_commitish }}

View file

@ -157,23 +157,47 @@ jobs:
if: steps.context.outputs.should_run == 'true' if: steps.context.outputs.should_run == 'true'
run: docker --version run: docker --version
- name: Pull Docker image (if available) - name: Pull Docker image (with retry logic)
if: steps.context.outputs.should_run == 'true' if: steps.context.outputs.should_run == 'true'
id: docker id: docker
continue-on-error: true continue-on-error: true
run: | run: |
IMAGE="rcourtman/pulse:${{ steps.context.outputs.tag }}" IMAGE="rcourtman/pulse:${{ steps.context.outputs.tag }}"
echo "Attempting to pull Docker image: $IMAGE" echo "Attempting to pull Docker image: $IMAGE"
echo "Docker Hub CDN propagation can take 2-5 minutes after push..."
echo ""
if docker pull "$IMAGE" 2>/dev/null; then # Retry logic: 10 attempts with exponential backoff
echo "✓ Docker image available: $IMAGE" # Total time: ~10 minutes max
echo "image_available=true" >> $GITHUB_OUTPUT MAX_ATTEMPTS=10
echo "image=$IMAGE" >> $GITHUB_OUTPUT ATTEMPT=1
else WAIT_TIME=30
echo "⚠️ Docker image not yet available: $IMAGE"
echo "⚠️ Will skip Docker image validation" while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
echo "image_available=false" >> $GITHUB_OUTPUT echo "Attempt $ATTEMPT/$MAX_ATTEMPTS: Pulling image..."
fi
if docker pull "$IMAGE" 2>/dev/null; then
echo "✓ Docker image available: $IMAGE"
echo "image_available=true" >> $GITHUB_OUTPUT
echo "image=$IMAGE" >> $GITHUB_OUTPUT
exit 0
fi
if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then
echo "⚠️ Image not yet available, waiting ${WAIT_TIME}s before retry..."
sleep $WAIT_TIME
WAIT_TIME=$((WAIT_TIME * 2)) # Exponential backoff
if [ $WAIT_TIME -gt 120 ]; then
WAIT_TIME=120 # Cap at 2 minutes
fi
fi
ATTEMPT=$((ATTEMPT + 1))
done
echo "⚠️ Docker image not available after $MAX_ATTEMPTS attempts"
echo "⚠️ Will skip Docker image validation"
echo "image_available=false" >> $GITHUB_OUTPUT
- name: Run validation script - name: Run validation script
if: steps.context.outputs.should_run == 'true' if: steps.context.outputs.should_run == 'true'