gitlab_quality-test_tooling 1.7.0 → 1.8.1

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: 6924fc592c0dbb5e1ae0aed8710f7f7714c336bdd1d1d31b343e6edddd358ead
4
- data.tar.gz: 0ebb5fbe0aeff0417193d4521cf52a78d849b83d116e08118b9cf87ee2655a71
3
+ metadata.gz: 4c8eda4a61584293cfb2f20a4ece0c5afd8963be75c56c5c3a1f71cbbf04a2ed
4
+ data.tar.gz: 72ea08e5a2fac3b5d9f0d5dada3bb71c7b655acbd7c03f4533e0bbe951be954e
5
5
  SHA512:
6
- metadata.gz: f9a64cbae7e3a34ae66450ae7fe20181560dc6860950a92e53c5aaf61ab10343372044968b5a726bef51b082a45dd9150d6f161d93a45a4ccf75d550cf981be1
7
- data.tar.gz: a77ea69469a02b3cbd089cade6be20347abc03cada1cf93fec8380456f000d083a914296e0b35faff573e60d73e4759abd1b5d224cb04e64b38862fe720cf65c
6
+ metadata.gz: fe64d9f93ff1343c36d1d478f63e9a4614587897b6414ec3a1f4c28fdd90ee1d245134e9350f546373350acf1f1355dd50d31da162a899d096ceb1114029767e
7
+ data.tar.gz: d4dd2ba2714e54c766592734481f7ba373692375f4c2011578f1b22da36fae3b8d58e721677e47ba214805d3798737c5ad6dec7711d586a46727029e555fb72e
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab_quality-test_tooling (1.7.0)
4
+ gitlab_quality-test_tooling (1.8.1)
5
5
  activesupport (>= 6.1, < 7.2)
6
6
  amatch (~> 0.4.1)
7
7
  gitlab (~> 4.19)
data/README.md CHANGED
@@ -77,6 +77,8 @@ Usage: exe/prepare-stage-reports [options]
77
77
  Purpose: Relate test failures to failure issues from RSpec report files (JSON or JUnit XML)
78
78
  Usage: exe/relate-failure-issue [options]
79
79
  -i, --input-files INPUT_FILES RSpec report files (JSON or JUnit XML)
80
+ -m METRICS_FILES, Test metrics files (JSON)
81
+ --metrics-files
80
82
  --max-diff-ratio MAX_DIFF_RATO
81
83
  Max stacktrace diff ratio for failure issues detection
82
84
  -p, --project PROJECT Can be an integer or a group/project string
@@ -128,11 +130,13 @@ Usage: exe/update-screenshot-paths [options]
128
130
 
129
131
  ```shell
130
132
  Purpose: Create slow test issues from JSON RSpec report files
131
- Usage: exe/slow-test-issue [options]
133
+ Usage: exe/slow-test-issues [options]
132
134
  -i, --input-files INPUT_FILES JSON RSpec report files JSON
133
135
  -p, --project PROJECT Can be an integer or a group/project string
134
136
  -t, --token TOKEN A valid access token with `api` scope and Maintainer permission in PROJECT
135
- --dry-run Perform a dry-run (don't create note)
137
+ -r RELATED_ISSUES_FILE, The file path for the related issues
138
+ --related-issues-file
139
+ --dry-run Perform a dry-run (don't create issues)
136
140
  -v, --version Show the version
137
141
  -h, --help Show the usage
138
142
  ```
@@ -141,13 +145,13 @@ Usage: exe/slow-test-issue [options]
141
145
 
142
146
  ```shell
143
147
  Purpose: Purpose: Create flaky test issues for any passed test coming from rspec-retry JSON report files
144
- Usage: exe/flaky-test-issue [options]
148
+ Usage: exe/flaky-test-issues [options]
145
149
  -i, --input-files INPUT_FILES JSON rspec-retry report files
146
150
  -p, --project PROJECT Can be an integer or a group/project string
147
151
  -m MERGE_REQUEST_IID, An integer merge request IID
148
152
  --merge_request_iid
149
153
  -t, --token TOKEN A valid access token with `api` scope and Maintainer permission in PROJECT
150
- --dry-run Perform a dry-run (don't create note)
154
+ --dry-run Perform a dry-run (don't create issues)
151
155
  -v, --version Show the version
152
156
  -h, --help Show the usage
153
157
  ```
@@ -158,11 +162,11 @@ Usage: exe/flaky-test-issue [options]
158
162
  Purpose: Create slow test note on merge requests from JSON RSpec report files
159
163
  Usage: exe/slow-test-merge-request-report-note [options]
160
164
  -i, --input-files INPUT_FILES JSON RSpec report files JSON
161
- --project PROJECT Can be an integer or a group/project string
165
+ -p, --project PROJECT Can be an integer or a group/project string
162
166
  -m MERGE_REQUEST_IID, An integer merge request IID
