Files
kandev/docs/specs/integrations/system-design/gitlab-integration-02.md
T
2026-08-24 11:09:03 +00:00

10 KiB

status, system, requirements, created, updated, owners
status system requirements created updated owners
draft integrations
REQ-INTEGRATIONS-GITLAB-INTEGRATION-001
2026-05-04 2026-08-05
tbd

GitLab Integration System Design Part 2

Purpose and boundaries

This design preserves the technical source detail for REQ-INTEGRATIONS-GITLAB-INTEGRATION-001 during migration.

Requirement mapping

Requirement Design section
REQ-INTEGRATIONS-GITLAB-INTEGRATION-001 Migrated source detail

Migrated source detail

Failure modes

  • Saving an invalid host or credential fails without replacing the last known working connection or secret.
  • A transient health or API failure keeps the saved config and linked/watch records. The UI shows an unavailable state and allows retry; pollers back off and do not create tasks from incomplete results.
  • Revoked credentials mark only the affected workspace auth_required and pause API work for it until a successful probe. Other workspaces continue.
  • Watch dispatch reserves the external item before creating a task. Task-create or auto-start failure releases or completes the reservation according to the shared watcher dispatcher, preventing both lost matches and duplicate tasks.
  • A deleted/soft-deleted watch dependency self-disables the watch with a visible error instead of creating an orphan task.
  • Link creation is atomic from the user's perspective: if URL validation or MR fetch fails, no association is written. Repeating a successful request returns the existing association.
  • Unlink failure leaves the association and refresh watch intact. Unlink never closes or unsubscribes from the upstream MR.
  • Watch delete is best-effort for owned-task cleanup: individual task-delete failures are logged, remaining owned tasks are attempted, and the watch/dedup rows are removed. It never schedules another poll.
  • Watch reset follows the shared GitHub watchreset contract: after preview and confirmation it best-effort attempts every owned task deletion (including archived), logs and continues past individual task-delete failures, then transactionally clears dedup and last_polled_at. A clear failure surfaces together with the count already deleted; otherwise the response reports the successful delete count. Review watches rerun immediately and issue watches are eligible on their next poll/run-now.
  • Reviewer, discussion, merge, and subscription failures leave the last fetched UI state visible and show an action error; the UI refreshes after success.
  • MR creation never retries against another host. A successful push followed by a failed MR request is reported as partial failure with the pushed branch intact so the user can retry without another commit.

Persistence guarantees

  • Workspace config rows, PAT secrets, watch definitions, dedup reservations, task-to-MR associations, and last known MR status survive backend restarts.
  • Archived tasks retain task-to-MR associations for later unarchive; hard task deletion removes task-owned associations and refresh watches.
  • The startup migration moves the legacy global host/token to the active workspace, or the earliest-created workspace when no active workspace is available. It is idempotent and never duplicates automation watches.
  • glab login and GITLAB_TOKEN remain host-process state and are not copied or backed up by Kandev.
  • In-flight HTTP requests and poll iterations do not resume after restart. The next health/poll cycle re-runs safely against durable dedup state.
  • GitLab notification subscriptions survive because GitLab owns them; Kandev re-reads their state after reload.

