Remove approval_rules_finalize_bulk_copy_approvers feature flag

Removes the approval_rules_finalize_bulk_copy_approvers feature flag. It has been enabled for 100% of projects on GitLab.com since 2026-09-24 with no regressions, so ApprovalRules::FinalizeService now always bulk inserts the approvers when it copies project approval rules to a merged merge request.

Detailed context for AI agents

What does this MR do and why?

  • Drops the bulk_copy_approvers? guard in ApprovalRules::FinalizeService#copy_project_rules. The copied rule is always built without users: / groups:, saved, and then copy_approvers inserts the approver join rows with one ApprovalMergeRequestRulesUser.insert_all per rule (idempotent on [approval_merge_request_rule_id, user_id], with project_id set) and assigns rule.groups. The old path assigned users: through the habtm association, which made autosave validate every User record inside the finalize transaction.
  • Removes the bulk_copy_approvers? method and its strong_memoize_attr.
  • Deletes the flag definition ee/config/feature_flags/gitlab_com_derisk/approval_rules_finalize_bulk_copy_approvers.yml.
  • Removes the flag-disabled spec context in ee/spec/services/approval_rules/finalize_service_spec.rb. The remaining examples assert the copied rules, users, groups and approved approvers, and that insert_all is called once.

Behaviour kept: rules that fail validation are still deleted from the association and logged, and copy_approvers is only called after save!. If the insert raises, the finalize transaction rolls back as before. No schema or data change; the rows written to approval_merge_request_rules_users are identical with the flag on or off.

Rollout history (from the rollout issue): staging and gitlab-org/gitlab 2026-09-23, 5% of projects 2026-09-23, 20% and 50% 2026-09-24, 100% 2026-09-24. Watched MergeWorker on the Sidekiq worker detail dashboard and the PatroniLongRunningTransactionDetected alerts; nothing regressed.

References

Screenshots or screen recordings

Not applicable, backend-only flag removal.

How to set up and validate locally

  1. On an EE GDK, in a project with approval rules that have user and group approvers, enable Settings > Merge requests > Prevent editing approval rules in merge requests.
  2. Merge a merge request in that project.
  3. In the Rails console confirm the copied rules carry the approvers: MergeRequest.last.approval_rules.regular.map { |r| [r.name, r.users.map(&:username), r.groups.map(&:path)] }.

Verification

  • bundle exec rspec ee/spec/services/approval_rules/finalize_service_spec.rb - 14 examples, 0 failures.
  • Rubocop clean on both changed Ruby files.

MR acceptance checklist

Evaluated against the MR acceptance checklist. Flag removal only, no new risk in quality, performance, reliability, security, or maintainability.

Merge request reports

Loading
Loading