163
167
  --merge_request_iid
164
168
  -t, --token TOKEN A valid access token with `api` scope and Maintainer permission in PROJECT
165
- --dry-run Perform a dry-run (don't create issues)
169
+ --dry-run Perform a dry-run (don't create note)
166
170
  -v, --version Show the version
167
171
  -h, --help Show the usage
168
172
  ```
@@ -15,6 +15,10 @@ options = OptionParser.new do |opts|
15
15
  params[:input_files] = input_files
16
16
  end
17
17
 
18
+ opts.on('-m', '--metrics-files METRICS_FILES', String, 'Test metrics files (JSON)') do |metrics_files|
19
+ params[:metrics_files] = metrics_files
20
+ end
21
+
18
22
  opts.on('--max-diff-ratio MAX_DIFF_RATO', Float, 'Max stacktrace diff ratio for failure issues detection') do |max_diff_ratio|
19
23
  params[:max_diff_ratio] = max_diff_ratio
20
24
  end
@@ -41,6 +41,7 @@ module GitlabQuality
41
41
  system_logs: [],
42
42
  base_issue_labels: nil,
43
43
  exclude_labels_for_search: nil,
44
+ metrics_files: [],
44
45
  **kwargs)
45
46
  super
46
47
  @max_diff_ratio = max_diff_ratio.to_f
@@ -49,11 +50,12 @@ module GitlabQuality
49
50
  @exclude_labels_for_search = Set.new(exclude_labels_for_search)
50
51
  @issue_type = 'issue'
51
52
  @commented_issue_list = Set.new
53
+ @metrics_files = Array(metrics_files)
52
54
  end
53
55
 
54
56
  private
55
57
 
56
- attr_reader :max_diff_ratio, :system_logs, :base_issue_labels, :exclude_labels_for_search
58
+ attr_reader :max_diff_ratio, :system_logs, :base_issue_labels, :exclude_labels_for_search, :metrics_files
57
59
 
58
60
  def run!
59
61
  puts "Reporting test failures in `#{files.join(',')}` as issues in project `#{project}` via the API at `#{Runtime::Env.gitlab_api_base}`."
@@ -66,16 +68,39 @@ module GitlabQuality
66
68
  write_issues_log_file
67
69
  end
68
70
 
71
+ def test_metric_collections
72
+ @test_metric_collections ||= Dir.glob(metrics_files).map do |path|
73
+ TestMetrics::JsonTestMetricCollection.new(path)
74
+ end
75
+ end
76
+
69
77
  def process_test_results(test_results)
70
78
  systemic_failures = systemic_failures_for_test_results(test_results)
71
79
 
72
80
  test_results.each do |test|
73
81
  collect_issues(test, relate_failure_to_issue(test)) if should_report?(test, systemic_failures)
82
+
83
+ copy_failure_issue_to_test_metrics(test) if metrics_files.any?
74
84
  end
75
85
 
76
86
  test_results.write
77
87
  end
78
88
 
89
+ def copy_failure_issue_to_test_metrics(test)
90
+ failure_issue = test.failure_issue
91
+
92
+ return unless failure_issue
93
+
94
+ test_metric_collections.find do |test_metric_collection|
95
+ test_metric = test_metric_collection.metric_for_test_id(test.example_id)
96
+
97
+ if test_metric
98
+ test_metric.fields['failure_issue'] = failure_issue
99
+ test_metric_collection.write
100
+ end
101
+ end
102
+ end
103
+
79
104
  def systemic_failures_for_test_results(test_results)
80
105
  test_results
81
106
  .flat_map { |test| test.failures.map { |failure| failure['message'].lines.first.chomp } }
@@ -142,9 +167,7 @@ module GitlabQuality
142
167
  def pipeline_issues_with_similar_stacktrace(test)
143
168
  search_labels = (base_issue_labels + Set.new(%w[test failure::new])).to_a
144
169
  not_labels = exclude_labels_for_search.to_a
145
- gitlab.find_issues(options: { labels: search_labels,
146
- not: { labels: not_labels },
147
- created_after: past_timestamp(2) }).select do |issue|
170
+ find_issues_created_after(past_timestamp(2), state: 'opened', labels: search_labels, not_labels: not_labels).select do |issue|
148
171
  job_url_from_issue = failed_issue_job_url(issue)
149
172
 
150
173
  next if pipeline != pipeline_env_from_job_url(job_url_from_issue)
@@ -171,6 +194,7 @@ module GitlabQuality
171
194
  def failure_issues(test)
172
195
  find_issues_for_test(
173
196
  test,
197
+ state: 'opened',
174
198
  labels: base_issue_labels + Set.new(%w[test]),
175
199
  not_labels: exclude_labels_for_search
176
200
  )
@@ -145,10 +145,19 @@ module GitlabQuality
145
145
  def find_issues_for_test(test, labels:, not_labels: Set.new, state: nil)
146
146
  search_options = { labels: labels.to_a, not: { labels: not_labels.to_a } }
147
147
  search_options[:state] = state if state
148
+ search_options[:search] = test.file.to_s.empty? ? test.name : partial_file_path(test.file)
149
+ search_options[:in] = 'title'
148
150
 
149
151
  gitlab.find_issues(options: search_options).find_all { |issue| issue_match_test?(issue, test) }
150
152
  end
151
153
 
154
+ def find_issues_created_after(timestamp, labels:, not_labels: Set.new, state: nil)
155
+ search_options = { labels: labels.to_a, not: { labels: not_labels.to_a }, created_after: timestamp }
156
+ search_options[:state] = state if state
157
+
158
+ gitlab.find_issues(options: search_options)
159
+ end
160
+
152
161
  def issue_match_test?(issue, test)
153
162
  issue_title = issue.title.strip
154
163
  test_file_path_found = !test.file.to_s.empty? && issue_title.include?(partial_file_path(test.file))
@@ -65,10 +65,18 @@ module GitlabQuality
65
65
  "1. #{Time.new.utc.strftime('%F')}: #{test.ci_job_url} (#{ENV.fetch('CI_PIPELINE_URL', 'pipeline url is missing')})"
66
66
  end
67
67
 
68
+ def slow_test_issues(test)
69
+ find_issues_for_test(
70
+ test,
71
+ state: 'opened',
72
+ labels: SEARCH_LABELS
73
+ )
74
+ end
75
+
68
76
  def create_slow_issue(test)
69
77
  puts " => Finding existing issues for slow test '#{test.name}' (run time: #{test.run_time} seconds)..."
70
78
 
71
- issues = find_issues_for_test(test, labels: SEARCH_LABELS, state: 'opened')
79
+ issues = slow_test_issues(test)
72
80
 
73
81
  if issues.blank?
74
82
  issues << create_issue(test)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitlabQuality
4
+ module TestTooling
5
+ module TestMetric
6
+ class JsonTestMetric
7
+ attr_reader :metric
8
+
9
+ def initialize(metric)
10
+ @metric = metric
11
+ end
12
+
13
+ def name
14
+ metric.fetch('name')
15
+ end
16
+
17
+ def time
18
+ metric.fetch('time')
19
+ end
20
+
21
+ def tags
22
+ @tags ||= metric.fetch('tags')
23
+ end
24
+
25
+ def fields
26
+ @fields ||= metric.fetch('fields')
27
+ end
28
+
29
+ def to_json(*options)
30
+ as_json.to_json(*options)
31
+ end
32
+
33
+ private
34
+
35
+ def as_json
36
+ {
37
+ name: name,
38
+ time: time,
39
+ tags: tags,
40
+ fields: fields
41
+ }
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module GitlabQuality
6
+ module TestTooling
7
+ module TestMetrics
8
+ class JsonTestMetricCollection
9
+ include Enumerable
10
+
11
+ attr_reader :path, :metrics
12
+
13
+ def initialize(path)
14
+ @path = path
15
+ @metrics = process
16
+ end
17
+
18
+ def metric_for_test_id(test_id)
19
+ metrics.find do |metric|
20
+ metric.fields['id'] == test_id
21
+ end
22
+ end
23
+
24
+ def write
25
+ File.write(path, JSON.pretty_generate(metrics))
26
+ end
27
+
28
+ private
29
+
30
+ def parse
31
+ JSON.parse(File.read(path))
32
+ rescue JSON::ParserError
33
+ Runtime::Logger.debug("#{self.class.name}##{__method__} attempted to parse invalid JSON at path: #{path}")
34
+ {}
35
+ end
36
+
37
+ def process
38
+ parse.map do |test|
39
+ GitlabQuality::TestTooling::TestMetric::JsonTestMetric.new(test)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GitlabQuality
4
4
  module TestTooling
5
- VERSION = "1.7.0"
5
+ VERSION = "1.8.1"
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.7.0
4
+ version: 1.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab Quality
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-29 00:00:00.000000000 Z
11
+ date: 2023-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -422,6 +422,8 @@ files:
422
422
  - lib/gitlab_quality/test_tooling/system_logs/log_types/rails/graphql_log.rb
423
423
  - lib/gitlab_quality/test_tooling/system_logs/shared_fields.rb
424
424
  - lib/gitlab_quality/test_tooling/system_logs/system_logs_formatter.rb
425
+ - lib/gitlab_quality/test_tooling/test_metric/json_test_metric.rb
426
+ - lib/gitlab_quality/test_tooling/test_metrics/json_test_metric_collection.rb
425
427
  - lib/gitlab_quality/test_tooling/test_result/base_test_result.rb
426
428
  - lib/gitlab_quality/test_tooling/test_result/j_unit_test_result.rb
427
429
  - lib/gitlab_quality/test_tooling/test_result/json_test_result.rb