Merge branch 'main' into feature/production-deployment-readiness
This commit is contained in:
commit
f1573edfa7
3 files changed
+206
No files matched your search
@@ -41,6 +41,31 @@ Python, SQLite и OpenSearch. На 2026-10-25 публичный `/review` и п
|
||||
- После каждого изменения инфраструктуры обновляй
|
||||
`docs/operations/CURRENT_STATE.md` по фактическим проверкам.
|
||||
|
||||
## Delivery First: проверка по уровню риска
|
||||
|
||||
- Перед работой укажи в PR уровень `LOW`, `MEDIUM` или `HIGH`; при сомнении
|
||||
выбери более высокий. Уровень добавляет нужную проверку, но никогда не
|
||||
отменяет CI, одобрение или защиту `main`.
|
||||
- Каждый PR сохраняет текущие проверки Gitea Actions: job IDs
|
||||
`tests-and-images` и `runner-smoke`. Не переименовывай и не обходи их, не
|
||||
удаляй тесты или проверки безопасности ради скорости.
|
||||
- `LOW`: документация, комментарии и тексты без изменения исполняемого
|
||||
поведения или контракта; проверяй diff и актуальность утверждений, затем
|
||||
дождись обычного CI.
|
||||
- `MEDIUM`: изменение поведения в одном компоненте; добавь регрессионный тест,
|
||||
выполни целевые проверки и обычный CI.
|
||||
- `HIGH`: доступ/авторизация, данные и ingestion, схемы/хранилища,
|
||||
backup/restore/recovery, production config, секреты, runner/CI, безопасность
|
||||
или deploy; выполни целевые тесты вместе с обычным CI и приложи проверяемое
|
||||
обоснование угроз, совместимости и rollback. Production-действия остаются
|
||||
за владельцем.
|
||||
- Ревью блокирует только конкретный воспроизводимый дефект, нарушение границы
|
||||
доступа/безопасности, несовместимость данных или контракта, пропущенную
|
||||
обязательную проверку либо отсутствие безопасного rollback. Идеи и стилистические
|
||||
замечания перечисляй отдельно как неблокирующие.
|
||||
- Полная процедура, метрики, Gitea-ограничения и проверенные временные бюджеты:
|
||||
[DELIVERY_POLICY.md](docs/development/DELIVERY_POLICY.md).
|
||||
|
||||
## Автономный workflow PR
|
||||
|
||||
- Маршруты ниже указаны из контекста оркестратора/root: оркестратор — thread
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
- Frontend `0.3.3` / Backend `0.13.2`: управление пользователями отображается
|
||||
согласно правам аккаунта, подписи ролей локализованы, повторяющиеся действия
|
||||
кабинета убраны, а знак лаборатории приведён к основному бренду.
|
||||
- Добавлена политика Delivery First по уровням `LOW`/`MEDIUM`/`HIGH`: описаны
|
||||
обязательная глубина проверок, регрессионные тесты и доказательства угроз,
|
||||
совместимости и отката; обычные CI, одобрение и защита `main` остаются
|
||||
обязательными.
|
||||
- Frontend `0.3.2`: устранены пересечения названия бренда с поиском и
|
||||
мобильной навигации документа; навигационные ссылки получили общие quiet и
|
||||
primary состояния.
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
# Delivery First: проверка изменений по риску
|
||||
|
||||
Эта политика помогает быстро принимать небольшие изменения и добавляет
|
||||
проверки там, где ошибка затрагивает пользователей, данные или границы
|
||||
безопасности. Класс риска выбирает глубину проверки; он не позволяет снять
|
||||
обязательную проверку, одобрение или защиту `main`.
|
||||
|
||||
## Порядок работы
|
||||
|
||||
1. До реализации укажи в PR `LOW`, `MEDIUM` или `HIGH` и коротко объясни
|
||||
причину. Если изменение пересекает несколько областей, выбери самый высокий
|
||||
класс. При неопределённости используй более высокий класс.
|
||||
2. Сначала проследи путь изменения от пользовательского/API входа до данных,
|
||||
внешних систем и отката. Для изменения поведения добавь регрессионный тест,
|
||||
который подтверждает конкретный контракт или прежний дефект.
|
||||
3. Запусти проверку именно затронутого поведения и обычный Gitea CI. Для UI
|
||||
дополнительно выполни `cd tools/frontend-visual-review && npm ci && npm test`;
|
||||
этот браузерный набор сейчас не входит в Gitea CI.
|
||||
4. В PR перечисли класс риска, команды и результаты, остаточные ограничения,
|
||||
а для high-risk — совместимость, угрозы и безопасный rollback. Не заявляй
|
||||
проверку, которой фактически не было.
|
||||
5. Ревьюер отделяет блокирующие дефекты от улучшений. Блокер должен указывать
|
||||
конкретное место, условие воспроизведения и последствие. Стилистические
|
||||
предпочтения и предложения на будущее фиксируются отдельно и не задерживают
|
||||
PR.
|
||||
|
||||
## Классы риска
|
||||
|
||||
| Класс | Когда применять | Требуемое подтверждение |
|
||||
|---|---|---|
|
||||
| `LOW` | Документация, комментарии, переименование без изменения поведения, форматирование без изменения конфигурационной семантики. Нет изменения контракта, доступа, данных или исполнения. | Проверить diff и сверить утверждения/команды с исходным кодом и действующей процедурой. Выполнить обычный CI. Если документация меняет операторский шаг, проверить его в безопасном локальном или synthetic окружении. |
|
||||
| `MEDIUM` | Ограниченное изменение поведения одного компонента, внутреннего API, UI или локального скрипта без изменения модели доверия и формата хранимых данных. | Целевые тесты затронутого компонента и регрессионная проверка, если меняется поведение; обычный CI. Для UI приложить результаты браузерного набора и synthetic визуальной проверки, если они относятся к изменённому экрану/потоку. Проверить обратную совместимость публичных запросов и ответов. |
|
||||
| `HIGH` | Авторизация и роли; secrets и credential flow; ingestion и происхождение данных; формат/миграция хранилища; backup/restore/recovery; production config; runner, CI и supply chain; безопасность; сетевые/host-границы; deploy и rollback. | Обычный CI плюс целевые проверки каждого затронутого trust/data boundary; regression-тест; проверка негативного пути и совместимости; независимое ревью конкретных угроз и последствий. Для операций с данными использовать synthetic/staging данные и план отката. Изменение production допускается только владельцем после отдельного согласования, проверки backup и готового rollback. |
|
||||
|
||||
Нельзя понижать класс из-за малого diff, срочности или простоты реализации:
|
||||
маленькое изменение правила доступа или восстановления всё равно `HIGH`.
|
||||
Нельзя считать отсутствие найденных тестов доказательством отсутствия риска.
|
||||
|
||||
## CI и ограничения Gitea
|
||||
|
||||
Проверенная конфигурация проекта:
|
||||
|
||||
- Репозиторий `admin/akyldash`, Gitea API вернул `1.25.5` 2026-10-24.
|
||||
- Workflow `.gitea/workflows/ci.yaml` запускается на `pull_request` и `push` в
|
||||
`main`; job ID, который следует сохранять для совместимости статусов, —
|
||||
`tests-and-images`.
|
||||
Он последовательно выполняет backend, Telegram, backup/restore, shell guards,
|
||||
deployment tests, Compose/Caddy validation и две production image builds.
|
||||
- `.gitea/workflows/runner-smoke.yaml` сохраняет отдельный job ID `runner-smoke`
|
||||
и проверяет runtime-изоляцию job-контейнера: отсутствие системного и
|
||||
rootless Docker socket, production env/secrets и host checkout. Smoke дополняет
|
||||
статические проверки runner/CI и не дублирует их.
|
||||
- Инфраструктурная конфигурация репозитория закрепляет официальный
|
||||
`act_runner 0.2.13`, label `akyldash-ci`, capacity 1 и ограничения job 2 CPU,
|
||||
3 GiB RAM, 512 процессов, 15 GiB store. Версия runner и лимиты приведены по
|
||||
IaC; в рамках этой задачи VPS не проверялся. Job-контейнеры не должны получать
|
||||
ни один Docker socket.
|
||||
- Текущая политика `main` из branch API: ветка защищена и требует одного
|
||||
одобрения. На момент проверки API также сообщил `enable_status_check=false`
|
||||
и пустой список status contexts. Это PR не меняет branch protection.
|
||||
Если владелец отдельно включит обязательные статусы, сначала проверьте их
|
||||
точные контексты: `CI / tests-and-images (pull_request)` и
|
||||
`Runner smoke test / runner-smoke (pull_request)`. Не переименовывайте job IDs.
|
||||
|
||||
Функции и границы текущих проверок:
|
||||
|
||||
| Блок workflow | Назначение и риск пропуска | Перекрытие |
|
||||
|---|---|---|
|
||||
| Checkout и Python setup | Подготовка повторяемой среды; пропуск может дать ложный успех на неподходящем образе. | Инфраструктурный шаг, не покрывается тестами приложения. |
|
||||
| Backend и Telegram tests | Регрессии API, логики поиска/аккаунтов и Telegram bot. Риск продуктовый; для auth/data изменений — `HIGH`. | Разные пакеты и контракты; отдельная ветка тестов. |
|
||||
| Backup/restore tests | Целостность backup, восстановление и отказные сценарии; риск потери данных — `HIGH`. | Не дублируется тестами backend. |
|
||||
| Bootstrap/recovery/verifier/host-audit/production-config guards | Отказ от root и защиты host identity, аргументов и production paths; обход может дать административное действие или затронуть host — `HIGH`. | Несколько guard-тестов проверяют разные скрипты и условия; считать их дублями без анализа каждого контракта нельзя. |
|
||||
| Runner config, installer guards и CI container isolation | Ограничения runner, repeatability установки и запрет socket/privileged/host mounts; риск — доступ к host/production — `HIGH`. | Статические/синтетические проверки дополняются реальным runtime smoke, это разные уровни. |
|
||||
| Shell syntax и Python AST parse | Раннее обнаружение ошибок парсинга; риск пропуска — поломка запуска скрипта/проверки. | Это синтаксис, а не функциональные тесты. |
|
||||
| Deployment contract/rollback tests, Compose config и Caddy validation | Совместимость deploy contract/rollback и конфигурации production stack/proxy; риск — deploy outage/data impact — `HIGH`. | Compose проверяет интерпретацию конфигурации, Caddy — синтаксис proxy, Python suite — contract/rollback logic. Функции отличаются. |
|
||||
| Две Kaniko image builds | Проверка Dockerfile и воспроизводимости backend/OpenSearch production images; риск — сломанная сборка/небезопасный путь supply chain — `HIGH`. | Два Dockerfile — две разные целевые images; build-only, оба `--no-push`. |
|
||||
| Runner smoke (отдельный workflow) | Runtime-проверка известного системного socket path, production paths/secrets и host checkout отсутствия в job; риск — нарушение изоляции — `HIGH`. | Дополняет статические runner/CI guards; не повторяет их. |
|
||||
|
||||
Gitea API не предоставляет пригодный список steps для завершённого run в этой
|
||||
версии; длительность каждой строки таблицы поэтому `N/A`. Не распределяй общий
|
||||
CI runtime между блоками пропорционально числу тестов или строк кода.
|
||||
|
||||
Gitea 1.25 документация подтверждает используемые события `push`,
|
||||
`pull_request` и `workflow_dispatch`. Она также документирует ограничения,
|
||||
которые запрещают строить безопасное ускорение на привычных GitHub Actions
|
||||
предположениях:
|
||||
|
||||
- `runs-on` поддерживает статическую метку или список меток; текущая
|
||||
`akyldash-ci` — статическая метка.
|
||||
- Выражения доступны ограниченно; в сравнении с GitHub Actions Gitea 1.25
|
||||
обещает функцию `always()`, поэтому workflow не должен зависеть от
|
||||
`if:`-выражений для динамического выбора набора тестов по diff или уровню
|
||||
риска.
|
||||
- `jobs.<job_id>.timeout-minutes`, `permissions`, `concurrency` и
|
||||
`jobs.<job_id>.environment` в Gitea 1.25 игнорируются. Не используйте их как
|
||||
защиту, срок исполнения, обязательный approval или средство экономии.
|
||||
- У runner capacity 1. Разделение текущей последовательной работы на
|
||||
параллельные jobs не даёт измеримого параллельного исполнения на этом runner
|
||||
и может добавить запуск/очередь. Сохраняйте проверку сборки обеих production
|
||||
images: она подтверждает Dockerfiles, но использует Kaniko с `--no-push` и не
|
||||
публикует образы.
|
||||
|
||||
Источники семантики: [Gitea 1.25 Actions comparison](https://docs.gitea.com/1.25/usage/actions/comparison/),
|
||||
[Gitea 1.25 Actions FAQ](https://docs.gitea.com/1.25/usage/actions/faq/) и
|
||||
[act_runner guide](https://docs.gitea.com/1.25/usage/actions/act-runner/).
|
||||
Перед использованием новой workflow-семантики сверяй её с документацией
|
||||
установленной версии и проверяй фактическим run. Не добавляй проверки самой
|
||||
этой политики или статические тесты, утверждающие её текст.
|
||||
|
||||
## Временные ориентиры и фактические измерения
|
||||
|
||||
Ориентиры — цель для поиска затрат, а не разрешение убрать тесты:
|
||||
|
||||
- Обычный полный CI: до 5 минут от старта job до завершения. При превышении
|
||||
сначала измерить и оптимизировать узкий участок, сохраняя тесты и изоляцию.
|
||||
- Расширенный путь для `HIGH` (обычный CI плюс целевые проверки): целевой
|
||||
суммарный интервал 10–15 минут. Это пока ориентир, а не отдельный
|
||||
автоматический workflow или установленный timeout.
|
||||
|
||||
Срез 2026-10-24 получен из документированного [Gitea Actions task API](https://docs.gitea.com/api/1.25/operations/list-action-tasks/)
|
||||
`/repos/admin/akyldash/actions/tasks?limit=50`. Взяты 20 последних завершённых
|
||||
`tests-and-images`; длительность оценена как `updated_at - run_started_at`:
|
||||
|
||||
| Метрика | Измерение |
|
||||
|---|---:|
|
||||
| CI completed sample | 20 прогонов, 20 success |
|
||||
| CI median | 147.5 s (2:27.5) |
|
||||
| CI p90 | 172 s (2:52) |
|
||||
| CI max | 192 s (3:12) |
|
||||
| Runner smoke median / max | 2 s / 3 s, последние 20 прогонов |
|
||||
|
||||
Прежней reconciliation или оценок длительности в доступной документации
|
||||
репозитория, workflows, PR и issues не найдено; этот срез является первой
|
||||
подтверждённой базой, и сравнить его с прежней оценкой нельзя.
|
||||
Все 20 измеренных полных CI прогонов ниже пяти минут; текущая конфигурация уже
|
||||
достигает обычного ориентира. Отдельного extended workflow нет, поэтому
|
||||
10–15-минутная цель пока не имеет фактической базы. В выборке нет breakdown по
|
||||
steps: документированный endpoint для jobs завершённого run возвратил пустой
|
||||
список; это известное ограничение Gitea 1.25.5 ([upstream issue #38286](https://github.com/go-gitea/gitea/issues/38286)).
|
||||
Не распределяй время между тестами и image builds по предположению. При будущих
|
||||
изменениях workflow записывай доступные timestamps и точный размер выборки;
|
||||
после изменения Gitea/runner перепроверь, стал ли доступен надёжный step timing.
|
||||
|
||||
## Метрики потока поставки
|
||||
|
||||
Для каждого релиза/месячного обзора отдельно собирать:
|
||||
|
||||
| Метрика | Определение и источник |
|
||||
|---|---|
|
||||
| Ready → merge | Время с момента, когда PR реально готов к ревью, до merge. Не подменять датой создания draft PR; при отсутствии точного ready timestamp записывать `N/A`. |
|
||||
| Merge → deploy | Merge timestamp до фактического production deploy timestamp. Deploy пока не автоматизирован; пока нет подтверждённого deploy evidence, записывать `N/A`, не ноль. |
|
||||
| CI duration | `run_started_at` → task completion (`updated_at`) по Actions API; отдельно указывать медиану, p90, максимум, период и число прогонов. |
|
||||
| Повторные прогоны | Число неуспешных/повторных прогонов на commit до первого успеха; отличать rerun от нового commit/push. |
|
||||
| Блокирующие замечания | Число ревью-находок, удовлетворяющих критериям blockers выше; неблокирующие считать отдельно. |
|
||||
| Вышедшие регрессии | Подтверждённые после merge дефекты, связанные с изменением; фиксировать компонент, тяжесть и пропущенный сигнал. |
|
||||
| Rollback | Количество фактически выполненных rollback, причина и результат проверки данных/сервиса. Не считать написанный план фактическим rollback. |
|
||||
|
||||
На момент этого аудита PR/API не дают надёжного ready timestamp для старых
|
||||
изменений; production deployment не автоматизирован, а задачи этого PR не
|
||||
содержат deploy telemetry. Поэтому ready→merge, merge→deploy, escaped
|
||||
regressions и rollback baseline остаются `N/A`, пока не появится проверяемая
|
||||
запись. Не придумывай значения из `created_at` или даты последнего update.
|
||||
|
||||
## Критерий блокирующего ревью
|
||||
|
||||
Блокирующие замечания ограничены случаями:
|
||||
|
||||
- воспроизводимый дефект с конкретным условием и последствием;
|
||||
- расширение доступа, утечка секрета или обход границы runner/production;
|
||||
- потеря/искажение данных или несовместимость API/storage без безопасного пути;
|
||||
- обязательный тест или подтверждение из таблицы риска отсутствует/не проходит;
|
||||
- опасная операция не имеет проверяемого backup/rollback плана.
|
||||
|
||||
Каждый блокер содержит файл/участок, шаги воспроизведения или точное условие,
|
||||
последствие и минимальный безопасный fix. Остальные замечания — отдельный
|
||||
неблокирующий список. Review и approval остаются за людьми; агент не начинает
|
||||
review сам и не сливает PR.
|
||||
Reference in new issue
Block a user