gitlab_quality-test_tooling 1.27.0 → 1.28.0

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: a5b3317b1df5c3f923259fb0dbb71e9cfdf9b4e32f9338b2189758538aaacb30
4
- data.tar.gz: 60fda58d2a830e1849c8175347050cb81f62658a20e1ee4c9bdde2cb3049d965
3
+ metadata.gz: 274b4abf8943ea35b4bfae544d82981cba229feb7864e6f8d5c3b0ccda8bbc24
4
+ data.tar.gz: 6cb2d671d4fa654b9744c289d8f2ead55d65c340b1fd7abb83fbf6cfae03522a
5
5
  SHA512:
6
- metadata.gz: 0c70f1860b051ccd633aae6cb58298a90edecdd8a93a598e76f90ac8b2a337f755d77e30fa8b1dd6bcd3df7473c9af31c8a6e46509b59a5047d1be03a4bb2910
7
- data.tar.gz: 1ae2fbf63375f49d43ef28cb5a5ec44af6940a5ffd46b43a07c07855085449994858bc49b4ca61c0cd73737c7d4960de9f5f092019681668ad339326f069c741
6
+ metadata.gz: 97e948985110b8742c7584e1526801a43c0cd99d8f14932329f8c34e2c0ed30c6994fb8681e3b68f6d10c9c71387d2aa9f597b2b006eefdf9d2d1c29d13ba138
7
+ data.tar.gz: 254cb3965e8b0a3e7f0596c8268c87871fbf20611a6627ef06c0cba44c268f643c7eeb74543852e3f435813443309c7c8f0e68cce210fe499cfb72991dcd44b5
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab_quality-test_tooling (1.27.0)
5
- activesupport (~> 7.1)
4
+ gitlab_quality-test_tooling (1.28.0)
5
+ activesupport (>= 7.0, < 7.2)
6
6
  amatch (~> 0.4.1)
7
7
  gitlab (~> 4.19)
8
8
  http (~> 5.0)
@@ -330,4 +330,4 @@ DEPENDENCIES
330
330
  webmock (= 3.7.0)
331
331
 
332
332
  BUNDLED WITH
333
- 2.5.4
333
+ 2.5.6
@@ -9,8 +9,9 @@ module GitlabQuality
9
9
  module IssueReports
