Что это за задача
Сейчас фабрика считает вердикт проверки кода (VerificationWorkflow), но наружу этот вердикт не показывает. Человек и дев-ревьюер, открыв MR в Forgejo, не видят, зелёный CI или нет. CI-7 публикует вердикт как commit-status Forgejo на том SHA, который был проверен.
Зависит от: CI-5 (верификация идёт на верном SHA из task_result.json), CI-9 (verify-джоба реально исполняет проверку и даёт success/failure).
Главное правило: домен — источник истины, Forgejo — зеркало
В этой фразе три слова, которые надо разобрать. Без них легко запутаться, кто тут «главный», а кто просто показывает результат.
Что такое «домен»
Домен — это собственная логика фабрики, её «мозги»: здесь это VerificationWorkflow и его activity. Это код, который фабрика пишет и контролирует сама, в отличие от внешних систем (Forgejo, Nomad, GitHub), которые фабрика только дёргает по API и не может переписать под себя.
Что значит «источник истины»
Источник истины — то место, где факт живёт по-настоящему и где ему можно верить. Вердикт «зелёный / красный» рождается только в домене: VerificationWorkflow прогнал проверку и сам решил — success или failure. Никто снаружи не может сказать «а давай перепишу вердикт»: чтобы его изменить, надо поменять сам домен.
Что значит «Forgejo — зеркало»
Зеркало — это копия, которая только отражает факт, но не владеет им. Forgejo показывает commit-status, но вердикт в нём — не свой, а скопированный из домена. Если зеркало и оригинал разойдутся, прав всегда оригинал: спрашивать «а точно ли CI зелёный?» надо у домена, а не у Forgejo.
Из этого правила — практические следствия:
- Вердикт не вычисляется при публикации. Activity, которая ставит статус в Forgejo, получает готовый success/failure и просто пересылает его — сама ничего не решает.
- Недоступность Forgejo не теряет вердикт. Если Forgejo временно не отвечает, публикация ретраится, а если попытки исчерпаны — вердикт домена остаётся как был. Зеркало может «запотевать», источник истины — нет.
- Статус ровно на проверенном SHA. Вердикт привязан к тому коммиту, который реально проверяли (SHA из task_result.json), а не к «последнему на ветке» — зеркало не решает, на какой коммит вешается факт.
Три состояния статуса
| Момент | Статус | Смысл |
|---|---|---|
| верификация стартовала на SHA | pending | проверка ещё идёт |
| верификация зелёная | success | вердикт домена — прошло |
| верификация красная | failure | вердикт домена — не прошло |
Повторная верификация того же SHA обновляет статус в том же контексте — второй commit-status не создаётся, число статусов коммита не растёт.
Как это ложится на уже готовое
CI-7 не придумывает механизм заново — он переиспользует приём, уже применённый к внешним вызовам:
VerificationWorkflow
владелец вердикта: он вызывает activity публикации и передаёт ей готовый success/failure — вердикт не считается в activity.
RetryPolicy + activity
публикация — отдельная Temporal activity с конечным maximum_attempts — тот же приём, что у create_mr в deploy_key_activities.py (NM-3).
Forgejo API
commit-status ставится через API Forgejo на проверенном SHA.
Три слова: публикация, activity, RetryPolicy
Фраза «публикация — отдельная activity с RetryPolicy» состоит из трёх терминов. Разберём каждый.
Что такое «публикация»
Публикация — это сам акт «записать статус в Forgejo». VerificationWorkflow уже знает вердикт (success / failure); публикация — это шаг, который берёт готовый вердикт и говорит Forgejo: «поставь вот на этот коммит значок success». То есть публикация = выставить значок наружу, а не посчитать вердикт.
Что такое «activity»
Activity — это один маленький шаг внутри Temporal-воркфлоу: отдельная функция, которая делает ровно одно действие. Воркфлоу — это сценарий «что за чем идёт», а activity — отдельный пункт сценария («сходи в Forgejo и поставь статус»). Activity выполняет внешний вызов (в Forgejo по HTTP), поэтому она изолирована: упадёт activity — воркфлоу увидит это отдельно и решит, что делать дальше.
Что такое «RetryPolicy»
RetryPolicy (буквально «правило повторов») — это правило, сколько раз Temporal должен
повторить упавшую activity. Внешние системы (Forgejo, Nomad) иногда не отвечают: сеть моргнула, сервис
перезапустился. RetryPolicy говорит: «не сдавайся с первой попытки — попробуй ещё, но не бесконечно»
(конечное maximum_attempts). Так случайный сбой не теряет вердикт: activity повторится и
статус всё-таки встанет.
create_mr в deploy_key_activities.py (NM-3). CI-7 просто применяет его к
публикации commit-status.Тесткейсы
Кейсы, привязанные к этой задаче в листе «Тесткейсы» (колонка «Единица бэклога»):
| TC-ID | Дано | Когда | Тогда |
|---|---|---|---|
TC-E4-a | агент запушил ветку, VerificationWorkflow завершился на SHA из task_result.json | дев-ревьюер открывает MR в Forgejo | вердикт AutoVerifier виден как commit-status ровно на проверенном SHA: ветка запушена + тесты зелёные |
TC-CI-7.1-a | VerificationWorkflow завершился на SHA | activity публикации commit-status | статус на проверенном SHA соответствует вердикту домена |
TC-CI-7.1-b | Forgejo API временно недоступен | публикация статуса | вызов ретраится по RetryPolicy, вердикт домена не теряется |
TC-CI-7.2-a | верификация того же SHA прогнана повторно | читаются статусы коммита | статус обновлён, второй не создан |
Срезы CI-7
Задача — из одного замыкающего среза. Срез закрыт.
Срез 1 · публикация вердикта · Done
Что сделано: вердикт VerificationWorkflow виден снаружи как commit-status Forgejo
ровно на проверенном SHA: при старте верификации — pending, по завершении —
success/failure по вердикту домена. Публикация — отдельная Temporal activity
(commit_status_activity.publish_commit_status) под RetryPolicy с конечным
maximum_attempts.
Как сделано: недоступность Forgejo API не меняет и не теряет вердикт; повторная верификация
того же SHA обновляет статус в том же контексте (meeseeks/verify), второго статуса нет.
Критерий (выполнен): commit-status на проверенном SHA соответствует вердикту домена; при старте pending; ретраи при недоступном Forgejo; повторный прогон — один статус; вердикт передаётся, не вычисляется. Тесты TC-CI-7.1-a/b, TC-CI-7.2-a зелёные.
Зависит: CI-9-S3 · подзадачи CI-7.1, CI-7.2 · замыкающий
Связанные задачи
Полный контекст CI-7 по всем листам таблицы: задачи-соседи, подзадачи, срезы, решения.
Задачи-соседи (лист «Задачи»)
| Задача | Статус | Что делает | Связь с CI-7 |
|---|---|---|---|
CI-5 | Done | Шаг после агента запускает VerificationWorkflow на SHA из task_result.json, не на «последнем на ветке». | Источник проверенного SHA — того, на который CI-7 ставит статус. |
CI-9 | Done | Nomad-диспатч verify-джобы: верификация исполняется в джобе (repo-fetch prestart + dind-сайдкар + verify), а не в воркере. | Источник вердикта success/failure, который CI-7 публикует. |
RA-2 | ToDo | Диспетч агента-ревьюера после зелёного CI: read-only чекаут того же SHA, прогон сьюта, отчёт verdict/findings. | Потребитель CI-7: стартует после зелёного CI, а вердикт CI теперь виден в MR. |
Подзадачи CI-7 (лист «Подзадачи»)
| ID | Слой | Изменение | Критерий готовности | Зависит от |
|---|---|---|---|---|
CI-7.1 | Orchestration | Activity публикации commit-status (pending/success/failure) через Forgejo API на SHA из task_result.json; вызов под RetryPolicy, как остальные внешние интеграции; источник вердикта — домен. | Статус появляется на проверенном SHA; при недоступности Forgejo API вызов ретраится. | — |
CI-7.2 | Тест | Соответствие SHA и повторный прогон. | Вердикт на MR относится к проверенному SHA; повторная верификация обновляет статус, не создаёт второй. | CI-7.1 |
Срезы CI-7 и соседей (лист «Срезы»)
| Срез | Родитель | Репозиторий | Критерий готовности | Зависит от | Замыкающий |
|---|---|---|---|---|---|
CI-7-S1 | CI-7 | nikell28/mr_meeseeks | commit-status на проверенном SHA соответствует вердикту домена; при старте pending; RetryPolicy при недоступности; повторный прогон — один статус; вердикт передаётся, не вычисляется. | CI-9-S3 | да · Done |
CI-9-S3 | CI-9 | nikell28/mr_meeseeks | Различимость причины красноты verify-джобы доказана прогоном; реестр тесткейсов CI-9 целиком зелёный. | CI-9-S1, CI-9-S2 | да · NeedSpec |
Решения, на которые опирается CI-7 (лист «Решения» и «Архитектура»)
| Источник | Суть |
|---|---|
| Архитектура — «Один факт живёт в одном месте» | У каждого факта один владелец и одна форма; остальное — зеркала, и зеркало обязано ломаться при расхождении. Владелец вердикта — домен, Forgejo — зеркало. |
| Решения — NM-3 (push/коммит/MR) | Внешний вызов (Forgejo API) — отдельная Temporal activity под стандартным RetryPolicy, не единственная попытка внутри job lifecycle. CI-7 применяет тот же приём к публикации commit-status. |
Связи
Вход
вердикт VerificationWorkflow (success/failure) + проверенный SHA из task_result.json.
Выход
commit-status (pending/success/failure) на проверенном SHA в Forgejo.
Перед
верификация идёт на верном SHA (CI-5) и реально исполняется (CI-9).
Дальше
RA-2 — ревьюер после зелёного CI; RA-3 — гейт «CI зелёный на SHA» в цепочке.