Quick action preview inconsistently omits commands due to transient MR state
Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.
Summary
The quick action preview in the MR comment box inconsistently omits commands when multiple quick actions are used together (e.g. /approve, /run_pipeline, /merge). Sometimes all three appear in the preview, sometimes only a subset (e.g. 2 out of 3) is shown. Which command is omitted varies — it is not always the same one.
Steps to reproduce
- Open a merge request
- In the comment box, type:
/approve /run_pipeline /merge - Observe the preview — it may show all three commands, or only a subset
- Repeat on different MRs — the behavior is inconsistent
Observed behavior
- In some MRs, all three commands appear in the preview
- In others, only 2 of 3 appear (e.g.
/run_pipelineand/mergeshow but/approvedoes not) - The subset shown can differ across MRs in the same project and across projects
See the original report in #210538 (comment 3060722435) for screenshots and specific examples.
Expected behavior
The preview should consistently show all applicable quick actions.
Root cause analysis
The preview is generated via the preview_markdown endpoint, which calls QuickActions::InterpretService#explain. For each command, CommandDefinition#explain (lib/gitlab/quick_actions/command_definition.rb:45-46) calls available?, which evaluates the command's condition block against the MR's current state. If available? returns false, the command is silently omitted from the preview.
Each command's condition (lib/gitlab/quick_actions/merge_request_actions.rb) performs stateful checks:
-
/approve(line 260): callseligible_for_approval_by?— in EE this loads approval rules, associated users/groups, and checks the approvals table viaApprovalState -
/run_pipeline(line 516): callsCreatePipelineService#allowed?— checks pipeline existence and user permissions -
/merge(line 47): callsmerge_orchestration_service.can_merge?— cascades intomergeable?→check_mergeability, which acquires an exclusive lease and can trigger a Gitalymerge-to-refoperation
All of these conditions are sensitive to the MR's transient state (e.g. merge_status being unchecked after a push, exclusive lease contention, approval rules loading). When any condition returns false due to timing, the corresponding command silently disappears from the preview.
Relevant files
-
lib/gitlab/quick_actions/command_definition.rb—available?/explaingating -
lib/gitlab/quick_actions/merge_request_actions.rb— condition blocks for/merge,/approve,/run_pipeline -
app/services/preview_markdown_service.rb— preview service -
app/services/quick_actions/interpret_service.rb—explainmethod -
app/services/merge_requests/merge_orchestration_service.rb—can_merge? -
app/services/merge_requests/mergeability_check_service.rb— exclusive lease logic