test: verify clean production bootstrap

This commit is contained in:
ik
2026-09-06 14:34:05 +07:00
parent 66fb1625da
commit 0f075469c8
9 changed files with 90 additions and 16 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ RF4 Spotter — неофициальный сервис свежих точек
Подробный план и актуальные чекбоксы находятся в [`docs/ROADMAP.md`](docs/ROADMAP.md). Результаты проверки интерфейса и пять приоритетных UX-пакетов описаны в [`docs/UI_UX_AUDIT.md`](docs/UI_UX_AUDIT.md).
Production-контур для домена `rf4spotter.ru`, TLS, секреты, backup/restore и команды первого запуска описаны в [`deploy/README.md`](deploy/README.md). Он использует отдельный `compose.production.yaml`; локальный `compose.yaml` остаётся средой разработки. Production seed добавляет только справочники — демонстрационные уловы отключены.
Production-контур для домена `rf4spotter.ru`, TLS, секреты, backup/restore и команды первого запуска описаны в [`deploy/README.md`](deploy/README.md). Он использует отдельный `compose.production.yaml`; локальный `compose.yaml` остаётся средой разработки. Production seed добавляет только справочники — демонстрационные уловы отключены. Изолированные проверки `deploy/test-production-bootstrap.sh` и `deploy/test-backup-restore.sh` подтверждают старт с пустых volumes и восстановление данных.
Gitea Actions workflow `.gitea/workflows/ci.yml` на каждый push и pull request проверяет Python, миграции на чистой PostgreSQL, Astro build и полный Compose/Playwright-сценарий. При падении E2E сохраняются логи контейнеров и Playwright-артефакты.
+2
View File
@@ -1,5 +1,7 @@
FROM node:22-alpine AS build
WORKDIR /app
ARG PUBLIC_API_URL=http://localhost:8000
ENV PUBLIC_API_URL=$PUBLIC_API_URL
COPY package*.json ./
RUN npm install
COPY . .
+2 -1
View File
@@ -9,7 +9,8 @@
"start": "node ./dist/server/entry.mjs",
"check": "astro check",
"test:unit": "node --test tests/unit/*.test.ts",
"test:e2e": "playwright test"
"test:e2e": "playwright test",
"test:bootstrap": "playwright test tests/production-bootstrap.spec.ts"
},
"dependencies": {
"@astrojs/check": "^0.9.10",
@@ -0,0 +1,23 @@
import { expect, test } from "@playwright/test";
test("production bootstrap supports submission and moderation", async ({ page, request }) => {
const player = `Bootstrap Player ${Date.now()}`;
const x = 7000 + Date.now() % 1000;
const y = x + 1;
await page.goto("/");
await expect(page.getByRole("heading", { name: "Выбирай место, пока клюёт." })).toBeVisible();
await page.goto("/report");
await page.getByLabel("Координата X *").fill(String(x));
await page.getByLabel("Координата Y *").fill(String(y));
await page.getByLabel("Вес, граммы *").fill("4321");
await page.getByLabel("Ник игрока").fill(player);
await page.getByRole("button", { name: "Отправить на проверку" }).click();
await expect(page.getByText("Улов отправлен на модерацию. Спасибо!")).toBeVisible();
const response = await request.get(`${process.env.BOOTSTRAP_API_URL}/api/v1/admin/catch-reports?status=pending`, {
headers: { Authorization: `Bearer ${process.env.BOOTSTRAP_ADMIN_TOKEN}` },
});
expect(response.ok()).toBeTruthy();
expect(await response.text()).toContain(player);
});
+4 -1
View File
@@ -105,7 +105,10 @@ services:
limits: {cpus: "1.00", memory: 1G}
web:
build: ./apps/web
build:
context: ./apps/web
args:
PUBLIC_API_URL: https://${SITE_DOMAIN:?Set SITE_DOMAIN}
restart: unless-stopped
environment:
PUBLIC_API_URL: https://${SITE_DOMAIN:?Set SITE_DOMAIN}
+8 -1
View File
@@ -32,6 +32,14 @@ curl -fsS https://rf4spotter.ru/health
curl -fsS https://rf4spotter.ru/ready
```
До запуска на сервере можно воспроизвести полный production bootstrap на пустых изолированных volumes. Скрипт собирает образы, применяет миграции, проверяет отсутствие демо-уловов, readiness и отправку заявки:
```bash
./deploy/test-production-bootstrap.sh
```
По умолчанию временно используются только loopback-порты `14321` и `18000`; PostgreSQL и MinIO наружу не публикуются. Контур и volumes удаляются после проверки. Drill успешно пройден 6 сентября 2026 года.
API-контейнер перед стартом применяет Alembic-миграции и запускает идемпотентный seed. В production он добавляет только минимальные справочники и точки; демонстрационные уловы жёстко отключены настройкой `SEED_DEMO_DATA=false`.
Проверка TLS и маршрутизации:
@@ -90,7 +98,6 @@ Drill успешно пройден 6 сентября 2026 года. На це
## 7. Что ещё блокирует приглашение альфа-пользователей
- проверка полного bootstrap на пустых volumes;
- политика хранения и удаления пользовательских данных;
- базовый мониторинг `/ready`, диска и срока TLS-сертификата.
+8
View File
@@ -0,0 +1,8 @@
services:
api:
ports:
- "127.0.0.1:${BOOTSTRAP_API_PORT:-18000}:8000"
web:
networks: [backend, edge]
ports:
- "127.0.0.1:${BOOTSTRAP_WEB_PORT:-14321}:4321"
+32
View File
@@ -0,0 +1,32 @@
#!/bin/sh
set -eu
repo=$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)
cd "$repo"
project="rf4-bootstrap-$$"
export COMPOSE_PROJECT_NAME="$project"
export BOOTSTRAP_API_PORT=${BOOTSTRAP_API_PORT:-18000}
export BOOTSTRAP_WEB_PORT=${BOOTSTRAP_WEB_PORT:-14321}
export POSTGRES_PASSWORD=bootstrap-postgres-password
export DATABASE_URL=postgresql+psycopg://rf4:bootstrap-postgres-password@db:5432/rf4_spotter
compose="docker compose --env-file .env.production.example -f compose.production.yaml -f deploy/compose.bootstrap.yaml"
cleanup() {
status=$?
if [ "$status" -ne 0 ]; then
$compose ps >&2 || true
$compose logs --no-color api web db minio >&2 || true
fi
$compose down --volumes --remove-orphans >/dev/null 2>&1 || true
}
trap cleanup EXIT INT TERM
$compose up --build -d --wait db minio api web
curl -fsS "http://127.0.0.1:$BOOTSTRAP_API_PORT/ready" >/dev/null
curl -fsS "http://127.0.0.1:$BOOTSTRAP_WEB_PORT/" >/dev/null
test "$($compose exec -T db psql -At -U rf4 -d rf4_spotter -c 'select version_num from alembic_version')" = "0010"
test "$($compose exec -T db psql -At -U rf4 -d rf4_spotter -c 'select count(*) from fish')" = "2"
test "$($compose exec -T db psql -At -U rf4 -d rf4_spotter -c 'select count(*) from waterbody')" = "2"
test "$($compose exec -T db psql -At -U rf4 -d rf4_spotter -c 'select count(*) from catch_report')" = "0"
WEB_URL="http://127.0.0.1:$BOOTSTRAP_WEB_PORT" BOOTSTRAP_API_URL="http://127.0.0.1:$BOOTSTRAP_API_PORT" BOOTSTRAP_ADMIN_TOKEN=replace-with-at-least-32-random-characters npm --prefix apps/web run test:bootstrap
echo "Production bootstrap passed from empty volumes"
+10 -12
View File
@@ -2,7 +2,7 @@
Этот файл — рабочий источник правды по развитию проекта. После завершения задачи её чекбокс меняется с `[ ]` на `[x]`, рядом добавляется ссылка на коммит или короткое подтверждение проверки. Новые задачи добавляются в соответствующий этап, а не хранятся только в переписке.
Последняя сверка плана со спецификацией, кодом и UI/UX-аудитом: 5 сентября 2026 года.
Последняя сверка плана со спецификацией, кодом и UI/UX-аудитом: 6 сентября 2026 года.
Обозначения:
@@ -59,7 +59,7 @@
- [x] Добавить health/readiness-проверки PostgreSQL, MinIO, API и импорта; отразить их в Compose (`/health` без зависимостей, `/ready` с компонентами и режимом обязательного импорта).
- [x] Добавить структурированные JSON-логи без пользовательских секретов и персональных технических данных (whitelist полей, redaction, request ID; Uvicorn access-log отключён).
- [x] Добавить Gitea Actions CI: backend tests, Astro check/build, E2E и применение всех миграций на чистой PostgreSQL; сохранять логи Compose и Playwright-артефакты при падении (`.gitea/workflows/ci.yml`).
- [ ] Добавить отдельный тест полного bootstrap: пустые volumes → миграции → seed → readiness → основной E2E.
- [x] Добавить отдельный тест полного bootstrap: пустые production volumes → миграции `0010` → seed без демо-уловов → readiness → браузерная отправка и проверка moderation API (`deploy/test-production-bootstrap.sh`, 6 сентября 2026).
- [x] Сделать seed устойчивым к частично заполненной БД: справочники досеиваются независимо, демо-уловы идемпотентны и принудительно отключены в production; повторный/частичный запуск покрыт конфигурационными и интеграционными проверками.
- [ ] Проверить списочные API по требованию раздела 12: пагинация, предсказуемая сортировка и валидация фильтров для справочников, импортов, модерации и внешнего staging.
- [ ] Проверить необходимые индексы PostgreSQL и планы запросов для activity, модерации, дедупликации и очистки rate limit; зафиксировать допустимый бюджет запросов пилота.
@@ -79,7 +79,7 @@
- [ ] Добавить smoke-проверку административной очереди внешних источников на desktop/mobile без публикации реальных записей.
- [ ] Обновить README: архитектура, все переменные окружения, импорт, модерация, backup/restore, эксплуатация логов и известные ограничения.
- [ ] Выбрать лицензию кода и политику использования данных.
- [ ] Завершить production-профиль для `rf4spotter.ru`: Compose, Caddy/TLS, закрытые внутренние сервисы, CORS, resource limits, fail-fast секреты, backup/restore и runbook добавлены; остаются полный bootstrap и проверка на целевом сервере.
- [ ] Завершить production-профиль для `rf4spotter.ru`: Compose, Caddy/TLS, закрытые внутренние сервисы, CORS, resource limits, fail-fast секреты, backup/restore, runbook и полный bootstrap готовы; остаётся проверка DNS/TLS на целевом сервере.
- [ ] Заменить демонстрационные секреты и определить целевое размещение перед внешней публикацией.
## Источники данных и согласование
@@ -115,17 +115,15 @@
## Ближайший рабочий пакет
Технические health/readiness и безопасные логи готовы. Следующие пункты выполняются строго по одному:
Технический production-контур, health/readiness, backup/restore и безопасные логи готовы. Следующие пункты выполняются строго по одному:
1. защита официального импорта от конкурентных запусков;
2. полный bootstrap-тест и исправление seed для частично заполненной БД;
3. security-аудит admin/CORS/headers/secrets и повторной загрузки скриншота;
4. backup/restore PostgreSQL и MinIO с реальной проверкой восстановления;
5. пагинация/сортировка списочных API и индексы PostgreSQL;
6. UI/UX-пакет A: единая шкала активности и числительные;
7. UI/UX-пакеты B–D: мобильная главная, форма и рекорды;
8. accessibility/admin safety и Lighthouse;
9. production-профиль и финальное обновление README.
2. пагинация/сортировка списочных API и индексы PostgreSQL;
3. политика хранения и автоматическая очистка персональных/staging данных;
4. UI/UX-пакеты B–D: мобильная главная, форма и рекорды;
5. accessibility/admin safety и Lighthouse;
6. мониторинг, DNS/TLS и проверка production-профиля на целевом сервере;
7. финальное обновление README, лицензия кода и политика данных.
После каждого пункта необходимо: