#!/bin/bash # 0.2.1 生产部署 (master 分支 CI 调用; 也可在服务器手工执行) # # 架构: app(3001 对外) + pg(内网) + powersync(内网), 见 deploy/prod/ # 幂等: 迁移 -> publication -> 起栈; 任一环节失败则退出, 不切换流量 # # 所需环境变量 (由 CI secrets 注入): # PG_PASSWORD, PS_STORAGE_PASSWORD, JWT_SECRET, POWERSYNC_JWT_SECRET, # POWERSYNC_JWT_KEY_B64, PUBLIC_URL(可选, 默认 https://iboard.honor3.com) set -euo pipefail ROOT="${ROOT:-/app/iboard-prod}" COMPOSE_FILE="$ROOT/deploy/prod/docker-compose.yml" ENV_FILE="$ROOT/deploy/prod/.env" PROJECT="iboard-prod" log() { echo "[deploy] $*"; } die() { echo "[deploy][ERROR] $*" >&2; exit 1; } for v in PG_PASSWORD PS_STORAGE_PASSWORD JWT_SECRET POWERSYNC_JWT_SECRET POWERSYNC_JWT_KEY_B64; do [ -n "${!v:-}" ] || die "缺少环境变量 $v (请在 Gitea Actions secrets 配置)" done [ -f "$COMPOSE_FILE" ] || die "找不到 $COMPOSE_FILE (源码需上传到 $ROOT)" log "写入 $ENV_FILE" umask 077 cat > "$ENV_FILE" </dev/null 2>&1; then break fi sleep 2 done log "执行数据库迁移" docker run --rm --network "${PROJECT}_default" \ -e DATABASE_URL="postgresql://iboard:${PG_PASSWORD}@pg:5432/iboard" \ iboard:latest npx prisma migrate deploy log "确保逻辑复制 publication 存在" docker compose --project-name "$PROJECT" --env-file "$ENV_FILE" -f "$COMPOSE_FILE" exec -T pg \ psql -U iboard -d iboard -v ON_ERROR_STOP=1 -f /dev/stdin < sql/publication.sql log "启动应用与同步服务" docker compose --project-name "$PROJECT" --env-file "$ENV_FILE" -f "$COMPOSE_FILE" up -d app powersync log "等待健康检查" for i in $(seq 1 30); do if curl -fsS --max-time 3 http://127.0.0.1:3001/api/health >/dev/null 2>&1; then log "健康检查通过" exit 0 fi sleep 2 done die "应用未通过健康检查, 请查看 docker compose logs"