food-market/deploy/db-schema-diff.sh
nns c4a59d7bf2
Some checks failed
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker API / Build + push API (push) Waiting to run
Docker API / Deploy API on stage (push) Blocked by required conditions
Docker Public / Build + push Public (test + latest) (push) Has been cancelled
Docker Web / Build + push Web (push) Has been cancelled
Docker Public / Deploy :test → test.food-market.kz (push) Has been cancelled
Docker Web / Deploy Web on stage (push) Has been cancelled
docs(prod): репа догоняет новую раскладку postgres на prod-vm
05.10.2026 общий postgres-инстанс с чужими боевыми базами (sklad, purchase,
calcman, calcman_staging, makesales + мусорная старая food_market) вынесен
из compose прода food-market в отдельный compose-проект shared-postgres
(контейнер shared-postgres, порт 5434, том food-market-postgres-data external).
Прод food-market поднимается в собственный контейнер food-market-prod-postgres
(порт 5437, том food-market-prod-postgres-data). Простой при разделении — 12с,
соседи живы. См. docs/shared-postgres-followup-progress.md.

Этот коммит синхронизирует репозиторий, чтобы следующий деплой из main не
воскресил старую раскладку:

- deploy/docker-compose.yml: container_name/port/volume приведены к прод-файлу
  (food-market-prod-postgres, 127.0.0.1:5437, food-market-prod-postgres-data).
- deploy/shared-postgres/ (новое): документационная копия соседнего compose'а,
  с явной пометкой «food-market им не управляет».
- deploy/food-market-backup.sh / anonymize-prod.sh / db-schema-diff.sh:
  defaults FM_PG_CONTAINER / FM_PROD_CONT = food-market-prod-postgres.
- docs/RUNBOOK.md: новый раздел «Postgres на prod-vm» с таблицей трёх
  инстансов и явным запретом трогать shared-postgres из наших скриптов.
- docs/backup-restore.md: контейнер в таблице и примерах — новый.

Guards (не в репе — живут в ~/deploy-stage.sh и ~/quality-watchdog.sh)
расширены симметрично: стенду запрещены shared-postgres, food-market-prod-
postgres[-data], 5434/5437; проду — food-market-postgres-data (чужие данные).
Проверка: docker compose config/ps на prod-vm shared-postgres не упоминают,
grep по репе — ни один скрипт не делает docker exec в shared-postgres.
2026-10-06 00:35:54 +05:00

109 lines
4.3 KiB
Bash
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
#
# Sprint 21: сравнение схемы БД stage vs prod.
#
# Делает `pg_dump --schema-only` с обеих БД, diff'ит. Если выводит
# непустой diff — миграция не доехала или local-only изменения.
#
# Подразумевает что обе БД доступны (например через SSH-туннель или
# pg_dump --host=<host>). Дефолтные подключения:
# stage = docker exec food-market-stage-postgres pg_dump (через ssh prod-vm)
# prod = docker exec food-market-prod-postgres pg_dump (через ssh prod-vm)
#
# ВАЖНО: прод-контейнер — `food-market-prod-postgres` (с 2026-10-05). Соседний
# `shared-postgres` на той же машине обслуживает ЧУЖИЕ боевые базы (sklad,
# purchase, calcman, calcman_staging, makesales) и в diff не участвует.
# См. docs/shared-postgres-followup-progress.md.
#
# Usage:
# deploy/db-schema-diff.sh [--stage-host HOST] [--prod-host HOST]
# [--quick] # без TOAST/sequence-details
# [--dry-run] # печать только команд
#
# Выход:
# 0 — схемы идентичны
# 1 — есть различия (печатает diff)
# 2 — ошибка получения дампа
set -uo pipefail
STAGE_HOST="${FM_STAGE_HOST:-nns@192.168.1.190}"
PROD_HOST="${FM_PROD_HOST:-nns@admin.food-market.kz}"
STAGE_CONT="${FM_STAGE_CONT:-food-market-stage-postgres}"
PROD_CONT="${FM_PROD_CONT:-food-market-prod-postgres}"
DB="${FM_PG_DB:-food_market}"
DB_USER="${FM_PG_USER:-food_market}"
QUICK=0
DRY_RUN=0
while [[ $# -gt 0 ]]; do
case "$1" in
--stage-host) STAGE_HOST="$2"; shift 2 ;;
--prod-host) PROD_HOST="$2"; shift 2 ;;
--quick) QUICK=1; shift ;;
--dry-run) DRY_RUN=1; shift ;;
--help|-h) grep -E '^#( |$)' "$0" | sed 's/^# \?//'; exit 0 ;;
*) echo "Unknown: $1" >&2; exit 2 ;;
esac
done
# Флаги pg_dump для schema-only сравнения. --schema-only + --no-owner +
# --no-privileges чтобы дамп был стабильный без role-mismatch'ей между
# инстансами. --no-comments — выключаем COMMENT'ы (они часто шумят).
PGDUMP_FLAGS="--schema-only --no-owner --no-privileges --no-comments"
if [[ $QUICK -eq 1 ]]; then
PGDUMP_FLAGS="$PGDUMP_FLAGS --exclude-table-data=pg_*"
fi
TMP_DIR=$(mktemp -d)
trap "rm -rf $TMP_DIR" EXIT
STAGE_SQL="$TMP_DIR/stage.sql"
PROD_SQL="$TMP_DIR/prod.sql"
log() { echo "[$(date -Iseconds)] $*" >&2; }
dump_remote() {
local host="$1" container="$2" out="$3"
log "dump from $host (container $container) → $out"
if [[ $DRY_RUN -eq 1 ]]; then
echo "[dry-run] ssh $host docker exec $container pg_dump $PGDUMP_FLAGS -U $DB_USER -d $DB > $out"
touch "$out"
return
fi
ssh -o ConnectTimeout=10 "$host" "docker exec $container pg_dump $PGDUMP_FLAGS -U $DB_USER -d $DB" > "$out" 2>/dev/null \
|| { log "FAIL: dump from $host"; return 2; }
}
dump_remote "$STAGE_HOST" "$STAGE_CONT" "$STAGE_SQL" || exit 2
dump_remote "$PROD_HOST" "$PROD_CONT" "$PROD_SQL" || exit 2
# Нормализация: убираем строки которые всегда отличаются (комментарии,
# даты, version-header'ы, OID'ы):
normalize() {
sed -e '/^-- /d' \
-e '/^SET /d' \
-e '/^SELECT pg_catalog.set_config/d' \
-e '/^[[:space:]]*$/d' "$1"
}
# Применяем нормализацию ин-плейс и сравниваем.
normalize "$STAGE_SQL" > "$TMP_DIR/stage.norm"
normalize "$PROD_SQL" > "$TMP_DIR/prod.norm"
log "comparing…"
if diff -u "$TMP_DIR/prod.norm" "$TMP_DIR/stage.norm" > "$TMP_DIR/diff" 2>&1; then
echo "✓ Схемы идентичны (stage == prod)"
exit 0
fi
LINES=$(wc -l < "$TMP_DIR/diff")
echo "✗ Найдены различия: $LINES строк diff'a"
echo
echo "===== diff (prod → stage) ====="
cat "$TMP_DIR/diff"
echo "==============================="
echo
echo "Если разница — новые миграции stage → prod, применить их перед deploy."
echo "Если разница — local-only изменения на prod, разобраться вручную."
exit 1