diff --git a/.github/workflows/update-geolite2.yml b/.github/workflows/update-geolite2.yml new file mode 100644 index 00000000..5623a413 --- /dev/null +++ b/.github/workflows/update-geolite2.yml @@ -0,0 +1,220 @@ +name: Update GeoLite2 Checksum + +on: + schedule: + - cron: '0 2 * * 1' # Weekly on Mondays at 2 AM UTC + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + issues: write + +jobs: + update-checksum: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Download and calculate checksum + id: checksum + run: | + set -euo pipefail + + echo "📥 Downloading GeoLite2-Country.mmdb..." + DOWNLOAD_URL="https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-Country.mmdb" + + # Download with retry logic + for i in {1..3}; do + if curl -fsSL "$DOWNLOAD_URL" -o /tmp/geolite2.mmdb; then + echo "✅ Download successful on attempt $i" + break + else + echo "❌ Download failed on attempt $i" + if [ $i -eq 3 ]; then + echo "error=download_failed" >> $GITHUB_OUTPUT + exit 1 + fi + sleep 5 + fi + done + + # Calculate checksum + CURRENT=$(sha256sum /tmp/geolite2.mmdb | cut -d' ' -f1) + + # Validate checksum format (64 hex characters) + if ! [[ "$CURRENT" =~ ^[a-f0-9]{64}$ ]]; then + echo "❌ Invalid checksum format: $CURRENT" + echo "error=invalid_checksum_format" >> $GITHUB_OUTPUT + exit 1 + fi + + # Extract current checksum from Dockerfile + OLD=$(grep "ARG GEOLITE2_COUNTRY_SHA256=" Dockerfile | cut -d'=' -f2) + + # Validate old checksum format + if ! [[ "$OLD" =~ ^[a-f0-9]{64}$ ]]; then + echo "❌ Invalid old checksum format in Dockerfile: $OLD" + echo "error=invalid_dockerfile_checksum" >> $GITHUB_OUTPUT + exit 1 + fi + + echo "🔍 Checksum comparison:" + echo " Current (Dockerfile): $OLD" + echo " Latest (Downloaded): $CURRENT" + + echo "current=$CURRENT" >> $GITHUB_OUTPUT + echo "old=$OLD" >> $GITHUB_OUTPUT + + if [ "$CURRENT" != "$OLD" ]; then + echo "needs_update=true" >> $GITHUB_OUTPUT + echo "⚠️ Checksum mismatch detected - update required" + else + echo "needs_update=false" >> $GITHUB_OUTPUT + echo "✅ Checksum matches - no update needed" + fi + + - name: Update Dockerfile + if: steps.checksum.outputs.needs_update == 'true' + run: | + set -euo pipefail + + echo "📝 Updating Dockerfile with new checksum..." + sed -i "s/ARG GEOLITE2_COUNTRY_SHA256=.*/ARG GEOLITE2_COUNTRY_SHA256=${{ steps.checksum.outputs.current }}/" Dockerfile + + # Verify the change was applied + if ! grep -q "ARG GEOLITE2_COUNTRY_SHA256=${{ steps.checksum.outputs.current }}" Dockerfile; then + echo "❌ Failed to update Dockerfile" + exit 1 + fi + + echo "✅ Dockerfile updated successfully" + + - name: Verify Dockerfile syntax + if: steps.checksum.outputs.needs_update == 'true' + run: | + set -euo pipefail + + echo "🔍 Verifying Dockerfile syntax..." + docker build --dry-run -f Dockerfile . || { + echo "❌ Dockerfile syntax validation failed" + exit 1 + } + echo "✅ Dockerfile syntax is valid" + + - name: Create Pull Request + if: steps.checksum.outputs.needs_update == 'true' + uses: peter-evans/create-pull-request@v6 + with: + title: "chore(docker): update GeoLite2-Country.mmdb checksum" + body: | + 🤖 **Automated GeoLite2 Database Checksum Update** + + The GeoLite2-Country.mmdb database has been updated upstream. + + ### Changes + - **Old checksum:** `${{ steps.checksum.outputs.old }}` + - **New checksum:** `${{ steps.checksum.outputs.current }}` + - **File modified:** `Dockerfile` (line 352) + + ### Verification Required + - [ ] Local build passes: `docker build --no-cache -t test .` + - [ ] Container starts successfully + - [ ] API health check responds: `curl http://localhost:8080/api/v1/health` + - [ ] CI build passes + + ### Testing Commands + ```bash + # Verify checksum locally + curl -fsSL "https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-Country.mmdb" | sha256sum + + # Build and test + docker build --no-cache --pull -t charon:test-geolite2 . + docker run --rm charon:test-geolite2 /app/charon --version + ``` + + ### Related Documentation + - [Dockerfile](/Dockerfile#L352) + - [Implementation Plan](/docs/plans/current_spec.md) + + --- + + **Auto-generated by:** `.github/workflows/update-geolite2.yml` + **Trigger:** Scheduled weekly check (Mondays 2 AM UTC) + branch: bot/update-geolite2-checksum + delete-branch: true + commit-message: | + chore(docker): update GeoLite2-Country.mmdb checksum + + Automated checksum update for GeoLite2-Country.mmdb database. + + Old: ${{ steps.checksum.outputs.old }} + New: ${{ steps.checksum.outputs.current }} + + Auto-generated by: .github/workflows/update-geolite2.yml + labels: | + dependencies + automated + docker + + - name: Report failure via GitHub Issue + if: failure() + uses: actions/github-script@v7 + with: + script: | + const errorType = '${{ steps.checksum.outputs.error }}' || 'unknown'; + const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; + + const errorMessages = { + 'download_failed': '❌ Failed to download GeoLite2-Country.mmdb after 3 attempts', + 'invalid_checksum_format': '❌ Downloaded file produced invalid checksum format', + 'invalid_dockerfile_checksum': '❌ Current Dockerfile contains invalid checksum format', + 'unknown': '❌ Workflow failed with unknown error' + }; + + const title = `🚨 GeoLite2 Checksum Update Failed (${errorType})`; + const body = ` + ## Automated GeoLite2 Update Workflow Failed + + **Error Type:** \`${errorType}\` + **Error Message:** ${errorMessages[errorType] || errorMessages.unknown} + + ### Workflow Details + - **Run URL:** ${runUrl} + - **Triggered:** ${context.eventName === 'schedule' ? 'Scheduled (weekly)' : 'Manual dispatch'} + - **Timestamp:** ${new Date().toISOString()} + + ### Required Actions + 1. Review workflow logs: ${runUrl} + 2. Check upstream source availability: https://github.com/P3TERX/GeoLite.mmdb + 3. Verify network connectivity from GitHub Actions runners + 4. If upstream is unavailable, consider alternative sources + + ### Manual Update (if needed) + \`\`\`bash + # Download and verify checksum + curl -fsSL "https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-Country.mmdb" | sha256sum + + # Update Dockerfile line 352 + vim Dockerfile # or use sed + + # Test build + docker build --no-cache -t test . + \`\`\` + + ### Related Documentation + - [Implementation Plan](/docs/plans/current_spec.md) + - [Workflow File](/.github/workflows/update-geolite2.yml) + + --- + + **Auto-generated by:** \`.github/workflows/update-geolite2.yml\` + `; + + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: title, + body: body, + labels: ['bug', 'automated', 'ci-cd', 'docker'] + });