feat(admin): apix-admin UI at admin.api-index.org
Deploy to Production / deploy (push) Failing after 47s
Deploy to Production / deploy (push) Failing after 47s
Internal maintainer dashboard: global stats, sandbox list with
tier-filter and pagination, sandbox drill-down with D3 world map,
tier-promotion form. API-key auth via HttpOnly cookie. Port 8084,
rolling a/b deploy alongside the existing service pairs.
- apix-common: AdminSandboxSummary, AdminSandboxListResponse, AdminStatsResponse DTOs
- apix-registry: AdminResource (4 endpoints), SandboxService.listAllSandboxes + getGlobalStats
- apix-registry: SandboxResource GET /{uuid}/dashboard endpoint (was missing — fixes portal 500)
- apix-portal: RegistryClient path corrected to /dashboard
- apix-admin: new Quarkus module — auth filter, registry REST client, 3 resources, 6 Qute templates, admin.js
- infra: Dockerfile.admin, docker-compose admin-a/b services, Caddyfile admin.api-index.org block
- scripts: deploy-bluegreen.sh extended for admin-a/b
Co-Authored-By: Mira Rehfeld <noreply@anthropic.com>
This commit is contained in:
@@ -59,24 +59,27 @@ docker build -f infra/Dockerfile.registry -t apix-registry:latest . -q
|
||||
docker build -f infra/Dockerfile.portal -t apix-portal:latest . -q
|
||||
docker build -f infra/Dockerfile.demo -t apix-demo:latest . -q
|
||||
docker build -f infra/Dockerfile.spider -t apix-spider:latest . -q
|
||||
docker build -f infra/Dockerfile.admin -t apix-admin:latest . -q
|
||||
|
||||
# ── 4. Rolling restart: a-stack (registry-a → portal-a + demo-a) ─────────────
|
||||
log "Rolling restart: a-stack..."
|
||||
$COMPOSE up -d --no-deps --force-recreate registry-a
|
||||
wait_healthy "registry-a"
|
||||
|
||||
$COMPOSE up -d --no-deps --force-recreate portal-a demo-a
|
||||
$COMPOSE up -d --no-deps --force-recreate portal-a demo-a admin-a
|
||||
wait_healthy "portal-a"
|
||||
wait_healthy "demo-a"
|
||||
wait_healthy "admin-a"
|
||||
|
||||
# ── 5. Rolling restart: b-stack ───────────────────────────────────────────────
|
||||
log "Rolling restart: b-stack..."
|
||||
$COMPOSE up -d --no-deps --force-recreate registry-b
|
||||
wait_healthy "registry-b"
|
||||
|
||||
$COMPOSE up -d --no-deps --force-recreate portal-b demo-b
|
||||
$COMPOSE up -d --no-deps --force-recreate portal-b demo-b admin-b
|
||||
wait_healthy "portal-b"
|
||||
wait_healthy "demo-b"
|
||||
wait_healthy "admin-b"
|
||||
|
||||
# ── 6. Spider (cron job — restart acceptable) ─────────────────────────────────
|
||||
log "Restarting spider..."
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
# promote-sandbox.sh — Promote a sandbox tier + fetch demo ecosystem UUID
|
||||
# Run on the server: bash promote-sandbox.sh
|
||||
set -euo pipefail
|
||||
|
||||
ENV_FILE="/opt/apix/.env"
|
||||
REGISTRY="https://api-index.org"
|
||||
|
||||
# ── Adjust these ───────────────────────────────────────────────────────────────
|
||||
SANDBOX_ID="25321050-4707-4e85-bd9f-877ab04e4a55"
|
||||
NEW_TIER="COMMUNITY"
|
||||
# ──────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
ADMIN_KEY=$(grep -oP '(?<=APIX_API_KEY=).+' "$ENV_FILE" | tr -d '[:space:]')
|
||||
|
||||
if [[ -z "$ADMIN_KEY" ]]; then
|
||||
echo "ERROR: APIX_API_KEY not found in $ENV_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> Promoting sandbox $SANDBOX_ID to $NEW_TIER ..."
|
||||
curl -s -X PATCH "$REGISTRY/sandbox/admin/$SANDBOX_ID/tier" \
|
||||
-H "X-Admin-Key: $ADMIN_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"tier\":\"$NEW_TIER\"}" | python3 -m json.tool
|
||||
|
||||
echo ""
|
||||
echo "==> Demo ecosystem sandbox UUID ..."
|
||||
docker exec "$(docker ps -qf name=demo-a)" \
|
||||
psql -U apix -d apix -t -A \
|
||||
-c "SELECT value FROM demo_config WHERE key='sandbox.id';"
|
||||
+8
-9
@@ -11,6 +11,12 @@ info() { echo -e "${GREEN}[apix]${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[warn]${NC} $*"; }
|
||||
die() { echo -e "${RED}[fail]${NC} $*" >&2; exit 1; }
|
||||
|
||||
_on_exit() {
|
||||
echo ""
|
||||
read -rp "Press Enter to close…" _
|
||||
}
|
||||
trap _on_exit EXIT
|
||||
|
||||
warn "This will DROP and recreate the local 'apix' database."
|
||||
read -rp "Continue? [y/N] " confirm
|
||||
[[ "${confirm,,}" == "y" ]] || { echo "Aborted."; exit 0; }
|
||||
@@ -58,12 +64,5 @@ for i in $(seq 1 30); do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
info "Running Liquibase migrations"
|
||||
mvn -q liquibase:update -pl apix-registry \
|
||||
-Dliquibase.url="jdbc:postgresql://localhost:${DB_PORT}/${DB_NAME}" \
|
||||
-Dliquibase.username="$DB_USER" \
|
||||
-Dliquibase.password="$DB_PASS"
|
||||
info "Migrations applied"
|
||||
|
||||
info "Reset complete — starting dev servers"
|
||||
"$SCRIPT_DIR/dev.sh"
|
||||
info "Reset complete — starting dev servers (Quarkus applies migrations at startup)"
|
||||
exec "$SCRIPT_DIR/dev.sh"
|
||||
|
||||
@@ -13,6 +13,9 @@ TARGET="${1:-all}"
|
||||
GREEN='\033[0;32m'; NC='\033[0m'
|
||||
info() { echo -e "${GREEN}[apix]${NC} $*"; }
|
||||
|
||||
_on_exit() { echo ""; read -rp "Press Enter to close…" _; }
|
||||
trap _on_exit EXIT
|
||||
|
||||
# ── tmux mode ────────────────────────────────────────────────────────────────
|
||||
if command -v tmux &>/dev/null && tmux has-session -t apix-dev 2>/dev/null; then
|
||||
_restart_window() {
|
||||
|
||||
+6
-20
@@ -116,27 +116,13 @@ for i in $(seq 1 30); do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# ── 6. Liquibase migrations ───────────────────────────────────────────────────
|
||||
# ── 6. Note on migrations ─────────────────────────────────────────────────────
|
||||
step "Database migrations"
|
||||
JDBC_URL="jdbc:postgresql://localhost:${DB_PORT}/${DB_NAME}"
|
||||
|
||||
if [[ ! -f "$PROJECT_ROOT/pom.xml" ]]; then
|
||||
warn "No pom.xml found — Maven project not scaffolded yet (WORKLOG Block 1 / C-00)."
|
||||
warn "Skipping Liquibase migrations. Run this script again after completing Block 1."
|
||||
else
|
||||
# apix-registry depends on apix-common and apix-verification; install them
|
||||
# to the local repository first so Maven can resolve them during the
|
||||
# liquibase:update goal (no source files yet — this completes in seconds).
|
||||
info "Installing shared modules to local repository…"
|
||||
mvn -q install -pl apix-common,apix-verification -DskipTests
|
||||
|
||||
info "Running Liquibase migrations on $JDBC_URL"
|
||||
mvn -q liquibase:update -pl apix-registry \
|
||||
-Dliquibase.url="$JDBC_URL" \
|
||||
-Dliquibase.username="$DB_USER" \
|
||||
-Dliquibase.password="$DB_PASS"
|
||||
info "Migrations applied"
|
||||
fi
|
||||
# Migrations are applied automatically by Quarkus at startup via
|
||||
# quarkus.liquibase.migrate-at-start=true. Running them separately via the
|
||||
# Maven Liquibase plugin records a different classpath prefix in DATABASECHANGELOG
|
||||
# than Quarkus uses, causing a "relation already exists" conflict on next start.
|
||||
info "Migrations will run automatically when Quarkus starts (migrate-at-start=true)."
|
||||
|
||||
# ── Done ──────────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
|
||||
Reference in New Issue
Block a user