Remove discard_stale_mergeability_verdicts feature flag

Removes the discard_stale_mergeability_verdicts feature flag. The flag has been enabled on GitLab.com since 2026-09-02 with no regressions, so the transactional claim in MergeabilityCheckService#write_merge_status becomes the only path and the old unconditional write goes away.

Detailed context for AI agents

What the flag gated

MergeRequests::MergeabilityCheckService#update_merge_status reads the merge request's merge status inputs (target branch and latest source diff) before the Gitaly checks. write_merge_status then opens a transaction, locks the row, and only calls mark_as_mergeable / mark_as_unmergeable if those inputs are still current. If they are not, the verdict is discarded, @merge_status_discarded is set, and the service returns a ServiceResponse error with reason stale_merge_status_discarded. With the flag off, the inputs were never read and the verdict was written unconditionally, so a caller holding a stale record could overwrite a current verdict after a retarget or a source diff reload. See #606487 (closed) for the original bug.

Rollout history (GitLab.com)

  • 2026-08-21: enabled for specific projects
  • 2026-08-26: 10% / 25% / 50% of actors, then 100% the same day
  • 2026-09-01: disabled while investigating Sidekiq concurrency-limit issues that suspected workers being held open too long
  • 2026-09-02: found unrelated, re-enabled; enabled since

The YAML was already default_enabled: true, so self-managed behaviour does not change.

Changes

  • app/services/merge_requests/mergeability_check_service.rb: removed the Feature.enabled? check and the memoized discard_stale_merge_status_writes? predicate; merge_status_inputs is now always read; the early yield / return true path in write_merge_status is gone.
  • config/feature_flags/beta/discard_stale_mergeability_verdicts.yml: deleted.
  • spec/services/merge_requests/mergeability_check_service_spec.rb: removed the three "when discard_stale_mergeability_verdicts is disabled" contexts. They covered the unconditional-write path (stale verdict overwrites current one, broken MR writes stale unmergeable status) and the "reads no inputs, locks no row" behaviour, none of which exists anymore.

Verification

  • bundle exec rspec spec/services/merge_requests/mergeability_check_service_spec.rb: 57 examples, 0 failures
  • Rubocop clean on both changed files
  • No docs reference the flag

Post-merge

Delete the flag from all environments:

/chatops gitlab run feature delete discard_stale_mergeability_verdicts --dev --pre --staging --staging-ref --production

Out of scope

No behaviour change beyond removing the flag. Anything stuck in checking because of a refused write is a separate concern and was not observed during rollout.

References

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Merge request reports

Loading
Loading