Разбор · CI фабрики

VerificationWorkflow

Единый CI фабрики: отдельный Temporal-воркфлоу, который запускается после коммита, прогоняет проверку кода (тесты и линт) и вешает на коммит значок «зелёный / красный» — commit-status в Forgejo, который видно прямо в MR. Что именно проверять — задаёт команда из .meeseeks/project.yml.

Файлы: temporal/worker/verification_workflow.py · nomad/verify.nomad.hcl · temporal/worker/domain/project_config.py · ← на главную · про DevPipeline · задача CI-7 →

Что это

VerificationWorkflow — это и есть весь CI фабрики. Другого CI нет: ни Forgejo Actions, ни альтернативных маршрутов. Это отдельный, дочерний workflow (в отличие от главного DevPipeline), который проверяет один конкретный коммит.

На вход он получает два значения — репозиторий и коммит (ref):

VerificationInput(
    repo = "forgejo.example.com/org/repo",   # какой репозиторий
    ref  = "9f2c…",                           # какой коммит проверить (SHA)
)
Простая аналогия: DevPipeline — это «сделать задачу». VerificationWorkflow — «проверить, что сделанное не сломало сборку»: прогнать тесты/линт и сказать зелёный или красный.
Правило «один факт живёт в одном месте»: что проверять — единственный источник .meeseeks/project.yml; как запускать — единственный источник этот workflow.

Откуда запускается — два пути

Проверку запускают двумя способами, но оба ведут в один и тот же VerificationWorkflow:

Путь А · после агента (CI-5)

DevPipeline после успешного шага DEV-AGENT берёт commit_sha из task_result.json и запускает дочерний workflow «в фоне» (fire-and-forget) — не на «последнем на ветке», а на том коммите, что реально сделал агент.

Путь Б · человек запушил (CI-6)

Приёмник вебхука Forgejo (webhook_receiver.py) на push/MR запускает VerificationWorkflow без участия агента, на коммите события. Это отдельный uvicorn-процесс, worker.py остаётся чистым поллером.

# путь А — родительский DevPipeline запускает дочерний workflow на SHA шага
await workflow.start_child_workflow(
    VerificationWorkflow.run,
    VerificationInput(repo=_DEFAULT_VERIFICATION_REPO, ref=commit_sha),
    id=f"{workflow_id}:{step_name}:verify",
)

# путь Б — вебхук стартует workflow на коммите события
await client.start_workflow(
    VerificationWorkflow.run,
    VerificationInput(repo=repo, ref=target.ref),
    id=f"webhook:{repo}:{ref}",
)

Что именно проверяется

Workflow сам ничего про «как проверять» не знает. Он читает команду из .meeseeks/project.yml репозитория — секцию verify.command:

# .meeseeks/project.yml — что значит «проверка пройдена»
verify:
  command: "make test && make lint"

Парсинг — в domain/project_config.py. Если поле verify.command отсутствует или пусто — workflow падает с явной ошибкой MissingVerifyCommandError (не гадает, что запускать).

Как исполняется — verify-джоба в Nomad

Сама проверка исполняется не в воркере, а в Nomad-джобе verify (nomad/verify.nomad.hcl) — по той же причине, по которой агенты бегают в Nomad: изоляция. Группа джобы собирается из четырёх тасков:

ТаскРольЧто делает
repo-fetchprestartскачивает снапшот репозитория (тот же образ, что у агента) и распаковывает до старта проверки.
dindprestart-сайдкарпривилегированный docker-демон (docker:27-dind) — чтобы стадии проверки могли собирать контейнеры.
wait-for-dockerdprestartждёт готовности docker-демона сайдкара до старта main-таска.
verifymainисполняет стадии верификации; образ — dev-env целевого репозитория (решение 2026-08-17).

Три таска делят одну bridge-сеть — поэтому verify ходит к docker-демону по tcp://127.0.0.1:2375. Это исполнение закрыто задачей CI-9.

Переиспользует готовое — без своего велосипеда

VerificationWorkflow не переизобретает доставку кода. Чтение project.yml идёт через activity load_project_config, которая клонирует репозиторий read-only тем же каналом, что и агент (NM-2 → NM-5):

Вердикт и его публикация (CI-7 — текущая задача)

После прогона у коммита появляется commit-status в Forgejo — тот самый «зелёный/красный», который видит человек и дев-ревьюер в MR:

МоментСтатус
верификация стартовалаpending
верификация зелёнаяsuccess
верификация краснаяfailure

Домен — источник истины: вердикт считается здесь, Forgejo — зеркало. Публикация — отдельная activity под RetryPolicy; недоступность Forgejo не теряет вердикт. Подробнее — на странице задачи CI-7.

Связь с задачами

ЗадачаЧто дала
CI-4Каркас VerificationWorkflow: (repo, ref) → читает verify.command из project.yml.
NM-5Чтение project.yml переиспользует read-бот → MinIO (clone_repo_snapshot), без write-доступа.
CI-5Путь А: DevPipeline запускает проверку на SHA из task_result.json.
CI-6Путь Б: вебхук Forgejo запускает проверку без агента.
CI-9Исполнение — Nomad verify-джоба (repo-fetch + dind + verify).
CI-7Публикация вердикта как commit-status Forgejo — текущая задача.