Skip to content

discussing: GitLab support — webhooks, events, MCP, and repo identity #359

Description

@eloylp

Motivation

Today the daemon is GitHub-only: webhooks, event vocabulary, repo identity (owner/repo), the GitHub MCP server registered on each AI CLI. GitLab support would broaden the audience meaningfully — most self-hosted Git is GitLab. This issue is to align on shape and scope before any code is written.

Not pushing for a decision today. The point is to surface the design questions so we don't accidentally bake GitHub assumptions deeper while doing other work.

What's load-bearing about being GitHub-only today

Concrete touchpoints, not exhaustive:

  • internal/webhook/handler.go — parses GitHub webhook envelopes; auth via HMAC SHA-256 on X-Hub-Signature-256; delivery dedup via X-GitHub-Delivery.
  • internal/fleet/binding.go + config validation — events: accepts a fixed list of GitHub event kinds (issues.labeled, pull_request.opened, push, …).
  • internal/workflow/engine.go::fanOut — matches event kinds against bindings.
  • fleet.Repo.Name is owner/repo form; binding lookup keys on it. GitLab projects are group[/subgroup]/project — slashes can be deeper.
  • AI backends are configured with the GitHub MCP server (https://api.githubcopilot.com/mcp). All GitHub writes flow through it.
  • UI: events/runners/traces pages style known GitHub kinds; the agents field on events resolves through traces, which is provider-agnostic.

Open questions

1. Scope for v1. Webhook surface only, or also the AI-side write surface (i.e., agents need a GitLab MCP server to comment on MRs / open MRs / etc.)? Without the latter the daemon can ingest GitLab events but agents can't act on GitLab — which is half a feature.

2. Event vocabulary: provider-prefixed or normalised?

  • Option A — keep verbatim: issues.opened (GitHub) and merge_request.open (GitLab) live as distinct kinds. Smallest blast radius.
  • Option B — normalise: introduce a provider-agnostic vocabulary like issue.opened, pr.opened, pr.synchronize, comment.created and translate at the webhook boundary. Bigger change but bindings become portable across providers.

I'd lean B if we go ahead, but it's a real refactor of the event table, the docs, the UI styling map, and any user with events: lists.

3. Repo identity. GitLab project paths can be group/subgroup/sub/project. The daemon currently splits repo.FullName on / in a few places (e.g. /repos/{owner}/{repo}). We'd need either:

  • A flat ID (e.g. GitLab project numeric ID) as the canonical key, with the path as a display name.
  • A leading provider prefix on the binding name (gitlab:group/subgroup/project).
  • Or accept the slash-rich path and audit every split site.

4. Webhook auth. GitHub uses HMAC SHA-256 over the body. GitLab uses a static X-Gitlab-Token header (constant-time compared). Two distinct paths in the webhook handler. New env var GITLAB_WEBHOOK_TOKEN.

5. MCP server for GitLab. Is there a stable GitLab MCP server we can reference in docs the way we reference the GitHub one? If not, this becomes a v1 blocker for the agent-side: agents need some way to write to GitLab.

6. Per-repo provider field. Whichever identity choice in (3), the runtime needs to know "this binding is for a GitLab repo, not a GitHub one" so the right webhook auth, the right event kinds, and the right MCP server are picked. New field on fleet.Repo: provider: github | gitlab (default github for back-compat).

7. Existing fleets. If we add provider as a per-repo field, existing imported configs default to GitHub — no migration pain. If we touch event kinds (option 2B), existing events: lists need a one-time rewrite.

Out of scope for the v1 of this work (suggested)

  • Bitbucket / Forgejo / Gitea — different story, revisit after GitLab works.
  • Cross-provider dispatch (an agent on a GitHub repo dispatching another agent on a GitLab repo). Tractable but multiplies the test surface.

What I'd want decided before anyone starts

The two questions that change the shape of the work:

  • Q2 — event vocabulary (verbatim vs. normalised)
  • Q3 — repo identity (flat ID vs. prefixed path vs. accept-slashes)

Everything else falls out from those.

Not ai ready

Discussion only. No agent should pick this up until the questions above are answered and the issue is rewritten as an unambiguous task (or split into several).

Metadata

Metadata

Assignees

No one assigned

    Labels

    discussingIssue is still under discussion — not ready for implementation

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions