1. deploy/check-prod-readiness.sh — pre-deploy gating: backup<60min, disk≥5GB на /opt+/var/lib/docker, /health/ready=Healthy, .env required-keys без placeholder'ов. --ssh-host для удалённой проверки. 2. deploy/prod-deploy.sh <api-tag> <web-tag> — blue-green release: pull → green-контейнер на :8088 → migrations (auto) → smoke (/health/ready + /api/me с тест-токеном) → nginx upstream switch → swap → docker compose up -d с обновлённым тэгом. Failure → удаление green, blue остаётся. --skip-web флаг. 3. deploy/prod-rollback.sh <to-tag> — docker pull (если нужно) → docker compose up -d --force-recreate с указанным tag'ом → wait /health/ready до 120с. --dry-run + --skip-web. 4. deploy/post-deploy-smoke.sh — 10 шагов (signup → login → /api/me → list products/counterparties/stores/stock → create+delete product → logout-via-session). JSON парсится через python3 (не grep — споткнулись на пробеле перед `:` в access_token). Telegram-alert через FM_TG_TOKEN/CHAT при провале. Stage-тест: 10/10 ✓. 5. deploy/db-schema-diff.sh — pg_dump --schema-only с обоих хостов через ssh+docker exec, нормализация (sed), diff -u. Exit: 0=идентичны, 1=разница, 2=ошибка. 6. deploy/generate-release-notes.sh <from-tag> <to-tag> — git log group by prefix через awk: feat→✨, fix→🐛, perf→⚡, docs→📚, test/refactor/chore→<details>. Сохраняет docs/release-notes/<tag>.md. 7. .forgejo/workflows/auto-tag.yml — на push в main: если HEAD не помечен → создаёт v<YYYYMMDD>.<N> annotated tag, push в origin, генерирует release-notes для будущего деплоя. Все скрипты идемпотентные, поддерживают --dry-run, не трогают прод. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
6.7 KiB
6.7 KiB
Sprint 21 — stage→prod migration toolchain
Цель: набор скриптов и workflow'ов чтобы первый прод-деплой был не импровизацией, а одной командой с понятным rollback'ом и автоматическими проверками.
Старт: 2026-06-07 (после Sprint 20). Исполнитель: Claude Opus 4.7.
Принципы
- Все mutating-скрипты поддерживают
--dry-run— печатают что бы сделали. - Прод НЕ трогается из этого спринта (только инструментарий).
- Скрипты — идемпотентные: повторный запуск не ломает уже сделанное.
- Failure-режим: оставляем старый контейнер, не каскадим ошибку.
- НЕ трогать:
global.json, prod admin.food-market.kz, POS WPF.
Чек-лист
- 1. Pre-deploy check —
deploy/check-prod-readiness.sh: backup<60min, disk ≥5GB на/opt+/var/lib/docker,/health/readyHealthy, .env содержит required keys без placeholder'ов (CHANGEME/ REPLACE_ME/TODO/dev). Поддерживает--ssh-hostдля удалённой проверки. Опциональная CI-проверка черезFM_CHECK_CI=1. - 2. Blue-green deploy —
deploy/prod-deploy.sh <api-tag> <web-tag>: pull → green-контейнерfood-market-api-nextна :8088 → migrations (auto черезDatabase.Migrate()в Program.cs) → smoke (/health/ready+/api/me) → nginx upstream switch → swap green→blue. Failure → удаляем green, оставляем blue.--skip-webдля api-only. - 3. Rollback —
deploy/prod-rollback.sh <to-tag>:docker image inspect+ fallbackdocker pull→docker compose up -d --force-recreate api webс указанным tag'ом → wait /health/ready до 120с.--skip-webподдерживается. - 4. Post-deploy smoke —
deploy/post-deploy-smoke.sh: 10 сценариев (signup → login → /api/me → list 5 endpoints → create product → delete → logout-via-session). Парсит JSON черезpython3, не grep/cut (после первого фейла на токене с пробелом перед:). Telegram-alert черезFM_TG_TOKEN+FM_TG_CHATпри провале. На stage прогнал 10/10 ✓ (тестовая прогонка). - 5. Stage-prod schema diff —
deploy/db-schema-diff.sh:pg_dump --schema-only --no-owner --no-privileges --no-commentsс обоих хостов черезssh + docker exec, нормализация (sed убирает SET/SELECT pg_catalog.set_config/пустые строки/комментарии),diff -u. Exit 0 = идентичны, 1 = разница, 2 = ошибка получения. - 6. Release notes generator —
deploy/generate-release-notes.sh <from-tag> <to-tag>:git logгруппирует по prefix черезawk: feat → ✨ Новые возможности, fix → 🐛 Исправления, perf → ⚡, docs → 📚, test/refactor/chore →<details>-свёрнутые. Сохраняет вdocs/release-notes/<to-tag>.md. Прогнал на HEAD~3..HEAD — markdown сгенерирован корректно. - 7. Auto-tag workflow —
.forgejo/workflows/auto-tag.yml: на push в main → если HEAD ещё не помечен → создаётv<YYYYMMDD>.<N>где N — порядковый счётчик в дне. Annotated tag (git tag -a), push в origin, дополнительно генерирует release-notes для будущего деплоя (черезdeploy/generate-release-notes.sh).
Журнал
2026-06-07 старт
Sprint 20 закрыт (7/7 ✓). Поехали по prod-toolchain.
2026-06-07 итог
Все 7 пунктов ✓. Прод не трогали (по правилам спринта).
Тестовые прогоны на stage (тест.admin.food-market.kz):
post-deploy-smoke.sh: 10/10 ✓ (signup, login, /api/me, 5×list, create+delete product, logout-via-session). Первая попытка упала на парсинге access_token (пробел перед:в JSON), починил черезpython3 -c 'json.load(...)'. Вторая — на отсутствующем/connect/revocation(OpenIddict не сконфигурирован для revoke), заменил step 10 на DELETE сессии через/api/me/sessions/{id}с fallback'ом на token-valid sanity-check.check-prod-readiness.sh: на stage backup-dir/opt/food-market-data/ backupsне существует (это нормально для stage'а) — FAIL, как и ожидалось. Скрипт фиксирует это с конкретной причиной.generate-release-notes.sh HEAD~3..HEAD: markdown с группировкой по prefix сгенерирован, файл сохранён вdocs/release-notes/.db-schema-diff.shиprod-deploy.sh/prod-rollback.shзапускать на dev-vm против prod невозможно без SSH-настройки — синтаксис проверенbash -n. Реальный прогон только когда user разрешит.
Итог
Все 7 пунктов ✓. Инструментарий для прод-деплоя готов:
| Скрипт | Назначение | --dry-run | Прогон |
|---|---|---|---|
check-prod-readiness.sh |
Pre-deploy gating | ✓ | partial (на stage) |
prod-deploy.sh |
Blue-green release | ✓ | синтаксис |
prod-rollback.sh |
Fast rollback | ✓ | синтаксис |
post-deploy-smoke.sh |
Smoke-suite 10 шагов | ✓ | 10/10 ✓ (stage) |
db-schema-diff.sh |
Stage↔prod schema | ✓ | синтаксис |
generate-release-notes.sh |
Markdown release | ✓ | ✓ (HEAD~3..HEAD) |
.forgejo/workflows/auto-tag.yml |
Auto-tag CI | — | синтаксис (yaml) |
Что нужно от пользователя для реального прода:
/etc/nginx/conf.d/food-market-upstream.confна prod-vm сupstream food_market_api { server 127.0.0.1:8080; }(создать пустым, скриптprod-deploy.shего перепишет).- SSH-ключ от dev-vm на prod-vm + alias
prodв~/.ssh/config. FM_TG_TOKEN/FM_TG_CHATenv-vars для notify (опц.).- Решение поднять prod-БД и сделать первый backup (
food-market-backup.sh). - Решение о dns/sertbot для admin.food-market.kz.