scripts(scripts): 🔨 Add/update scripts for build automation and deployment workflows
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
7dd9b2b5ed
commit
34961b06c5
4 changed files with 286 additions and 0 deletions
53
scripts/deploy.sh
Executable file
53
scripts/deploy.sh
Executable file
|
|
@ -0,0 +1,53 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# @analytics — Deploy to vps-0 (1984 hosting)
|
||||||
|
# =============================================================================
|
||||||
|
# Usage: ./scripts/deploy.sh
|
||||||
|
# or via: ./run deploy (once wired into run script)
|
||||||
|
#
|
||||||
|
# Requires: quinn-vps SSH alias configured in ~/.ssh/config
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
REMOTE="quinn-vps"
|
||||||
|
REMOTE_DIR="~/analytics"
|
||||||
|
|
||||||
|
echo "==> [1/5] Building services..."
|
||||||
|
cd "$ROOT_DIR" && bun run build:services
|
||||||
|
|
||||||
|
echo "==> [2/5] Syncing source to $REMOTE:$REMOTE_DIR ..."
|
||||||
|
rsync -avz --delete \
|
||||||
|
--exclude=node_modules \
|
||||||
|
--exclude=dist \
|
||||||
|
--exclude=.env \
|
||||||
|
--exclude=.env.* \
|
||||||
|
"$ROOT_DIR/services/" "$REMOTE:$REMOTE_DIR/services/"
|
||||||
|
|
||||||
|
rsync -avz \
|
||||||
|
"$ROOT_DIR/infrastructure/docker-compose.prod.yaml" \
|
||||||
|
"$ROOT_DIR/infrastructure/init.sql" \
|
||||||
|
"$REMOTE:$REMOTE_DIR/infrastructure/"
|
||||||
|
|
||||||
|
rsync -avz \
|
||||||
|
"$ROOT_DIR/package.json" \
|
||||||
|
"$ROOT_DIR/bun.lock" \
|
||||||
|
"$ROOT_DIR/turbo.json" \
|
||||||
|
"$ROOT_DIR/tsconfig.base.json" \
|
||||||
|
"$REMOTE:$REMOTE_DIR/"
|
||||||
|
|
||||||
|
echo "==> [3/5] Installing dependencies on remote..."
|
||||||
|
ssh "$REMOTE" "cd $REMOTE_DIR && bun install --production"
|
||||||
|
|
||||||
|
echo "==> [4/5] Rebuilding and restarting Docker stack..."
|
||||||
|
ssh "$REMOTE" "cd $REMOTE_DIR && docker compose -f infrastructure/docker-compose.prod.yaml --env-file infrastructure/.env.prod up -d --build"
|
||||||
|
|
||||||
|
echo "==> [5/5] Health check..."
|
||||||
|
sleep 5
|
||||||
|
ssh "$REMOTE" "curl -sf http://localhost:4001/health/live && echo 'collector OK' || echo 'collector NOT READY'"
|
||||||
|
ssh "$REMOTE" "curl -sf http://localhost:4003/health/live && echo 'api OK' || echo 'api NOT READY'"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Deployed at $(date '+%Y-%m-%d %H:%M:%S %Z')"
|
||||||
|
echo "Collector: https://data.transquinnftw.com/health"
|
||||||
27
scripts/run/build.sh
Executable file
27
scripts/run/build.sh
Executable file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Build commands for @analytics
|
||||||
|
# Sourced by the top-level ./run script — do not execute directly.
|
||||||
|
# ROOT_DIR is set by the caller.
|
||||||
|
|
||||||
|
case "${2:-all}" in
|
||||||
|
all | "")
|
||||||
|
# ./run build
|
||||||
|
cd "$ROOT_DIR" && bun run build
|
||||||
|
;;
|
||||||
|
|
||||||
|
packages)
|
||||||
|
# ./run build:packages
|
||||||
|
cd "$ROOT_DIR" && bun run build:lib
|
||||||
|
;;
|
||||||
|
|
||||||
|
services)
|
||||||
|
# ./run build:services
|
||||||
|
cd "$ROOT_DIR" && bun run build:services
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Unknown build command: build:${2}"
|
||||||
|
echo "Usage: ./run build[:<packages|services>]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
119
scripts/run/dev.sh
Executable file
119
scripts/run/dev.sh
Executable file
|
|
@ -0,0 +1,119 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Dev environment commands for @analytics
|
||||||
|
# Sourced by the top-level ./run script — do not execute directly.
|
||||||
|
# SCRIPT_DIR and ROOT_DIR are set by the caller.
|
||||||
|
|
||||||
|
ENV_FILE="$ROOT_DIR/infrastructure/.env.dev"
|
||||||
|
COMPOSE_FILE="$ROOT_DIR/infrastructure/docker-compose.dev.yaml"
|
||||||
|
|
||||||
|
_require_env() {
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "ERROR: $ENV_FILE not found."
|
||||||
|
echo " cp infrastructure/.env.dev.example infrastructure/.env.dev"
|
||||||
|
echo " # then edit as needed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_load_env() {
|
||||||
|
_require_env
|
||||||
|
set -a
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$ENV_FILE"
|
||||||
|
set +a
|
||||||
|
}
|
||||||
|
|
||||||
|
_start_infra() {
|
||||||
|
docker compose -f "$COMPOSE_FILE" up -d
|
||||||
|
echo "TimescaleDB: localhost:25434"
|
||||||
|
echo "Redis: localhost:26379"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${2:-}" in
|
||||||
|
"")
|
||||||
|
# ./run dev — full stack
|
||||||
|
_load_env
|
||||||
|
_start_infra
|
||||||
|
echo "Starting all services..."
|
||||||
|
(cd "$ROOT_DIR/services/collector" && bun run dev) &
|
||||||
|
COLLECTOR_PID=$!
|
||||||
|
(cd "$ROOT_DIR/services/processor" && bun run dev) &
|
||||||
|
PROCESSOR_PID=$!
|
||||||
|
(cd "$ROOT_DIR/services/api" && bun run dev) &
|
||||||
|
API_PID=$!
|
||||||
|
(cd "$ROOT_DIR/services/realtime" && bun run dev) &
|
||||||
|
REALTIME_PID=$!
|
||||||
|
echo " Collector → :4001"
|
||||||
|
echo " Processor → (background worker)"
|
||||||
|
echo " API → :4003"
|
||||||
|
echo " Realtime → :4004"
|
||||||
|
echo ""
|
||||||
|
echo "Press Ctrl+C to stop all services."
|
||||||
|
wait $COLLECTOR_PID $PROCESSOR_PID $API_PID $REALTIME_PID
|
||||||
|
;;
|
||||||
|
|
||||||
|
infra)
|
||||||
|
# ./run dev:infra
|
||||||
|
_start_infra
|
||||||
|
;;
|
||||||
|
|
||||||
|
collector)
|
||||||
|
# ./run dev:collector
|
||||||
|
_load_env
|
||||||
|
cd "$ROOT_DIR/services/collector" && bun run dev
|
||||||
|
;;
|
||||||
|
|
||||||
|
processor)
|
||||||
|
# ./run dev:processor
|
||||||
|
_load_env
|
||||||
|
cd "$ROOT_DIR/services/processor" && bun run dev
|
||||||
|
;;
|
||||||
|
|
||||||
|
api)
|
||||||
|
# ./run dev:api
|
||||||
|
_load_env
|
||||||
|
cd "$ROOT_DIR/services/api" && bun run dev
|
||||||
|
;;
|
||||||
|
|
||||||
|
realtime)
|
||||||
|
# ./run dev:realtime
|
||||||
|
_load_env
|
||||||
|
cd "$ROOT_DIR/services/realtime" && bun run dev
|
||||||
|
;;
|
||||||
|
|
||||||
|
stop)
|
||||||
|
# ./run dev:stop
|
||||||
|
docker compose -f "$COMPOSE_FILE" down
|
||||||
|
echo "Dev infrastructure stopped."
|
||||||
|
;;
|
||||||
|
|
||||||
|
status)
|
||||||
|
# ./run dev:status
|
||||||
|
echo "=== Infrastructure ==="
|
||||||
|
docker compose -f "$COMPOSE_FILE" ps
|
||||||
|
echo ""
|
||||||
|
echo "=== Collector (port 4001) ==="
|
||||||
|
curl -sf http://localhost:4001/health/live && echo "" || echo "Not running"
|
||||||
|
echo "=== API (port 4003) ==="
|
||||||
|
curl -sf http://localhost:4003/health/live && echo "" || echo "Not running"
|
||||||
|
echo "=== Realtime (port 4004) ==="
|
||||||
|
curl -sf http://localhost:4004/health/live && echo "" || echo "Not running"
|
||||||
|
;;
|
||||||
|
|
||||||
|
logs)
|
||||||
|
# ./run dev:logs [service]
|
||||||
|
SERVICE="${3:-}"
|
||||||
|
if [ -n "$SERVICE" ]; then
|
||||||
|
docker compose -f "$COMPOSE_FILE" logs -f "$SERVICE"
|
||||||
|
else
|
||||||
|
docker compose -f "$COMPOSE_FILE" logs -f
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Unknown dev command: dev:${2}"
|
||||||
|
echo "Usage: ./run dev[:<infra|collector|processor|api|realtime|stop|status|logs>]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
87
scripts/run/prod.sh
Executable file
87
scripts/run/prod.sh
Executable file
|
|
@ -0,0 +1,87 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Production commands for @analytics
|
||||||
|
# Sourced by the top-level ./run script — do not execute directly.
|
||||||
|
# ROOT_DIR is set by the caller.
|
||||||
|
|
||||||
|
ENV_FILE="$ROOT_DIR/infrastructure/.env.prod"
|
||||||
|
COMPOSE_FILE="$ROOT_DIR/infrastructure/docker-compose.prod.yaml"
|
||||||
|
|
||||||
|
_require_env() {
|
||||||
|
if [ ! -f "$ENV_FILE" ]; then
|
||||||
|
echo "ERROR: $ENV_FILE not found."
|
||||||
|
echo " cp infrastructure/.env.prod.example infrastructure/.env.prod"
|
||||||
|
echo " # then fill in all CHANGE_ME values"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${2:-}" in
|
||||||
|
up)
|
||||||
|
# ./run prod:up
|
||||||
|
_require_env
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d
|
||||||
|
echo "Production stack started."
|
||||||
|
echo " Collector → 127.0.0.1:4001"
|
||||||
|
echo " API → 127.0.0.1:4003"
|
||||||
|
echo " Realtime → 127.0.0.1:4004"
|
||||||
|
echo " TimescaleDB external → :25434"
|
||||||
|
;;
|
||||||
|
|
||||||
|
down)
|
||||||
|
# ./run prod:down
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" down
|
||||||
|
echo "Production stack stopped."
|
||||||
|
;;
|
||||||
|
|
||||||
|
restart)
|
||||||
|
# ./run prod:restart [service]
|
||||||
|
SERVICE="${3:-}"
|
||||||
|
if [ -n "$SERVICE" ]; then
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" restart "$SERVICE"
|
||||||
|
else
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" restart
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
status)
|
||||||
|
# ./run prod:status
|
||||||
|
echo "=== Containers ==="
|
||||||
|
docker compose -f "$COMPOSE_FILE" ps
|
||||||
|
echo ""
|
||||||
|
echo "=== Collector (port 4001) ==="
|
||||||
|
curl -sf http://localhost:4001/health/live && echo "" || echo "Not running"
|
||||||
|
echo "=== API (port 4003) ==="
|
||||||
|
curl -sf http://localhost:4003/health/live && echo "" || echo "Not running"
|
||||||
|
echo "=== Realtime (port 4004) ==="
|
||||||
|
curl -sf http://localhost:4004/health/live && echo "" || echo "Not running"
|
||||||
|
;;
|
||||||
|
|
||||||
|
logs)
|
||||||
|
# ./run prod:logs [service]
|
||||||
|
SERVICE="${3:-}"
|
||||||
|
if [ -n "$SERVICE" ]; then
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" logs -f "$SERVICE"
|
||||||
|
else
|
||||||
|
docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" logs -f
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
keygen)
|
||||||
|
# ./run prod:keygen — generate a new COLLECTOR_WRITE_KEY
|
||||||
|
KEY=$(openssl rand -hex 32)
|
||||||
|
echo ""
|
||||||
|
echo "Generated write key:"
|
||||||
|
echo ""
|
||||||
|
echo " COLLECTOR_WRITE_KEY=$KEY"
|
||||||
|
echo ""
|
||||||
|
echo "Add to infrastructure/.env.prod, then set the same value as"
|
||||||
|
echo "'writeKey' in the AnalyticsConfig passed to AnalyticsProvider."
|
||||||
|
echo ""
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Unknown prod command: prod:${2}"
|
||||||
|
echo "Usage: ./run prod:<up|down|restart|status|logs|keygen>"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Loading…
Add table
Reference in a new issue