Fix any_merge_request policy violations stuck in running on fork MRs
What does this MR do and why?
- Fixes
Security::ScanResultPolicyViolationrows forany_merge_requestapproval policy rules getting stuck atstatus: runningforever on fork MRs, especially personal-namespace forks. - While stuck running,
CheckSecurityPolicyViolationsServicereportschecking, sodetailed_merge_statusissecurity_policy_violationsand the merge widget spins with no automatic recovery. - Since 18.4 removed the
policy_mergability_checkflag, this status is a hard merge gate, so a lost sync now permanently blocks the MR. - Close/reopen currently works around it (
ReopenServicere-creates rules and re-schedules the sync), but that's manual. - Reported via customer escalation: request-for-help work item 5212 and two Zendesk tickets, recurring across versions.
Three root causes, one commit each (review order: 2, 3, 1):
| # | Where | Bug | Fix |
|---|---|---|---|
| 1 | EE::MergeRequests::CreateService#after_create |
Violations created after super already enqueued NewMergeRequestWorker, the only thing that resolves them at creation time |
Create violations before super |
| 2 | MergeRequests::Refresh::ApprovalService#sync_any_merge_request_approval_rules |
Worker enqueue gated on the pushed-to project (the fork, no policies/license), while still re-creating running violations from the target project's rules on every push | Gate per MR on merge_request.project (target project), memoized per project id, matching SyncMergeRequestsService |
| 3 | UnenforceablePolicyRulesPipelineNotificationWorker / UnblockPendingMergeRequestViolationsWorker |
Gated on pipeline.project; fork pipelines run in the fork, so the 90s unblock safety net never fired for fork MRs |
Gate per related MR on its target project |
Fourth commit is perf-only, no behavior change:
- restores a cheap short-circuit in the notification worker for non-fork, non-MR pipelines (they can only match MRs targeting their own project)
- preloads the target project in
opened_merge_requests_with_head_shainstead of in the workers - memoizes the unblock worker's availability check
- renames a shadowing
projectparam totarget_projectinApprovalService
Notes:
-
Defect 2 side effect: MRs whose target project has no commit-targeting policies are no longer enqueued. Safe, since
SyncAnyMergeRequestRulesServicealready early-returns. -
Defect 3 is roughly query-neutral: loads related MRs before gating, drops a project-level
approval_rulesexistence query. -
UnenforceablePolicyRulesNotificationWorkercall sites are unchanged; it already gates per MR. -
No data migration for already-stuck MRs. A push or a close/reopen unsticks one; so does
merge_request.synchronize_approval_rules_from_target_project+schedule_policy_synchronizationin a console. -
No feature flag: small, strictly corrective fix. A flag on the create-path ordering change would be untestable in the field.
References
Screenshots or screen recordings
| Before | After |
|---|---|
| N/A | N/A |
How to set up and validate locally
- GDK with an Ultimate license. Create a group with a security policy project.
- Add an approval policy rule:
type: any_merge_request,commits: any, an approval action,fallback_behavior: fail: closed. - Create a project in that group with a protected default branch and no
.gitlab-ci.yml. - As a second user, fork the project into their personal namespace and push a branch.
- Open an MR from the fork branch into the upstream project.
- Before this fix: the violation stays
running, is re-createdrunningon every push, and the widget spins on "Checking if merge request can be merged." - After this fix: the violation moves to
failed(until approved) or is deleted, and the widget resolves. Pushing again re-evaluates the violation correctly. - Relevant specs:
ee/spec/services/ee/merge_requests/create_service_spec.rb,ee/spec/services/merge_requests/refresh/approval_service_spec.rb,ee/spec/workers/security/unenforceable_policy_rules_pipeline_notification_worker_spec.rb,ee/spec/workers/security/scan_result_policies/unblock_pending_merge_request_violations_worker_spec.rb.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist.