summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStan Hu <stanhu@gmail.com>2018-10-25 13:04:03 -0700
committerStan Hu <stanhu@gmail.com>2018-10-29 16:51:22 -0700
commit0509c3cf17976a2acb53ea84a51b0f50d1f400fb (patch)
tree24130858287add307a940d172739d61bb4bfb0da
parent44a6b8d4f7feb8ba42981526379e8395fdd6f67e (diff)
downloadgitlab-ce-0509c3cf17976a2acb53ea84a51b0f50d1f400fb.tar.gz
Fix extra merge request versions created from forked merge requestssh-fix-issue-53153
When a forked merge request was created with the same branch name as the target name, MergeRequests::RefreshService would always create a new diff even though nothing had changed. For example, on GitLab.com: 1. There were a number of merge requests in the gitlab-ce and www-gitlab-com projects that had old merge requests from the community. 2. These merge requests originated from forked projects and used the source branch master. 3. When someone pushed to master in the main repository, MergeRequests::RefreshService would see that master matched the merge requests in question and generated a new diff. 4. This led to an explosion of merge request diffs and slowed down the "Changes" tab considerably. This change alters MergeRequests::RefreshService so that it will only refresh the diff if the merge request's source project and branch match. Otherwise, the refresh will only happen if a pushed commit contains a commit relevant to the existing merge request. Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/53153
-rw-r--r--app/services/merge_requests/refresh_service.rb7
-rw-r--r--changelogs/unreleased/sh-fix-issue-53153.yml5
-rw-r--r--spec/services/merge_requests/refresh_service_spec.rb60
3 files changed, 71 insertions, 1 deletions
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index b03d14fa3cc..f01872b205e 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -85,7 +85,7 @@ module MergeRequests
.where.not(target_project: @project).to_a
filter_merge_requests(merge_requests).each do |merge_request|
- if merge_request.source_branch == @push.branch_name || @push.force_push?
+ if branch_and_project_match?(merge_request) || @push.force_push?
merge_request.reload_diff(current_user)
else
mr_commit_ids = merge_request.commit_shas
@@ -104,6 +104,11 @@ module MergeRequests
end
# rubocop: enable CodeReuse/ActiveRecord
+ def branch_and_project_match?(merge_request)
+ merge_request.source_project == @project &&
+ merge_request.source_branch == @push.branch_name
+ end
+
def reset_merge_when_pipeline_succeeds
merge_requests_for_source_branch.each(&:reset_merge_when_pipeline_succeeds)
end
diff --git a/changelogs/unreleased/sh-fix-issue-53153.yml b/changelogs/unreleased/sh-fix-issue-53153.yml
new file mode 100644
index 00000000000..ee51631f959
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-issue-53153.yml
@@ -0,0 +1,5 @@
+---
+title: Fix extra merge request versions created from forked merge requests
+merge_request: 22611
+author:
+type: fixed
diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb
index 2536c6e2514..61c6ba7d550 100644
--- a/spec/services/merge_requests/refresh_service_spec.rb
+++ b/spec/services/merge_requests/refresh_service_spec.rb
@@ -306,6 +306,66 @@ describe MergeRequests::RefreshService do
end
end
+ context 'forked projects with the same source branch name as target branch' do
+ let!(:first_commit) do
+ @fork_project.repository.create_file(@user, 'test1.txt', 'Test data',
+ message: 'Test commit',
+ branch_name: 'master')
+ end
+ let!(:second_commit) do
+ @fork_project.repository.create_file(@user, 'test2.txt', 'More test data',
+ message: 'Second test commit',
+ branch_name: 'master')
+ end
+ let!(:forked_master_mr) do
+ create(:merge_request,
+ source_project: @fork_project,
+ source_branch: 'master',
+ target_branch: 'master',
+ target_project: @project)
+ end
+ let(:force_push_commit) { @project.commit('feature').id }
+
+ it 'should reload a new diff for a push to the forked project' do
+ expect do
+ service.new(@fork_project, @user).execute(@oldrev, first_commit, 'refs/heads/master')
+ reload_mrs
+ end.to change { forked_master_mr.merge_request_diffs.count }.by(1)
+ end
+
+ it 'should reload a new diff for a force push to the source branch' do
+ expect do
+ service.new(@fork_project, @user).execute(@oldrev, force_push_commit, 'refs/heads/master')
+ reload_mrs
+ end.to change { forked_master_mr.merge_request_diffs.count }.by(1)
+ end
+
+ it 'should reload a new diff for a force push to the target branch' do
+ expect do
+ service.new(@project, @user).execute(@oldrev, force_push_commit, 'refs/heads/master')
+ reload_mrs
+ end.to change { forked_master_mr.merge_request_diffs.count }.by(1)
+ end
+
+ it 'should reload a new diff for a push to the target project that contains a commit in the MR' do
+ expect do
+ service.new(@project, @user).execute(@oldrev, first_commit, 'refs/heads/master')
+ reload_mrs
+ end.to change { forked_master_mr.merge_request_diffs.count }.by(1)
+ end
+
+ it 'should not increase the diff count for a new push to target branch' do
+ new_commit = @project.repository.create_file(@user, 'new-file.txt', 'A new file',
+ message: 'This is a test',
+ branch_name: 'master')
+
+ expect do
+ service.new(@project, @user).execute(@newrev, new_commit, 'refs/heads/master')
+ reload_mrs
+ end.not_to change { forked_master_mr.merge_request_diffs.count }
+ end
+ end
+
context 'push to origin repo target branch after fork project was removed' do
before do
@fork_project.destroy