GitLab MR Conform Checker is an automated tool designed to enforce compliance and quality standards on GitLab merge requests (MRs). By programmatically validating MRs against organizational rules, it reduces human error, ensures consistency, and accelerates code reviews. It integrates directly with GitLab and leaves a structured discussion on each MR highlighting any conformity violations.
- 🔎 MR Title & Description Validation: Enforces format (e.g., JIRA/Asana key), length, and structure.
- 💬 Commit Message Checks: Ensures message compliance with standards (e.g., Conventional Commits).
- 🏷️ Issue Tracking Integration: Verifies associated issue/task keys in MRs or commits (supports JIRA and Asana).
- 🌱 Branch Rules: Validates naming conventions (e.g.,
feature/,bugfix/,hotfix/). - 📦 Squash Commit Enforcement: Checks MR squash settings when required.
- 👥 Approval Rules: Ensures required reviewers have approved the MR.
- 📁 CODEOWNERS Integration: Extends approver validation to include owners defined in the
.gitlab/CODEOWNERSfile using GitLab syntax and validation, enabling fine-grained and automated review enforcement based on file paths or directories. See CODEOWNERS docs. See caveats. - 🛠️ Extensible Rules Engine: Easily add custom checks or adjust rule strictness per project.
- Creates structured discussions on merge requests with violation details
- Provides clear, actionable feedback for developers
- Tracks compliance status across projects
Prerequisites: Go 1.21+ and GitLab API access token
# Clone and build
make buildSet up your environment:
export GITLAB_MR_BOT_GITLAB_TOKEN="your_gitlab_token"
export GITLAB_MR_BOT_GITLAB_SECRET_TOKEN="your_webhook_secret"
# Optional: For Asana API validation (if validate_existence: true)
export GITLAB_MR_BOT_INTEGRATIONS_ASANA_API_TOKEN="your_asana_token"Create a config.yaml file to define your compliance rules:
server:
port: 8080
host: "0.0.0.0"
log_level: info
gitlab:
base_url: "https://gitlab.com"
rules:
title:
enabled: true
min_length: 10
max_length: 100
conventional:
types: ["feat", "fix", "docs", "refactor", "release"]
jira:
keys: ["PROJ", "JIRA"]
asana:
keys: ["DESIGN", "MARKETING"]
validate_existence: false # Set to true to verify tasks exist via Asana API
description:
enabled: true
required: true
min_length: 20
branch:
enabled: true
allowed_prefixes: ["feature/", "bugfix/", "hotfix/", "release/"]
forbidden_names: ["master", "main", "develop"]
commits:
enabled: true
max_length: 72
conventional:
types: ["feat", "fix", "docs", "refactor", "release"]
jira:
keys: ["PROJ"]
asana:
keys: ["DESIGN"]
validate_existence: false
approvals:
enabled: false
use_codeowners: true # Use .gitlab/CODEOWNERS file to require approvals from owners
min_count: 1 # Checking just number of approvals, skipped if use_codeowners set to true
exclude_creator_from_count: false # If true, the MR creator cannot be counted as an approver
squash:
enabled: true
enforce_branches: ["feature/*", "fix/*"]
integrations:
asana:
# Set via environment variable:
# GITLAB_MR_BOT_INTEGRATIONS_ASANA_API_TOKEN
api_token: ""Tip
You can configure settings per project by adding a .mr-conform.yaml file to the root of the repository's default branch.
To define your settings, simply include a rules object in the file.
The tool supports both Jira and Asana for issue tracking validation:
Jira Format:
PROJ-123or[PROJ-123]- Standard Jira issue key
Asana Formats:
PROJ-1234567890123456- Project prefix + 16-digit task IDhttps://app.asana.com/.../task/1234567890123456- Full Asana task URL
Validation Modes:
- Regex-only (default): Fast validation checking format and project keys
- API validation (opt-in): Verify tasks actually exist (requires API token)
Note
When both Jira and Asana are configured, commits pass if they have a valid reference to either system.
- Navigate to your GitLab project → Settings → Webhooks
- Add webhook:
- URL:
https://your-domain.com/webhook - Trigger: Merge request events
- Secret Token: Your webhook secret
- URL:
- Start the service:
make run
📄 Issue 1: 3 commit(s) have invalid Conventional Commit format:
- Merge branch 'security-300265-13-18' into '13-18-s... (d6b32537)
- Update CHANGELOG and VERSION (be84773e)
- Modify regex to prevent partial matches (1f04c93c)
💡 Tip: Use format:
type(scope?): descriptionExample:
feat(auth): add login retry mechanism
📄 Issue 2:
| Code owners | Approvals | Allowed approvers | |
|---|---|---|---|
| ⬜ | Default* |
0 of 1 | @root, @i-user-0-1737465646, @i-user-1-1737465646, @i-user-2-1737465646, @project_3_bot_d4ac3dc65e519f6b59b9f8272e89115e |
| ⬜ | Default/client/*test* |
0 of 1 | @root, @mr-bot |
| ⬜ | DocumentationD\[ocumentationaddedfile |
0 of 1 | @root |
| ⬜ | DocumentationREADME.md |
0 of 1 | @illa, @sheridan |
💡 Tip: Wait for required approvals before merging
🚨 Syntax errors:
- Line 13: error parsing owners: invalid owners ignored: [@@@approveuser @@randomgroup]
docker run -p 8080:8080 \
-e GITLAB_MR_BOT_GITLAB_TOKEN=$GITLAB_TOKEN \
-e GITLAB_MR_BOT_GITLAB_SECRET_TOKEN=$WEBHOOK_SECRET \
-e GITLAB_MR_BOT_INTEGRATIONS_ASANA_API_TOKEN=$ASANA_TOKEN \
ghcr.io/chrxmvtik/gitlab-mr-conform:mainNote: Only include Asana token environment variables if you're using Asana API validation (validate_existence: true).
version: "3.8"
services:
mr-checker:
image: ghcr.io/chrxmvtik/gitlab-mr-conform:main
ports:
- "8080:8080"
environment:
- GITLAB_MR_BOT_GITLAB_TOKEN=${GITLAB_TOKEN}
- GITLAB_MR_BOT_GITLAB_SECRET_TOKEN=${WEBHOOK_SECRET}
# Optional: For Asana API validation
- GITLAB_MR_BOT_INTEGRATIONS_ASANA_API_TOKEN=${ASANA_TOKEN}
volumes:
- ./config.yaml:/app/config.yamlBest Practice: Use Docker secrets instead of environment variables for production:
secrets:
- asana_token
environment:
- GITLAB_MR_BOT_INTEGRATIONS_ASANA_API_TOKEN=/run/secrets/asana_tokenDeploy using our:
- Helm chart - see charts/README.md for details.
- Plain manifest - manifest
| Endpoint | Method | Description |
|---|---|---|
/webhook |
POST | GitLab webhook receiver |
/health |
GET | Health check |
/status |
GET | Merge request status checker |
# Setup development environment
make dev-setup
# Run tests
make test
# Run locally
make run
# Build for production
make buildWebhook not receiving events?
- Verify GitLab can reach your endpoint
- Check webhook secret configuration
- Review GitLab webhook logs
False positive violations?
- Adjust rule strictness in
config.yaml - Review regex patterns for validation
- Test rules against existing MRs
While CODEOWNERS integration greatly improves automated enforcement of approvals, there are some important limitations to be aware of:
- Lack of group detection: Using GitLab groups like
@group/frontend/membersis not currently supported. This would require admin-level privileges to resolve group membership and map groups to individual users.