gitlab_quality-test_tooling 3.15.0 → 3.16.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 +15 -0
- data/lib/gitlab_quality/test_tooling/code_coverage/click_house/jest_quarantined_tests_table.rb +78 -0
- data/lib/gitlab_quality/test_tooling/code_coverage/click_house/test_health_risk_aggregation.sql +12 -4
- data/lib/gitlab_quality/test_tooling/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4c662ad8ff8b0b48b868eb201c12bd783c4a446bf0647d01e42778d59fd9f334
|
|
4
|
+
data.tar.gz: 3b26b7d715a0d55314e35194f490bef33aefc590356095bfb247e3f81cc2da5b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b09d7935e13222a40f137f51a4ddc0164e3da841b9fc30eba901f8cead0f237a5ff1cc6c8df44a121e42d207fe0b1442e62ab3bc415f477a95a95ae05553c8c7
|
|
7
|
+
data.tar.gz: 2d9f33720064de7b9f8b78c00fafe7ff0b582e7554b7c7f7d89e690b080cf5e71aa515407e3825ce110f48221f3761816268841c594c823b2539576530a4e938
|
data/Gemfile.lock
CHANGED
data/exe/test-coverage
CHANGED
|
@@ -12,6 +12,7 @@ require_relative '../lib/gitlab_quality/test_tooling/code_coverage/click_house/c
|
|
|
12
12
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/click_house/coverage_metrics_table'
|
|
13
13
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/click_house/per_test_coverage_table'
|
|
14
14
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/click_house/test_file_mappings_table'
|
|
15
|
+
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/click_house/jest_quarantined_tests_table'
|
|
15
16
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/click_house/test_health_risk_aggregator'
|
|
16
17
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/coverage_data'
|
|
17
18
|
require_relative '../lib/gitlab_quality/test_tooling/code_coverage/lcov_file'
|
|
@@ -73,6 +74,13 @@ options = OptionParser.new do |opts|
|
|
|
73
74
|
params[:per_test_coverage] = pattern
|
|
74
75
|
end
|
|
75
76
|
|
|
77
|
+
opts.on('--jest-quarantine-file PATH',
|
|
78
|
+
'Optional. Path to quarantined_vue3_specs.txt. When provided alongside ' \
|
|
79
|
+
'--per-test-coverage, populates code_coverage.jest_quarantined_tests_today ' \
|
|
80
|
+
'before the nightly aggregation so Jest tests count toward is_quarantined.') do |path|
|
|
81
|
+
params[:jest_quarantine_file] = path
|
|
82
|
+
end
|
|
83
|
+
|
|
76
84
|
opts.separator ""
|
|
77
85
|
opts.separator "Environment variables:"
|
|
78
86
|
opts.separator " GLCI_CLICKHOUSE_METRICS_PASSWORD ClickHouse password (required, not passed via CLI for security)"
|
|
@@ -217,6 +225,13 @@ if params.any? && (required_params - params.keys).none?
|
|
|
217
225
|
per_test_coverage_table = GitlabQuality::TestTooling::CodeCoverage::ClickHouse::PerTestCoverageTable.new(**clickhouse_data)
|
|
218
226
|
per_test_coverage_table.push(per_test_data.as_db_table)
|
|
219
227
|
|
|
228
|
+
if params[:jest_quarantine_file] && File.exist?(params[:jest_quarantine_file])
|
|
229
|
+
jest_qt = GitlabQuality::TestTooling::CodeCoverage::ClickHouse::JestQuarantinedTestsTable.new(**clickhouse_data)
|
|
230
|
+
jest_qt.populate(quarantine_file: params[:jest_quarantine_file])
|
|
231
|
+
elsif params[:jest_quarantine_file]
|
|
232
|
+
puts "Jest quarantine file not found at #{params[:jest_quarantine_file]}; skipping jest quarantine ingestion."
|
|
233
|
+
end
|
|
234
|
+
|
|
220
235
|
aggregator = GitlabQuality::TestTooling::CodeCoverage::ClickHouse::TestHealthRiskAggregator.new(**clickhouse_data)
|
|
221
236
|
aggregator.run
|
|
222
237
|
else
|
data/lib/gitlab_quality/test_tooling/code_coverage/click_house/jest_quarantined_tests_table.rb
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'table'
|
|
4
|
+
|
|
5
|
+
module GitlabQuality
|
|
6
|
+
module TestTooling
|
|
7
|
+
module CodeCoverage
|
|
8
|
+
module ClickHouse
|
|
9
|
+
# Replaces `code_coverage.jest_quarantined_tests_today` with the current
|
|
10
|
+
# contents of `scripts/frontend/quarantined_vue3_specs.txt` before each
|
|
11
|
+
# nightly risk aggregation. The helper table is a transient snapshot:
|
|
12
|
+
# it is truncated and repopulated on every aggregation run so the
|
|
13
|
+
# aggregation SQL can treat it as a simple LEFT JOIN for is_quarantined
|
|
14
|
+
# enrichment without needing a time-windowed query.
|
|
15
|
+
class JestQuarantinedTestsTable
|
|
16
|
+
include Client
|
|
17
|
+
|
|
18
|
+
TABLE_NAME = 'jest_quarantined_tests_today'
|
|
19
|
+
|
|
20
|
+
def initialize(url:, database:, username: nil, password: nil, logger: nil)
|
|
21
|
+
@url = url
|
|
22
|
+
@database = database
|
|
23
|
+
@username = username
|
|
24
|
+
@password = password
|
|
25
|
+
@logger = logger || Runtime::Logger.logger
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Reads `quarantine_file`, truncates `jest_quarantined_tests_today`,
|
|
29
|
+
# then inserts one row per non-blank, non-comment line. Idempotent:
|
|
30
|
+
# repeated calls with the same flat file produce the same table state.
|
|
31
|
+
#
|
|
32
|
+
# @param quarantine_file [String] path to the quarantine flat file
|
|
33
|
+
# @return [void]
|
|
34
|
+
def populate(quarantine_file:)
|
|
35
|
+
truncate_and_insert(read_quarantine_file(quarantine_file))
|
|
36
|
+
rescue StandardError => e
|
|
37
|
+
logger.error("#{LOG_PREFIX} Error populating #{full_table_name}: #{e.message}")
|
|
38
|
+
raise
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
attr_reader :url, :database, :username, :password, :logger
|
|
44
|
+
|
|
45
|
+
def truncate_and_insert(test_files)
|
|
46
|
+
logger.info(
|
|
47
|
+
"#{LOG_PREFIX} Populating #{full_table_name} with #{test_files.size} Jest quarantined test files"
|
|
48
|
+
)
|
|
49
|
+
client.query("TRUNCATE TABLE #{full_table_name}", format: 'TabSeparated')
|
|
50
|
+
insert_rows(test_files) if test_files.any?
|
|
51
|
+
logger.info("#{LOG_PREFIX} Populated #{full_table_name} with #{test_files.size} rows")
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def insert_rows(test_files)
|
|
55
|
+
rows_sql = test_files.map { |f| "('#{escape(f)}')" }.join(",\n")
|
|
56
|
+
client.query(<<~SQL, format: 'TabSeparated')
|
|
57
|
+
INSERT INTO #{full_table_name} (test_file) VALUES #{rows_sql}
|
|
58
|
+
SQL
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def read_quarantine_file(path)
|
|
62
|
+
File.readlines(path, chomp: true)
|
|
63
|
+
.reject { |line| line.start_with?('#') || line.strip.empty? }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def full_table_name
|
|
67
|
+
"#{database}.#{TABLE_NAME}"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# ClickHouse string escape: backslash then single quote.
|
|
71
|
+
def escape(str)
|
|
72
|
+
str.to_s.gsub('\\', '\\\\\\\\').gsub("'", "''")
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
data/lib/gitlab_quality/test_tooling/code_coverage/click_house/test_health_risk_aggregation.sql
CHANGED
|
@@ -71,6 +71,13 @@ WITH
|
|
|
71
71
|
GROUP BY test_file
|
|
72
72
|
HAVING is_flaky
|
|
73
73
|
),
|
|
74
|
+
-- Jest quarantine comes from a flat file (quarantined_vue3_specs.txt) rather
|
|
75
|
+
-- than the issue-based RSpec ledger. It is populated into this helper table
|
|
76
|
+
-- by JestQuarantinedTestsTable before each nightly aggregation run.
|
|
77
|
+
jest_quarantine_status AS (
|
|
78
|
+
SELECT test_file
|
|
79
|
+
FROM code_coverage.jest_quarantined_tests_today FINAL
|
|
80
|
+
),
|
|
74
81
|
per_test_status AS (
|
|
75
82
|
SELECT
|
|
76
83
|
tc.source_file,
|
|
@@ -79,11 +86,12 @@ WITH
|
|
|
79
86
|
tc.section,
|
|
80
87
|
tc.total_lines,
|
|
81
88
|
tc.covered_lines,
|
|
82
|
-
coalesce(qs.is_quarantined, FALSE) AS is_quarantined,
|
|
83
|
-
coalesce(fs.is_flaky, FALSE)
|
|
89
|
+
(coalesce(qs.is_quarantined, FALSE) OR (jq.test_file IS NOT NULL)) AS is_quarantined,
|
|
90
|
+
coalesce(fs.is_flaky, FALSE) AS is_flaky
|
|
84
91
|
FROM code_coverage.test_coverage_per_file tc FINAL
|
|
85
|
-
LEFT JOIN quarantine_status
|
|
86
|
-
LEFT JOIN
|
|
92
|
+
LEFT JOIN quarantine_status qs ON qs.test_file = tc.test_file
|
|
93
|
+
LEFT JOIN jest_quarantine_status jq ON jq.test_file = tc.test_file
|
|
94
|
+
LEFT JOIN flaky_status fs ON fs.test_file = tc.test_file
|
|
87
95
|
WHERE tc.timestamp >= now() - INTERVAL {coverage_window}
|
|
88
96
|
),
|
|
89
97
|
per_file AS (
|
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.16.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-05-
|
|
11
|
+
date: 2026-05-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: climate_control
|
|
@@ -493,6 +493,7 @@ files:
|
|
|
493
493
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/category_owners_table.rb
|
|
494
494
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/client.rb
|
|
495
495
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/coverage_metrics_table.rb
|
|
496
|
+
- lib/gitlab_quality/test_tooling/code_coverage/click_house/jest_quarantined_tests_table.rb
|
|
496
497
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/per_test_coverage_table.rb
|
|
497
498
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/table.rb
|
|
498
499
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/test_file_mappings_table.rb
|