Add admin container image verification in deploy workflow (#5752)

* Add eagle0.net as server name alias

Allows accessing the site via eagle0.net in addition to prod.eagle0.net.

Note: After deploying, run certbot to add eagle0.net to the SSL certificate:
  certbot --nginx -d prod.eagle0.net -d eagle0.net

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add admin container image verification in deploy workflow

The admin container was running a stale image after the entrypoint was
changed from /app/admin_server to /app/admin_server_linux_amd64. This
happened because:

1. crane pull + docker load doesn't update the :latest tag locally
2. docker-compose fallback to :latest used the old cached image
3. --force-recreate recreated the container but with the old image

Fixes:
- Tag pulled admin image as :latest after docker load (ensures fallback
  uses correct image)
- Add image digest verification after deploy (fails early if wrong
  image is running)
- Add admin startup verification in deploy-blue-green.sh (catches
  container crashes with helpful logs)

This follows the same pattern used in auth_build.yml for auth service
verification.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-31 06:48:53 -08:00
committed by GitHub
co-authored by Claude Opus 4.5
parent af2efce7d2
commit 049f639322
2 changed files with 30 additions and 1 deletions
+17
View File
@@ -330,6 +330,8 @@ jobs:
echo "Pulling Admin image..."
./crane pull "\${ADMIN_IMAGE}" admin.tar && docker load -i admin.tar && rm admin.tar
# Tag as :latest locally so docker-compose fallback uses correct image
docker tag "\${ADMIN_IMAGE}" registry.digitalocean.com/eagle0/admin-server:latest
echo "Pulling JFR Sidecar image..."
./crane pull "\${JFR_SIDECAR_IMAGE}" jfr-sidecar.tar && docker load -i jfr-sidecar.tar && rm jfr-sidecar.tar
@@ -382,6 +384,21 @@ jobs:
docker compose -f docker-compose.prod.yml ps
docker compose -f docker-compose.prod.yml images
# Verify admin container is running the correct image
echo "=== Verifying admin container image ==="
ADMIN_RUNNING_DIGEST=\$(docker inspect admin-server --format '{{.Image}}')
ADMIN_EXPECTED_DIGEST=\$(docker inspect "\${ADMIN_IMAGE}" --format '{{.Id}}')
echo "Expected image: \${ADMIN_IMAGE}"
echo "Expected digest: \${ADMIN_EXPECTED_DIGEST}"
echo "Running digest: \${ADMIN_RUNNING_DIGEST}"
if [ "\${ADMIN_RUNNING_DIGEST}" != "\${ADMIN_EXPECTED_DIGEST}" ]; then
echo "ERROR: Admin container is running wrong image!"
echo "Container entrypoint:"
docker inspect admin-server --format '{{.Config.Entrypoint}}'
exit 1
fi
echo "Admin image verification passed"
# Cleanup
docker container prune -f
docker image prune -f
+13 -1
View File
@@ -317,11 +317,23 @@ main() {
echo "JFR_SIDECAR_ADDR=jfr-sidecar:8081" >> "${env_file}"
fi
# Restart admin to pick up new .env
# Restart admin to pick up new .env and ensure latest image
# Use --no-deps to prevent cascading to auth (which has secrets not available here)
log_info "Restarting admin service..."
docker compose -f "${COMPOSE_FILE}" up -d --force-recreate --no-deps admin
# Verify admin container is running
sleep 3
if ! docker inspect admin-server --format '{{.State.Running}}' 2>/dev/null | grep -q "true"; then
log_error "Admin container failed to start!"
log_error "Container logs:"
docker logs admin-server --tail 20 2>&1 || true
log_error "Container inspect:"
docker inspect admin-server 2>&1 | head -50 || true
exit 1
fi
log_info "Admin service restarted successfully"
# Clean up old instance
log_info "Cleaning up old eagle-${active}..."
docker compose -f "${COMPOSE_FILE}" rm -f "eagle-${active}" 2>/dev/null || true