gitlab-dangerfiles 3.6.0 → 3.6.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af0d569b13b09e65dfaed6f7eaf3519e314e510e71279b395eabccdb49901f83
4
- data.tar.gz: 24050d6f8149c4e902d3c98a8b7d89aa8070a0e2445724f0f1733498d824800c
3
+ metadata.gz: 34ff9782c4b20cd3c7dbb4a25d7ecdf66cf49ef303e1deb0bb04074e1c4fca21
4
+ data.tar.gz: b21f8643147b7147fca7e5cba536c67bf98d65f827cb169d72fd2ac5ff3de355
5
5
  SHA512:
6
- metadata.gz: 84d10142bb9fbf7fe03c9b4d6aee7f39cf0e9ff0ca90c167b484f3d5f1f3a13ef7aed7756c2d1b7b2873e896025ac91dc17b40b5c625d3d2cebad95f4114f3d9
7
- data.tar.gz: 87cb02420672c5f9bb171837852733ee9550f30afc918ddb948a1e469224261eda5896ad18993b6aa550cc3d9ec5a782c1d17c278a40d3fc7a316edbf32d63c0
6
+ metadata.gz: 7f9f43daf58a905f330ad98020327073a47692f24c0494d407d7e76aa8b18819b74839772c58b19d9081b04034154a06e8dee588c70898b71db08bab03fa31a9
7
+ data.tar.gz: f30572b11ac8e2d9a4ab9cc35c19000c68ecdaefd72f8e276f18e73da3beeb64b81a44d2e4919977c0aabecafec5d3fa64a25443604c27168865a5acb7c6bf97
data/.rubocop.yml CHANGED
@@ -32,6 +32,9 @@ Style/HashSyntax:
32
32
  Style/StringLiterals:
33
33
  EnforcedStyle: double_quotes
34
34
 
35
+ Style/TrailingCommaInHashLiteral:
36
+ EnforcedStyleForMultiline: consistent_comma
37
+
35
38
  # Was problematic, and not included in the .rubocop_todo.yml
36
39
  GitlabSecurity/PublicSend:
37
40
  Enabled: false
data/README.md CHANGED
@@ -128,8 +128,12 @@ project. To use it in your project, perform the following steps:
128
128
  see how to set it up.
129
129
  1. When using the default roulette, use `import_defaults` or import it manually when setting
130
130
  up the gitlab-dangerfiles instance:
131
+
131
132
  ```ruby
133
+ require 'gitlab-dangerfiles'
134
+
132
135
  Gitlab::Dangerfiles.for_project(self) do |dangerfiles|
136
+ dangerfiles.import_plugins
133
137
  dangerfiles.import_dangerfiles(only: %w[simple_roulette])
134
138
  end
135
139
  ```
@@ -17,6 +17,7 @@ module Danger
17
17
  none: "",
18
18
  qa: "~QA",
19
19
  ux: "~UX",
20
+ codeowners: '~"Code Owners"',
20
21
  test: "~test for `spec/features/*`",
21
22
  # Deprecated as of 2.3.0 in favor of tooling
22
23
  engineering_productivity: '~"Engineering Productivity" for CI, Danger',
@@ -26,6 +27,7 @@ module Danger
26
27
  integrations_be: '~"group::integrations" (backend)',
27
28
  integrations_fe: '~"group::integrations" (frontend)',
28
29
  "Authentication and Authorization": '~"group::authentication and authorization"',
30
+ Compliance: '~"group::compliance"',
29
31
  }.freeze
30
32
 
31
33
  # Allows to set specific rule's configuration by passing a block.
@@ -234,7 +236,13 @@ module Danger
234
236
  # @return [String] the GFM for a category label, making its best guess if it's not
235
237
  # a category we know about.
236
238
  def label_for_category(category)
237
- CATEGORY_LABELS.fetch(category, %Q{~"#{category}"})
239
+ CATEGORY_LABELS[category] ||
240
+
241
+ if category.start_with?("`")
242
+ category.to_s
243
+ else
244
+ %Q{~"#{category}"}
245
+ end
238
246
  end
239
247
 
240
248
  # @return [String] +""+ when not in the CI context, and the MR Source Project ID as a string otherwise.
@@ -20,7 +20,13 @@ module Danger
20
20
 
21
21
  Approval = Struct.new(:category, :spin) do
22
22
  def self.from_approval_rule(rule, maintainer)
23
- category = rule["section"].to_sym
23
+ category =
24
+ if rule["section"] == "codeowners"
25
+ "`#{rule["name"]}`"
26
+ else
27
+ rule["section"]
28
+ end.to_sym
29
+
24
30
  spin = Spin.new(category, nil, maintainer, :reviewer)
