Skip to content

ADR-0005: Forge abstraction: GitLab first, GitHub second

Status Accepted (partial: merge-result / Reconcile obligations per ADR-0017 §1/§7; P2-E5)
Date 2026-07-21
Deciders Konrad Heimel
Context links ADR-0006 testing

Context

The tool must act like a reviewer on both major forges: post findings as resolvable review threads, comment, approve/deny, and auto-merge. The primitives differ: GitLab has MR discussions with per-thread resolution and an "all discussions resolved" merge gate; GitHub has PR reviews (REQUEST_CHANGES/APPROVE) and review-thread resolution with different semantics. Self-approval restrictions, bot identities, and merge APIs also differ.

Options

Option Pros Cons
Forge-neutral Forge port with capability flags; GitLab adapter first, GitHub second; e2e conformance suite runs against both core stays platform-free; conformance suite defines the port semantics; capability flags make gaps explicit instead of leaky port design must resist "GitLab-shaped" bias — mitigated by writing the GitHub mapping into the spec from day one
GitLab-only v1, abstract later fastest MVP retrofitting an abstraction under a shipped behaviour contract is the classic trap
Lowest common denominator simple port wastes the strongest feature of each forge (e.g. GitLab resolvable-thread merge gate)

Decision (proposed)

Forge port designed for both from day one; GitLab adapter implemented first. The port is specified in behavioural terms ("publish findings such that merging is blocked until each is acknowledged/resolved") and each adapter maps that to native primitives — GitLab: blocking discussions + all-resolved merge gate; GitHub: REQUEST_CHANGES review + thread resolution. Where a forge cannot express a behaviour, the adapter declares a capability gap and the engine falls back (documented, not silent). A single conformance test suite runs against both adapters (kind-hosted GitLab; GitHub test org) and is the executable definition of the port.

Consequences

  • CI entrypoints stay thin: a GitLab CI template and (later) a GitHub Action wrap the same CLI.
  • Auth models per forge (project token / GitHub App) live entirely in the adapter.

Counterpoints considered

  • "Abstractions before the second implementation are guesses." — True in general; here the second implementation's API is fully known and stable, so the mapping can be spec'd (not guessed) up front, and the conformance suite catches drift.