10
10
  JOB_URL_REGEX = %r{(?<job_url>https://(?<host>[\w.]+)/(?<project_path>[\w\-./]+)/-/jobs/\d+)}
11
11
  FAILED_JOB_DESCRIPTION_REGEX = /First happened in #{JOB_URL_REGEX}\./m
12
- REPORT_ITEM_REGEX = /^1\. \d{4}-\d{2}-\d{2}: #{JOB_URL_REGEX} \((?<pipeline_url>\S+)\)/
12
+ REPORT_ITEM_REGEX = /^1\. (?<report_date>\d{4}-\d{2}-\d{2}): #{JOB_URL_REGEX} \((?<pipeline_url>\S+)\) ?(?<extra_content>.*)$/
13
13
  LATEST_REPORTS_TO_SHOW = 10
14
+ DAILY_REPORTS_THRESHOLDS = 10
14
15
 
15
16
  class ReportsList
16
17
  def initialize(preserved_content:, section_header:, reports:, extra_content:)
@@ -21,7 +22,12 @@ module GitlabQuality
21
22
  end
22
23
 
23
24
  def self.report_list_item(test, item_extra_content: nil)
24
- "1. #{Time.new.utc.strftime('%F')}: #{test.ci_job_url} (#{ENV.fetch('CI_PIPELINE_URL', 'pipeline url is missing')}) #{item_extra_content}".strip
25
+ ReportListItem.new(job_url: test.ci_job_url, extra_content: item_extra_content)
26
+ end
27
+
28
+ def self.parse_report_date_from_string(date_string)
29
+ parsed_time = Time.strptime(date_string, '%F')
30
+ Time.utc(parsed_time.year, parsed_time.month, parsed_time.day)
25
31
  end
26
32
 
27
33
  def reports_count
@@ -32,21 +38,27 @@ module GitlabQuality
32
38
  [
33
39
  preserved_content,
34
40
  "#{section_header} (#{reports_count})",
35
- reports_list(reports),
41
+ reports_list,
36
42
  extra_content
37
43
  ].reject(&:blank?).compact.join("\n\n")
38
44
  end
39
45
 
46
+ def spiked_in_short_period?
47
+ latest_report = sorted_reports.first
48
+
49
+ reports_for_latest_report_day = sorted_reports.count { |report| report.report_date == latest_report.report_date }
50
+
51
+ reports_for_latest_report_day >= DAILY_REPORTS_THRESHOLDS
52
+ end
53
+
40
54
  private
41
55
 
42
56
  attr_reader :preserved_content, :section_header, :reports, :extra_content
43
57
 
44
- def reports_list(reports)
45
- sorted_reports = reports.sort.reverse
46
-
58
+ def reports_list
47
59
  if sorted_reports.size > LATEST_REPORTS_TO_SHOW
48
60
  [
49
- "Last 10 reports:",
61
+ "Last #{LATEST_REPORTS_TO_SHOW} reports:",
50
62
  sorted_reports[...LATEST_REPORTS_TO_SHOW].join("\n"),
51
63
  "<details><summary>See #{sorted_reports.size - LATEST_REPORTS_TO_SHOW} more reports</summary>",
52
64
  sorted_reports[LATEST_REPORTS_TO_SHOW..].join("\n"),
@@ -56,6 +68,41 @@ module GitlabQuality
56
68
  sorted_reports.join("\n")
57
69
  end
58
70
  end
71
+
72
+ def sorted_reports
73
+ @sorted_reports ||= reports.sort.reverse
74
+ end
75
+ end
76
+
77
+ class ReportListItem
78
+ attr_reader :report_date
79
+
80
+ def initialize(job_url:, report_date: now, pipeline_url: default_pipeline_url, extra_content: '')
81
+ @job_url = job_url
82
+ @report_date = report_date
83
+ @pipeline_url = pipeline_url
84
+ @extra_content = extra_content
85
+ end
86
+
87
+ def to_s
88
+ "1. #{report_date}: #{job_url} (#{pipeline_url}) #{extra_content}".strip
89
+ end
90
+
91
+ def <=>(other)
92
+ to_s <=> other.to_s
93
+ end
94
+
95
+ private
96
+
97
+ attr_reader :job_url, :pipeline_url, :extra_content
98
+
99
+ def default_pipeline_url
100
+ ENV.fetch('CI_PIPELINE_URL', 'pipeline url is missing')
101
+ end
102
+
103
+ def now
104
+ Time.new.utc.strftime('%F')
105
+ end
59
106
  end
60
107
 
61
108
  def initial_reports_section(test)
@@ -98,7 +145,13 @@ module GitlabQuality
98
145
  private
99
146
 
100
147
  def report_lines(content)
101
- content.lines.grep(REPORT_ITEM_REGEX).map(&:strip)
148
+ content.lines.filter_map do |line|
149
+ match = line.match(REPORT_ITEM_REGEX)
150
+ next unless match
151
+
152
+ match_data_hash = match.named_captures.transform_keys(&:to_sym)
153
+ ReportListItem.new(**match_data_hash.slice(:job_url, :report_date, :pipeline_url, :extra_content))
154
+ end
102
155
  end
103
156
 
104
157
  def job_urls_from_description(issue_description, regex)
@@ -94,7 +94,7 @@ module GitlabQuality
94
94
 
95
95
  note_body = [
96
96
  new_reports_list.to_s,
97
- identity_labels_quick_action,
97
+ labels_quick_action(new_reports_list),
98
98
  relate_issues_quick_actions(related_issues)
99
99
  ].join("\n")
100
100
 
@@ -227,9 +227,16 @@ module GitlabQuality
227
227
  end
228
228
  end
229
229
 
230
- def identity_labels_quick_action
231
- labels_list = IDENTITY_LABELS.map { |label| %(~"#{label}") }.join(' ')
232
- %(/label #{labels_list})
230
+ def labels_quick_action(reports_list)
231
+ labels_to_apply = identity_labels
232
+
233
+ labels_to_apply.push('~"severity::1"') if reports_list.spiked_in_short_period?
234
+
235
+ %(/label #{labels_to_apply.join(' ')})
236
+ end
237
+
238
+ def identity_labels
239
+ IDENTITY_LABELS.map { |label| %(~"#{label}") }
233
240
  end
234
241
 
235
242
  def relate_issues_quick_actions(issues)
@@ -38,7 +38,11 @@ module GitlabQuality
38
38
  console_log = console_logger(source: source, level: Env.log_level)
39
39
  file_log = file_logger(source: source, path: log_path)
40
40
 
41
- ActiveSupport::BroadcastLogger.new(console_log, file_log, file_log)
41
+ if ActiveSupport.const_defined?(:BroadcastLogger) # only available in ActiveSupport >= 7.1.0
42
+ ActiveSupport::BroadcastLogger.new(console_log, file_log, file_log)
43
+ else
44
+ console_log.extend(ActiveSupport::Logger.broadcast(file_log))
45
+ end
42
46
  end
43
47
  end
44
48
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'time'
4
+
3
5
  module GitlabQuality
4
6
  module TestTooling
5
7
  module TestMetricsExporter
@@ -11,7 +13,7 @@ module GitlabQuality
11
13
  return @time if defined?(@time)
12
14
 
13
15
  created_at = Time.strptime(env('CI_PIPELINE_CREATED_AT'), '%Y-%m-%dT%H:%M:%S%z') if env('CI_PIPELINE_CREATED_AT')
14
- @time = (created_at || Time.now).utc.strftime('%Y-%m-%dT%H:%M:%S%z')
16
+ @time = Time.parse((created_at || Time.now).utc.strftime('%Y-%m-%d %H:%M:%S %z'))
15
17
  end
16
18
 
17
19
  # rubocop:disable Metrics/AbcSize
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GitlabQuality
4
4
  module TestTooling
5
- VERSION = "1.27.0"
5
+ VERSION = "1.28.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.27.0
4
+ version: 1.28.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-05-23 00:00:00.000000000 Z
11
+ date: 2024-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -196,16 +196,22 @@ dependencies:
196
196
  name: activesupport
197
197
  requirement: !ruby/object:Gem::Requirement
198
198
  requirements:
199
- - - "~>"
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '7.0'
202
+ - - "<"
200
203
  - !ruby/object:Gem::Version
201
- version: '7.1'
204
+ version: '7.2'
202
205
  type: :runtime
203
206
  prerelease: false
204
207
  version_requirements: !ruby/object:Gem::Requirement
205
208
  requirements:
206
- - - "~>"
209
+ - - ">="
210
+ - !ruby/object:Gem::Version
211
+ version: '7.0'
212
+ - - "<"
207
213
  - !ruby/object:Gem::Version
208
- version: '7.1'
214
+ version: '7.2'
209
215
  - !ruby/object:Gem::Dependency
210
216
  name: amatch
211
217
  requirement: !ruby/object:Gem::Requirement