debian-mirror-gitlab/spec/services/merge_requests/squash_service_spec.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

251 lines
8.4 KiB
Ruby
Raw Permalink Normal View History

2019-07-31 22:56:46 +05:30
# frozen_string_literal: true
2018-11-08 19:23:39 +05:30
require 'spec_helper'
2023-05-27 22:25:52 +05:30
RSpec.describe MergeRequests::SquashService, feature_category: :source_code_management do
2021-06-08 01:23:25 +05:30
let(:service) { described_class.new(project: project, current_user: user, params: { merge_request: merge_request }) }
2022-03-02 08:16:31 +05:30
let(:user) { project.first_owner }
2018-11-08 19:23:39 +05:30
let(:project) { create(:project, :repository) }
let(:repository) { project.repository.raw }
let(:log_error) { "Failed to squash merge request #{merge_request.to_reference(full: true)}:" }
let(:squash_dir_path) do
File.join(Gitlab.config.shared.path, 'tmp/squash', repository.gl_repository, merge_request.id.to_s)
end
2020-10-24 23:57:45 +05:30
2018-11-08 19:23:39 +05:30
let(:merge_request_with_one_commit) do
2023-07-09 08:55:56 +05:30
create(
:merge_request,
source_branch: 'feature', source_project: project,
target_branch: 'master', target_project: project
)
2018-11-08 19:23:39 +05:30
end
let(:merge_request_with_only_new_files) do
2023-07-09 08:55:56 +05:30
create(
:merge_request,
source_branch: 'video', source_project: project,
target_branch: 'master', target_project: project
)
2018-11-08 19:23:39 +05:30
end
let(:merge_request_with_large_files) do
2023-07-09 08:55:56 +05:30
create(
:merge_request,
source_branch: 'squash-large-files', source_project: project,
target_branch: 'master', target_project: project
)
2018-11-08 19:23:39 +05:30
end
shared_examples 'the squash succeeds' do
it 'returns the squashed commit SHA' do
2019-03-02 22:35:43 +05:30
result = service.execute
2018-11-08 19:23:39 +05:30
expect(result).to match(status: :success, squash_sha: a_string_matching(/\h{40}/))
expect(result[:squash_sha]).not_to eq(merge_request.diff_head_sha)
end
it 'cleans up the temporary directory' do
2019-03-02 22:35:43 +05:30
service.execute
2018-11-08 19:23:39 +05:30
expect(File.exist?(squash_dir_path)).to be(false)
end
it 'does not keep the branch push event' do
2019-03-02 22:35:43 +05:30
expect { service.execute }.not_to change { Event.count }
end
context 'when there is a single commit in the merge request' do
before do
expect(merge_request).to receive(:commits_count).at_least(:once).and_return(1)
end
2022-01-26 12:08:38 +05:30
it 'will still perform the squash' do
expect(merge_request.target_project.repository).to receive(:squash).and_return('sha')
2019-03-02 22:35:43 +05:30
service.execute
end
2022-01-26 12:08:38 +05:30
context 'when squash message matches commit message' do
let(:service) { described_class.new(project: project, current_user: user, params: { merge_request: merge_request, squash_commit_message: merge_request.first_commit.safe_message }) }
2019-03-02 22:35:43 +05:30
2022-01-26 12:08:38 +05:30
it 'returns that commit SHA' do
result = service.execute
2019-03-02 22:35:43 +05:30
2022-01-26 12:08:38 +05:30
expect(result).to match(status: :success, squash_sha: merge_request.diff_head_sha)
end
it 'does not perform any git actions' do
expect(repository).not_to receive(:squash)
service.execute
end
end
context 'when squash message matches commit message but without trailing new line' do
let(:service) { described_class.new(project: project, current_user: user, params: { merge_request: merge_request, squash_commit_message: merge_request.first_commit.safe_message.strip }) }
it 'returns that commit SHA' do
result = service.execute
expect(result).to match(status: :success, squash_sha: merge_request.diff_head_sha)
end
it 'does not perform any git actions' do
expect(repository).not_to receive(:squash)
service.execute
end
2019-03-02 22:35:43 +05:30
end
2018-11-08 19:23:39 +05:30
end
context 'the squashed commit' do
2019-03-02 22:35:43 +05:30
let(:squash_sha) { service.execute[:squash_sha] }
2018-11-08 19:23:39 +05:30
let(:squash_commit) { project.repository.commit(squash_sha) }
2019-03-02 22:35:43 +05:30
it 'copies the author info from the merge request' do
2018-11-08 19:23:39 +05:30
expect(squash_commit.author_name).to eq(merge_request.author.name)
expect(squash_commit.author_email).to eq(merge_request.author.email)
end
it 'sets the current user as the committer' do
expect(squash_commit.committer_name).to eq(user.name.chomp('.'))
expect(squash_commit.committer_email).to eq(user.email)
end
it 'has the same diff as the merge request, but a different SHA' do
2023-01-13 00:05:48 +05:30
mr_diff = project.repository.diff(merge_request.diff_base_sha, merge_request.diff_head_sha)
squash_diff = project.repository.diff(merge_request.diff_start_sha, squash_sha)
2018-11-08 19:23:39 +05:30
2023-01-13 00:05:48 +05:30
expect(squash_diff.size).to eq(mr_diff.size)
2018-11-08 19:23:39 +05:30
expect(squash_commit.sha).not_to eq(merge_request.diff_head_sha)
end
2019-03-02 22:35:43 +05:30
it 'has a default squash commit message if no message was provided' do
expect(squash_commit.message.chomp).to eq(merge_request.default_squash_commit_message.chomp)
end
context 'if a message was provided' do
2021-06-08 01:23:25 +05:30
let(:service) { described_class.new(project: project, current_user: user, params: { merge_request: merge_request, squash_commit_message: message }) }
2019-03-02 22:35:43 +05:30
let(:message) { 'My custom message' }
let(:squash_sha) { service.execute[:squash_sha] }
it 'has the same message as the message provided' do
expect(squash_commit.message.chomp).to eq(message)
end
end
2018-11-08 19:23:39 +05:30
end
end
describe '#execute' do
context 'when there is only one commit in the merge request' do
2019-03-02 22:35:43 +05:30
let(:merge_request) { merge_request_with_one_commit }
2022-01-26 12:08:38 +05:30
include_examples 'the squash succeeds'
2018-11-08 19:23:39 +05:30
end
context 'when squashing only new files' do
let(:merge_request) { merge_request_with_only_new_files }
include_examples 'the squash succeeds'
end
2020-07-28 23:09:34 +05:30
context 'when squashing is disabled by default on the project' do
# Squashing is disabled by default, but it should still allow you
# to squash-and-merge if selected through the UI
let(:merge_request) { merge_request_with_only_new_files }
before do
merge_request.project.project_setting.squash_default_off!
end
include_examples 'the squash succeeds'
end
context 'when squashing is forbidden on the project' do
let(:merge_request) { merge_request_with_only_new_files }
before do
merge_request.project.project_setting.squash_never!
end
it 'raises a squash error' do
expect(service.execute).to match(
status: :error,
2022-04-04 11:22:00 +05:30
message: a_string_including('allow you to squash commits when merging'))
2020-07-28 23:09:34 +05:30
end
end
context 'when squashing is enabled by default on the project' do
let(:merge_request) { merge_request_with_only_new_files }
before do
merge_request.project.project_setting.squash_always!
end
include_examples 'the squash succeeds'
end
2018-11-08 19:23:39 +05:30
context 'when squashing with files too large to display' do
let(:merge_request) { merge_request_with_large_files }
include_examples 'the squash succeeds'
end
context 'git errors' do
let(:merge_request) { merge_request_with_only_new_files }
let(:error) { 'A test error' }
2020-05-24 23:13:21 +05:30
context 'with an error in Gitaly UserSquash RPC' do
2018-11-08 19:23:39 +05:30
before do
allow(repository.gitaly_operation_client).to receive(:user_squash)
.and_raise(Gitlab::Git::Repository::GitError, error)
end
2020-05-24 23:13:21 +05:30
it 'logs the error' do
expect(service).to receive(:log_error).with(exception: an_instance_of(Gitlab::Git::Repository::GitError), message: 'Failed to squash merge request')
2018-11-08 19:23:39 +05:30
2019-03-02 22:35:43 +05:30
service.execute
2018-11-08 19:23:39 +05:30
end
it 'returns an error' do
2022-04-04 11:22:00 +05:30
expect(service.execute).to match(status: :error, message: a_string_including('Squash'))
2018-11-08 19:23:39 +05:30
end
end
end
context 'when any other exception is thrown' do
let(:merge_request) { merge_request_with_only_new_files }
2020-05-24 23:13:21 +05:30
let(:merge_request_ref) { merge_request.to_reference(full: true) }
let(:exception) { RuntimeError.new('A test error') }
2018-11-08 19:23:39 +05:30
before do
2020-05-24 23:13:21 +05:30
allow(merge_request.target_project.repository).to receive(:squash).and_raise(exception)
2018-11-08 19:23:39 +05:30
end
2020-05-24 23:13:21 +05:30
it 'logs the error' do
expect(service).to receive(:log_error).with(exception: exception, message: 'Failed to squash merge request').and_call_original
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(exception,
2022-07-16 23:28:13 +05:30
{
class: described_class.to_s,
merge_request: merge_request_ref,
merge_request_id: merge_request.id,
message: 'Failed to squash merge request',
save_message_on_model: false
}).and_call_original
2018-11-08 19:23:39 +05:30
2019-03-02 22:35:43 +05:30
service.execute
2018-11-08 19:23:39 +05:30
end
it 'returns an error' do
2022-04-04 11:22:00 +05:30
expect(service.execute).to match(status: :error, message: a_string_including('Squash'))
2018-11-08 19:23:39 +05:30
end
it 'cleans up the temporary directory' do
2019-03-02 22:35:43 +05:30
service.execute
2018-11-08 19:23:39 +05:30
expect(File.exist?(squash_dir_path)).to be(false)
end
end
end
end