1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
# frozen_string_literal: true
module Gitlab
module GithubImport
module Importer
class PullRequestReviewImporter
# review - An instance of `Gitlab::GithubImport::Representation::PullRequestReview`
# project - An instance of `Project`
# client - An instance of `Gitlab::GithubImport::Client`
def initialize(review, project, client)
@review = review
@project = project
@client = client
@merge_request = project.merge_requests.find_by_id(review.merge_request_id)
end
def execute
user_finder = GithubImport::UserFinder.new(project, client)
gitlab_user_id = begin
user_finder.user_id_for(review.author)
rescue ::Octokit::NotFound
nil
end
if gitlab_user_id
add_review_note!(gitlab_user_id)
add_approval!(gitlab_user_id)
add_reviewer!(gitlab_user_id)
else
add_complementary_review_note!(project.creator_id)
end
end
private
attr_reader :review, :merge_request, :project, :client
def add_review_note!(author_id)
return if review.note.empty?
add_note!(author_id, review_note_content)
end
def add_complementary_review_note!(author_id)
return if review.note.empty? && !review.approval?
note_body = MarkdownText.format(
review_note_content,
review.author
)
add_note!(author_id, note_body)
end
def review_note_content
header = "**Review:** #{review.review_type.humanize}"
if review.note.present?
"#{header}\n\n#{review.note}"
else
header
end
end
def add_note!(author_id, note)
note = Note.new(note_attributes(author_id, note))
note.save!
end
def note_attributes(author_id, note, extra = {})
{
importing: true,
noteable_id: merge_request.id,
noteable_type: 'MergeRequest',
project_id: project.id,
author_id: author_id,
note: note,
system: false,
created_at: submitted_at,
updated_at: submitted_at
}.merge(extra)
end
def add_approval!(user_id)
return unless review.review_type == 'APPROVED'
approval_attribues = {
merge_request_id: merge_request.id,
user_id: user_id,
created_at: submitted_at,
updated_at: submitted_at
}
result = ::Approval.insert(
approval_attribues,
returning: [:id],
unique_by: [:user_id, :merge_request_id]
)
if result.rows.present?
add_approval_system_note!(user_id)
end
end
def add_reviewer!(user_id)
return if review_re_requested?(user_id)
::MergeRequestReviewer.create!(
merge_request_id: merge_request.id,
user_id: user_id,
state: ::MergeRequestReviewer.states['reviewed'],
created_at: submitted_at
)
rescue ActiveRecord::RecordNotUnique
# multiple reviews from single person could make a SQL concurrency issue here
nil
end
# rubocop:disable CodeReuse/ActiveRecord
def review_re_requested?(user_id)
# records that were imported on previous stage with "unreviewed" status
MergeRequestReviewer.where(merge_request_id: merge_request.id, user_id: user_id).exists?
end
# rubocop:enable CodeReuse/ActiveRecord
def add_approval_system_note!(user_id)
attributes = note_attributes(
user_id,
'approved this merge request',
system: true,
system_note_metadata: SystemNoteMetadata.new(action: 'approved')
)
Note.create!(attributes)
end
def submitted_at
@submitted_at ||= (review.submitted_at || merge_request.updated_at)
end
end
end
end
end
|