gitlab_quality-test_tooling 3.20.2 → 3.21.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/Gemfile.lock +1 -1
- data/exe/test-coverage +21 -3
- data/lib/gitlab_quality/test_tooling/code_coverage/per_test_coverage_exporter.rb +20 -10
- data/lib/gitlab_quality/test_tooling/report/relate_failure_issue.rb +0 -9
- data/lib/gitlab_quality/test_tooling/report/report_as_issue.rb +0 -1
- data/lib/gitlab_quality/test_tooling/report/report_results.rb +0 -5
- data/lib/gitlab_quality/test_tooling/report/results_in_test_cases.rb +4 -5
- data/lib/gitlab_quality/test_tooling/test_meta/processor/meta_processor.rb +2 -2
- data/lib/gitlab_quality/test_tooling/test_result/j_unit_test_result.rb +0 -2
- data/lib/gitlab_quality/test_tooling/test_result/json_test_result.rb +0 -8
- data/lib/gitlab_quality/test_tooling/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6fa78c58b83ed94504f42df7a78f5bdbddea78f9466134618b6c9b34fa99d679
|
|
4
|
+
data.tar.gz: bb3b04f2dee89712fd561a944de2d397db62867351f562ac0b0e7cac721424d2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d969c70fbf9efb0aac4020367999aca505d226125a63daeaa8dc6f5ad409f84d8f9bc6a411ada6c9aa5c91627ef8bec768a165bcf4258df0e7e65426d63776c3
|
|
7
|
+
data.tar.gz: d3329d8d499320cd0fdad6a8a2c9ea669d7310b1076aa5c8130e3c4b79e6f12e2fc2a32ecaa0a11f057860f8c8f82db9551120f5f0b5ce28f9a1898597a74842
|
data/Gemfile.lock
CHANGED
data/exe/test-coverage
CHANGED
|
@@ -73,7 +73,9 @@ options = OptionParser.new do |opts|
|
|
|
73
73
|
'Inserts rows into code_coverage.test_coverage_per_file and runs the daily ' \
|
|
74
74
|
'test_health_risk aggregation unless --skip-aggregation. Needs only the ' \
|
|
75
75
|
'--clickhouse-* options; --test-reports and --jest-quarantine-file are ' \
|
|
76
|
-
'optional enrichment.
|
|
76
|
+
'optional enrichment. --test-reports also requires --clickhouse-shared-database, ' \
|
|
77
|
+
'since category ownership is read from the shared database. ' \
|
|
78
|
+
'(e.g., "tmp/per-test-coverage-*.ndjson")') do |pattern|
|
|
77
79
|
params[:per_test_coverage] = pattern
|
|
78
80
|
end
|
|
79
81
|
|
|
@@ -135,7 +137,16 @@ mode =
|
|
|
135
137
|
clickhouse_required = [:clickhouse_url, :clickhouse_database, :clickhouse_username]
|
|
136
138
|
full_export_required =
|
|
137
139
|
[:test_reports, :coverage_report, :test_map, :responsibility_patterns, :clickhouse_shared_database] + clickhouse_required
|
|
138
|
-
|
|
140
|
+
# Per-test mode reads category_owners from the shared database only when it enriches
|
|
141
|
+
# rows (--test-reports present), so require the shared database exactly then.
|
|
142
|
+
per_test_enriching = mode == :per_test && params[:test_reports]
|
|
143
|
+
required_params =
|
|
144
|
+
case mode
|
|
145
|
+
when :full_export
|
|
146
|
+
full_export_required
|
|
147
|
+
else
|
|
148
|
+
per_test_enriching ? clickhouse_required + [:clickhouse_shared_database] : clickhouse_required
|
|
149
|
+
end
|
|
139
150
|
|
|
140
151
|
unless params.any? && (required_params - params.keys).none?
|
|
141
152
|
puts "Missing argument(s). Required arguments are: #{required_params}\nPassed arguments are: #{params}\n"
|
|
@@ -149,7 +160,13 @@ if clickhouse_password.to_s.strip.empty?
|
|
|
149
160
|
exit 1
|
|
150
161
|
end
|
|
151
162
|
|
|
152
|
-
non_empty_params =
|
|
163
|
+
non_empty_params =
|
|
164
|
+
if mode == :full_export || per_test_enriching
|
|
165
|
+
clickhouse_required + [:clickhouse_shared_database]
|
|
166
|
+
else
|
|
167
|
+
clickhouse_required
|
|
168
|
+
end
|
|
169
|
+
|
|
153
170
|
non_empty_params.each do |param|
|
|
154
171
|
next unless params[param].to_s.strip.empty?
|
|
155
172
|
|
|
@@ -189,6 +206,7 @@ when :per_test
|
|
|
189
206
|
GitlabQuality::TestTooling::CodeCoverage::PerTestCoverageExporter.new(
|
|
190
207
|
coverage_glob: params[:per_test_coverage],
|
|
191
208
|
clickhouse: clickhouse_data,
|
|
209
|
+
clickhouse_shared_database: params[:clickhouse_shared_database],
|
|
192
210
|
test_reports: params[:test_reports],
|
|
193
211
|
jest_quarantine_file: params[:jest_quarantine_file],
|
|
194
212
|
skip_aggregation: params.fetch(:skip_aggregation, false)
|
|
@@ -23,12 +23,15 @@ module GitlabQuality
|
|
|
23
23
|
# aggregation once at the end.
|
|
24
24
|
class PerTestCoverageExporter
|
|
25
25
|
# @param clickhouse [Hash] connection params (:url, :database, :username, :password)
|
|
26
|
+
# @param clickhouse_shared_database [String, nil] the shared database holding the
|
|
27
|
+
# canonical `category_owners`. Required only when enriching (test_reports present).
|
|
26
28
|
def initialize(
|
|
27
|
-
coverage_glob:, clickhouse:,
|
|
29
|
+
coverage_glob:, clickhouse:, clickhouse_shared_database: nil,
|
|
28
30
|
test_reports: nil, jest_quarantine_file: nil,
|
|
29
31
|
captured_sha: ENV.fetch('CI_COMMIT_SHA', ''), skip_aggregation: false, logger: nil)
|
|
30
32
|
@coverage_glob = coverage_glob
|
|
31
33
|
@clickhouse = clickhouse
|
|
34
|
+
@clickhouse_shared_database = clickhouse_shared_database
|
|
32
35
|
@test_reports = test_reports
|
|
33
36
|
@jest_quarantine_file = jest_quarantine_file
|
|
34
37
|
@captured_sha = captured_sha.to_s
|
|
@@ -65,8 +68,8 @@ module GitlabQuality
|
|
|
65
68
|
|
|
66
69
|
private
|
|
67
70
|
|
|
68
|
-
attr_reader :coverage_glob, :clickhouse, :
|
|
69
|
-
:captured_sha, :skip_aggregation, :logger
|
|
71
|
+
attr_reader :coverage_glob, :clickhouse, :clickhouse_shared_database, :test_reports,
|
|
72
|
+
:jest_quarantine_file, :captured_sha, :skip_aggregation, :logger
|
|
70
73
|
|
|
71
74
|
def insert(coverage_files)
|
|
72
75
|
tests_to_categories, feature_categories_to_teams = resolve_categories
|
|
@@ -144,14 +147,21 @@ module GitlabQuality
|
|
|
144
147
|
[tests_to_categories_from(report_files), feature_categories_to_teams]
|
|
145
148
|
end
|
|
146
149
|
|
|
147
|
-
# Category to group/stage/section, read from `
|
|
148
|
-
#
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
#
|
|
152
|
-
#
|
|
150
|
+
# Category to group/stage/section, read from `category_owners` in the shared
|
|
151
|
+
# database, the same source the full coverage export uses. The shared copy is
|
|
152
|
+
# refreshed by sync-category-owners; the legacy `code_coverage.category_owners`
|
|
153
|
+
# stopped updating in December 2025, so reading it would drop every category
|
|
154
|
+
# added since. `owner_records` gives string-keyed values; PerTestCoverageData
|
|
155
|
+
# reads symbol keys.
|
|
153
156
|
def feature_categories_to_teams
|
|
154
|
-
|
|
157
|
+
if clickhouse_shared_database.to_s.strip.empty?
|
|
158
|
+
raise ArgumentError,
|
|
159
|
+
'clickhouse_shared_database is required to enrich per-test rows with category owners'
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
shared_credentials = clickhouse_credentials.merge(database: clickhouse_shared_database)
|
|
163
|
+
|
|
164
|
+
ClickHouse::CategoryOwnersTable.new(**shared_credentials).owner_records.transform_values do |owner|
|
|
155
165
|
{ group: owner["group"], stage: owner["stage"], section: owner["section"] }
|
|
156
166
|
end
|
|
157
167
|
end
|
|
@@ -151,7 +151,6 @@ module GitlabQuality
|
|
|
151
151
|
line_number: extract_line_number(test),
|
|
152
152
|
exception: extract_exception_data(test),
|
|
153
153
|
ci_job_url: test.ci_job_url,
|
|
154
|
-
testcase: extract_test_id_or_name(test),
|
|
155
154
|
product_group: extract_product_group(test),
|
|
156
155
|
level: extract_level(test)
|
|
157
156
|
}
|
|
@@ -184,14 +183,6 @@ module GitlabQuality
|
|
|
184
183
|
}
|
|
185
184
|
end
|
|
186
185
|
|
|
187
|
-
def extract_test_id_or_name(test)
|
|
188
|
-
return test.example_id if test.respond_to?(:example_id)
|
|
189
|
-
return test.id if test.respond_to?(:id)
|
|
190
|
-
return test.name if test.respond_to?(:name)
|
|
191
|
-
|
|
192
|
-
"#{test.relative_file}:#{test.respond_to?(:line_number) ? test.line_number : 'unknown'}"
|
|
193
|
-
end
|
|
194
|
-
|
|
195
186
|
def new_issue_labels(test)
|
|
196
187
|
up_to_date_labels(test: test, new_labels: NEW_ISSUE_LABELS + group_and_category_labels_for_test(test))
|
|
197
188
|
end
|
|
@@ -63,7 +63,6 @@ module GitlabQuality
|
|
|
63
63
|
| Test level | `#{test.level}` |
|
|
64
64
|
| Hash | `#{test_hash(test)}` |
|
|
65
65
|
| Max expected duration | < #{test.max_duration_for_test} seconds |
|
|
66
|
-
#{"| Test case | #{test.testcase} |" if test.testcase}
|
|
67
66
|
<!-- Don't modify this section as it's auto-generated -->
|
|
68
67
|
DESCRIPTION
|
|
69
68
|
end
|
|
@@ -49,16 +49,11 @@ module GitlabQuality
|
|
|
49
49
|
|
|
50
50
|
report_test(test)
|
|
51
51
|
end
|
|
52
|
-
|
|
53
|
-
test_results.write
|
|
54
52
|
end
|
|
55
53
|
end
|
|
56
54
|
|
|
57
55
|
def report_test(test)
|
|
58
56
|
testcase = testcase_project_reporter.find_or_create_testcase(test)
|
|
59
|
-
# The API returns the test case with an issue URL since it is technically a type of issue.
|
|
60
|
-
# This updates the URL to a valid test case link.
|
|
61
|
-
test.testcase = testcase.web_url.sub('/issues/', '/quality/test_cases/')
|
|
62
57
|
|
|
63
58
|
result_issue, is_new = results_issue_project_reporter.get_related_issue(testcase, test)
|
|
64
59
|
|
|
@@ -18,18 +18,17 @@ module GitlabQuality
|
|
|
18
18
|
find_testcase(test) || create_issue(test)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def add_result_issue_link_to_testcase(testcase, result_issue,
|
|
21
|
+
def add_result_issue_link_to_testcase(testcase, result_issue, _test)
|
|
22
22
|
results_section = testcase.description.include?(TEST_CASE_RESULTS_SECTION_TEMPLATE) ? '' : TEST_CASE_RESULTS_SECTION_TEMPLATE
|
|
23
23
|
|
|
24
24
|
gitlab.edit_issue(iid: testcase.iid,
|
|
25
25
|
options: { description: (testcase.description + results_section + "\n\n#{result_issue.web_url}") })
|
|
26
|
-
|
|
27
|
-
puts "Added results issue #{result_issue.web_url} link to test case #{test.testcase}"
|
|
26
|
+
puts "Added results issue #{result_issue.web_url} link to test case #{testcase.web_url}"
|
|
28
27
|
end
|
|
29
28
|
|
|
30
29
|
def update_testcase(testcase, test)
|
|
31
|
-
puts "Labels updated for test case #{
|
|
32
|
-
puts "Quarantine section updated for test case #{
|
|
30
|
+
puts "Labels updated for test case #{testcase.web_url}." if update_labels(testcase, test)
|
|
31
|
+
puts "Quarantine section updated for test case #{testcase.web_url}." if update_quarantine_section(testcase, test)
|
|
33
32
|
end
|
|
34
33
|
|
|
35
34
|
private
|
|
@@ -37,7 +37,7 @@ module GitlabQuality
|
|
|
37
37
|
description_start_index + description_length
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
# List specs in markdown with details such as link to code,
|
|
40
|
+
# List specs in markdown with details such as link to code, metrics and failure issue
|
|
41
41
|
#
|
|
42
42
|
# @param [Hash<String,Hash>] commits The commits hash to use for spec details
|
|
43
43
|
# @return String
|
|
@@ -45,7 +45,7 @@ module GitlabQuality
|
|
|
45
45
|
commits.each_with_index.map do |(changed_line_number, spec), index|
|
|
46
46
|
<<~MARKDOWN
|
|
47
47
|
#{index + 1}. [`#{spec['name']}`](https://gitlab.com/#{context.project}/-/blob/#{context.ref}/#{spec['file_path']}#L#{changed_line_number.to_i + 1})
|
|
48
|
-
| [
|
|
48
|
+
| [Spec metrics](#{context.single_spec_metrics_link(spec['file_path'])})
|
|
49
49
|
#{failure_issue_text(spec)}
|
|
50
50
|
MARKDOWN
|
|
51
51
|
end.join("\n")
|
|
@@ -60,14 +60,6 @@ module GitlabQuality
|
|
|
60
60
|
report.fetch('ci_job_url', '')
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
def testcase
|
|
64
|
-
report.fetch('testcase', '')
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def testcase=(new_testcase)
|
|
68
|
-
report['testcase'] = new_testcase
|
|
69
|
-
end
|
|
70
|
-
|
|
71
63
|
def quarantine_type
|
|
72
64
|
quarantine['type'] if quarantine?
|
|
73
65
|
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: 3.
|
|
4
|
+
version: 3.21.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: 2026-
|
|
11
|
+
date: 2026-08-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: climate_control
|