gitlab_quality-test_tooling 1.32.0 → 1.33.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f3c72dad2be7e5a1e112667f8239dff242bac1d69298fd5bf664745c707d26ba
4
- data.tar.gz: 2261f70832512fd425cc4f49316f3a0a2e5211b4a0d83d5149ae72cb9d899cb2
3
+ metadata.gz: 19bea0cdd5a0f100cec11b00c6415c39f8ab637165f67171ad6edac7c33128b9
4
+ data.tar.gz: 9727a96a8ca06238ae89bacdb6f3cc88b66451a6190cac8df48fc82102e7c155
5
5
  SHA512:
6
- metadata.gz: '0395ec1d6abafc42099e47d961c468690265996fd903c1c105742735122aeef300baf27597163ccd510dc61d33721fa92180a72990881144f6a9a017a7a5d616'
7
- data.tar.gz: 7b179fbba4870967780b53fc68b98f0f237bcc0c5595d9b68c37e5976b3964f286aeb480d321ff4e5daa1b8456881f1f49e3d72fb929809bc175ace04d70437e
6
+ metadata.gz: 5dfdfea69e7e2f3500b243d83489050e6d0f2a251a1657a43250206a3710c0b848bdbb38ac34e645a2ec1dc4fc19ce4df47afa21a8c038754ac76f6b606cb14f
7
+ data.tar.gz: 7aa7942d0f0f86c75a2f07eea937c70c9f725b4025302778176e0fb0b9a14db41acd983d1202f86b6a59ce6f00b1c6f85ba214d86deb1a947167a57ff82ad3a4
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab_quality-test_tooling (1.32.0)
4
+ gitlab_quality-test_tooling (1.33.0)
5
5
  activesupport (>= 7.0, < 7.2)
6
6
  amatch (~> 0.4.1)
7
7
  gitlab (~> 4.19)
@@ -4,19 +4,39 @@ module GitlabQuality
4
4
  module TestTooling
5
5
  module KnapsackReports
6
6
  class SpecRunTime
7
- attr_reader :project, :file, :expected, :actual, :expected_suite_duration, :actual_suite_duration
7
+ attr_reader :file, :expected, :actual, :expected_suite_duration, :actual_suite_duration, :project, :ref
8
8
 
9
9
  ACTUAL_TO_EXPECTED_SPEC_RUN_TIME_RATIO_THRESHOLD = 1.5 # actual run time is longer than expected by 50% +
10
10
  SPEC_WEIGHT_PERCENTAGE_TRESHOLD = 15 # a spec file takes 15%+ of the total test suite run time
11
11
  SUITE_DURATION_THRESHOLD = 70 * 60 # if test suite takes more than 70 minutes, job risks timing out
12
-
13
- def initialize(project:, file:, expected:, actual:, expected_suite_duration:, actual_suite_duration:)
14
- @project = project
12
+ FEATURE_CATEGORY_METADATA_REGEX = /(?<=feature_category: :)(?<feature_category>\w+)/
13
+
14
+ def initialize(
15
+ file:,
16
+ expected:,
17
+ actual:,
18
+ expected_suite_duration:,
19
+ actual_suite_duration:,
20
+ token: '',
21
+ project: Runtime::Env.ci_project_path,
22
+ ref: Runtime::Env.ci_commit_ref_name)
15
23
  @file = file
16
24
  @expected = expected.to_f
17
25
  @actual = actual.to_f
18
26
  @expected_suite_duration = expected_suite_duration.to_f
19
27
  @actual_suite_duration = actual_suite_duration.to_f
28
+ @token = token
29
+ @project = project
30
+ @ref = ref
31
+ end
32
+
33
+ def feature_category
34
+ file_lines.each do |line|
35
+ match = FEATURE_CATEGORY_METADATA_REGEX.match(line)
36
+ next unless match
37
+
38
+ break match[:feature_category]
39
+ end
20
40
  end
21
41
 
22
42
  def should_report?
@@ -50,6 +70,8 @@ module GitlabQuality
50
70
 
51
71
  private
52
72
 
73
+ attr_reader :token
74
+
53
75
  def exceed_actual_to_expected_ratio_threshold?
54
76
  actual / expected >= ACTUAL_TO_EXPECTED_SPEC_RUN_TIME_RATIO_THRESHOLD
55
77
  end
@@ -80,6 +102,18 @@ module GitlabQuality
80
102
  def file_link
81
103
  "https://gitlab.com/#{project}/-/blob/#{Runtime::Env.ci_commit_ref_name}/#{file}"
