bytelyst-devops-tools/scripts/deploy-gigafactory.sh
saravanakumardb1 ae7909018a feat(scripts): one-shot gigafactory deploy + product registration
deploy-gigafactory.sh loads platform-service/.env, starts the fleet backend,
waits for /health, and registers the ecosystem products (idempotent) so live
/api/fleet/* calls resolve. Supports --stop / --register-only / --no-register.
Registered the 11 ecosystem products against the configured Cosmos during a
live run; note fleet metrics needs a composite index on real Azure Cosmos.

Generated with [Devin](https://cli.devin.ai/docs)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-05-30 22:51:27 -07:00

133 lines
5.1 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# deploy-gigafactory.sh — one-shot local deploy of the Agent Gigafactory
# (platform-service fleet module) against the configured backend, then register
# the ecosystem products so live /api/fleet/* calls return data.
#
# Prereqs:
# - learning_ai_common_plat checked out as a sibling of this repo
# - services/platform-service/.env filled (Cosmos endpoint/key, JWT_SECRET, ...)
# e.g. populated from Azure: COSMOS_ENDPOINT/COSMOS_KEY/AZURE_BLOB_CONNECTION_STRING
# - pnpm deps installed in common_plat; Node 18+
#
# Usage:
# ./deploy-gigafactory.sh # start service, wait for health, register products, smoke
# ./deploy-gigafactory.sh --register-only # service already running on $PORT; just register products
# ./deploy-gigafactory.sh --stop # stop a service started by this script
# ./deploy-gigafactory.sh --no-register # start + health only, skip product registration
#
# Env overrides:
# COMMON_PLAT path to learning_ai_common_plat (default: ../learning_ai_common_plat)
# PORT platform-service port (default: 4003)
# PRODUCTS space-separated "id|DisplayName|PREFIX" tuples (default: ecosystem set)
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COMMON_PLAT="${COMMON_PLAT:-$(cd "$HERE/../../learning_ai_common_plat" 2>/dev/null && pwd || true)}"
PORT="${PORT:-4003}"
PS_DIR="$COMMON_PLAT/services/platform-service"
ENV_FILE="$PS_DIR/.env"
PID_FILE="$HERE/.gigafactory-platform-service.pid"
LOG_FILE="${TMPDIR:-/tmp}/gigafactory-platform-service.log"
BASE="http://localhost:$PORT"
PRODUCTS="${PRODUCTS:-\
lysnrai|LysnrAI|LYS \
mindlyst|MindLyst|MIND \
chronomind|ChronoMind|CHR \
jarvisjr|JarvisJr|JAR \
nomgap|NomGap|NOM \
peakpulse|PeakPulse|PEAK \
flowmonk|FlowMonk|FLOW \
notelett|NoteLett|NOTE \
actiontrail|ActionTrail|ACT \
localmemgpt|LocalMemGPT|LMG \
efforise|EffoRise|EFF}"
die() { echo "error: $*" >&2; exit 1; }
stop_service() {
if [ -f "$PID_FILE" ]; then
local pid; pid="$(cat "$PID_FILE")"
if kill -0 "$pid" 2>/dev/null; then kill "$pid" && echo "stopped platform-service (pid $pid)"; fi
rm -f "$PID_FILE"
else
echo "no pid file; nothing started by this script"
fi
}
mint_token() {
node -e '
const c=require("crypto");const s=process.env.JWT_SECRET;
if(!s){console.error("JWT_SECRET not set");process.exit(1);}
const b=o=>Buffer.from(JSON.stringify(o)).toString("base64url");
const h=b({alg:"HS256",typ:"JWT"});const n=Math.floor(Date.now()/1e3);
const p=b({sub:"gigafactory-deploy",email:"deploy@bytelyst.local",role:"admin",type:"access",iat:n,exp:n+3600});
console.log(`${h}.${p}.`+c.createHmac("sha256",s).update(`${h}.${p}`).digest("base64url"));
'
}
wait_for_health() {
echo -n "waiting for $BASE/health "
for _ in $(seq 1 60); do
if curl -fsS "$BASE/health" >/dev/null 2>&1; then echo "— ok"; return 0; fi
echo -n "."; sleep 1
done
echo; die "platform-service did not become healthy (see $LOG_FILE)"
}
register_products() {
local token; token="$(mint_token)"
local created=0 existed=0 failed=0
for tuple in $PRODUCTS; do
IFS='|' read -r id name prefix <<<"$tuple"
local code; code="$(curl -s -o /dev/null -w '%{http_code}' -X POST "$BASE/api/products" \
-H "Authorization: Bearer $token" -H "content-type: application/json" \
-H "x-product-id: $id" \
-d "{\"productId\":\"$id\",\"displayName\":\"$name\",\"licensePrefix\":\"$prefix\"}")"
case "$code" in
200|201) echo " created $id"; created=$((created+1));;
409) echo " exists $id"; existed=$((existed+1));;
*) echo " FAILED $id (HTTP $code)"; failed=$((failed+1));;
esac
done
echo "products: created=$created existed=$existed failed=$failed"
# live smoke: fleet metrics for the first product
local first; first="$(echo "$PRODUCTS" | awk '{print $1}' | cut -d'|' -f1)"
echo -n "smoke GET /api/fleet/metrics ($first): "
curl -s -H "Authorization: Bearer $(mint_token)" -H "x-product-id: $first" \
"$BASE/api/fleet/metrics" | head -c 200; echo
}
# ── main ─────────────────────────────────────────────────────────
case "${1:-}" in
--stop) stop_service; exit 0;;
esac
[ -n "$COMMON_PLAT" ] && [ -d "$PS_DIR" ] || die "platform-service not found (set COMMON_PLAT). Looked in: $PS_DIR"
[ -f "$ENV_FILE" ] || die "$ENV_FILE missing — fill it (Cosmos endpoint/key, JWT_SECRET, blob CS)"
set -a; . "$ENV_FILE"; set +a
if [ "${1:-}" != "--register-only" ]; then
if curl -fsS "$BASE/health" >/dev/null 2>&1; then
echo "platform-service already healthy on :$PORT — reusing it"
else
echo "starting platform-service on :$PORT (log: $LOG_FILE)"
( cd "$PS_DIR" && pnpm exec tsx src/server.ts >"$LOG_FILE" 2>&1 ) &
echo $! >"$PID_FILE"
wait_for_health
fi
fi
if [ "${1:-}" != "--no-register" ]; then
register_products
fi
cat <<EOF
Gigafactory is up on $BASE (health: $BASE/health)
Next:
- Run e2e: (cd "$COMMON_PLAT/dashboards/tracker-web" && pnpm exec playwright test)
- Stop: $HERE/$(basename "$0") --stop
EOF