Apply patches when creating MR via email
This allows users to add patches as attachments to merge request created via email. When an email to create a merge request is sent, all the attachments ending in `.patch` will be applied to the branch specified in the subject of the email. If the branch did not exist, it will be created from the HEAD of the repository. When the patches could not be applied, the error message will be replied to the user. The patches can have a maximum combined size of 2MB for now.
This commit is contained in:
parent
6d8810a64f
commit
6fbdc5ed52
26 changed files with 1022 additions and 4 deletions
61
app/services/commits/commit_patch_service.rb
Normal file
61
app/services/commits/commit_patch_service.rb
Normal file
|
@ -0,0 +1,61 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Commits
|
||||
class CommitPatchService < CreateService
|
||||
# Requires:
|
||||
# - project: `Project` to be committed into
|
||||
# - user: `User` that will be the committer
|
||||
# - params:
|
||||
# - branch_name: `String` the branch that will be committed into
|
||||
# - start_branch: `String` the branch that will will started from
|
||||
# - patches: `Gitlab::Git::Patches::Collection` that contains the patches
|
||||
def initialize(*args)
|
||||
super
|
||||
|
||||
@patches = Gitlab::Git::Patches::Collection.new(Array(params[:patches]))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def new_branch?
|
||||
!repository.branch_exists?(@branch_name)
|
||||
end
|
||||
|
||||
def create_commit!
|
||||
if @start_branch && new_branch?
|
||||
prepare_branch!
|
||||
end
|
||||
|
||||
Gitlab::Git::Patches::CommitPatches
|
||||
.new(current_user, project.repository, @branch_name, @patches)
|
||||
.commit
|
||||
end
|
||||
|
||||
def prepare_branch!
|
||||
branch_result = CreateBranchService.new(project, current_user)
|
||||
.execute(@branch_name, @start_branch)
|
||||
|
||||
if branch_result[:status] != :success
|
||||
raise ChangeError, branch_result[:message]
|
||||
end
|
||||
end
|
||||
|
||||
# Overridden from the Commits::CreateService, to skip some validations we
|
||||
# don't need:
|
||||
# - validate_on_branch!
|
||||
# Not needed, the patches are applied on top of HEAD if the branch did not
|
||||
# exist
|
||||
# - validate_branch_existence!
|
||||
# Not needed because we continue applying patches on the branch if it
|
||||
# already existed, and create it if it did not exist.
|
||||
def validate!
|
||||
validate_patches!
|
||||
validate_new_branch_name! if new_branch?
|
||||
validate_permissions!
|
||||
end
|
||||
|
||||
def validate_patches!
|
||||
raise_error("Patches are too big") unless @patches.valid_size?
|
||||
end
|
||||
end
|
||||
end
|
|
@ -19,7 +19,12 @@ module Commits
|
|||
new_commit = create_commit!
|
||||
|
||||
success(result: new_commit)
|
||||
rescue ValidationError, ChangeError, Gitlab::Git::Index::IndexError, Gitlab::Git::CommitError, Gitlab::Git::PreReceiveError => ex
|
||||
rescue ValidationError,
|
||||
ChangeError,
|
||||
Gitlab::Git::Index::IndexError,
|
||||
Gitlab::Git::CommitError,
|
||||
Gitlab::Git::PreReceiveError,
|
||||
Gitlab::Git::CommandError => ex
|
||||
error(ex.message)
|
||||
end
|
||||
|
||||
|
|
|
@ -6,8 +6,10 @@ module MergeRequests
|
|||
|
||||
def execute
|
||||
@params_issue_iid = params.delete(:issue_iid)
|
||||
self.merge_request = MergeRequest.new
|
||||
merge_quick_actions_into_params!(merge_request)
|
||||
merge_request.assign_attributes(params)
|
||||
|
||||
self.merge_request = MergeRequest.new(params)
|
||||
merge_request.author = current_user
|
||||
merge_request.compare_commits = []
|
||||
merge_request.source_project = find_source_project
|
||||
|
|
|
@ -40,6 +40,8 @@ class EmailReceiverWorker
|
|||
"You are not allowed to perform this action. If you believe this is in error, contact a staff member."
|
||||
when Gitlab::Email::NoteableNotFoundError
|
||||
"The thread you are replying to no longer exists, perhaps it was deleted? If you believe this is in error, contact a staff member."
|
||||
when Gitlab::Email::InvalidAttachment
|
||||
error.message
|
||||
when Gitlab::Email::InvalidRecordError
|
||||
can_retry = true
|
||||
error.message
|
||||
|
|
5
changelogs/unreleased/bvl-patches-via-mail.yml
Normal file
5
changelogs/unreleased/bvl-patches-via-mail.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Allow adding patches when creating a merge request via email
|
||||
merge_request: 22723
|
||||
author: Serdar Dogruyol
|
||||
type: added
|
|
@ -166,6 +166,23 @@ administrator to do so.
|
|||
|
||||
![Create new merge requests by email](img/create_from_email.png)
|
||||
|
||||
### Adding patches when creating a merge request via e-mail
|
||||
|
||||
> **Note**: This feature was [implemented in GitLab 11.5](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22723)
|
||||
|
||||
You can add commits to the merge request being created by adding
|
||||
patches as attachments to the email, all attachments with a filename
|
||||
ending in `.patch` will be considered patches. The patches will be processed
|
||||
ordered by name.
|
||||
|
||||
The combined size of the patches can be 2MB.
|
||||
|
||||
If the source branch from the subject does not exist, it will be
|
||||
created from the repository's HEAD or the specified target branch to
|
||||
apply the patches. The target branch can be specified using the
|
||||
[`/target_branch` quick action](../quick_actions.md). If the source
|
||||
branch already exists, the patches will be applied on top of it.
|
||||
|
||||
## Find the merge request that introduced a change
|
||||
|
||||
> **Note**: this feature was [implemented in GitLab 10.5](https://gitlab.com/gitlab-org/gitlab-ce/issues/2383).
|
||||
|
|
|
@ -44,10 +44,26 @@ module Gitlab
|
|||
@project ||= Project.find_by_full_path(project_path)
|
||||
end
|
||||
|
||||
def metrics_params
|
||||
super.merge(includes_patches: patch_attachments.any?)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_merge_request
|
||||
MergeRequests::BuildService.new(project, author, merge_request_params).execute
|
||||
end
|
||||
|
||||
def create_merge_request
|
||||
merge_request = MergeRequests::BuildService.new(project, author, merge_request_params).execute
|
||||
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
|
||||
|
||||
if merge_request.errors.any?
|
||||
merge_request
|
||||
|
@ -59,12 +75,42 @@ module Gitlab
|
|||
def merge_request_params
|
||||
params = {
|
||||
source_project_id: project.id,
|
||||
source_branch: mail.subject,
|
||||
source_branch: source_branch,
|
||||
target_project_id: project.id
|
||||
}
|
||||
params[:description] = message if message.present?
|
||||
params
|
||||
end
|
||||
|
||||
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) }
|
||||
# reset the message, so it needs to be reporocessed when the attachments
|
||||
# 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
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,6 +18,7 @@ module Gitlab
|
|||
InvalidIssueError = Class.new(InvalidRecordError)
|
||||
InvalidMergeRequestError = Class.new(InvalidRecordError)
|
||||
UnknownIncomingEmail = Class.new(ProcessingError)
|
||||
InvalidAttachment = Class.new(ProcessingError)
|
||||
|
||||
class Receiver
|
||||
def initialize(raw)
|
||||
|
|
33
lib/gitlab/git/patches/collection.rb
Normal file
33
lib/gitlab/git/patches/collection.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Git
|
||||
module Patches
|
||||
class Collection
|
||||
MAX_PATCH_SIZE = 2.megabytes
|
||||
|
||||
def initialize(one_or_more_patches)
|
||||
@patches = Array(one_or_more_patches).map do |patch_content|
|
||||
Gitlab::Git::Patches::Patch.new(patch_content)
|
||||
end
|
||||
end
|
||||
|
||||
def content
|
||||
@patches.map(&:content).join("\n")
|
||||
end
|
||||
|
||||
def valid_size?
|
||||
size < MAX_PATCH_SIZE
|
||||
end
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
# `@patches` is not an `ActiveRecord` relation, but an `Enumerable`
|
||||
# We're using sum from `ActiveSupport`
|
||||
def size
|
||||
@size ||= @patches.sum(&:size)
|
||||
end
|
||||
# rubocop: enable CodeReuse/ActiveRecord
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
31
lib/gitlab/git/patches/commit_patches.rb
Normal file
31
lib/gitlab/git/patches/commit_patches.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Git
|
||||
module Patches
|
||||
class CommitPatches
|
||||
include Gitlab::Git::WrapsGitalyErrors
|
||||
|
||||
def initialize(user, repository, branch, patch_collection)
|
||||
@user, @repository, @branch, @patches = user, repository, branch, patch_collection
|
||||
end
|
||||
|
||||
def commit
|
||||
repository.with_cache_hooks do
|
||||
wrapped_gitaly_errors do
|
||||
operation_service.user_commit_patches(user, branch, patches.content)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :user, :repository, :branch, :patches
|
||||
|
||||
def operation_service
|
||||
repository.raw.gitaly_operation_client
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
19
lib/gitlab/git/patches/patch.rb
Normal file
19
lib/gitlab/git/patches/patch.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Git
|
||||
module Patches
|
||||
class Patch
|
||||
attr_reader :content
|
||||
|
||||
def initialize(content)
|
||||
@content = content
|
||||
end
|
||||
|
||||
def size
|
||||
content.bytesize
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -299,6 +299,29 @@ module Gitlab
|
|||
Gitlab::Git::OperationService::BranchUpdate.from_gitaly(response.branch_update)
|
||||
end
|
||||
|
||||
def user_commit_patches(user, branch_name, patches)
|
||||
header = Gitaly::UserApplyPatchRequest::Header.new(
|
||||
repository: @gitaly_repo,
|
||||
user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
|
||||
target_branch: encode_binary(branch_name)
|
||||
)
|
||||
reader = binary_stringio(patches)
|
||||
|
||||
chunks = Enumerator.new do |chunk|
|
||||
chunk.yield Gitaly::UserApplyPatchRequest.new(header: header)
|
||||
|
||||
until reader.eof?
|
||||
patch_chunk = reader.read(MAX_MSG_SIZE)
|
||||
|
||||
chunk.yield(Gitaly::UserApplyPatchRequest.new(patches: patch_chunk))
|
||||
end
|
||||
end
|
||||
|
||||
response = GitalyClient.call(@repository.storage, :operation_service, :user_apply_patch, chunks)
|
||||
|
||||
Gitlab::Git::OperationService::BranchUpdate.from_gitaly(response.branch_update)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def call_cherry_pick_or_revert(rpc, user:, commit:, branch_name:, message:, start_branch_name:, start_repository:)
|
||||
|
|
181
spec/fixtures/emails/merge_request_multiple_patches.eml
vendored
Normal file
181
spec/fixtures/emails/merge_request_multiple_patches.eml
vendored
Normal file
|
@ -0,0 +1,181 @@
|
|||
From: "Jake the Dog" <jake@adventuretime.ooo>
|
||||
To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
|
||||
Subject: new-branch-with-a-patch
|
||||
Date: Wed, 31 Oct 2018 17:27:52 +0100
|
||||
X-Mailer: MailMate (1.12r5523)
|
||||
Message-ID: <7BE7C2E6-F0D9-4C85-9F55-B2A4BA01BFEC@gitlab.com>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_="
|
||||
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
|
||||
|
||||
This applies nicely to a branch freshly created from the root-ref
|
||||
|
||||
The other attachments in this email are ignored
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
|
||||
Content-Disposition: attachment;
|
||||
filename=0002-This-does-not-apply-to-the-feature-branch.patch
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
=46rom 00c68c2b4f954370ce82a1162bc29c13f524897e Mon Sep 17 00:00:00 2001
|
||||
From: Patch user <patchuser@gitlab.org>
|
||||
Date: Mon, 22 Oct 2018 11:05:48 +0200
|
||||
Subject: [PATCH] This does not apply to the `feature` branch
|
||||
|
||||
---
|
||||
files/ruby/feature.rb | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
create mode 100644 files/ruby/feature.rb
|
||||
|
||||
diff --git a/files/ruby/feature.rb b/files/ruby/feature.rb
|
||||
new file mode 100644
|
||||
index 0000000..fef26e4
|
||||
--- /dev/null
|
||||
+++ b/files/ruby/feature.rb
|
||||
@@ -0,0 +1,5 @@
|
||||
+class Feature
|
||||
+ def bar
|
||||
+ puts 'foo'
|
||||
+ end
|
||||
+end
|
||||
-- =
|
||||
|
||||
2.19.1
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
|
||||
Content-Disposition: attachment; filename=0001-A-commit-from-a-patch.patch
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
=46rom 3fee0042e610fb3563e4379e316704cb1210f3de Mon Sep 17 00:00:00 2001
|
||||
From: Patch user <patchuser@gitlab.org>
|
||||
Date: Thu, 18 Oct 2018 13:40:35 +0200
|
||||
Subject: [PATCH] A commit from a patch
|
||||
|
||||
---
|
||||
README | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/README b/README
|
||||
index 3742e48..e40a3b9 100644
|
||||
--- a/README
|
||||
+++ b/README
|
||||
@@ -1 +1,3 @@
|
||||
Sample repo for testing gitlab features
|
||||
+
|
||||
+This was applied in a patch!
|
||||
-- =
|
||||
|
||||
2.19.1
|
||||
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
|
||||
Content-Disposition: attachment; filename=really-not-a-patch.png
|
||||
Content-Type: image/png
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
iVBORw0KGgoAAAANSUhEUgAAAjMAAAAfCAYAAAASo0ymAAABfGlDQ1BJQ0MgUHJvZmlsZQAAKJFj
|
||||
YGAqSSwoyGFhYGDIzSspCnJ3UoiIjFJgv8PAzcDDIMRgxSCemFxc4BgQ4MOAE3y7xsAIoi/rgsxK
|
||||
8/x506a1fP4WNq+ZclYlOrj1gQF3SmpxMgMDIweQnZxSnJwLZOcA2TrJBUUlQPYMIFu3vKQAxD4B
|
||||
ZIsUAR0IZN8BsdMh7A8gdhKYzcQCVhMS5AxkSwDZAkkQtgaInQ5hW4DYyRmJKUC2B8guiBvAgNPD
|
||||
RcHcwFLXkYC7SQa5OaUwO0ChxZOaFxoMcgcQyzB4MLgwKDCYMxgwWDLoMjiWpFaUgBQ65xdUFmWm
|
||||
Z5QoOAJDNlXBOT+3oLQktUhHwTMvWU9HwcjA0ACkDhRnEKM/B4FNZxQ7jxDLX8jAYKnMwMDcgxBL
|
||||
msbAsH0PA4PEKYSYyjwGBn5rBoZt5woSixLhDmf8xkKIX5xmbARh8zgxMLDe+///sxoDA/skBoa/
|
||||
E////73o//+/i4H2A+PsQA4AJHdp4IxrEg8AAAGcaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8
|
||||
eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA1LjQu
|
||||
MCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1y
|
||||
ZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAg
|
||||
ICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAg
|
||||
ICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjU2MzwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAg
|
||||
ICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4zMTwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAg
|
||||
IDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpZ5vHZAAAS+ElE
|
||||
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
|
||||
E+AEOAFWAv8PxvdR0yK8jugAAAAASUVORK5CYII=
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=--
|
45
spec/fixtures/emails/merge_request_with_conflicting_patch.eml
vendored
Normal file
45
spec/fixtures/emails/merge_request_with_conflicting_patch.eml
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
From: "Jake the Dog" <jake@adventuretime.ooo>
|
||||
To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
|
||||
Subject: feature
|
||||
Date: Wed, 31 Oct 2018 17:27:52 +0100
|
||||
X-Mailer: MailMate (1.12r5523)
|
||||
Message-ID: <7BE7C2E6-F0D9-4C85-9F55-B2A4BA01BFEC@gitlab.com>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_="
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
|
||||
|
||||
This does not apply
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
|
||||
Content-Disposition: attachment;
|
||||
filename=0002-This-does-not-apply-to-the-feature-branch.patch
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
=46rom 00c68c2b4f954370ce82a1162bc29c13f524897e Mon Sep 17 00:00:00 2001
|
||||
From: Patch user <patchuser@gitlab.org>
|
||||
Date: Mon, 22 Oct 2018 11:05:48 +0200
|
||||
Subject: [PATCH] This does not apply to the `feature` branch
|
||||
|
||||
---
|
||||
files/ruby/feature.rb | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
create mode 100644 files/ruby/feature.rb
|
||||
|
||||
diff --git a/files/ruby/feature.rb b/files/ruby/feature.rb
|
||||
new file mode 100644
|
||||
index 0000000..fef26e4
|
||||
--- /dev/null
|
||||
+++ b/files/ruby/feature.rb
|
||||
@@ -0,0 +1,5 @@
|
||||
+class Feature
|
||||
+ def bar
|
||||
+ puts 'foo'
|
||||
+ end
|
||||
+end
|
||||
-- =
|
||||
|
||||
2.19.1
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=--
|
44
spec/fixtures/emails/merge_request_with_patch_and_target_branch.eml
vendored
Normal file
44
spec/fixtures/emails/merge_request_with_patch_and_target_branch.eml
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
From: "Jake the Dog" <jake@adventuretime.ooo>
|
||||
To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
|
||||
Subject: new-branch-with-a-patch
|
||||
Date: Wed, 24 Oct 2018 16:39:49 +0200
|
||||
X-Mailer: MailMate (1.12r5523)
|
||||
Message-ID: <F1F36291-728D-4E8F-AFEB-C398B8D9BB4E@gitlab.com>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_="
|
||||
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
|
||||
|
||||
This applies nicely to a branch freshly created from the root-ref
|
||||
|
||||
The other attachments in this email are ignored
|
||||
|
||||
/target_branch with-codeowners
|
||||
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
|
||||
Content-Disposition: attachment; filename=0001-A-commit-from-a-patch.patch
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
=46rom 3fee0042e610fb3563e4379e316704cb1210f3de Mon Sep 17 00:00:00 2001
|
||||
From: Patch user <patchuser@gitlab.org>
|
||||
Date: Thu, 18 Oct 2018 13:40:35 +0200
|
||||
Subject: [PATCH] A commit from a patch
|
||||
|
||||
---
|
||||
README | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/README b/README
|
||||
index 3742e48..e40a3b9 100644
|
||||
--- a/README
|
||||
+++ b/README
|
||||
@@ -1 +1,3 @@
|
||||
Sample repo for testing gitlab features
|
||||
+
|
||||
+This was applied in a patch!
|
||||
-- =
|
||||
|
||||
2.19.1
|
151
spec/fixtures/emails/valid_merge_request_with_patch.eml
vendored
Normal file
151
spec/fixtures/emails/valid_merge_request_with_patch.eml
vendored
Normal file
|
@ -0,0 +1,151 @@
|
|||
From: "Jake the Dog" <jake@adventuretime.ooo>
|
||||
To: incoming+gitlabhq/gitlabhq+merge-request+auth_token@appmail.adventuretime.ooo
|
||||
Subject: new-branch-with-a-patch
|
||||
Date: Wed, 24 Oct 2018 16:39:49 +0200
|
||||
X-Mailer: MailMate (1.12r5523)
|
||||
Message-ID: <F1F36291-728D-4E8F-AFEB-C398B8D9BB4E@gitlab.com>
|
||||
MIME-Version: 1.0
|
||||
Content-Type: multipart/mixed;
|
||||
boundary="=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_="
|
||||
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
|
||||
|
||||
This applies nicely to a branch freshly created from the root-ref
|
||||
|
||||
The other attachments in this email are ignored
|
||||
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
|
||||
Content-Disposition: attachment; filename=0001-A-commit-from-a-patch.patch
|
||||
Content-Transfer-Encoding: quoted-printable
|
||||
|
||||
=46rom 3fee0042e610fb3563e4379e316704cb1210f3de Mon Sep 17 00:00:00 2001
|
||||
From: Patch user <patchuser@gitlab.org>
|
||||
Date: Thu, 18 Oct 2018 13:40:35 +0200
|
||||
Subject: [PATCH] A commit from a patch
|
||||
|
||||
---
|
||||
README | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/README b/README
|
||||
index 3742e48..e40a3b9 100644
|
||||
--- a/README
|
||||
+++ b/README
|
||||
@@ -1 +1,3 @@
|
||||
Sample repo for testing gitlab features
|
||||
+
|
||||
+This was applied in a patch!
|
||||
-- =
|
||||
|
||||
2.19.1
|
||||
|
||||
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=
|
||||
Content-Disposition: attachment; filename=really-not-a-patch.png
|
||||
Content-Type: image/png
|
||||
Content-Transfer-Encoding: base64
|
||||
|
||||
iVBORw0KGgoAAAANSUhEUgAAAjMAAAAfCAYAAAASo0ymAAABfGlDQ1BJQ0MgUHJvZmlsZQAAKJFj
|
||||
YGAqSSwoyGFhYGDIzSspCnJ3UoiIjFJgv8PAzcDDIMRgxSCemFxc4BgQ4MOAE3y7xsAIoi/rgsxK
|
||||
8/x506a1fP4WNq+ZclYlOrj1gQF3SmpxMgMDIweQnZxSnJwLZOcA2TrJBUUlQPYMIFu3vKQAxD4B
|
||||
ZIsUAR0IZN8BsdMh7A8gdhKYzcQCVhMS5AxkSwDZAkkQtgaInQ5hW4DYyRmJKUC2B8guiBvAgNPD
|
||||
RcHcwFLXkYC7SQa5OaUwO0ChxZOaFxoMcgcQyzB4MLgwKDCYMxgwWDLoMjiWpFaUgBQ65xdUFmWm
|
||||
Z5QoOAJDNlXBOT+3oLQktUhHwTMvWU9HwcjA0ACkDhRnEKM/B4FNZxQ7jxDLX8jAYKnMwMDcgxBL
|
||||
msbAsH0PA4PEKYSYyjwGBn5rBoZt5woSixLhDmf8xkKIX5xmbARh8zgxMLDe+///sxoDA/skBoa/
|
||||
E////73o//+/i4H2A+PsQA4AJHdp4IxrEg8AAAGcaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8
|
||||
eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA1LjQu
|
||||
MCI+CiAgIDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1y
|
||||
ZGYtc3ludGF4LW5zIyI+CiAgICAgIDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiCiAgICAg
|
||||
ICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIj4KICAgICAg
|
||||
ICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjU2MzwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAg
|
||||
ICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4zMTwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAg
|
||||
IDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgpZ5vHZAAAS+ElE
|
||||
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
|
||||
E+AEOAFWAv8PxvdR0yK8jugAAAAASUVORK5CYII=
|
||||
--=_MailMate_D2C4B06A-4F8D-4AAB-B247-C507E35AAED6_=--
|
19
spec/fixtures/patchfiles/0001-A-commit-from-a-patch.patch
vendored
Normal file
19
spec/fixtures/patchfiles/0001-A-commit-from-a-patch.patch
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
From 3fee0042e610fb3563e4379e316704cb1210f3de Mon Sep 17 00:00:00 2001
|
||||
From: Patch User <patchuser@gitlab.org>
|
||||
Date: Thu, 18 Oct 2018 13:40:35 +0200
|
||||
Subject: [PATCH] A commit from a patch
|
||||
|
||||
---
|
||||
README | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/README b/README
|
||||
index 3742e48..e40a3b9 100644
|
||||
--- a/README
|
||||
+++ b/README
|
||||
@@ -1 +1,3 @@
|
||||
Sample repo for testing gitlab features
|
||||
+
|
||||
+This was applied in a patch!
|
||||
--
|
||||
2.19.1
|
23
spec/fixtures/patchfiles/0001-This-does-not-apply-to-the-feature-branch.patch
vendored
Normal file
23
spec/fixtures/patchfiles/0001-This-does-not-apply-to-the-feature-branch.patch
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
From 00c68c2b4f954370ce82a1162bc29c13f524897e Mon Sep 17 00:00:00 2001
|
||||
From: Patch User <patchuser@gitlab.org>
|
||||
Date: Mon, 22 Oct 2018 11:05:48 +0200
|
||||
Subject: [PATCH] This does not apply to the `feature` branch
|
||||
|
||||
---
|
||||
files/ruby/feature.rb | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
create mode 100644 files/ruby/feature.rb
|
||||
|
||||
diff --git a/files/ruby/feature.rb b/files/ruby/feature.rb
|
||||
new file mode 100644
|
||||
index 0000000..fef26e4
|
||||
--- /dev/null
|
||||
+++ b/files/ruby/feature.rb
|
||||
@@ -0,0 +1,5 @@
|
||||
+class Feature
|
||||
+ def bar
|
||||
+ puts 'foo'
|
||||
+ end
|
||||
+end
|
||||
--
|
||||
2.19.1
|
|
@ -93,5 +93,74 @@ describe Gitlab::Email::Handler::CreateMergeRequestHandler do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the email contains patch attachments' do
|
||||
let(:email_raw) { fixture_file("emails/valid_merge_request_with_patch.eml") }
|
||||
|
||||
it 'creates the source branch and applies the patches' do
|
||||
receiver.execute
|
||||
|
||||
branch = project.repository.find_branch('new-branch-with-a-patch')
|
||||
|
||||
expect(branch).not_to be_nil
|
||||
expect(branch.dereferenced_target.message).to include('A commit from a patch')
|
||||
end
|
||||
|
||||
it 'creates the merge request' do
|
||||
expect { receiver.execute }
|
||||
.to change { project.merge_requests.where(source_branch: 'new-branch-with-a-patch').size }.by(1)
|
||||
end
|
||||
|
||||
it 'does not mention the patches in the created merge request' do
|
||||
receiver.execute
|
||||
|
||||
merge_request = project.merge_requests.find_by!(source_branch: 'new-branch-with-a-patch')
|
||||
|
||||
expect(merge_request.description).not_to include('0001-A-commit-from-a-patch.patch')
|
||||
end
|
||||
|
||||
context 'when the patch could not be applied' do
|
||||
let(:email_raw) { fixture_file("emails/merge_request_with_conflicting_patch.eml") }
|
||||
|
||||
it 'raises an error' do
|
||||
expect { receiver.execute }.to raise_error(Gitlab::Email::InvalidAttachment)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when specifying the target branch using quick actions' do
|
||||
let(:email_raw) { fixture_file('emails/merge_request_with_patch_and_target_branch.eml') }
|
||||
|
||||
it 'creates the merge request with the correct target branch' do
|
||||
receiver.execute
|
||||
|
||||
merge_request = project.merge_requests.find_by!(source_branch: 'new-branch-with-a-patch')
|
||||
|
||||
expect(merge_request.target_branch).to eq('with-codeowners')
|
||||
end
|
||||
|
||||
it 'based the merge request of the target_branch' do
|
||||
receiver.execute
|
||||
|
||||
merge_request = project.merge_requests.find_by!(source_branch: 'new-branch-with-a-patch')
|
||||
|
||||
expect(merge_request.diff_base_commit).to eq(project.repository.commit('with-codeowners'))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#patch_attachments' do
|
||||
let(:email_raw) { fixture_file('emails/merge_request_multiple_patches.eml') }
|
||||
let(:mail) { Mail::Message.new(email_raw) }
|
||||
subject(:handler) { described_class.new(mail, mail_key) }
|
||||
|
||||
it 'orders attachments ending in `.patch` by name' do
|
||||
expected_filenames = ["0001-A-commit-from-a-patch.patch",
|
||||
"0002-This-does-not-apply-to-the-feature-branch.patch"]
|
||||
|
||||
attachments = handler.__send__(:patch_attachments).map(&:filename)
|
||||
|
||||
expect(attachments).to eq(expected_filenames)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
28
spec/lib/gitlab/git/patches/collection_spec.rb
Normal file
28
spec/lib/gitlab/git/patches/collection_spec.rb
Normal file
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Git::Patches::Collection do
|
||||
let(:patches_folder) { Rails.root.join('spec/fixtures/patchfiles') }
|
||||
let(:patch_content1) do
|
||||
File.read(File.join(patches_folder, "0001-This-does-not-apply-to-the-feature-branch.patch"))
|
||||
end
|
||||
let(:patch_content2) do
|
||||
File.read(File.join(patches_folder, "0001-A-commit-from-a-patch.patch"))
|
||||
end
|
||||
|
||||
subject(:collection) { described_class.new([patch_content1, patch_content2]) }
|
||||
|
||||
describe '#size' do
|
||||
it 'combines the size of the patches' do
|
||||
expect(collection.size).to eq(549.bytes + 424.bytes)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#valid_size?' do
|
||||
it 'is not valid if the total size is bigger than 2MB' do
|
||||
expect(collection).to receive(:size).and_return(2500.kilobytes)
|
||||
|
||||
expect(collection).not_to be_valid_size
|
||||
end
|
||||
end
|
||||
end
|
49
spec/lib/gitlab/git/patches/commit_patches_spec.rb
Normal file
49
spec/lib/gitlab/git/patches/commit_patches_spec.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Git::Patches::CommitPatches do
|
||||
describe '#commit' do
|
||||
let(:patches) do
|
||||
patches_folder = Rails.root.join('spec/fixtures/patchfiles')
|
||||
content_1 = File.read(File.join(patches_folder, "0001-This-does-not-apply-to-the-feature-branch.patch"))
|
||||
content_2 = File.read(File.join(patches_folder, "0001-A-commit-from-a-patch.patch"))
|
||||
|
||||
Gitlab::Git::Patches::Collection.new([content_1, content_2])
|
||||
end
|
||||
let(:user) { build(:user) }
|
||||
let(:branch_name) { 'branch-with-patches' }
|
||||
let(:repository) { create(:project, :repository).repository }
|
||||
|
||||
subject(:commit_patches) do
|
||||
described_class.new(user, repository, branch_name, patches)
|
||||
end
|
||||
|
||||
it 'applies the patches' do
|
||||
new_rev = commit_patches.commit
|
||||
|
||||
expect(repository.commit(new_rev)).not_to be_nil
|
||||
end
|
||||
|
||||
it 'updates the branch cache' do
|
||||
expect(repository).to receive(:after_create_branch)
|
||||
|
||||
commit_patches.commit
|
||||
end
|
||||
|
||||
context 'when the repository does not exist' do
|
||||
let(:repository) { create(:project).repository }
|
||||
|
||||
it 'raises the correct error' do
|
||||
expect { commit_patches.commit }.to raise_error(Gitlab::Git::Repository::NoRepository)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the patch does not apply' do
|
||||
let(:branch_name) { 'feature' }
|
||||
|
||||
it 'raises the correct error' do
|
||||
expect { commit_patches.commit }.to raise_error(Gitlab::Git::CommandError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
16
spec/lib/gitlab/git/patches/patch_spec.rb
Normal file
16
spec/lib/gitlab/git/patches/patch_spec.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Git::Patches::Patch do
|
||||
let(:patches_folder) { Rails.root.join('spec/fixtures/patchfiles') }
|
||||
let(:patch_content) do
|
||||
File.read(File.join(patches_folder, "0001-This-does-not-apply-to-the-feature-branch.patch"))
|
||||
end
|
||||
let(:patch) { described_class.new(patch_content) }
|
||||
|
||||
describe '#size' do
|
||||
it 'is correct' do
|
||||
expect(patch.size).to eq(549.bytes)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -335,4 +335,37 @@ describe Gitlab::GitalyClient::OperationService do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#user_commit_patches' do
|
||||
let(:patches_folder) { Rails.root.join('spec/fixtures/patchfiles') }
|
||||
let(:patch_content) do
|
||||
patch_names.map { |name| File.read(File.join(patches_folder, name)) }.join("\n")
|
||||
end
|
||||
let(:patch_names) { %w(0001-This-does-not-apply-to-the-feature-branch.patch) }
|
||||
let(:branch_name) { 'branch-with-patches' }
|
||||
|
||||
subject(:commit_patches) do
|
||||
client.user_commit_patches(user, branch_name, patch_content)
|
||||
end
|
||||
|
||||
it 'applies the patch correctly' do
|
||||
branch_update = commit_patches
|
||||
|
||||
expect(branch_update).to be_branch_created
|
||||
|
||||
commit = repository.commit(branch_update.newrev)
|
||||
expect(commit.author_email).to eq('patchuser@gitlab.org')
|
||||
expect(commit.committer_email).to eq(user.email)
|
||||
expect(commit.message.chomp).to eq('This does not apply to the `feature` branch')
|
||||
end
|
||||
|
||||
context 'when the patch could not be applied' do
|
||||
let(:patch_names) { %w(0001-This-does-not-apply-to-the-feature-branch.patch) }
|
||||
let(:branch_name) { 'feature' }
|
||||
|
||||
it 'raises the correct error' do
|
||||
expect { commit_patches }.to raise_error(GRPC::FailedPrecondition)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
92
spec/services/commits/commit_patch_service_spec.rb
Normal file
92
spec/services/commits/commit_patch_service_spec.rb
Normal file
|
@ -0,0 +1,92 @@
|
|||
# frozen_string_literal: true
|
||||
require 'spec_helper'
|
||||
|
||||
describe Commits::CommitPatchService do
|
||||
describe '#execute' do
|
||||
let(:patches) do
|
||||
patches_folder = Rails.root.join('spec/fixtures/patchfiles')
|
||||
content_1 = File.read(File.join(patches_folder, "0001-This-does-not-apply-to-the-feature-branch.patch"))
|
||||
content_2 = File.read(File.join(patches_folder, "0001-A-commit-from-a-patch.patch"))
|
||||
|
||||
[content_1, content_2]
|
||||
end
|
||||
let(:user) { project.creator }
|
||||
let(:branch_name) { 'branch-with-patches' }
|
||||
let(:project) { create(:project, :repository) }
|
||||
let(:start_branch) { nil }
|
||||
let(:params) { { branch_name: branch_name, patches: patches, start_branch: start_branch } }
|
||||
|
||||
subject(:service) do
|
||||
described_class.new(project, user, params)
|
||||
end
|
||||
|
||||
it 'returns a successful result' do
|
||||
result = service.execute
|
||||
|
||||
branch = project.repository.find_branch(branch_name)
|
||||
|
||||
expect(result[:status]).to eq(:success)
|
||||
expect(result[:result]).to eq(branch.target)
|
||||
end
|
||||
|
||||
it 'is based off HEAD when no start ref is passed' do
|
||||
service.execute
|
||||
|
||||
merge_base = project.repository.merge_base(project.repository.root_ref, branch_name)
|
||||
|
||||
expect(merge_base).to eq(project.repository.commit('HEAD').sha)
|
||||
end
|
||||
|
||||
context 'when specifying a different start branch' do
|
||||
let(:start_branch) { 'with-codeowners' }
|
||||
|
||||
it 'is based of the correct branch' do
|
||||
service.execute
|
||||
|
||||
merge_base = project.repository.merge_base(start_branch, branch_name)
|
||||
|
||||
expect(merge_base).to eq(project.repository.commit(start_branch).sha)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'an error response' do |expected_message|
|
||||
it 'returns the correct error' do
|
||||
result = service.execute
|
||||
|
||||
expect(result[:status]).to eq(:error)
|
||||
expect(result[:message]).to match(expected_message)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user does not have access' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it_behaves_like 'an error response',
|
||||
'You are not allowed to push into this branch'
|
||||
end
|
||||
|
||||
context 'when the patches are not valid' do
|
||||
let(:patches) { "a" * 2.1.megabytes }
|
||||
|
||||
it_behaves_like 'an error response', 'Patches are too big'
|
||||
end
|
||||
|
||||
context 'when the new branch name is invalid' do
|
||||
let(:branch_name) { 'HEAD' }
|
||||
|
||||
it_behaves_like 'an error response', 'Branch name is invalid'
|
||||
end
|
||||
|
||||
context 'when the patches do not apply' do
|
||||
let(:branch_name) { 'feature' }
|
||||
|
||||
it_behaves_like 'an error response', 'Patch failed at'
|
||||
end
|
||||
|
||||
context 'when specifying a non existent start branch' do
|
||||
let(:start_branch) { 'does-not-exist' }
|
||||
|
||||
it_behaves_like 'an error response', 'Invalid reference name'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -392,5 +392,13 @@ describe MergeRequests::BuildService do
|
|||
expect(merge_request.source_project).to eq(project)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when specifying target branch in the description' do
|
||||
let(:description) { "A merge request targeting another branch\n\n/target_branch with-codeowners" }
|
||||
|
||||
it 'sets the attribute from the quick actions' do
|
||||
expect(merge_request.target_branch).to eq('with-codeowners')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -46,6 +46,21 @@ describe EmailReceiverWorker, :mailer do
|
|||
should_not_email_anyone
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the error is Gitlab::Email::InvalidAttachment' do
|
||||
let(:error) { Gitlab::Email::InvalidAttachment.new("Could not deal with that") }
|
||||
|
||||
it 'reports the error to the sender' do
|
||||
perform_enqueued_jobs do
|
||||
described_class.new.perform(raw_message)
|
||||
end
|
||||
|
||||
email = ActionMailer::Base.deliveries.last
|
||||
expect(email).not_to be_nil
|
||||
expect(email.to).to eq(["jake@adventuretime.ooo"])
|
||||
expect(email.body.parts.last.to_s).to include("Could not deal with that")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue