Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ jobs:
done
curl -fsS http://localhost:8080/ | grep -q "Agentage Design System" \
|| { echo "::error::showcase did not render"; docker logs ds; exit 1; }
# Assert provenance here too, so a build that failed to bake COMMIT_SHA
# fails before prod rather than as an unexplained post-deploy timeout.
got="$(curl -fsS http://localhost:8080/health | grep -o '"commit":"[0-9a-f]\{7,40\}"' | cut -d'"' -f4)"
[ "$got" = "$GITHUB_SHA" ] \
|| { echo "::error::/health commit '$got' != '$GITHUB_SHA'"; exit 1; }
echo "PASS image /health reports $got"
env:
GITHUB_SHA: ${{ github.sha }}

Expand Down Expand Up @@ -107,13 +113,8 @@ jobs:
run: echo "${{ secrets.GITHUB_TOKEN }}" | ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "docker login ghcr.io -u ${{ github.actor }} --password-stdin"
- name: Deploy stack
run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "cd /opt/agentage/ds && docker stack deploy -c docker-compose.yml agentage-ds --with-registry-auth"
- name: Wait + live smoke
- name: Verify deploy
env:
SITE_FQDN: ${{ vars.SITE_FQDN }}
run: |
for i in $(seq 1 40); do
curl -fsS "https://${SITE_FQDN}/" 2>/dev/null | grep -q "Agentage Design System" && { ok=1; break; }
sleep 5
done
echo "Smoke: https://${SITE_FQDN}/"
[ -n "${ok:-}" ] || { echo "::error::${SITE_FQDN} never served the showcase"; exit 1; }
COMMIT_SHA: ${{ github.sha }}
run: bash scripts/verify-deploy.sh
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Single source of truth for the Agentage design system (OKLCH tokens + React comp
- LIVE at https://ds.agentage.io since 2026-08-06. The `dev/` showcase deploys as its own Swarm stack (`agentage-ds`) behind Traefik on the main prod box. Dockerfile builds the static SPA → nginx-unprivileged; `docker-compose.yml` carries the Traefik labels; `.github/workflows/deploy.yml` builds → smokes → deploys on push to master.
- Production-only (the platform-wide dev env was removed 2026-07-30). Gated on `vars.DEPLOY_ENABLED == 'true'` + the `production` environment (`vars.SITE_FQDN`, `SSH_PRIVATE_KEY` / `SSH_HOST` / `SSH_USER`).
- Container healthcheck must probe `127.0.0.1`, not `localhost` — nginx binds IPv4 only; busybox wget picks `::1`.
- Post-deploy verification lives in `scripts/verify-deploy.sh` (estate standard, same shape as auth/dashboard): it asserts `https://${SITE_FQDN}/health` reports **this** commit before checking that the page renders. A content grep alone is fail-open — on a failed rollout Swarm keeps the old task serving and the grep still matches.

## Conventions

Expand Down
46 changes: 46 additions & 0 deletions scripts/verify-deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# Verify the deployed showcase from the public edge after `docker stack deploy`.
# 1. Serves-this-commit - the image bakes COMMIT_SHA into /health, so a failed
# rollout (Swarm keeps the OLD task serving) can't pass silently. Prefix match.
# 2. Renders - the SPA shell is really there, not just a live health file.
# Ordered commit-first on purpose: the content grep alone is fail-open, since the
# previous container answers it just as happily as the new one.
set -euo pipefail

SITE_FQDN="${SITE_FQDN:-ds.agentage.io}"
want="${COMMIT_SHA:?COMMIT_SHA required}"

# grep, not jq/python: the payload is a flat static file and the runner is
# guaranteed nothing beyond coreutils + curl.
read_commit() {
curl -sf "https://${SITE_FQDN}/health" 2>/dev/null |
grep -o '"commit":"[0-9a-f]\{7,40\}"' | cut -d'"' -f4 || true
}

echo "-- serves-this-commit --"
ok=
for i in $(seq 1 30); do
got="$(read_commit)"
case "${want}" in
"${got:-__none__}"*)
echo "PASS showcase serving ${got}"
ok=1
break
;;
esac
echo " attempt $i/30: showcase commit='${got:-<none>}' want='${want:0:12}...'"
[ "$i" -lt 30 ] && sleep 10
done
[ -n "$ok" ] || {
echo "::error::${SITE_FQDN} is not serving ${want} (stale task - rollout did not land)"
exit 1
}

echo "-- renders --"
curl -fsS "https://${SITE_FQDN}/" | grep -q "Agentage Design System" || {
echo "::error::${SITE_FQDN} answered /health but did not render the showcase"
exit 1
}
echo "PASS showcase renders"

echo "Deploy verified against ${SITE_FQDN} (commit ${want:0:12}...)."
Loading