Задача · CI-7 · СРЕЗ 1 · P0 · Done

Вердикт CI как commit-status Forgejo

Результат VerificationWorkflow публикуется как commit-status в Forgejo на проверенном SHA. Домен — источник истины, Forgejo — зеркало; публикация — отдельная activity с RetryPolicy.

Статус: Done · зависит от CI-5, CI-9 · все задачи · на главную

Что это за задача

Сейчас фабрика считает вердикт проверки кода (VerificationWorkflow), но наружу этот вердикт не показывает. Человек и дев-ревьюер, открыв MR в Forgejo, не видят, зелёный CI или нет. CI-7 публикует вердикт как commit-status Forgejo на том SHA, который был проверен.

Зависит от: CI-5 (верификация идёт на верном SHA из task_result.json), CI-9 (verify-джоба реально исполняет проверку и даёт success/failure).

Простая аналогия: раньше фабрика сама знала, что проверка прошла, но никому не говорила. CI-7 — это табличка на двери «зелёный / красный», которую видит каждый, кто открыл MR.
Принцип из листа «Архитектура» — «Один факт живёт в одном месте»: у каждого факта один владелец и одна форма, остальное — зеркала, и зеркало обязано ломаться при расхождении. Здесь владелец вердикта — домен (VerificationWorkflow), а Forgejo — зеркало.

Главное правило: домен — источник истины, Forgejo — зеркало

В этой фразе три слова, которые надо разобрать. Без них легко запутаться, кто тут «главный», а кто просто показывает результат.

Что такое «домен»

Домен — это собственная логика фабрики, её «мозги»: здесь это VerificationWorkflow и его activity. Это код, который фабрика пишет и контролирует сама, в отличие от внешних систем (Forgejo, Nomad, GitHub), которые фабрика только дёргает по API и не может переписать под себя.

Что значит «источник истины»

Источник истины — то место, где факт живёт по-настоящему и где ему можно верить. Вердикт «зелёный / красный» рождается только в домене: VerificationWorkflow прогнал проверку и сам решил — success или failure. Никто снаружи не может сказать «а давай перепишу вердикт»: чтобы его изменить, надо поменять сам домен.

Что значит «Forgejo — зеркало»

Зеркало — это копия, которая только отражает факт, но не владеет им. Forgejo показывает commit-status, но вердикт в нём — не свой, а скопированный из домена. Если зеркало и оригинал разойдутся, прав всегда оригинал: спрашивать «а точно ли CI зелёный?» надо у домена, а не у Forgejo.

Из этого правила — практические следствия:

Откуда правило — принцип из листа «Архитектура» «Один факт живёт в одном месте»: у каждого факта один владелец и одна форма, остальное — зеркала, и зеркало обязано ломаться при расхождении.

Три состояния статуса

МоментСтатусСмысл
верификация стартовала на SHApendingпроверка ещё идёт
верификация зелёная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 повторится и статус всё-таки встанет.

Соберём вместе: VerificationWorkflow посчитал вердикт → публикация (отдельный шаг activity) относит его в Forgejo → если Forgejo не ответил, RetryPolicy повторяет шаг, пока не получится (но с потолком попыток). Вердикт при этом никуда не девается.
Это не новое изобретение: тот же приём уже применён к созданию MR — 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-aVerificationWorkflow завершился на SHAactivity публикации commit-statusстатус на проверенном SHA соответствует вердикту домена
TC-CI-7.1-bForgejo 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-5DoneШаг после агента запускает VerificationWorkflow на SHA из task_result.json, не на «последнем на ветке».Источник проверенного SHA — того, на который CI-7 ставит статус.
CI-9DoneNomad-диспатч verify-джобы: верификация исполняется в джобе (repo-fetch prestart + dind-сайдкар + verify), а не в воркере.Источник вердикта success/failure, который CI-7 публикует.
RA-2ToDoДиспетч агента-ревьюера после зелёного CI: read-only чекаут того же SHA, прогон сьюта, отчёт verdict/findings.Потребитель CI-7: стартует после зелёного CI, а вердикт CI теперь виден в MR.

Подзадачи CI-7 (лист «Подзадачи»)

IDСлойИзменениеКритерий готовностиЗависит от
CI-7.1OrchestrationActivity публикации 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-S1CI-7nikell28/mr_meeseekscommit-status на проверенном SHA соответствует вердикту домена; при старте pending; RetryPolicy при недоступности; повторный прогон — один статус; вердикт передаётся, не вычисляется.CI-9-S3да · Done
CI-9-S3CI-9nikell28/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» в цепочке.