`npm test` did nothing until now. CI that runs no tests is theatre, so the tests came first — 39 of them, over the two places where an error would be silent and expensive. packages/core: the margin arithmetic. Every dashboard figure, idle-capacity alert and agent answer resolves through it, and wrong numbers still look like numbers. The cases pin decisions rather than implementation: cost is charged against the full commitment (a naive version reports the opposite sign on a loss-making block), aggregation sums cents rather than averaging percentages (averaging reports +22% on a book that is losing money), break-even prices the remaining hours and returns null rather than Infinity when there are none, and internal research burn counts as cost with no revenue. packages/prime: the upstream mapping. Rounding rather than truncating cents, because 2.43 is 2.4299999 in binary and a lost cent compounds across millions of GPU-hours. And interconnect normalisation, where an unrecognised fabric maps to Unknown rather than Ethernet — guessing low loses a deal, guessing high sells a training customer a cluster that cannot train. CI runs on push and pull request: typecheck all six packages, unit tests, migrations applied twice to a real Postgres, a seed-idempotency assertion that fails the build if row counts move on a second run, a server boot, the front-end build, and a Docker build. It also asserts the inline theme script's hash still matches the CSP the proxy allows. That script prevents a white flash for dark-mode users; if it changes without the CSP being updated, the browser silently blocks it and nothing anywhere reports an error. Deployment stays a script rather than push-to-deploy. Automating it would put an SSH key with production write access on the CI runner — a real escalation for a project this size. The script takes a database dump before migrating and refuses to finish if an unauthenticated request returns anything but 401. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Executable
+69
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Deploy PIG. Run on the host that serves it.
|
||||
#
|
||||
# ./scripts/deploy.sh
|
||||
#
|
||||
# Deliberately a script rather than automated push-to-deploy. Automating it
|
||||
# would mean putting an SSH key with write access to the production host onto
|
||||
# the CI runner, which is a meaningful escalation for a project this size. CI
|
||||
# proves the commit is sound; a human decides when it ships.
|
||||
#
|
||||
# Safe to re-run. Migrations are additive and tracked.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
echo "==> Fetching"
|
||||
git fetch -q origin
|
||||
BEFORE=$(git rev-parse --short HEAD)
|
||||
git reset --hard -q origin/main
|
||||
AFTER=$(git rev-parse --short HEAD)
|
||||
|
||||
if [ "$BEFORE" = "$AFTER" ]; then
|
||||
echo " Already at $AFTER"
|
||||
else
|
||||
echo " $BEFORE -> $AFTER"
|
||||
git --no-pager log --oneline "$BEFORE..$AFTER" | sed 's/^/ /'
|
||||
fi
|
||||
|
||||
echo "==> Backing up the database first"
|
||||
# Cheap insurance. A migration that goes wrong on a database holding real deal
|
||||
# data is not something to discover without a dump in hand.
|
||||
mkdir -p backups
|
||||
BACKUP="backups/pig-$(date +%Y%m%d-%H%M%S).sql.gz"
|
||||
sudo docker compose -p pig exec -T db pg_dump -U pig pig | gzip > "$BACKUP"
|
||||
echo " $BACKUP ($(du -h "$BACKUP" | cut -f1))"
|
||||
|
||||
echo "==> Building and starting"
|
||||
sudo docker compose -p pig up -d --build
|
||||
|
||||
echo "==> Waiting for health"
|
||||
for _ in $(seq 1 60); do
|
||||
if curl -sf http://127.0.0.1:8920/api/health > /dev/null; then break; fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
echo "==> Migrating"
|
||||
sudo docker compose -p pig exec -T app npx tsx packages/db/src/migrate.ts
|
||||
|
||||
echo "==> Verifying"
|
||||
if curl -sf http://127.0.0.1:8920/api/health | grep -q '"ok":true'; then
|
||||
echo " health ok"
|
||||
else
|
||||
echo " HEALTH CHECK FAILED"
|
||||
sudo docker compose -p pig logs app --tail 40
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Authentication must be enforced. A deploy that accidentally serves the CRM
|
||||
# unauthenticated is the one failure worth blocking on.
|
||||
CODE=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8920/api/dashboard)
|
||||
if [ "$CODE" != "401" ]; then
|
||||
echo " UNAUTHENTICATED REQUEST RETURNED $CODE, EXPECTED 401"
|
||||
exit 1
|
||||
fi
|
||||
echo " auth enforced"
|
||||
|
||||
echo "==> Deployed $AFTER"
|
||||
Reference in New Issue
Block a user