Forge
markdown3407750f
1# FORGE-ADR-0005: CI webhook bridge — не свой GitLab CI
2
3| | |
4|---|---|
5| **Status** | Accepted |
6| **Date** | 2026-06-09 |
7| **Relates to** | [FORGE-ADR-0001](FORGE-ADR-0001-agent-first-not-gitlab-clone.md), [FORGE-ADR-0004](FORGE-ADR-0004-git-transport-ssh-http.md) |
8| **Target** | v0.2–v0.3 |
9
10## Context
11
12Команды привыкли: MR → pipeline. GitLab CI встроен в монолит. Forge **не** строит runner zoo в ядре ([FORGE-ADR-0001](FORGE-ADR-0001-agent-first-not-gitlab-clone.md) — CI в **MEF plugin** / bridge).
13
14Нужен **минимальный контракт**: forge знает, что pipeline запущен/зелёный/красный — для thin web approve и MCP status. Запуск CI — **существующая** инфра (GitLab runner, Jenkins, custom docker) через **webhook**.
15
16## Decision
17
18### 1. Принцип
19
20- **Forge не исполняет** build/test в ядре v0.2.
21- Forge **эмитит** события и **принимает** callbacks.
22- Plugin `IForgeCiBridge` (MEF) — адаптер под конкретную CI; default — **generic webhook**.
23
24### 2. События forge → CI (outbound)
25
26| Событие | Когда | Payload (JSON) |
27|---------|-------|----------------|
28| `repo.created` | POST `/api/v1/repos` | `repo`, `cloneUrl` |
29| `mr.opened` | POST merge-request | `repo`, `mr`, `sourceBranch`, `targetBranch` |
30| `push` | post-receive hook (ADR-0004) | `repo`, `ref`, `commit`, `pusher` |
31
32`POST {FORGE_CI_WEBHOOK_URL}` с HMAC подписью `FORGE_CI_WEBHOOK_SECRET`.
33
34### 3. Callback CI → forge (inbound)
35
36```
37POST /api/v1/ci/callback
38Authorization: Bearer {FORGE_CI_CALLBACK_TOKEN}
39```
40
41| Поле | Смысл |
42|------|--------|
43| `repo` | slug |
44| `mr` | number (optional) |
45| `commit` | sha |
46| `status` | `pending` \| `success` \| `failure` \| `cancelled` |
47| `url` | ссылка на лог pipeline (view-only) |
48
49Хранится в WitDatabase (`ci_runs` table, v0.3). MR approve в thin web может показывать **last status** (ADR-0002).
50
51### 4. MCP / chat
52
53- `get_merge_request` расширить полем `ciStatus`, `ciUrl` (read-only).
54- Агент **не** триггерит CI напрямую в v0.2, если не настроен plugin — только читает callback.
55
56### 5. Non-goals
57
58- `.gitlab-ci.yml` parser в ядре.
59- Собственный runner fleet.
60- Required status checks как hard gate day-one (advisory v0.3, enforce v0.4+).
61
62## Consequences
63
64### Positive
65
66- Пилот CAD: оставляют **существующий** runner, forge — metadata + webhook.
67- Зоопарк CI — в плагинах, не в Core.
68
69### Negative / trade-offs
70
71- Две системы (forge + CI) — нужен runbook для секретов и URL.
72- Без callback MR status устаревает — документировать.
73
74## Alternatives considered
75
76| Alternative | Why not |
77|-------------|---------|
78| Встроенный docker runner | Ops + не MCP-first. |
79| Только GitLab CI | Monolith dependency. |
80| Нет CI вообще | Reviewer хочет зелёную галочку. |
81
82## Implementation notes
83
84- Env: `FORGE_CI_WEBHOOK_URL`, `FORGE_CI_WEBHOOK_SECRET`, `FORGE_CI_CALLBACK_TOKEN`.
85- v0.2: outbound webhook only; v0.3: callback + DB + thin web badge.
86- Plugin: `ForgeCiBridge.GitLab`, `ForgeCiBridge.GenericHttp` — позже.
87
88## Links
89
90- [FORGE-ADR-0004](FORGE-ADR-0004-git-transport-ssh-http.md) — post-receive
91- [FORGE-ADR-0002](FORGE-ADR-0002-mcp-first-web-view-only.md) — MR approve UI
92- [FORGE-ADR-0016](FORGE-ADR-0016-visual-ci-plugin-and-runner-fleet.md) — Visual CI product (Plugin.Ci + runner fleet; extends this bridge)
93
View only · write via MCP/CIDE