Automatically create Merge Requests in GitLab using a lightweight Go binary.
- âś… Zero external dependencies - uses only Go standard library
- âś… Small Docker image (~26MB with Alpine 3.22)
- âś… Fast execution (~10ms startup time)
- âś… Compatible with GitLab CI/CD
- âś… Cross-platform support (Linux, macOS, Windows)
- âś… Built with Go 1.25 for optimal performance
- âś… Safe MR management - explicit control over creating or updating MRs
- âś… Prevents accidental overwrites - requires
--update-mrflag to update existing MRs
Docker images are automatically built and published to GitHub Container Registry for each release.
latest- Latest stable releasevX.Y.Z- Specific version (e.g.,v1.6.0)vX.Y- Latest patch version of a minor release (e.g.,v1.6)vX- Latest minor and patch version of a major release (e.g.,v1)
# Latest release
docker pull ghcr.io/batonogov/gitlab-auto-mr:latest
# Specific version
docker pull ghcr.io/batonogov/gitlab-auto-mr:v1.6.0linux/amd64linux/arm64
- Set required environment variables:
export GITLAB_PRIVATE_TOKEN="your-gitlab-token"
export GITLAB_USER_ID="your-user-id"
export CI_PROJECT_ID="12345"
export CI_PROJECT_URL="https://gitlab.com/user/project"
export CI_COMMIT_REF_NAME="feature/my-branch"- Run with Docker (recommended):
# Creates new MR or informs if MR already exists
docker run --rm \
-e GITLAB_PRIVATE_TOKEN \
-e GITLAB_USER_ID \
-e CI_PROJECT_ID \
-e CI_PROJECT_URL \
-e CI_COMMIT_REF_NAME \
ghcr.io/batonogov/gitlab-auto-mr:latest \
gitlab_auto_mr --target-branch main --commit-prefix "Ready"- Or build and run locally:
git clone https://github.com/user/gitlab-auto-mr.git
cd gitlab-auto-mr
task build
# Creates new MR or informs if MR already exists
./gitlab_auto_mr --target-branch main --commit-prefix "Ready"create_mr:
stage: create-mr
image: ghcr.io/batonogov/gitlab-auto-mr:latest
script:
- |
# Creates new MR or informs if MR already exists
gitlab_auto_mr \
--target-branch main \
--commit-prefix "Ready" \
--remove-branch \
--squash-commits
rules:
- if: $CI_COMMIT_BRANCH != "main" && $CI_PIPELINE_SOURCE != "merge_request_event"update_mr:
stage: update-mr
image: ghcr.io/batonogov/gitlab-auto-mr:latest
script:
- |
# Updates existing MR (requires --update-mr flag)
gitlab_auto_mr \
--update-mr \
--target-branch main \
--commit-prefix "Ready" \
--description .gitlab/merge_request_template.md \
--use-issue-name \
--reviewer-id "${REVIEWER_IDS}"
rules:
- if: $CI_COMMIT_BRANCH != "main" && $CI_PIPELINE_SOURCE != "merge_request_event"# Force update only (fail if MR doesn't exist)
update_only:
script:
- gitlab_auto_mr --update-mr --target-branch main
# Force create only (fail if MR already exists)
create_only:
script:
- gitlab_auto_mr --create-only --target-branch mainGITLAB_PRIVATE_TOKEN- GitLab personal access token withapiscopeGITLAB_USER_ID- Your GitLab user ID (comma-separated for multiple assignees)CI_PROJECT_ID- GitLab project IDCI_PROJECT_URL- GitLab URLCI_COMMIT_REF_NAME- Source branch name
| Option | Short | Description | Default |
|---|---|---|---|
--target-branch |
-t |
Target branch for MR | Project default branch |
--commit-prefix |
-c |
MR title prefix | Draft |
--title |
Custom MR title | Source branch name | |
--description |
-d |
Path to description file | - |
--remove-branch |
-r |
Delete source branch after merge | false |
--squash-commits |
-s |
Squash commits on merge | false |
--use-issue-name |
-i |
Use issue data from branch name | false |
--allow-collaboration |
-a |
Allow commits from merge target members | false |
--reviewer-id |
Reviewer user ID(s) (comma-separated) | - | |
--mr-exists |
Only check if MR exists (dry run) | false |
|
--update-mr |
Update existing MR (required to update, fail if none exists) | false |
|
--create-only |
Force create new MR (fail if already exists) | false |
|
--insecure |
-k |
Skip SSL certificate verification | false |
- Go 1.25 or later
- Task (optional, for build automation)
# Using Task (recommended)
task build # Build binary
task test # Run tests
task docker-build # Build Docker image
task clean # Clean artifacts
task --list # Show all tasks
# Or using Go directly
go build -o gitlab_auto_mr .
go test ./...This project uses pre-commit hooks for code quality and consistency:
# Install pre-commit (if not already installed)
pip install pre-commit
# Install hooks
pre-commit install
# Run hooks on all files
pre-commit run --all-files
# Run hooks on specific files
pre-commit run --files main.goIncluded hooks:
- Go dependency verification
- Go code formatting
- Go linting
- Go tests
- Taskfile validation
- Dockerfile validation
- YAML validation
- Markdown formatting
- Large file detection
- Merge conflict detection
task docker-build
# or
docker build -t gitlab-auto-mr .# Creates new MR or informs if MR already exists
./gitlab_auto_mr \
--target-branch main \
--commit-prefix "Ready"./gitlab_auto_mr \
--target-branch main \
--reviewer-id "12345,67890"./gitlab_auto_mr \
--mr-exists \
--target-branch main# Update existing MR (requires --update-mr flag, fail if MR doesn't exist)
./gitlab_auto_mr \
--update-mr \
--target-branch main \
--title "Updated Title" \
--description new_description.md# Only create new MR (fail if MR already exists)
./gitlab_auto_mr \
--create-only \
--target-branch main \
--reviewer-id "12345,67890"Authentication Error
Error: unable to get project 12345: unauthorized access, check your access token is valid
- Check your
GITLAB_PRIVATE_TOKENis valid and hasapiscope
MR Already Exists
Merge request already exists: Feature XYZ (IID: 42). Use --update-mr flag to update it.
- This is the default behavior when MR already exists
- Add
--update-mrflag to update the existing MR instead
Update Mode Error
Error: merge request does not exist for this branch feature/test to main, cannot update non-existent MR
- This happens when using
--update-mrflag but no MR exists - Remove
--update-mrflag to create a new MR instead
Force Create Mode Error
Error: merge request already exists for this branch feature/test to main, cannot create new MR in create-only mode
- This happens when using
--create-onlyflag but MR already exists - Remove
--create-onlyflag to allow the tool to inform about existing MR - Use
--update-mrflag instead if you want to update the existing MR
Same Source/Target Branch
Error: source branch and target branches must be different
- Ensure you're not running on the target branch
| Metric | Go Version | Python Version |
|---|---|---|
| Binary Size | ~5.7MB | ~50MB+ |
| Docker Image | ~26MB | ~80MB+ |
| Startup Time | ~10ms | ~200ms+ |
| Memory Usage | ~5MB | ~20MB+ |
| Dependencies | 0 external | 10+ packages |
MIT License - see LICENSE file for details.