debian-mirror-gitlab/lib/gitlab/email/handler/create_merge_request_handler.rb

128 lines
4.2 KiB
Ruby
Raw Normal View History

2018-11-20 20:47:30 +05:30
# frozen_string_literal: true
2018-03-17 18:26:18 +05:30
require 'gitlab/email/handler/base_handler'
require 'gitlab/email/handler/reply_processing'
2019-02-15 15:39:39 +05:30
# handles merge request creation emails with these formats:
# incoming+gitlab-org-gitlab-ce-20-Author_Token12345678-merge-request@incoming.gitlab.com
# incoming+gitlab-org/gitlab-ce+merge-request+Author_Token12345678@incoming.gitlab.com (legacy)
2018-03-17 18:26:18 +05:30
module Gitlab
module Email
module Handler
class CreateMergeRequestHandler < BaseHandler
include ReplyProcessing
2019-02-15 15:39:39 +05:30
HANDLER_REGEX = /\A#{HANDLER_ACTION_BASE_REGEX}-(?<incoming_email_token>.+)-merge-request\z/.freeze
HANDLER_REGEX_LEGACY = /\A(?<project_path>[^\+]*)\+merge-request\+(?<incoming_email_token>.*)/.freeze
2018-03-17 18:26:18 +05:30
def initialize(mail, mail_key)
super(mail, mail_key)
2019-02-15 15:39:39 +05:30
if !mail_key&.include?('/') && (matched = HANDLER_REGEX.match(mail_key.to_s))
@project_slug = matched[:project_slug]
@project_id = matched[:project_id]&.to_i
@incoming_email_token = matched[:incoming_email_token]
elsif matched = HANDLER_REGEX_LEGACY.match(mail_key.to_s)
@project_path = matched[:project_path]
@incoming_email_token = matched[:incoming_email_token]
2018-03-17 18:26:18 +05:30
end
end
def can_handle?
2019-02-15 15:39:39 +05:30
incoming_email_token && (project_id || project_path)
2018-03-17 18:26:18 +05:30
end
def execute
raise ProjectNotFound unless project
2018-05-09 12:01:36 +05:30
validate_permission!(:create_merge_request_in)
validate_permission!(:create_merge_request_from)
2018-03-17 18:26:18 +05:30
verify_record!(
record: create_merge_request,
invalid_exception: InvalidMergeRequestError,
record_name: 'merge_request')
end
2018-12-05 23:21:45 +05:30
# rubocop: disable CodeReuse/ActiveRecord
2018-03-17 18:26:18 +05:30
def author
@author ||= User.find_by(incoming_email_token: incoming_email_token)
end
2018-12-05 23:21:45 +05:30
# rubocop: enable CodeReuse/ActiveRecord
2018-03-17 18:26:18 +05:30
2018-12-13 13:39:08 +05:30
def metrics_params
super.merge(includes_patches: patch_attachments.any?)
end
2019-12-04 20:38:33 +05:30
def metrics_event
:receive_email_create_merge_request
end
2018-03-17 18:26:18 +05:30
private
2018-12-13 13:39:08 +05:30
def build_merge_request
MergeRequests::BuildService.new(project, author, merge_request_params).execute
end
2018-03-17 18:26:18 +05:30
def create_merge_request
2018-12-13 13:39:08 +05:30
merge_request = build_merge_request
if patch_attachments.any?
apply_patches_to_source_branch(start_branch: merge_request.target_branch)
remove_patch_attachments
# Rebuild the merge request as the source branch might just have
# been created, so we should re-validate.
merge_request = build_merge_request
end
2018-03-17 18:26:18 +05:30
if merge_request.errors.any?
merge_request
else
MergeRequests::CreateService.new(project, author).create(merge_request)
end
end
def merge_request_params
params = {
source_project_id: project.id,
2018-12-13 13:39:08 +05:30
source_branch: source_branch,
2018-03-17 18:26:18 +05:30
target_project_id: project.id
}
params[:description] = message if message.present?
params
end
2018-12-13 13:39:08 +05:30
def apply_patches_to_source_branch(start_branch:)
patches = patch_attachments.map { |patch| patch.body.decoded }
result = Commits::CommitPatchService
.new(project, author, branch_name: source_branch, patches: patches, start_branch: start_branch)
.execute
if result[:status] != :success
message = "Could not apply patches to #{source_branch}:\n#{result[:message]}"
raise InvalidAttachment, message
end
end
def remove_patch_attachments
patch_attachments.each { |patch| mail.parts.delete(patch) }
2019-02-15 15:39:39 +05:30
# reset the message, so it needs to be reprocessed when the attachments
2018-12-13 13:39:08 +05:30
# have been modified
@message = nil
end
def patch_attachments
@patches ||= mail.attachments
.select { |attachment| attachment.filename.ends_with?('.patch') }
.sort_by(&:filename)
end
def source_branch
@source_branch ||= mail.subject
end
2018-03-17 18:26:18 +05:30
end
end
end
end