# CI gate Dzentra **Статус:** Repository implementation complete; Canary Pending **Область:** CI-GATE.0–CI-GATE.2 **Дата фактической проверки Gitea:** 2026-08-04 --- ## 1. Что означает CI gate CI gate — автоматический барьер качества между изменением кода и его принятием в `main`. Он не доказывает отсутствие любых ошибок, но не даёт считать изменение готовым, пока обязательные воспроизводимые проверки не завершились успешно. Первый gate Dzentra вводится безопасно, в два шага: 1. repository-side contract фиксируется и проверяется локально; 2. после отдельного разрешения он публикуется и вручную запускается на реальном Gitea runner как canary. До зелёного canary workflow не запускается автоматически и не участвует в branch protection. ## 2. Состав CI-GATE.0–CI-GATE.2 | Этап | Смысл | Текущий статус | |---|---|---| | CI-GATE.0 | Проверить готовность Gitea/runner и зафиксировать ручной canary contract | Repository часть готова; runner и серверный запуск не подтверждены | | CI-GATE.1 | Создать единый hash-locked набор developer/CI dependencies | Реализовано локально | | CI-GATE.2 | Добавить три независимые обязательные проверки без внешних сервисов | Реализовано локально; Canary Pending | Зелёный canary означает реальный успешный запуск всех трёх jobs, а не только корректный локальный YAML или зелёные локальные тесты. ## 3. Фактическое состояние CI-GATE.0 Read-only проверка публичного сервера подтвердила: - репозиторий находится на Gitea 1.25.5; - вкладка Actions доступна; - до добавления этого contract сервер показывал «Пока нет рабочих процессов»; - версия, регистрация и labels `act_runner` без административного доступа не видны и поэтому не считаются подтверждёнными. На данном этапе не изменялись настройки Gitea, Actions, runner registration или branch protection. Workflow использует объявленный repository contract label `dzentra-python312`. Runner с этим label должен предоставлять изолированную Linux-среду со следующими компонентами: - Python 3.12, `venv` и `pip`; - Bash, Git и CA certificates; - Node.js 20 для `actions/checkout` v4; - GNU `timeout`; - возможность слушать временный socket только на `127.0.0.1`; - отсутствие privileged mode и подключённого Docker socket. До отдельного подтверждения нельзя регистрировать runner или подбирать его label «на глаз». Если runner отсутствует, jobs останутся в очереди — это ожидаемый незакрытый инфраструктурный пункт, а не зелёный результат. ## 4. Hash-locked developer/CI environment Читаемый источник прямых зависимостей остаётся в [`app/requirements-dev.txt`](../../app/requirements-dev.txt). Установка для разработки и CI выполняется только из [`app/requirements-dev.lock`](../../app/requirements-dev.lock): ```bash python3.12 -m venv app/.venv app/.venv/bin/python -m pip install \ --require-hashes \ -r app/requirements-dev.lock app/.venv/bin/python -m pip check ``` Developer lock сохраняет все версии Production lock и добавляет только инструменты разработки с их транзитивными зависимостями. Это предотвращает ситуацию, когда CI тестирует приложение на более новых Production-библиотеках, чем Production image. Регенерация выполняется намеренно из корня репозитория: ```bash uv pip compile app/requirements-dev.txt \ --constraints app/requirements.lock \ --generate-hashes \ --universal \ --python-version 3.12 \ --no-header \ --no-annotate \ --output-file app/requirements-dev.lock ``` После генерации в начале файла сохраняются только три служебные строки на русском языке. Любое изменение lock-файла рассматривается как dependency update и требует отдельного diff review. ## 5. Контракт CI-GATE.2 Workflow находится в [`ci-required.yml`](../../.gitea/workflows/ci-required.yml) и пока имеет только `workflow_dispatch`. Его стабильные jobs: | Job | Проверяет | Не использует | |---|---|---| | `quality` | `pip check`, Pyright, documentation gate, static tests, `compileall`, whitespace | сеть приложения, PostgreSQL, Docker | | `offline-regression` | полную default pytest-регрессию | integration, stress, live | | `loopback-integration` | локальные WebSocket/reconnect/recovery scenarios | внешние endpoints и PostgreSQL | Все потенциально долгие shell-команды ограничены GNU `timeout`. Это обязательно, потому что Gitea 1.25.5 игнорирует GitHub-совместимое поле `timeout-minutes`. По той же причине workflow не использует вводящие в заблуждение `permissions`, `concurrency`, `continue-on-error` и `timeout-minutes`. Сам шаг checkout выполняется action, а не shell-командой, поэтому этим timeout не ограничен. Перед canary необходимо отдельно подтвердить системный job timeout и cleanup policy `act_runner`. Checkout закреплён полным commit SHA официального [`actions/checkout` v4.3.1](https://github.com/actions/checkout/releases/tag/v4.3.1), а `persist-credentials` выключен. До появления внутреннего mirror runner должен иметь исходящий HTTPS-доступ к GitHub только для загрузки этого закреплённого action. Изменение SHA требует отдельного review. Workflow не получает application secrets, не печатает environment, не запускает PostgreSQL, Docker, stress/soak или live Dzengi checks. ## 6. Локальный эквивалент Один entrypoint используется человеком и workflow: ```bash ./scripts/run_ci_gate.sh quality ./scripts/run_ci_gate.sh offline-regression ./scripts/run_ci_gate.sh loopback-integration ``` Для последовательного локального запуска всех трёх режимов: ```bash ./scripts/run_ci_gate.sh all ``` Локальная проверка не требует чистого `git status`, поэтому она не мешает разработчику с незавершёнными изменениями. Внутри чистого canary checkout каждая job дополнительно проверяет, что тесты не создали новых файлов репозитория. ## 7. Первый canary Первый реальный запуск выполняется только после отдельного подтверждения: 1. провести read-only review repository diff; 2. отдельно согласовать commit и push workflow; 3. с административным доступом подтвердить фактическую версию `act_runner`, включённость Actions и отсутствие неизвестных runners; 4. зарегистрировать изолированный runner с точным label `dzentra-python312` и зафиксировать его image/version; 5. вручную запустить `CI Required` для принятого commit; 6. убедиться, что `quality`, `offline-regression` и `loopback-integration` завершились успешно, не были skipped и не остались queued; 7. проверить логи на отсутствие secrets и записать реальные status contexts, показанные Gitea. Только после этого canary считается зелёным. Автоматические triggers и branch protection согласуются отдельным решением уже по фактическим status contexts; заранее угадывать их имена нельзя. ## 8. Критерий перехода к Build 061.00 Build 061.00.0 можно начинать после одновременного выполнения условий: - локальная матрица CI-GATE.0–CI-GATE.2 зелёная; - реальный manual canary в Gitea зелёный; - версия и изоляция runner зафиксированы; - пользователь отдельно подтвердил переход к production-коду. Пока серверный canary не выполнен, корректный статус — `Canary Pending`. ## 9. Связанные источники - [Gitea Actions quick start](https://docs.gitea.com/1.25/usage/actions/quickstart/) - [Отличия Gitea Actions от GitHub Actions](https://docs.gitea.com/1.25/usage/actions/comparison/) - [Gitea act_runner](https://docs.gitea.com/1.25/usage/actions/act-runner/) - [Protected branches](https://docs.gitea.com/1.25/usage/access-control/protected-branches/)