Scenarios

  • GIVEN two workspaces connected to different GitLab hosts, WHEN each opens its GitLab page, THEN each sees only data fetched with its own host and credential.
  • GIVEN a workspace without a GitLab connection, WHEN the user enters a public gitlab.com repository URL in Remote task creation, THEN Kandev lists its branches anonymously without making any other GitLab browse or write capability available.
  • GIVEN a legacy global GitLab host and token, WHEN Kandev starts after upgrade, THEN one deterministic workspace receives the config and secret and other workspaces remain unconfigured.
  • GIVEN a self-managed workspace connection, WHEN a user links a valid MR URL from that host, THEN the task shows the linked MR and its live review details after reload.
  • GIVEN a task with no linked MR in a GitLab-configured workspace, WHEN the task detail opens, THEN the top bar has no Link MR action and the task's contextual Link submenu offers GitLab Merge Request.
  • GIVEN a touch viewport and a task with no linked MR in a GitLab-configured workspace, WHEN the user opens the task row's visible actions menu and chooses Link then GitLab Merge Request, THEN the GitLab MR link dialog opens without relying on right-click or long press.
  • GIVEN a task with a linked GitLab MR, WHEN the task detail opens, THEN the top bar shows the linked MR status control rather than a generic link action.
  • GIVEN an MR URL from a different host, WHEN it is linked in the current workspace, THEN the request is rejected and no association is written.
  • GIVEN a linked MR, WHEN the user unlinks it, THEN it disappears from the task and GitLab list indicator while the upstream MR is unchanged.
  • GIVEN a GitLab MR or issue search row, WHEN the user launches a preset, THEN the task-create dialog is prefilled with the matching project and context and successful creation navigates to the task.
  • GIVEN a linked MR with discussions, approvals, conflicts, and a pipeline, WHEN the user opens its task review panel, THEN all states and thread actions are available without leaving Kandev.
  • GIVEN an eligible project member, WHEN the user selects them as a reviewer, THEN GitLab and the refreshed MR panel both show that reviewer.
  • GIVEN a linked MR with auto-fix enabled, an open state, a settled failing pipeline, and a promptable session, WHEN automation evaluates the MR, THEN it sends or queues exactly one @mr-auto-fix prompt and auto_fix_round_count increments by one; an unchanged snapshot on the next evaluation dispatches nothing.
  • GIVEN a linked MR with auto-merge enabled and every readiness gate satisfied, WHEN automation evaluates the MR, THEN Kandev merges it exactly once, routed through the workspace client resolved with the linked row's own host; a host mismatch never merges.
  • GIVEN a linked MR reaches merged, closed, or locked, WHEN auto-fix is still enabled, THEN no further auto-fix prompt is dispatched for that MR.
  • GIVEN a task with exactly one linked MR on desktop, WHEN the user hovers the topbar button past the open delay, THEN a preview popover shows the pass-rate bar, approval row, unresolved-discussions row, Automation controls, a merge action when ready, and link/open/unlink actions, all without a click.
  • GIVEN a task with exactly one linked MR on desktop, WHEN the user clicks the topbar button, THEN the MR detail panel opens directly (no dropdown) and any open hover popover closes.
  • GIVEN a task with two or more linked MRs, or any touch/coarse-pointer viewport regardless of MR count, WHEN the user interacts with the topbar button, THEN no hover popover is ever rendered and clicking/tapping opens the existing per-MR dropdown.
  • GIVEN a task with two linked MRs, one merged and one open with a failing pipeline, WHEN the Kanban card renders its MR badge, THEN the badge shows a count of two and the open MR's (red) colour, not the merged MR's.
  • GIVEN an MR or issue the user does not subscribe to, WHEN they enable notifications, THEN GitLab reports it subscribed and no Kandev watch or task is created.
  • GIVEN an enabled review watch, WHEN a new matching MR requests the user as reviewer, THEN one linked task is created in the configured step and auto-starts with the configured profiles when requested.
  • GIVEN an enabled issue watch, WHEN a matching issue appears, THEN one task is created with the issue URL and interpolated issue context.
  • GIVEN a paused watch, WHEN scheduled polling or run-now occurs, THEN no task is created and existing dedup state is retained.
  • GIVEN a watch with owned tasks, WHEN the user previews and confirms reset, THEN all shown tasks are attempted, the response reports successful deletions, dedup state is cleared, the watch remains enabled, and currently matching items can create new tasks immediately (review) or next poll (issue).
  • GIVEN a watch with owned tasks, WHEN the user deletes the watch, THEN Kandev best-effort deletes those tasks and removes the watch/dedup state without recreating tasks from current matches.
  • GIVEN a watch whose bound profile or repository was deleted, WHEN a match is dispatched, THEN the watch disables with a visible error and no orphan task is created.
  • GIVEN a GitLab task branch with committed changes, WHEN the user creates a draft merge request, THEN the branch is pushed to the configured host, the returned MR URL is linked to that task repository, and the UI uses merge-request terminology on desktop and mobile.
  • GIVEN a revoked token in Workspace A, WHEN health polling runs, THEN Workspace A shows auth_required, its watches stop dispatching, and Workspace B continues using its own connection.

Out of scope

  • GitLab webhook ingestion; this iteration uses polling.
  • Durable GitLab issue-to-task linking, issue state synchronization, or Jira/Linear-style structured issue import.
  • Editing GitLab approval rules, protected branches, CI configuration, pipeline jobs/logs, or merge request templates.
  • Group-wide dashboards beyond results visible to the configured user.
  • OAuth-based Kandev sign-in, GitLab Duo, repository migration between hosts, and Bitbucket parity.
  • Multiple named GitLab connections inside one Kandev workspace.
  • A multi-MR aggregate hover preview (the popover only covers the single-MR topbar case; a task with 2+ linked MRs keeps the existing click-only dropdown).
  • GitLab's per-reviewer requested_changes states as a three-way review label; "awaiting review" is approvals-count-based only (version/tier dependent otherwise).
  • Per-job CI log tailing in the auto-fix prompt.