25
31
 
26
32
  new(category, spin)
@@ -14,6 +14,7 @@ module Gitlab
14
14
  {
15
15
  subject_too_short: "The %s must contain at least #{MIN_SUBJECT_WORDS_COUNT} words",
16
16
  subject_too_long: "The %s may not be longer than #{MAX_LINE_LENGTH} characters",
17
+ subject_starts_with_a_space: "The %s must not start with a space",
17
18
  subject_starts_with_lowercase: "The %s must start with a capital letter",
18
19
  subject_ends_with_a_period: "The %s must not end with a period",
19
20
  }
@@ -49,6 +50,10 @@ module Gitlab
49
50
  add_problem(:subject_too_long, self.class.subject_description)
50
51
  end
51
52
 
53
+ if subject_starts_with_a_space?
54
+ add_problem(:subject_starts_with_a_space, self.class.subject_description)
55
+ end
56
+
52
57
  if subject_starts_with_lowercase?
53
58
  add_problem(:subject_starts_with_lowercase, self.class.subject_description)
54
59
  end
@@ -78,8 +83,13 @@ module Gitlab
78
83
  line.length > MAX_LINE_LENGTH
79
84
  end
80
85
 
86
+ def subject_starts_with_a_space?
87
+ subject.start_with?(" ")
88
+ end
89
+
81
90
  def subject_starts_with_lowercase?
82
91
  return false if subject.empty?
92
+ return false if subject_starts_with_a_space?
83
93
  return false if ("A".."Z").cover?(subject[0])
84
94
 
85
95
  first_char = subject.sub(/\A(\[[^\]]+\]|[^:\s]+:)\s/, "")[0]
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module Dangerfiles
5
+ CategoryStruct = Struct.new(:name, :project, :kind, :labels, keyword_init: true)
6
+
7
+ class Category < CategoryStruct
8
+ def self.for(name, **arguments)
9
+ (name_to_class[name] || self).new(name: name, **arguments)
10
+ end
11
+
12
+ def self.name_to_class
13
+ @name_to_class ||= {
14
+ test: Test,
15
+ tooling: Tooling,
16
+ integrations_be: IntegrationsBE,
17
+ integrations_fe: IntegrationsFE,
18
+ ux: UX,
19
+ }.freeze
20
+ end
21
+ private_class_method :name_to_class
22
+
23
+ def has_capability?(...)
24
+ has_particular_capability?(...) || has_universal_capability?(...)
25
+ end
26
+
27
+ private
28
+
29
+ def has_particular_capability?(teammate)
30
+ teammate.capabilities(project).include?(capability)
31
+ end
32
+
33
+ def has_universal_capability?(teammate)
34
+ false
35
+ end
36
+
37
+ def capability
38
+ # name can be nil
39
+ @capability ||= "#{kind} #{name}".strip
40
+ end
41
+
42
+ class Test < Category
43
+ private
44
+
45
+ def has_particular_capability?(teammate)
46
+ return false if kind != :reviewer
47
+
48
+ area = teammate.role[/Software Engineer in Test(?:.*?, (\w+))/, 1]
49
+
50
+ area && labels.any?("devops::#{area.downcase}")
51
+ end
52
+ end
53
+
54
+ class Tooling < Category
55
+ private
56
+
57
+ def has_particular_capability?(teammate)
58
+ if super
59
+ true
60
+ elsif %i[trainee_maintainer maintainer].include?(kind)
61
+ false
62
+ else # fallback to backend reviewer
63
+ teammate.capabilities(project).include?("#{kind} backend")
64
+ end
65
+ end
66
+ end
67
+
68
+ class IntegrationsBE < Category
69
+ private
70
+
71
+ def has_particular_capability?(teammate)
72
+ kind == :reviewer &&
73
+ teammate.role.match?(/Backend Engineer.+Manage:Integrations/)
74
+ end
75
+ end
76
+
77
+ class IntegrationsFE < Category
78
+ private
79
+
80
+ def has_particular_capability?(teammate)
81
+ kind == :reviewer &&
82
+ teammate.role.match?(/Frontend Engineer.+Manage:Integrations/)
83
+ end
84
+ end
85
+
86
+ class UX < Category
87
+ private
88
+
89
+ def has_universal_capability?(teammate)
90
+ teammate.projects.each_value.find do |capabilities|
91
+ capabilities.include?(capability)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "category"
4
+
3
5
  module Gitlab
4
6
  module Dangerfiles
5
7
  class Teammate
6
- attr_reader :options, :username, :name, :role, :projects, :available, :hungry, :reduced_capacity, :tz_offset_hours
8
+ attr_reader :options, :username, :name, :role, :projects, :available, :hungry, :reduced_capacity, :tz_offset_hours,
9
+ :only_maintainer_reviews
7
10
 
