Configurable merge train pipeline limits (3/4)
What does this MR do and why?
This is MR 3 of 4 in a stacked series that adds configurable merge train pipeline limits, addressing gitlab-org/gitlab#374188.
| MR | Branch | Base | Content |
|---|---|---|---|
| 1 | 374188-1-add-max-pipelines-per-merge-train-plan-limit |
master |
Database migrations (!228370 (merged)) |
| 2 | 374188-2-backend-logic-and-api |
374188-1-add-max-pipelines-per-merge-train-plan-limit |
Backend logic, REST API, GraphQL, tests (!228371 (merged)) |
| 3 (this MR) | 374188-3-admin-and-project-ui |
374188-2-backend-logic-and-api |
Admin UI, Project UI, validations |
| 4 | 374188-4-documentation |
master |
Documentation (!228488 (merged)) |
This MR adds UI form fields and model validations for the configurable merge train pipeline limit at both the instance and project level.
Screenshots
| Before | After |
|---|---|
![]() |
![]() |
Files to review in this MR
Note: This is a stacked MR. The diff includes files from MR 1 and MR 2. Only the files listed below are new in this MR.
Admin UI:
app/views/admin/application_settings/_ci_cd.html.haml- New number field in Plan Limits formapp/helpers/plan_limits_helper.rb- Label description for the new field
Project UI:
ee/app/views/projects/settings/merge_requests/_merge_trains_settings.html.haml- New number field withmaxconstrained to instance limit, help text shows current instance limit
Model validations:
app/models/plan_limits.rb->= 1validation (prevents 0 or negative values)app/models/project_ci_cd_setting.rb->= 1, allow_nilvalidation
RefreshService hardening:
ee/app/services/merge_trains/refresh_service.rb- Fallback guard: if limit is 0 due to direct DB manipulation, falls back to DEFAULT_CONCURRENCY (20)
Tests:
spec/helpers/plan_limits_helper_spec.rb- New limit name in known limits listspec/models/plan_limits_spec.rb- Numericality validation testspec/models/project_ci_cd_setting_spec.rb- Numericality validation testspec/controllers/admin/plan_limits_controller_spec.rb- Controller accepts new parameteree/spec/graphql/ee/mutations/ci/project_ci_cd_settings_update_spec.rb- GraphQL mutation sets valueee/spec/services/merge_trains/refresh_service_spec.rb- Edge case: plan limit is 0
Auto-generated:
locale/gitlab.pot- New translatable strings
How to validate locally
Admin UI
Navigate to Admin > Settings > CI/CD > CI/CD Limits and verify the new "Maximum number of pipelines in a merge train running in parallel" field.
Project UI
Navigate to Project > Settings > Merge requests > Merge options and verify
the new "Maximum pipelines per merge train" field. The help text shows the
current instance limit, and the field enforces max to the instance limit.
Validations (Rails console)
# Plan limit rejects 0
Plan.default.actual_limits.update(max_pipelines_per_merge_train: 0)
# => false
# Project limit rejects 0
Project.find(<id>).ci_cd_settings.update(max_pipelines_per_merge_train: 0)
# => false
# Project limit allows nil (inherits instance limit)
Project.find(<id>).ci_cd_settings.update!(max_pipelines_per_merge_train: nil)
# => trueMR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
- Admin UI form field with min: 1
- Project UI form field with max constrained to instance limit
- Model validations prevent invalid values via UI and API
- RefreshService fallback guard for corrupted DB values
- Tests for validations, controller, GraphQL mutation, and edge case
Related issues
Part of gitlab-org/gitlab#374188 (parent epic: gitlab-org&2219)



