docs: split integrator guide (Diplodoc) vs internal docs + add build-docs CI
Чёткое разделение audiences:
- docs/ — consumer-facing only, Diplodoc-built. Public contract для
интеграторов (Альтум, BI, third-party).
- docs-internal/ — operator runbooks, status snapshots, legacy tech pages.
НЕ в Diplodoc build, НЕ публикуются.
Изменения:
- Move docs/{ops,status,tech} → docs-internal/{ops,status,tech}
- docs/toc.yaml: убраны секции Operations, Архитектура (legacy), Status
- docs/index.md: убран tab "оператор / on-call", focus на integrators
- docs/README.md: rewritten — scope только integrator guide, editorial
guidelines (no leak internal architecture, stable API contract)
- .yfm: убран явный ignore status/* (теперь не нужно — папка переехала)
- docs-internal/README.md: index для внутренней документации с rationale
разделения
Scrubbing implementation details из Diplodoc страниц:
- events.md: убраны Strimzi/cluster.142 references, OutboxPoller детали,
internal alert names (OrdinisOutboxLagHigh, OrdinisOutboxDLQNonEmpty),
metric names (nsi_outbox_*). Заменены на consumer-observable contract.
- webhooks.md: убраны metric names (nsi_webhook_ssrf_rejected_total),
alert table (OrdinisWebhookHighFailureRate и т.д.). Retry policy
переписана на user-side perspective.
- errors.md: убран alert name OrdinisReadApiErrorBudgetBurnFast, Tempo
endpoint URL, internal connection details.
- x-references.md: OrphanReferenceScanner → general "Ordinis периодически
детектирует". Убраны metric/alert names. Cascade roadmap без link на
internal design doc.
- auth.md: убран file path ScopeContext.java.
- bundle-cuod.md: убран Maven module path.
- caching.md: cascade design link заменён на text reference.
CI:
- .gitlab-ci.yml: новый job build-docs (stage: build) — Node 20 alpine,
pnpm install --frozen-lockfile + pnpm build, artifact docs/_dist на
неделю. Triggers: auto на docs/**, либо manual web. Готов к follow-up
pages-deploy job когда host решён.
- Новый pattern .docs-changes для rules.
Build verified clean: 13 HTML pages, 6.9M, no broken links/refs.
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
# Runbook: Liquibase миграции БД
|
||||
|
||||
**Источник правды:** `ordinis-migrations/src/main/resources/db/changelog/`
|
||||
- `master.xml` — список включённых changelog'ов в порядке применения.
|
||||
- `changes/00NN-*.xml` — конкретные изменения (CREATE TABLE, ADD COLUMN и т.д.).
|
||||
|
||||
Миграции применяются **автоматически** при старте `ordinis-app` через
|
||||
`spring.liquibase` (Spring Boot starter). Если миграция падает — pod
|
||||
не стартует, остальные pods тоже не поднимутся (read-api/projection-writer
|
||||
имеют startup-зависимость от схемы БД).
|
||||
|
||||
## 1. Просмотр applied миграций
|
||||
|
||||
```bash
|
||||
export KUBECONFIG=/tmp/kubeconfig-161
|
||||
PG_PASS=$(kubectl get secret -n ordinis-staging ordinis-postgres-app \
|
||||
-o jsonpath='{.data.password}' | base64 -d)
|
||||
kubectl exec -n ordinis-staging ordinis-postgres-1 -c postgres -- \
|
||||
env PGPASSWORD="$PG_PASS" psql -h localhost -U ordinis_app -d ordinis -c \
|
||||
"SELECT id, author, dateexecuted, exectype FROM databasechangelog ORDER BY orderexecuted;"
|
||||
```
|
||||
|
||||
Колонка `exectype`:
|
||||
- `EXECUTED` — миграция применена успешно
|
||||
- `FAILED` — упала (pod не должен стартовать в этом случае)
|
||||
- `MARK_RAN` — пропущена через preCondition
|
||||
- `RERAN` — была применена повторно (manual)
|
||||
|
||||
## 2. Добавление новой миграции
|
||||
|
||||
1. Создать `ordinis-migrations/src/main/resources/db/changelog/changes/00NN-<topic>.xml`.
|
||||
- Номер строго следующий (последний +1).
|
||||
- Author = `ordinis`.
|
||||
- Idempotent: использовать `<preConditions onFail="MARK_RAN">` для добавлений.
|
||||
2. Зарегистрировать в `master.xml` через `<include file="changes/00NN-*.xml"/>`.
|
||||
3. Тестировать локально на dev-Postgres:
|
||||
```bash
|
||||
docker run -d --rm --name ord-pg -e POSTGRES_PASSWORD=dev \
|
||||
-p 5432:5432 postgres:18
|
||||
mvn -pl ordinis-migrations -am liquibase:update \
|
||||
-Dliquibase.url=jdbc:postgresql://localhost:5432/postgres \
|
||||
-Dliquibase.username=postgres -Dliquibase.password=dev
|
||||
```
|
||||
4. Commit + push. CI пересобирает app image, deploy применяет новые миграции
|
||||
при следующем старте pod'а.
|
||||
|
||||
## 3. Откат миграции
|
||||
|
||||
⚠️ **Liquibase rollback требует `<rollback>` блок в changeset**. Без него
|
||||
автоматический откат невозможен — только manual SQL.
|
||||
|
||||
### Если changeset имеет `<rollback>`
|
||||
|
||||
```bash
|
||||
# Через kubectl exec на pod где есть mvn — обычно нет, проще локально:
|
||||
mvn -pl ordinis-migrations -am liquibase:rollback \
|
||||
-Dliquibase.url=jdbc:postgresql://192.168.100.161:5432/ordinis \
|
||||
-Dliquibase.username=ordinis_app \
|
||||
-Dliquibase.password=$PG_PASS \
|
||||
-Dliquibase.rollbackCount=1
|
||||
```
|
||||
|
||||
### Manual SQL (если rollback не задан)
|
||||
|
||||
1. Прочитать changeset XML — посмотреть какие изменения сделаны.
|
||||
2. Написать обратные SQL (DROP TABLE, ALTER TABLE DROP COLUMN и т.д.).
|
||||
3. Удалить запись из `databasechangelog`:
|
||||
```sql
|
||||
DELETE FROM databasechangelog WHERE id = '00NN-1-some-id' AND author = 'ordinis';
|
||||
```
|
||||
4. После этого Liquibase при следующем старте либо переприменит миграцию
|
||||
(если она всё ещё в master.xml), либо считает её не-применённой.
|
||||
|
||||
## 4. Failed migration recovery
|
||||
|
||||
Сценарий: миграция упала, pod в CrashLoopBackOff.
|
||||
|
||||
### A) Миграция частично применилась
|
||||
|
||||
Liquibase помечает changeset как FAILED в `databasechangelog`. Чтобы
|
||||
повторить:
|
||||
|
||||
```sql
|
||||
DELETE FROM databasechangelog WHERE id = '00NN-1-broken' AND exectype = 'FAILED';
|
||||
```
|
||||
|
||||
После этого pod рестарт → Liquibase снова попытается. Если миграция всё ещё
|
||||
broken, исправить XML (или применённый частично state в БД), пересобрать
|
||||
image, redeploy.
|
||||
|
||||
### B) Миграция полностью применилась но с ошибкой в данных
|
||||
|
||||
Например column добавлена с NOT NULL без default. Manual SQL:
|
||||
|
||||
```sql
|
||||
ALTER TABLE my_table ALTER COLUMN broken_col DROP NOT NULL;
|
||||
-- либо UPDATE my_table SET broken_col = 'default' WHERE broken_col IS NULL;
|
||||
```
|
||||
|
||||
И исправить XML на `defaultValueComputed=...` для следующих deployments.
|
||||
|
||||
## 5. Текущий список миграций (на 2026-05-05)
|
||||
|
||||
| ID | Назначение |
|
||||
|---|---|
|
||||
| 0001-extensions.xml | PostGIS, btree_gist (для tstzrange exclusion) |
|
||||
| 0002-dictionary-definitions.xml | Таблица `dictionary_definitions` |
|
||||
| 0003-dictionary-records.xml | Таблица `dictionary_records` + tstzrange exclusion |
|
||||
| 0004-audit-log.xml | Таблица `audit_log` |
|
||||
| 0005-outbox-events.xml | Таблица `outbox_events` + partial index |
|
||||
| 0006-idempotency-keys.xml | Таблица `idempotency_keys` |
|
||||
| 0007-add-version-columns.xml | JPA optimistic lock columns |
|
||||
| 0008-fix-scope-check-uppercase.xml | Чек на scope в верхнем регистре |
|
||||
| 0009-fix-records-scope-check.xml | Чек consistency dictionary↔record scope |
|
||||
| 0010-envers-tables.xml | Hibernate Envers (revinfo, *_aud) |
|
||||
| 0011-outbox-dlq.xml | DLQ column + partial indexes |
|
||||
|
||||
## 6. Эскалация
|
||||
|
||||
| Проблема | Действие |
|
||||
|---|---|
|
||||
| Migration на staging упала, pod не стартует | DELETE FAILED row + fix XML + redeploy. См. §4A. |
|
||||
| Migration on prod упала | **СТОП**. Не делать manual fix без apply tech lead. Возможно нужен rollback всего deployment. |
|
||||
| `databasechangelog` lock застрял (другая миграция параллельно) | `DELETE FROM databasechangelog_lock WHERE id=1; INSERT INTO databasechangelog_lock VALUES (1, false, NULL, NULL);` |
|
||||
| Postgres недоступен | См. CNPG cluster status: `kubectl get cluster -n ordinis-staging` |
|
||||
Reference in New Issue
Block a user