8
11
  # The options data are produced by https://gitlab.com/gitlab-org/gitlab-roulette/-/blob/master/lib/team_member.rb
9
12
  def initialize(options = {})
@@ -18,6 +21,7 @@ module Gitlab
18
21
  @hungry = options["hungry"]
19
22
  @reduced_capacity = options["reduced_capacity"]
20
23
  @tz_offset_hours = options["tz_offset_hours"]
24
+ @only_maintainer_reviews = options["only_maintainer_reviews"]
21
25
  end
22
26
 
23
27
  def to_h
@@ -74,6 +78,10 @@ module Gitlab
74
78
  (Time.now.utc + tz_offset_hours * 3600).hour
75
79
  end
76
80
 
81
+ def capabilities(project)
82
+ projects.fetch(project, [])
83
+ end
84
+
77
85
  protected
78
86
 
79
87
  def floored_offset_hours
@@ -123,42 +131,7 @@ module Gitlab
123
131
  end
124
132
 
125
133
  def has_capability?(project, category, kind, labels)
126
- case category
127
- when :test
128
- area = role[/Software Engineer in Test(?:.*?, (\w+))/, 1]
129
-
130
- area && labels.any?("devops::#{area.downcase}") if kind == :reviewer
131
- when :tooling, :engineering_productivity # Deprecated as of 2.3.0 in favor of tooling
132
- return true if capabilities(project).include?("#{kind} #{category}")
133
- return false if %i[trainee_maintainer maintainer].include?(kind)
134
-
135
- capabilities(project).include?("#{kind} backend") # fallback to backend reviewer
136
- when :integrations_be
137
- kind == :reviewer &&
138
- role.match?(/Backend Engineer.+Ecosystem:Integrations/)
139
- when :integrations_fe
140
- kind == :reviewer &&
141
- role.match?(/Frontend Engineer.+Ecosystem:Integrations/)
142
- when nil
143
- capabilities(project).include?("#{kind}")
144
- else
145
- capabilities(project).include?("#{kind} #{category}")
146
- end || has_universal_capability?(category, kind, labels)
147
- end
148
-
149
- def has_universal_capability?(category, kind, labels)
150
- case category
151
- when :ux
152
- capacity = "#{kind} #{category}"
153
-
154
- projects.each_value.find do |capabilities|
155
- capabilities.include?(capacity)
156
- end
157
- end
158
- end
159
-
160
- def capabilities(project)
161
- projects.fetch(project, [])
134
+ Category.for(category, project: project, kind: kind, labels: labels).has_capability?(self)
162
135
  end
163
136
 
164
137
  def pluralize(count, singular, plural)
@@ -1,5 +1,5 @@
1
1
  module Gitlab
2
2
  module Dangerfiles
3
- VERSION = "3.6.0"
3
+ VERSION = "3.6.4"
4
4
  end
5
5
  end
@@ -33,6 +33,7 @@ module Gitlab
33
33
  # https://gitlab.com/gitlab-org/gitlab/issues/26723
34
34
 
35
35
  remove_traintainers_from_reviewers!
36
+ remove_maintainer_only_from_reviewers!
36
37
 
37
38
  weighted_reviewers + weighted_traintainers
38
39
  end
@@ -49,6 +50,11 @@ module Gitlab
49
50
  reviewers.reject! { |reviewer| traintainers.include?(reviewer) }
50
51
  end
51
52
 
53
+ def remove_maintainer_only_from_reviewers!
54
+ # Using a maintainer-only reviewer emoji, team members can ensure they only get maintainer reviews
55
+ reviewers.reject! { |reviewer| reviewer&.only_maintainer_reviews }
56
+ end
57
+
52
58
  def weighted_reviewers
53
59
  reviewers.each_with_object([]) do |reviewer, total_reviewers|
54
60
  add_weighted_reviewer(total_reviewers, reviewer, DEFAULT_REVIEWER_WEIGHT)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-dangerfiles
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0
4
+ version: 3.6.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-10-17 00:00:00.000000000 Z
11
+ date: 2022-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -183,6 +183,7 @@ files:
183
183
  - lib/gitlab/Dangerfile
184
184
  - lib/gitlab/dangerfiles.rb
185
185
  - lib/gitlab/dangerfiles/base_linter.rb
186
+ - lib/gitlab/dangerfiles/category.rb
186
187
  - lib/gitlab/dangerfiles/changes.rb
187
188
  - lib/gitlab/dangerfiles/commit_linter.rb
188
189
  - lib/gitlab/dangerfiles/config.rb