Detect when merge train ref includes legacy commit message
Problem to solve
During and after an upgrade to a version with fast-forward merge train support, there can be existing merge train refs with legacy commit messages. They should NEVER be merged into the target branch.
Background
In the upcoming fast-forward merge trains, we merge via a fast-forward merge from the merge train ref instead of re-performing the merge from the source branch (which is what the traditional merge commit method does). The problem with that is that merge train refs are currently constructed with a commit message as follows (source):
def commit_message(merge_request, previous_ref)
"Merge branch #{merge_request.source_branch} with #{previous_ref} " \
"into #{merge_request.train_ref_path}"
end
Once we have fully rolled out #420161 (closed), the merge train ref will be representative for any new merge train. But this does not apply to merge train refs that have already been created:
- In an upgrade with downtime: There may be an existing train that gets picked up by the new version.
- In a zero-downtime upgrade (e.g. GitLab.com): New train refs may get touched by old code and vice versa.
Proposal
When merging a merge train, if a legacy commit is detected in the train ref, fall back to the legacy merge strategy.
Outline:
- When constructing the train ref for a given car, check whether the the previous car is fast-forward compatible:
- If it is, then construct the given car as fast-forward compatible as well
- Otherwise, fall back to the legacy strategy
- When picking a merge strategy for a mergeable car, check whether the train ref is fast-forward compatible.
- If it is, attempt the fast-forward.
- If not, fall back to the legacy strategy
Now, the detection for a given car works as follows:
- Compare the car's commit SHA against
merge_request.merge_params.dig('train_ref', 'commit_sha')
. The latter will only be recorded when standard commit messages are enabled. - Compare the car's commit message against the legacy commit message.