Remove the whole-widget checking state from the MR widget
Removes the whole-widget "checking" state from the merge request widget. When detailedMergeStatus was CHECKING, the widget rendered a single "Checking if merge request can be merged..." row instead of the merge checks section, hiding approvals, discussions, and other checks. The merge checks section already covers this case with its own "Checking for merge conflicts." row, so the override was redundant and inconsistent with how UNCHECKED was already handled.
| Before | After | |
|---|---|---|
| Developer (cannot merge) | ![]() |
![]() |
| Root (can merge, auto-merge available) | ![]() |
![]() |
Detailed context for AI agents
What changed
app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js: removed theCHECKINGbranch that returned thecheckingstate key.app/assets/javascripts/vue_merge_request_widget/stores/state_maps.js: removedcheckingfrom both maps.app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue: removed the import/registration of the checking component and removedcheckingfrom themergeBlockedComponentVisibleexclusion list.- Deleted
app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_checking.vueand its spec. - Updated
spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.jsand one case inspec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js(now uses themergeChecksFailedstate to assert the merge button is hidden). - Regenerated
locale/gitlab.pot(themrWidget|Checking if merge request can be merged...string is no longer used). - Net diff: 8 files, 1 insertion, 51 deletions. Changelog trailer: changed. Not behind a feature flag.
Why
The backend conflict mergeability check (MergeRequests::Mergeability::CheckConflictStatusService) returns status CHECKING whenever merge_status is neither can_be_merged nor cannot_be_merged, so for both unchecked and checking. merge_checks.vue already renders the summary "Checking if merge request can be merged..." with a loading icon, plus a "Checking for merge conflicts." row, whenever any check is CHECKING. The frontend override duplicated that text while hiding all the other checks.
The override also treated the two pending statuses inconsistently. UNCHECKED was never mapped in get_state_key.js, so it fell through to readyToMerge (when merge_when_checks_pass was available) or to null. CHECKING got the override row instead. Removing the override means both statuses now fall through the same path, so no UNCHECKED mapping is needed.
On EE, users who can merge never saw the override anyway. ee/app/assets/javascripts/vue_merge_request_widget/stores/get_state_key.js returns readyToMerge first whenever an auto-merge strategy (merge_when_checks_pass, merge train variants) is available and auto-merge is not enabled, and merge_when_checks_pass is available while the verdict is pending. Those users already got the merge checks section with "Checking for merge conflicts." plus a "Set to auto-merge" button. Only users without merge rights, and CE users, saw the override row.
Behaviour after
A pending MR now falls through deviseState to null (or readyToMerge when an auto-merge strategy is available). null is not in the exclusion list, so merge_checks.vue renders with the conflict check spinning. ready_to_merge.vue hides the merge controls because shouldShowMergeControls requires mr.state === 'readyToMerge'.
When the mergeability worker writes the verdict, the existing mergeRequestMergeStatusUpdated subscription (merge_checks.subscription.graphql) updates the checks and the widget moves to the right state.
Relationship to other MRs
Split out of !255070 (closed) (backend: track pending mergeability checks in a Redis marker instead of writing checking to the database during GET requests, behind the mergeability_check_redis_marker flag). That change makes UNCHECKED visible more often (marker expiry after a lost job, a stale verdict discarded without a state transition, or the gap between a GraphQL poll and the REST poll re-claiming the marker), which is what surfaced this inconsistency. The two MRs are independent and can merge in either order, but the flag rollout should wait for this one.
An earlier revision of this MR instead added an UNCHECKED mapping so it rendered the override row too. That commit was reverted in favor of deleting the override entirely (both commits are in the branch history; the MR squashes).
Alternative rejected: collapsing unchecked into checking in the backend DetailedMergeStatusService. Not needed once the frontend stops distinguishing them, and UNCHECKED is a public GraphQL enum / REST value.
Verification
Jest: spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js, ee/spec/frontend/vue_merge_request_widget/stores/get_state_key_spec.js, spec/frontend/vue_merge_request_widget/components/states/mr_widget_ready_to_merge_spec.js (CE and EE), spec/frontend/vue_merge_request_widget/mr_widget_options_spec.js (CE and EE): 6 suites, 194 passed, 2 skipped (pre-existing skips).
Pre-push eslint and prettier hooks clean.
Screenshots
The table above the details block was captured on GDK with the MR pinned in checking (merge_status set to checking and the mergeability_check:<id> exclusive lease held so the synchronous check could not resolve it), after a full gdk stop and gdk start on each commit: base 16bc70d0 for "before", branch head for "after". Two users: a developer without merge rights, and root (can merge, merge_when_checks_pass available). Root is identical in both because users with an auto-merge strategy already took the merge checks path.
Related to #628132 (closed)



