Architecture
Overview
Section titled “Overview”GitLab Auto Merge is a Kotlin/Ktor backend service. It connects to one GitLab project via the GitLab API and manages merge requests autonomously.
+-----------------+ GitLab API +-------------------+| | ----------------------> | || Auto Merge | | GitLab Instance || (port 8711) | <---------------------- | || | Webhooks +-------------------++-----------------+Tech Stack
Section titled “Tech Stack”| Layer | Technology |
|---|---|
| Backend | Kotlin/JVM, Ktor Server |
| GitLab Integration | gitlab4j-api |
| CLI | Clikt |
| Serialization | Kotlinx Serialization + Jackson |
| Containerization | Jib (Google) |
Execution Model
Section titled “Execution Model”Scheduling
Section titled “Scheduling”- Polls every 15 seconds (configurable)
- Also triggered by GitLab webhooks (MR and pipeline events)
- Webhook triggers are debounced to avoid redundant runs
- A mutex prevents concurrent executions
Four-Phase Execution
Section titled “Four-Phase Execution”Each auto-merge run executes in strict sequence:
- Data Collection — Fetches MRs, pipelines, runners from GitLab API
- Calculation — Builds command objects from MR state. No side effects.
- Execution — Executes all collected commands against GitLab
- Result — Records audit protocol, updates dashboard state
Command Pattern
Section titled “Command Pattern”All actions are modeled as command objects:
| Command | Action |
|---|---|
SetStatusLabel | Update MR status label |
SetQueueLabel | Set queue position label |
Merge | Merge the MR |
Rebase | Rebase onto target branch |
CancelPipeline | Cancel a running pipeline |
RetryJob | Retry a failed job |
ApplyDesiredLabels | Apply desired-state labels |
CancelAutoMerge | Cancel GitLab’s built-in “merge when pipeline succeeds” |
AddNoteToMergeRequest | Add comment to MR |
Benefits:
- DryRun shows all planned commands without executing
- Calculation logic is testable independently of execution
- Commands can be analyzed, filtered, or reordered before execution
Desired-State Label Model
Section titled “Desired-State Label Model”Labels are managed declaratively. The system computes the desired label set for each MR and applies the diff — preventing toggling issues where labels are added and removed in rapid succession.
Execution Protocol
Section titled “Execution Protocol”Every run is recorded with:
- Start/finish timestamps
- MRs retrieved and categorized
- Commands executed (with dry-run flag)
- All events stored for audit trail and UI display
Docker Image
Section titled “Docker Image”The official Docker image is available on Docker Hub: