gitlab-org--gitlab-foss/app/services/merge_requests/merge_service.rb
Jan Provaznik d973872072 Save and expose only generic merge error
When an error occurs during merge, the error message is exposed to user
and it is also saved in DB. This error message may be user unfriendly
(as in !41820) and it could also expose a detailed backend information.

Instead of displaying the specific error message, only sanitized generic
message is displayed. This is potentially controversial change because
disadvantage is that user doesn't get specific reason of failure.

Additional changes:
* repository.merge including exceptions is is extracted into a
separate method to make things clearer
* update! is used instead of update so we don't silently ignore
an error

Related to !41857
2018-05-02 09:22:20 +02:00

124 lines
3.8 KiB
Ruby

module MergeRequests
# MergeService class
#
# Do git merge and in case of success
# mark merge request as merged and execute all hooks and notifications
# Executed when you do merge via GitLab UI
#
class MergeService < MergeRequests::BaseService
MergeError = Class.new(StandardError)
attr_reader :merge_request, :source
delegate :merge_jid, :state, to: :@merge_request
def execute(merge_request)
if project.merge_requests_ff_only_enabled && !self.is_a?(FfMergeService)
FfMergeService.new(project, current_user, params).execute(merge_request)
return
end
@merge_request = merge_request
error_check!
merge_request.in_locked_state do
if commit
after_merge
clean_merge_jid
success
end
end
log_info("Merge process finished on JID #{merge_jid} with state #{state}")
rescue MergeError => e
handle_merge_error(log_message: e.message, save_message_on_model: true)
end
private
def error_check!
error =
if @merge_request.should_be_rebased?
'Only fast-forward merge is allowed for your project. Please update your source branch'
elsif !@merge_request.mergeable?
'Merge request is not mergeable'
elsif !source
'No source for merge'
end
raise MergeError, error if error
end
def commit
log_info("Git merge started on JID #{merge_jid}")
commit_id = try_merge
if commit_id
log_info("Git merge finished on JID #{merge_jid} commit #{commit_id}")
else
raise MergeError, 'Conflicts detected during merge'
end
merge_request.update!(merge_commit_sha: commit_id)
end
def try_merge
message = params[:commit_message] || merge_request.merge_commit_message
repository.merge(current_user, source, merge_request, message)
rescue Gitlab::Git::HooksService::PreReceiveError => e
handle_merge_error(log_message: e.message)
raise MergeError, 'Something went wrong during merge pre-receive hook'
rescue => e
handle_merge_error(log_message: e.message)
raise MergeError, 'Something went wrong during merge'
ensure
merge_request.update!(in_progress_merge_commit_sha: nil)
end
def after_merge
log_info("Post merge started on JID #{merge_jid} with state #{state}")
MergeRequests::PostMergeService.new(project, current_user).execute(merge_request)
log_info("Post merge finished on JID #{merge_jid} with state #{state}")
if delete_source_branch?
DeleteBranchService.new(@merge_request.source_project, branch_deletion_user)
.execute(merge_request.source_branch)
end
end
def clean_merge_jid
merge_request.update_column(:merge_jid, nil)
end
def branch_deletion_user
@merge_request.force_remove_source_branch? ? @merge_request.author : current_user
end
# Verify again that the source branch can be removed, since branch may be protected,
# or the source branch may have been updated, or the user may not have permission
#
def delete_source_branch?
params.fetch('should_remove_source_branch', @merge_request.force_remove_source_branch?) &&
@merge_request.can_remove_source_branch?(branch_deletion_user)
end
def handle_merge_error(log_message:, save_message_on_model: false)
Rails.logger.error("MergeService ERROR: #{merge_request_info} - #{log_message}")
@merge_request.update(merge_error: log_message) if save_message_on_model
end
def log_info(message)
@logger ||= Rails.logger
@logger.info("#{merge_request_info} - #{message}")
end
def merge_request_info
merge_request.to_reference(full: true)
end
def source
@source ||= @merge_request.diff_head_sha
end
end
end