test: verify clean production bootstrap
This commit is contained in:
@@ -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-артефакты.
|
||||
|
||||
|
||||
@@ -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 . .
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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
@@ -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-сертификата.
|
||||
|
||||
|
||||
@@ -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"
|
||||
Executable
+32
@@ -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
@@ -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, лицензия кода и политика данных.
|
||||
|
||||
После каждого пункта необходимо:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user