Fix broken merge train merge when target branch deleted for add to merge train when checks pass

Problem

This bug can leave a car on the train that should have been removed for merge trains using 'auto merge when checks pass' . Users can end up with MRs where the only workaround is to create a new MR. Please see: #483097 (closed) for full details around the bug.

Fix

The following discussion from !165216 (merged) should be addressed:

Implementation guide

module AutoMerge
  class AddToMergeTrainWhenChecksPassService < AutoMerge::BaseService
    ...
    def abort(merge_request, reason)
      # If the merge request is already on a merge train, we need to destroy the car
      # i.e. If the target branch is deleted which causes an abort with this strategy,
      # after the pipeline succeeded and was added
      # 
      if merge_request.merge_train_car
        AutoMerge::MergeTrainService.new(project, current_user).abort(merge_request, reason)
      # Before the pipeline checks pass and was added to the merge train
      else
        super do
          SystemNoteService.abort_add_to_merge_train_when_checks_pass(merge_request, project, current_user, reason)
        end
      end
    end
    ...

Tweaking the availability check might work as well but it's still prone to be a bit racy as this stuff happens in the background.

follow-up

We should be able to create a base class AutoMerge::MergeTrain::AddToMergeTrainService because the two SystemNoteService methods go through many layers of abstraction but the underlying implementation is actually 100% same.

module AutoMerge
  module MergeTrain
    class AddToMergeTrainService < AutoMerge::BaseService
      ...
      def abort(merge_request, reason)
        # If the merge request is already on a merge train, we need to destroy the car
        # i.e. If the target branch is deleted which causes an abort with this strategy,
        # after the pipeline succeeded and was added
        # 
        if merge_request.merge_train_car
          AutoMerge::MergeTrainService.new(project, current_user).abort(merge_request, reason)
        # Before the pipeline checks pass and was added to the merge train
        else
          super do
            SystemNoteService.abort_add_to_merge_train(merge_request, project, current_user, reason)
          end
        end
      end
    ...
Edited by Allison Browne