82
104
  end
105
+
106
+ def file_lines
107
+ files_client.file_contents.lines(chomp: true)
108
+ end
109
+
110
+ def files_client
111
+ @files_client ||= GitlabClient::RepositoryFilesClient.new(
112
+ token: token,
113
+ project: project,
114
+ file_path: file,
115
+ ref: ref)
116
+ end
83
117
  end
84
118
  end
85
119
  end
@@ -8,10 +8,11 @@ module GitlabQuality
8
8
  class SpecRunTimeReport
9
9
  attr_reader :project, :expected_report, :actual_report
10
10
 
11
- def initialize(project:, expected_report_path:, actual_report_path:)
11
+ def initialize(project:, expected_report_path:, actual_report_path:, token: '')
12
12
  @project = project
13
13
  @expected_report = parse(expected_report_path)
14
14
  @actual_report = parse(actual_report_path)
15
+ @token = token
15
16
  end
16
17
 
17
18
  def filtered_report
@@ -25,6 +26,7 @@ module GitlabQuality
25
26
  end
26
27
 
27
28
  spec_run_time = SpecRunTime.new(
29
+ token: token,
28
30
  project: project,
29
31
  file: spec_file,
30
32
  expected: expected_run_time,
@@ -39,6 +41,8 @@ module GitlabQuality
39
41
 
40
42
  private
41
43
 
44
+ attr_reader :token
45
+
42
46
  def parse(report_path)
43
47
  JSON.parse(File.read(report_path))
44
48
  end
@@ -10,7 +10,6 @@ module GitlabQuality
10
10
  WWW_GITLAB_COM_SITE = 'https://about.gitlab.com'
11
11
  WWW_GITLAB_COM_GROUPS_JSON = "#{WWW_GITLAB_COM_SITE}/groups.json".freeze
12
12
  WWW_GITLAB_COM_CATEGORIES_JSON = "#{WWW_GITLAB_COM_SITE}/categories.json".freeze
13
- FEATURE_CATEGORY_METADATA_REGEX = /(?<=feature_category: :)\w+/
14
13
 
15
14
  def infer_labels_from_product_group(product_group)
16
15
  [groups_mapping.dig(product_group, 'label')].compact.to_set
@@ -10,11 +10,14 @@ module GitlabQuality
10
10
  end
11
11
 
12
12
  def new_issue_labels(test)
13
- puts " => [DEBUG] product_group: #{test.product_group}; feature_category: #{test.feature_category}"
13
+ debug_line = ' => [DEBUG] '
14
+ debug_line += "product_group: #{test&.product_group}; " if test.respond_to?(:product_group)
15
+ debug_line += "feature_category: #{test&.feature_category}" if test.respond_to?(:feature_category)
16
+ puts debug_line
14
17
 
15
- new_labels = self.class::NEW_ISSUE_LABELS +
16
- labels_inference.infer_labels_from_product_group(test.product_group) +
17
- labels_inference.infer_labels_from_feature_category(test.feature_category)
18
+ new_labels = self.class::NEW_ISSUE_LABELS
19
+ new_labels += labels_inference.infer_labels_from_product_group(test.product_group) if test.respond_to?(:product_group)
20
+ new_labels += labels_inference.infer_labels_from_feature_category(test.feature_category) if test.respond_to?(:feature_category)
18
21
  up_to_date_labels(test: test, new_labels: new_labels)
19
22
  end
20
23
  end
@@ -14,6 +14,8 @@ module GitlabQuality
14
14
  # - If not found:
15
15
  # - Create a new issue with the run time data
16
16
  class KnapsackReportIssue < ReportAsIssue
17
+ include Concerns::GroupAndCategoryLabels
18
+
17
19
  NEW_ISSUE_LABELS = Set.new(['test', 'type::maintenance', 'maintenance::performance', 'priority::3', 'severity::3', 'knapsack_report']).freeze
18
20
  SEARCH_LABELS = %w[test maintenance::performance knapsack_report].freeze
19
21
  JOB_TIMEOUT_EPIC_URL = 'https://gitlab.com/groups/gitlab-org/quality/engineering-productivity/-/epics/19'
@@ -36,6 +38,7 @@ module GitlabQuality
36
38
 
37
39
  def search_and_create_issue
38
40
  filtered_report = KnapsackReports::SpecRunTimeReport.new(
41
+ token: token,
39
42
  project: project,
40
43
  expected_report_path: expected_report_path,
41
44
  actual_report_path: actual_report_path
@@ -67,10 +70,6 @@ module GitlabQuality
67
70
  files.first
68
71
  end
69
72
 
70
- def new_issue_labels(_spec_run_time)
71
- NEW_ISSUE_LABELS
72
- end
73
-
74
73
  def new_issue_title(spec_run_time)
75
74
  "Job timeout risk: #{spec_run_time.file} ran much longer than expected"
76
75
  end
@@ -124,12 +124,12 @@ module GitlabQuality
124
124
  issue_attrs = {}
125
125
 
126
126
  new_description = new_issue_description(test)
127
- issue_attrs[:description] = new_description unless issue.description == new_description
127
+ issue_attrs[:description] = new_description if issue.description != new_description
128
128
 
129
129
  new_labels = up_to_date_labels(test: test, issue: issue).to_a
130
- issue_attrs[:labels] = new_labels unless issue.labels == new_labels
130
+ issue_attrs[:add_labels] = new_labels if (new_labels - issue.labels).any?
131
131
 
132
- gitlab.edit_issue(iid: issue.iid, options: issue_attrs) unless issue_attrs.empty?
132
+ gitlab.edit_issue(iid: issue.iid, options: issue_attrs) if issue_attrs.any?
133
133
  end
134
134
 
135
135
  def issue_labels(issue)
@@ -149,14 +149,14 @@ module GitlabQuality
149
149
  labels |= new_labels.to_set
150
150
  ee_test?(test) ? labels << 'Enterprise Edition' : labels.delete('Enterprise Edition')
151
151
 
152
- if test.quarantine?
152
+ if test.respond_to?(:quarantine?) && test.quarantine?
153
153
  labels << 'quarantine'
154
154
  labels << "quarantine::#{test.quarantine_type}"
155
155
  else
156
156
  labels.delete_if { |label| label.include?('quarantine') }
157
157
  end
158
158
 
159
- labels << 'rspec-shared-examples' if test.calls_shared_examples?
159
+ labels << 'rspec-shared-examples' if test.respond_to?(:calls_shared_examples?) && test.calls_shared_examples?
160
160
 
161
161
  labels
162
162
  end
@@ -44,11 +44,11 @@ module GitlabQuality
44
44
 
45
45
  def health_problem_status_label_quick_action(reports_list)
46
46
  case reports_list.reports_count
47
- when 40..Float::INFINITY
47
+ when 6099..Float::INFINITY
48
48
  '/label ~"slowness::1"'
49
- when 28..39
49
+ when 2177..6098
50
50
  '/label ~"slowness::2"'
51
- when 12..27
51
+ when 521..2176
52
52
  '/label ~"slowness::3"'
53
53
  else
54
54
  '/label ~"slowness::4"'
@@ -32,10 +32,6 @@ module GitlabQuality
32
32
  raise NotImplementedError
33
33
  end
34
34
 
35
- def line_number
36
- raise NotImplementedError
37
- end
38
-
39
35
  def section
40
36
  raise NotImplementedError
41
37
  end
@@ -52,10 +48,53 @@ module GitlabQuality
52
48
  raise NotImplementedError
53
49
  end
54
50
 
51
+ def product_group
52
+ report['product_group'].to_s
53
+ end
54
+
55
+ def feature_category
56
+ report['feature_category']
57
+ end
58
+
55
59
  def failures?
56
60
  failures.any?
57
61
  end
58
62
 
63
+ def product_group?
64
+ product_group != ''
65
+ end
66
+
67
+ def failure_issue
68
+ report['failure_issue']
69
+ end
70
+
71
+ def failure_issue=(new_failure_issue)
72
+ report['failure_issue'] = new_failure_issue
73
+ end
74
+
75
+ def line_number
76
+ report['line_number']
77
+ end
78
+
79
+ def level
80
+ report['level']
81
+ end
82
+
83
+ def run_time
84
+ report['run_time'].to_f.round(2)
85
+ end
86
+
87
+ def screenshot?
88
+ !!screenshot
89
+ end
90
+
91
+ def quarantine?
92
+ # The value for 'quarantine' could be nil, a hash, a string,
93
+ # or true (if the test just has the :quarantine tag)
94
+ # But any non-nil or false value should means the test is in quarantine
95
+ !!quarantine
96
+ end
97
+
59
98
  def file
60
99
  @file ||= relative_file.start_with?('qa/') ? "qa/#{relative_file}" : relative_file
61
100
  end
@@ -98,6 +137,14 @@ module GitlabQuality
98
137
  private
99
138
 
100
139
  attr_reader :token, :project, :ref
140
+
141
+ def screenshot
142
+ report.fetch('screenshot', nil)
143
+ end
144
+
145
+ def quarantine
146
+ report.fetch('quarantine', nil)
147
+ end
101
148
  end
102
149
  end
103
150
  end
@@ -40,64 +40,13 @@ module GitlabQuality
40
40
  end
41
41
  end
42
42
 
43
- def quarantine
44
- !report['quarantine'].nil?
45
- end
46
-
47
- def quarantine?
48
- # The value for 'quarantine' could be nil, a hash, a string,
49
- # or true (if the test just has the :quarantine tag)
50
- # But any non-nil or false value should means the test is in quarantine
51
- !!quarantine
52
- end
53
-
54
- def line_number
55
- report['line_number']
56
- end
57
-
58
- def level
59
- report['level']
60
- end
61
-
62
- def run_time
63
- report['run_time'].to_f.round(2)
64
- end
65
-
66
- def screenshot
67
- report['screenshot']
68
- end
69
-
70
- def screenshot?
71
- !!screenshot
72
- end
73
-
74
43
  def max_duration_for_test
75
- ""
44
+ ''
76
45
  end
77
46
 
78
47
  def ci_job_url
79
48
  ENV.fetch('CI_JOB_URL', '')
80
49
  end
81
-
82
- def product_group
83
- report['product_group'].to_s
84
- end
85
-
86
- def product_group?
87
- product_group != ''
88
- end
89
-
90
- def feature_category
91
- report['feature_category']
92
- end
93
-
94
- def failure_issue
95
- report['failure_issue']
96
- end
97
-
98
- def failure_issue=(new_failure_issue)
99
- report['failure_issue'] = new_failure_issue
100
- end
101
50
  end
102
51
  end
103
52
  end
@@ -68,21 +68,6 @@ module GitlabQuality
68
68
  report['testcase'] = new_testcase
69
69
  end
70
70
 
71
- def failure_issue
72
- report['failure_issue']
73
- end
74
-
75
- def failure_issue=(new_failure_issue)
76
- report['failure_issue'] = new_failure_issue
77
- end
78
-
79
- def quarantine?
80
- # The value for 'quarantine' could be nil, a hash, a string,
81
- # or true (if the test just has the :quarantine tag)
82
- # But any non-nil or false value should means the test is in quarantine
83
- !!quarantine
84
- end
85
-
86
71
  def quarantine_type
87
72
  quarantine['type'] if quarantine?
88
73
  end
@@ -91,26 +76,10 @@ module GitlabQuality
91
76
  quarantine['issue'] if quarantine?
92
77
  end
93
78
 
94
- def screenshot?
95
- !!screenshot
96
- end
97
-
98
79
  def screenshot_image
99
80
  screenshot['image'] if screenshot?
100
81
  end
101
82
 
102
- def product_group
103
- report['product_group'].to_s
104
- end
105
-
106
- def product_group?
107
- product_group != ''
108
- end
109
-
110
- def feature_category
111
- report['feature_category']
112
- end
113
-
114
83
  def section
115
84
  report['section']
116
85
  end
@@ -119,22 +88,10 @@ module GitlabQuality
119
88
  report['category']
120
89
  end
121
90
 
122
- def run_time
123
- report['run_time'].to_f.round(2)
124
- end
125
-
126
91
  def example_id
127
92
  report['id']
128
93
  end
129
94
 
130
- def line_number
131
- report['line_number']
132
- end
133
-
134
- def level
135
- report['level']
136
- end
137
-
138
95
  def ci_job_id
139
96
  report['ci_job_url'].split('/').last
140
97
  end
@@ -180,14 +137,6 @@ module GitlabQuality
180
137
 
181
138
  private
182
139
 
183
- def quarantine
184
- report.fetch('quarantine', nil)
185
- end
186
-
187
- def screenshot
188
- report.fetch('screenshot', nil)
189
- end
190
-
191
140
  def format_message_lines(message_lines)
192
141
  message_lines.is_a?(Array) ? message_lines.join("\n") : message_lines
193
142
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GitlabQuality
4
4
  module TestTooling
5
- VERSION = "1.32.0"
5
+ VERSION = "1.33.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab_quality-test_tooling
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.32.0
4
+ version: 1.33.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab Quality
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-07-19 00:00:00.000000000 Z
11
+ date: 2024-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control