diff --git a/deploy/DEPLOY.md b/deploy/DEPLOY.md index aa27dd8..f9aaa15 100644 --- a/deploy/DEPLOY.md +++ b/deploy/DEPLOY.md @@ -122,27 +122,21 @@ cp deploy/replicas.env.example deploy/replicas.env # once; add real DSNs bash deploy/sync-replica-schema.sh --init # once, when schemas already match ``` -For every release on **publisher** (`/var/www/superadmin/api`): +For every release, on the publisher (`/var/www/superadmin/api`) and on each replica API directory: ```bash -git pull -npm run replicas:sync # 1) DDL on replicas 2) migrate deploy 3) repair data drift if any -npx prisma generate -npm run build -pm2 restart superadmin-api +npm run update ``` +On the publisher this pulls, installs, applies DDL on the replicas before `prisma migrate deploy`, refreshes subscriptions with `copy_data=false`, builds, and restarts `superadmin-api`. On a replica (no `deploy/replicas.env`) the same command only pulls, installs, generates, builds, and restarts. It does not run `sync-replica-data.sh`. + Check only: ```bash npm run replicas:check # schema + subscription + row counts (settings, tenants, …) ``` -Force data realign from publisher (rare — e.g. after fixing subscriber permissions): - -```bash -npm run replicas:repair-data -``` +Do not use `npm run replicas:sync` or `npm run replicas:repair-data` for a release. Both run the data repair, which disables a subscription and recopies rows without advancing the replication origin. The apply worker then dies replaying old WAL. `npm run update` is the release command. `replicas:sync` runs `sync-replica-data.sh --repair-if-needed` automatically when `settings` / `setting_templates` / `tenants` counts differ from publisher. diff --git a/deploy/update.sh b/deploy/update.sh new file mode 100755 index 0000000..693f50d --- /dev/null +++ b/deploy/update.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# One-step API update. +# +# Master (deploy/replicas.env present): pull, install, ship DDL to replicas, +# generate, build, restart. Schema is applied on subscribers before the publisher +# migrates, then subscriptions are refreshed with copy_data=false. +# +# Replica (no replicas.env): pull, install, generate, build, restart. +# Does not migrate and does not touch the subscription. +# +# Never calls sync-replica-data.sh. That repair disables subscriptions and +# leaves the replication origin behind, so the apply worker dies on replay. +# +# Usage (inside the API directory, or from anywhere): +# bash deploy/update.sh # master if replicas.env exists, else replica +# bash deploy/update.sh --master +# bash deploy/update.sh --replica +# PM2_APP=superadmin-api bash deploy/update.sh +set -euo pipefail + +API_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$API_DIR" + +MODE="${1:-auto}" +case "$MODE" in + auto|--master|--replica) ;; + *) + echo "Usage: $0 [--master|--replica]" >&2 + exit 1 + ;; +esac + +if [[ "$MODE" == auto ]]; then + if [[ -f "$API_DIR/deploy/replicas.env" ]]; then + MODE=--master + else + MODE=--replica + fi +fi + +if [[ "$MODE" == --master && ! -f "$API_DIR/deploy/replicas.env" ]]; then + echo "deploy/replicas.env is missing, so this host is not the publisher." >&2 + exit 1 +fi + +APP="${PM2_APP:-superadmin-api}" +echo "== update $MODE app=$APP dir=$API_DIR" + +git pull --ff-only +npm ci + +if [[ "$MODE" == --master ]]; then + bash "$API_DIR/deploy/sync-replica-schema.sh" +fi + +npx prisma generate +npm run build + +restart_pm2() { + if pm2 describe "$APP" >/dev/null 2>&1; then + pm2 restart "$APP" + return + fi + local user + for user in montime ubuntu; do + if id "$user" >/dev/null 2>&1 && sudo -u "$user" pm2 describe "$APP" >/dev/null 2>&1; then + sudo -u "$user" pm2 restart "$APP" + return + fi + done + echo "pm2 process '$APP' not found. Set PM2_APP to the name from: pm2 list" >&2 + pm2 list || true + exit 1 +} + +restart_pm2 +echo "== update done ($MODE)" diff --git a/package.json b/package.json index f796e23..a099e2f 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "prisma:repair-khanegi-ui-config": "ts-node --transpile-only prisma/repair-khanegi-ui-config.ts", "prisma:copy-sms-between-tenants": "ts-node --transpile-only prisma/copy-sms-between-tenants.ts", "prisma:list-tenants": "ts-node --transpile-only prisma/list-tenants.ts", + "update": "bash deploy/update.sh", "replicas:sync": "bash deploy/sync-replica-schema.sh && bash deploy/sync-replica-data.sh --repair-if-needed", "replicas:check": "bash deploy/sync-replica-schema.sh --check && bash deploy/sync-replica-data.sh --check", "replicas:repair-data": "bash deploy/sync-replica-data.sh --repair",