gitlab-dangerfiles 3.13.0 → 4.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +0 -1
- data/.gitlab/CODEOWNERS +1 -1
- data/.gitlab/merge_request_templates/Release.md +1 -1
- data/.gitlab-ci.yml +21 -42
- data/.rubocop.yml +6 -16
- data/.rubocop_todo.yml +5 -8
- data/Gemfile +0 -16
- data/Gemfile.lock +234 -0
- data/README.md +96 -9
- data/gitlab-dangerfiles.gemspec +13 -5
- data/lefthook.yml +0 -5
- data/lib/danger/plugins/changelog.rb +9 -7
- data/lib/danger/plugins/duo_code.rb +12 -0
- data/lib/danger/plugins/internal/helper.rb +34 -10
- data/lib/danger/plugins/roulette.rb +95 -256
- data/lib/danger/rules/commit_messages/Dangerfile +2 -7
- data/lib/danger/rules/duo_code_review/Dangerfile +10 -0
- data/lib/danger/rules/simple_roulette/Dangerfile +17 -10
- data/lib/danger/rules/type_label/Dangerfile +0 -8
- data/lib/danger/rules/z_add_labels/Dangerfile +3 -3
- data/lib/gitlab/dangerfiles/approval.rb +22 -0
- data/lib/gitlab/dangerfiles/base_linter.rb +1 -1
- data/lib/gitlab/dangerfiles/capability.rb +82 -0
- data/lib/gitlab/dangerfiles/commit_linter.rb +2 -2
- data/lib/gitlab/dangerfiles/config.rb +29 -3
- data/lib/gitlab/dangerfiles/emoji_checker.rb +1 -1
- data/lib/gitlab/dangerfiles/spec_helper.rb +231 -1
- data/lib/gitlab/dangerfiles/spin.rb +15 -0
- data/lib/gitlab/dangerfiles/spinner.rb +191 -0
- data/lib/gitlab/dangerfiles/teammate.rb +94 -20
- data/lib/gitlab/dangerfiles/type_label_guesser.rb +2 -2
- data/lib/gitlab/dangerfiles/version.rb +1 -1
- data/lib/gitlab/dangerfiles.rb +0 -1
- metadata +100 -25
- data/lib/danger/rules/subtype_label/Dangerfile +0 -14
- data/lib/gitlab/dangerfiles/category.rb +0 -111
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
TYPE_LABEL_MISSING_MESSAGE = "Please add a [merge request type](https://about.gitlab.com/handbook/engineering/metrics/#work-type-classification) to this merge request."
|
|
4
|
-
|
|
5
3
|
require_relative "../../../gitlab/dangerfiles/type_label_guesser"
|
|
6
4
|
|
|
7
5
|
return if helper.has_scoped_label_with_scope?("type")
|
|
@@ -10,9 +8,3 @@ if respond_to?(:changelog)
|
|
|
10
8
|
type_label_guesser = Gitlab::Dangerfiles::TypeLabelGuesser.new
|
|
11
9
|
helper.labels_to_add.concat(type_label_guesser.labels_from_changelog_categories(changelog.categories))
|
|
12
10
|
end
|
|
13
|
-
|
|
14
|
-
if ENV['DANGER_ERROR_WHEN_TYPE_LABEL_IS_MISSING'] == 'true'
|
|
15
|
-
fail TYPE_LABEL_MISSING_MESSAGE
|
|
16
|
-
else
|
|
17
|
-
warn TYPE_LABEL_MISSING_MESSAGE
|
|
18
|
-
end
|
|
@@ -6,10 +6,10 @@ return unless helper.ci?
|
|
|
6
6
|
|
|
7
7
|
def post_labels(labels)
|
|
8
8
|
gitlab.api.update_merge_request(helper.mr_target_project_id,
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
helper.mr_iid,
|
|
10
|
+
add_labels: labels.join(","))
|
|
11
11
|
rescue Gitlab::Error::Forbidden
|
|
12
|
-
warn("
|
|
12
|
+
warn("Labels missing: please ask a reviewer or maintainer to add #{helper.labels_list(labels)} to this merge request.")
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
post_labels(helper.labels_to_add) if helper.labels_to_add.any?
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "spin"
|
|
4
|
+
|
|
5
|
+
module Gitlab
|
|
6
|
+
module Dangerfiles
|
|
7
|
+
Approval = Struct.new(:category, :spin) do
|
|
8
|
+
def self.from_approval_rule(rule, maintainer)
|
|
9
|
+
category =
|
|
10
|
+
if rule["section"] == "codeowners"
|
|
11
|
+
"`#{rule['name']}`"
|
|
12
|
+
else
|
|
13
|
+
rule["section"]
|
|
14
|
+
end.to_sym
|
|
15
|
+
|
|
16
|
+
spin = Spin.new(category, nil, maintainer, :reviewer)
|
|
17
|
+
|
|
18
|
+
new(category, spin)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -16,7 +16,7 @@ module Gitlab
|
|
|
16
16
|
subject_too_long: "The %s may not be longer than #{MAX_LINE_LENGTH} characters",
|
|
17
17
|
subject_starts_with_a_space: "The %s must not start with a space",
|
|
18
18
|
subject_starts_with_lowercase: "The %s must start with a capital letter",
|
|
19
|
-
subject_ends_with_a_period: "The %s must not end with a period"
|
|
19
|
+
subject_ends_with_a_period: "The %s must not end with a period"
|
|
20
20
|
}
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Gitlab
|
|
4
|
+
module Dangerfiles
|
|
5
|
+
CapabilityStruct = Struct.new(:category, :project, :kind, :labels, keyword_init: true)
|
|
6
|
+
|
|
7
|
+
class Capability < CapabilityStruct
|
|
8
|
+
def self.for(category, **arguments)
|
|
9
|
+
(category_to_class[category] || self)
|
|
10
|
+
.new(category: category, **arguments)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.category_to_class
|
|
14
|
+
@category_to_class ||= {
|
|
15
|
+
none: None,
|
|
16
|
+
test: Test,
|
|
17
|
+
tooling: Tooling,
|
|
18
|
+
import_integrate_be: ImportIntegrateBE,
|
|
19
|
+
import_integrate_fe: ImportIntegrateFE,
|
|
20
|
+
ux: UX
|
|
21
|
+
}.freeze
|
|
22
|
+
end
|
|
23
|
+
private_class_method :category_to_class
|
|
24
|
+
|
|
25
|
+
def has_capability?(teammate)
|
|
26
|
+
teammate.capabilities(project).include?(capability)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def capability
|
|
32
|
+
@capability ||= "#{kind} #{category}"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class None < Capability
|
|
36
|
+
def capability
|
|
37
|
+
@capability ||= kind.to_s
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
class Test < Capability
|
|
42
|
+
def has_capability?(teammate)
|
|
43
|
+
return false if kind != :reviewer
|
|
44
|
+
|
|
45
|
+
area = teammate.role[/Software Engineer in Test(?:.*?, (\w+))/, 1]
|
|
46
|
+
|
|
47
|
+
!!area && labels.any?("devops::#{area.downcase}")
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class Tooling < Capability
|
|
52
|
+
def has_capability?(teammate)
|
|
53
|
+
if super
|
|
54
|
+
true
|
|
55
|
+
elsif %i[trainee_maintainer maintainer].include?(kind)
|
|
56
|
+
false
|
|
57
|
+
else # fallback to backend reviewer
|
|
58
|
+
teammate.capabilities(project).include?("#{kind} backend")
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class ImportIntegrateBE < Capability
|
|
64
|
+
def has_capability?(teammate)
|
|
65
|
+
kind == :reviewer && teammate.role.match?(/Backend Engineer.+:Import and Integrate/)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
class ImportIntegrateFE < Capability
|
|
70
|
+
def has_capability?(teammate)
|
|
71
|
+
kind == :reviewer && teammate.role.match?(/Frontend Engineer.+:Import and Integrate/)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
class UX < Capability
|
|
76
|
+
def has_capability?(teammate)
|
|
77
|
+
super && teammate.member_of_the_group?(labels)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -26,7 +26,7 @@ module Gitlab
|
|
|
26
26
|
message_contains_unicode_emoji: "Avoid the use of Unicode Emoji. These add no value to the commit " \
|
|
27
27
|
"message, and may not be displayed properly everywhere",
|
|
28
28
|
message_contains_short_reference: "Use full URLs instead of short references (`gitlab-org/gitlab#123` or " \
|
|
29
|
-
"`!123`), as short references are displayed as plain text outside of GitLab"
|
|
29
|
+
"`!123`), as short references are displayed as plain text outside of GitLab"
|
|
30
30
|
}
|
|
31
31
|
)
|
|
32
32
|
end
|
|
@@ -148,7 +148,7 @@ module Gitlab
|
|
|
148
148
|
|
|
149
149
|
def message_contains_short_reference?
|
|
150
150
|
match_data = commit.message.match(SHORT_REFERENCE_REGEX) ||
|
|
151
|
-
|
|
151
|
+
commit.message.match(MS_SHORT_REFERENCE_REGEX)
|
|
152
152
|
|
|
153
153
|
return false unless match_data
|
|
154
154
|
|
|
@@ -21,31 +21,54 @@ module Gitlab
|
|
|
21
21
|
# match changed lines in files that match +filename_regex+. Used in `helper.changes_by_category`, `helper.changes`, and `helper.categories_for_file`.
|
|
22
22
|
attr_accessor :files_to_category
|
|
23
23
|
|
|
24
|
+
# @!attribute custom_labels_for_categories
|
|
25
|
+
# @return [{String => String}] A hash of the form +{ category_name => label }+.
|
|
26
|
+
# Used in `helper.custom_labels_for_categories`.
|
|
27
|
+
attr_accessor :custom_labels_for_categories
|
|
28
|
+
|
|
29
|
+
# @!attribute disabled_roulette_categories
|
|
30
|
+
# @return [Array] indicating which categories would be disabled for the simple roulette. Default to `[]` (all categories are enabled)
|
|
31
|
+
attr_accessor :disabled_roulette_categories
|
|
32
|
+
|
|
33
|
+
# Rule: changes_size
|
|
24
34
|
# @!attribute code_size_thresholds
|
|
25
35
|
# @return [{ high: Integer, medium: Integer }] a hash of the form +{ high: 42, medium: 12 }+ where +:high+ is the lines changed threshold which triggers an error, and +:medium+ is the lines changed threshold which triggers a warning. Also, see +DEFAULT_CHANGES_SIZE_THRESHOLDS+ for the format of the hash.
|
|
26
36
|
attr_accessor :code_size_thresholds
|
|
27
37
|
|
|
38
|
+
# Rule: commit_messages
|
|
28
39
|
# @!attribute max_commits_count
|
|
29
40
|
# @return [Integer] the maximum number of allowed non-squashed/non-fixup commits for a given MR. A warning is triggered if the MR has more commits.
|
|
30
41
|
attr_accessor :max_commits_count
|
|
31
42
|
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
|
|
43
|
+
# Rule: duo_code_review
|
|
44
|
+
# @!attribute duo_code_review
|
|
45
|
+
# @return [Symbol] whether a review from GitLab Duo Code is `:mandatory` or `:optional`. Default to `:optional`.
|
|
46
|
+
attr_accessor :duo_code_review
|
|
35
47
|
|
|
48
|
+
# Rule: simple_roulette
|
|
36
49
|
# @!attribute included_optional_codeowners_sections_for_roulette
|
|
37
50
|
# @return [Array] indicating which optional codeowners sections should be included in roulette. Default to `[]`.
|
|
38
51
|
attr_accessor :included_optional_codeowners_sections_for_roulette
|
|
39
52
|
|
|
53
|
+
# Rule: simple_roulette
|
|
40
54
|
# @!attribute excluded_required_codeowners_sections_for_roulette
|
|
41
55
|
# @return [Array] indicating which required codeowners sections should be excluded from roulette. Default to `[]`.
|
|
42
56
|
attr_accessor :excluded_required_codeowners_sections_for_roulette
|
|
43
57
|
|
|
58
|
+
# @!attribute auto_assign_for_roulette_roles
|
|
59
|
+
# @return [Array<Symbol>] which roles to auto assign as reviewers, given roulette recommendations (:reviewer, :maintainer, or both). If empty, auto-assignment is disabled. Default to `[]`.
|
|
60
|
+
attr_accessor :auto_assign_for_roulette_roles
|
|
61
|
+
|
|
62
|
+
# @!attribute auto_assign_for_roulette_labels
|
|
63
|
+
# @return [Array<String>] MR labels that allow auto reviewer assignment. If empty, applies to all MRs, provided :auto_assign_for_roulette_roles is not empty. Default to `[]`.
|
|
64
|
+
attr_accessor :auto_assign_for_roulette_labels
|
|
65
|
+
|
|
44
66
|
DEFAULT_CHANGES_SIZE_THRESHOLDS = { high: 2_000, medium: 500 }.freeze
|
|
45
67
|
DEFAULT_COMMIT_MESSAGES_MAX_COMMITS_COUNT = 10
|
|
46
68
|
|
|
47
69
|
def initialize
|
|
48
70
|
@files_to_category = {}
|
|
71
|
+
@custom_labels_for_categories = {}
|
|
49
72
|
@project_root = nil
|
|
50
73
|
@project_name = ENV["CI_PROJECT_NAME"]
|
|
51
74
|
@ci_only_rules = []
|
|
@@ -54,6 +77,9 @@ module Gitlab
|
|
|
54
77
|
@disabled_roulette_categories = []
|
|
55
78
|
@included_optional_codeowners_sections_for_roulette = []
|
|
56
79
|
@excluded_required_codeowners_sections_for_roulette = []
|
|
80
|
+
@auto_assign_for_roulette_roles = []
|
|
81
|
+
@auto_assign_for_roulette_labels = []
|
|
82
|
+
@duo_code_review = :optional
|
|
57
83
|
end
|
|
58
84
|
end
|
|
59
85
|
end
|
|
@@ -17,7 +17,7 @@ module DangerSpecHelper
|
|
|
17
17
|
"GITLAB_CI" => "true",
|
|
18
18
|
"DANGER_GITLAB_HOST" => "gitlab.example.com",
|
|
19
19
|
"CI_MERGE_REQUEST_IID" => 28_493,
|
|
20
|
-
"DANGER_GITLAB_API_TOKEN" => "123sbdq54erfsd3422gdfio"
|
|
20
|
+
"DANGER_GITLAB_API_TOKEN" => "123sbdq54erfsd3422gdfio"
|
|
21
21
|
}
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -45,6 +45,19 @@ module DangerSpecHelper
|
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
RSpec::Matchers.define :match_teammates do |expected|
|
|
49
|
+
match do |actual|
|
|
50
|
+
expected.each do |expected_person|
|
|
51
|
+
matched_person = actual.find { |actual_person| actual_person.name == expected_person.username }
|
|
52
|
+
|
|
53
|
+
matched_person &&
|
|
54
|
+
matched_person.name == expected_person.name &&
|
|
55
|
+
matched_person.role == expected_person.role &&
|
|
56
|
+
matched_person.projects == expected_person.projects
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
48
61
|
RSpec.shared_context "with dangerfile" do
|
|
49
62
|
let(:dangerfile) { DangerSpecHelper.testing_dangerfile }
|
|
50
63
|
let(:added_files) { %w[added-from-git] }
|
|
@@ -68,3 +81,220 @@ RSpec.shared_context "with dangerfile" do
|
|
|
68
81
|
allow(dangerfile.helper).to receive(:changes).and_return(changes) if dangerfile.respond_to?(:helper)
|
|
69
82
|
end
|
|
70
83
|
end
|
|
84
|
+
|
|
85
|
+
RSpec.shared_context "with teammates" do
|
|
86
|
+
let(:backend_available) { true }
|
|
87
|
+
let(:backend_tz_offset_hours) { 2.0 }
|
|
88
|
+
let(:backend_maintainer_project) { { "gitlab" => "maintainer backend" } }
|
|
89
|
+
let(:backend_maintainer) do
|
|
90
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
91
|
+
"username" => "backend-maintainer",
|
|
92
|
+
"name" => "Backend maintainer",
|
|
93
|
+
"role" => "Backend engineer",
|
|
94
|
+
"projects" => backend_maintainer_project,
|
|
95
|
+
"available" => backend_available,
|
|
96
|
+
"tz_offset_hours" => backend_tz_offset_hours
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
let(:another_backend_maintainer) do
|
|
101
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
102
|
+
"username" => "another-backend-maintainer",
|
|
103
|
+
"name" => "Another Backend Maintainer",
|
|
104
|
+
"role" => "Backend engineer",
|
|
105
|
+
"projects" => backend_maintainer_project,
|
|
106
|
+
"available" => backend_available,
|
|
107
|
+
"tz_offset_hours" => backend_tz_offset_hours
|
|
108
|
+
)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
let(:backend_reviewer_available) { true }
|
|
112
|
+
let(:backend_reviewer) do
|
|
113
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
114
|
+
"username" => "backend-reviewer",
|
|
115
|
+
"name" => "Backend reviewer",
|
|
116
|
+
"role" => "Backend engineer",
|
|
117
|
+
"projects" => { "gitlab" => "reviewer backend" },
|
|
118
|
+
"available" => backend_reviewer_available,
|
|
119
|
+
"tz_offset_hours" => 1.0
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
let(:frontend_reviewer) do
|
|
124
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
125
|
+
"username" => "frontend-reviewer",
|
|
126
|
+
"name" => "Frontend reviewer",
|
|
127
|
+
"role" => "Frontend engineer",
|
|
128
|
+
"projects" => { "gitlab" => "reviewer frontend" },
|
|
129
|
+
"available" => true,
|
|
130
|
+
"tz_offset_hours" => 2.0
|
|
131
|
+
)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
let(:frontend_maintainer) do
|
|
135
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
136
|
+
"username" => "frontend-maintainer",
|
|
137
|
+
"name" => "Frontend maintainer",
|
|
138
|
+
"role" => "Frontend engineer",
|
|
139
|
+
"projects" => { "gitlab" => "maintainer frontend" },
|
|
140
|
+
"available" => true,
|
|
141
|
+
"tz_offset_hours" => 2.0
|
|
142
|
+
)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
let(:ux_reviewer) do
|
|
146
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
147
|
+
"username" => "ux-reviewer",
|
|
148
|
+
"name" => "UX reviewer",
|
|
149
|
+
"role" => "Product Designer",
|
|
150
|
+
"projects" => { "gitlab" => "reviewer ux" },
|
|
151
|
+
"specialty" => "Create: Source Code",
|
|
152
|
+
"available" => true,
|
|
153
|
+
"tz_offset_hours" => 2.0
|
|
154
|
+
)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
let(:software_engineer_in_test) do
|
|
158
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
159
|
+
"username" => "software-engineer-in-test",
|
|
160
|
+
"name" => "Software Engineer in Test",
|
|
161
|
+
"role" => "Software Engineer in Test, Create:Source Code",
|
|
162
|
+
"projects" => { "gitlab" => "maintainer qa", "gitlab-qa" => "maintainer" },
|
|
163
|
+
"available" => true,
|
|
164
|
+
"tz_offset_hours" => 2.0
|
|
165
|
+
)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
let(:software_engineer_in_import_integrate_fe) do
|
|
169
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
170
|
+
"username" => "software-engineer-in-import-and-integrate-fe",
|
|
171
|
+
"name" => "Frontend Engineer in Import and Integrate",
|
|
172
|
+
"role" => "AnyRole Frontend Engineer, AnyStage:Import and Integrate",
|
|
173
|
+
"projects" => { "gitlab" => "reviewer frontend" },
|
|
174
|
+
"available" => true,
|
|
175
|
+
"tz_offset_hours" => 2.0
|
|
176
|
+
)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
let(:software_engineer_in_import_integrate_be) do
|
|
180
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
181
|
+
"username" => "software-engineer-in-import-and-integrate-be",
|
|
182
|
+
"name" => "Backend Engineer in Import and Integrate",
|
|
183
|
+
"role" => "AnyRole Backend Engineer, AnyStage:Import and Integrate",
|
|
184
|
+
"projects" => { "gitlab" => "reviewer backend" },
|
|
185
|
+
"available" => true,
|
|
186
|
+
"tz_offset_hours" => 2.0
|
|
187
|
+
)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
let(:tooling_reviewer) do
|
|
191
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
192
|
+
"username" => "eng-prod-reviewer",
|
|
193
|
+
"name" => "EP engineer",
|
|
194
|
+
"role" => "Engineering Productivity",
|
|
195
|
+
"projects" => { "gitlab" => "reviewer tooling" },
|
|
196
|
+
"available" => true,
|
|
197
|
+
"tz_offset_hours" => 2.0
|
|
198
|
+
)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
let(:ci_template_reviewer) do
|
|
202
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
203
|
+
"username" => "ci-template-maintainer",
|
|
204
|
+
"name" => "CI Template engineer",
|
|
205
|
+
"role" => '~"ci::templates"',
|
|
206
|
+
"projects" => { "gitlab" => "reviewer ci_template" },
|
|
207
|
+
"available" => true,
|
|
208
|
+
"tz_offset_hours" => 2.0
|
|
209
|
+
)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
let(:analytics_instrumentation_reviewer) do
|
|
213
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
214
|
+
"username" => "analytics-instrumentation-reviewer",
|
|
215
|
+
"name" => "PI engineer",
|
|
216
|
+
"role" => "Backend Engineer, Analytics: Analytics Instrumentation",
|
|
217
|
+
"projects" => { "gitlab" => "reviewer analytics_instrumentation" },
|
|
218
|
+
"available" => true,
|
|
219
|
+
"tz_offset_hours" => 2.0
|
|
220
|
+
)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
let(:import_and_integrate_backend_reviewer) do
|
|
224
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
225
|
+
"username" => "import-and-integrate-backend-reviewer",
|
|
226
|
+
"name" => "Import and Integrate BE engineer",
|
|
227
|
+
"role" => "AnyRole Backend Engineer, AnyStage:Import and Integrate",
|
|
228
|
+
"projects" => { "gitlab" => "reviewer backend" },
|
|
229
|
+
"available" => backend_reviewer_available,
|
|
230
|
+
"tz_offset_hours" => 2.0
|
|
231
|
+
)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
let(:import_and_integrate_frontend_reviewer) do
|
|
235
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
236
|
+
"username" => "import-and-integrate-frontend-reviewer",
|
|
237
|
+
"name" => "Import and Integrate FE engineer",
|
|
238
|
+
"role" => "AnyRole Frontend Engineer, AnyStage:Import and Integrate",
|
|
239
|
+
"projects" => { "gitlab" => "reviewer frontend" },
|
|
240
|
+
"available" => true,
|
|
241
|
+
"tz_offset_hours" => 2.0
|
|
242
|
+
)
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
let(:workhorse_reviewer) do
|
|
246
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
247
|
+
"username" => "workhorse-reviewer",
|
|
248
|
+
"name" => "Workhorse reviewer",
|
|
249
|
+
"role" => "Backend engineer",
|
|
250
|
+
"projects" => { "gitlab-workhorse" => "reviewer" },
|
|
251
|
+
"available" => true,
|
|
252
|
+
"tz_offset_hours" => 2.0
|
|
253
|
+
)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
let(:workhorse_maintainer) do
|
|
257
|
+
Gitlab::Dangerfiles::Teammate.new(
|
|
258
|
+
"username" => "workhorse-maintainer",
|
|
259
|
+
"name" => "Workhorse maintainer",
|
|
260
|
+
"role" => "Backend engineer",
|
|
261
|
+
"projects" => { "gitlab-workhorse" => "maintainer" },
|
|
262
|
+
"available" => true,
|
|
263
|
+
"tz_offset_hours" => 2.0
|
|
264
|
+
)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
let(:teammates) do
|
|
268
|
+
[
|
|
269
|
+
backend_maintainer.to_h,
|
|
270
|
+
backend_reviewer.to_h,
|
|
271
|
+
frontend_maintainer.to_h,
|
|
272
|
+
frontend_reviewer.to_h,
|
|
273
|
+
ux_reviewer.to_h,
|
|
274
|
+
software_engineer_in_test.to_h,
|
|
275
|
+
tooling_reviewer.to_h,
|
|
276
|
+
ci_template_reviewer.to_h,
|
|
277
|
+
workhorse_reviewer.to_h,
|
|
278
|
+
workhorse_maintainer.to_h,
|
|
279
|
+
analytics_instrumentation_reviewer.to_h,
|
|
280
|
+
import_and_integrate_backend_reviewer.to_h,
|
|
281
|
+
import_and_integrate_frontend_reviewer.to_h,
|
|
282
|
+
software_engineer_in_import_integrate_fe.to_h,
|
|
283
|
+
software_engineer_in_import_integrate_be.to_h
|
|
284
|
+
]
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
let(:teammate_json) { teammates.to_json }
|
|
288
|
+
let(:ux_fallback_reviewer) { instance_double(Gitlab::Dangerfiles::Teammate) }
|
|
289
|
+
let(:company_members) { Gitlab::Dangerfiles::Teammate.fetch_company_members }
|
|
290
|
+
|
|
291
|
+
before do
|
|
292
|
+
WebMock
|
|
293
|
+
.stub_request(:get, Gitlab::Dangerfiles::Teammate::ROULETTE_DATA_URL)
|
|
294
|
+
.to_return(body: teammate_json)
|
|
295
|
+
|
|
296
|
+
# This avoid changing the internal state of the class
|
|
297
|
+
allow(Gitlab::Dangerfiles::Teammate).to receive(:warnings).and_return([])
|
|
298
|
+
allow(Gitlab::Dangerfiles::Teammate).to receive(:company_members).and_return(company_members)
|
|
299
|
+
end
|
|
300
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Gitlab
|
|
4
|
+
module Dangerfiles
|
|
5
|
+
Spin = Struct.new(:category, :reviewer, :maintainer, :optional_role) do
|
|
6
|
+
def no_reviewer?
|
|
7
|
+
reviewer.nil?
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def no_maintainer?
|
|
11
|
+
maintainer.nil?
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|