gitlab_quality-test_tooling 3.0.0 → 3.7.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 +2 -4
- data/README.md +47 -14
- data/exe/sync-category-owners +95 -0
- data/exe/test-coverage +59 -15
- data/lib/gitlab_quality/test_tooling/code_coverage/README.md +162 -0
- data/lib/gitlab_quality/test_tooling/code_coverage/artifacts.rb +5 -2
- data/lib/gitlab_quality/test_tooling/code_coverage/category_owners.rb +32 -28
- data/lib/gitlab_quality/test_tooling/code_coverage/click_house/category_owners_table.rb +102 -35
- data/lib/gitlab_quality/test_tooling/code_coverage/click_house/coverage_metrics_table.rb +44 -37
- data/lib/gitlab_quality/test_tooling/code_coverage/click_house/table.rb +17 -0
- data/lib/gitlab_quality/test_tooling/code_coverage/click_house/test_file_mappings_table.rb +52 -0
- data/lib/gitlab_quality/test_tooling/code_coverage/coverage_data.rb +77 -34
- data/lib/gitlab_quality/test_tooling/code_coverage/lcov_file.rb +11 -1
- data/lib/gitlab_quality/test_tooling/code_coverage/responsibility_classifier.rb +47 -0
- data/lib/gitlab_quality/test_tooling/code_coverage/responsibility_patterns_config.rb +46 -0
- data/lib/gitlab_quality/test_tooling/code_coverage/test_file_mapping_data.rb +46 -0
- data/lib/gitlab_quality/test_tooling/report/results_in_test_cases.rb +2 -4
- data/lib/gitlab_quality/test_tooling/runtime/env.rb +4 -0
- data/lib/gitlab_quality/test_tooling/test_meta/processor/meta_processor.rb +1 -1
- data/lib/gitlab_quality/test_tooling/test_meta/test_meta_updater.rb +4 -4
- data/lib/gitlab_quality/test_tooling/test_metrics_exporter/config.rb +8 -0
- data/lib/gitlab_quality/test_tooling/test_metrics_exporter/test_metrics.rb +36 -10
- data/lib/gitlab_quality/test_tooling/test_metrics_exporter/utils.rb +2 -0
- data/lib/gitlab_quality/test_tooling/test_quarantine/quarantine_formatter.rb +38 -0
- data/lib/gitlab_quality/test_tooling/test_quarantine/quarantine_helper.rb +76 -0
- data/lib/gitlab_quality/test_tooling/test_result/base_test_result.rb +15 -1
- data/lib/gitlab_quality/test_tooling/version.rb +1 -1
- metadata +11 -28
- data/exe/existing-test-health-issue +0 -59
- data/exe/generate-test-session +0 -70
- data/lib/gitlab_quality/test_tooling/report/generate_test_session.rb +0 -288
- data/lib/gitlab_quality/test_tooling/report/test_health_issue_finder.rb +0 -79
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GitlabQuality
|
|
4
|
+
module TestTooling
|
|
5
|
+
module CodeCoverage
|
|
6
|
+
class TestFileMappingData
|
|
7
|
+
# @param [Hash<String, Array<String>>] test_to_sources Test files
|
|
8
|
+
# mapped to all source files they cover
|
|
9
|
+
# @param [Hash<String, Array<String>>] tests_to_categories Test files
|
|
10
|
+
# mapped to their feature categories
|
|
11
|
+
# @param [Hash<String, Hash>] feature_categories_to_teams Feature categories
|
|
12
|
+
# mapped to their org hierarchy (group, stage, section)
|
|
13
|
+
def initialize(test_to_sources, tests_to_categories: {}, feature_categories_to_teams: {})
|
|
14
|
+
@test_to_sources = test_to_sources
|
|
15
|
+
@tests_to_categories = tests_to_categories
|
|
16
|
+
@feature_categories_to_teams = feature_categories_to_teams
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @return [Array<Hash<Symbol, String>>] Mapping data formatted for database insertion
|
|
20
|
+
# @example Return value
|
|
21
|
+
# [
|
|
22
|
+
# { test_file: "spec/models/user_spec.rb", source_file: "app/models/user.rb",
|
|
23
|
+
# category: "team_planning", group: "project_management", stage: "plan", section: "dev" },
|
|
24
|
+
# ...
|
|
25
|
+
# ]
|
|
26
|
+
def as_db_table
|
|
27
|
+
@test_to_sources.flat_map do |test_file, source_files|
|
|
28
|
+
category = @tests_to_categories[test_file]&.first || ''
|
|
29
|
+
team = @feature_categories_to_teams[category] || {}
|
|
30
|
+
|
|
31
|
+
source_files.map do |source_file|
|
|
32
|
+
{
|
|
33
|
+
test_file: test_file,
|
|
34
|
+
source_file: source_file,
|
|
35
|
+
category: category,
|
|
36
|
+
group: team[:group] || '',
|
|
37
|
+
stage: team[:stage] || '',
|
|
38
|
+
section: team[:section] || ''
|
|
39
|
+
}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'erb'
|
|
4
|
-
|
|
5
3
|
module GitlabQuality
|
|
6
4
|
module TestTooling
|
|
7
5
|
module Report
|
|
@@ -68,12 +66,12 @@ module GitlabQuality
|
|
|
68
66
|
end
|
|
69
67
|
|
|
70
68
|
def execution_graph_section(test)
|
|
71
|
-
|
|
69
|
+
formatted_path = CGI.escape(test.relative_file)
|
|
72
70
|
|
|
73
71
|
<<~MKDOWN.strip
|
|
74
72
|
### Executions
|
|
75
73
|
|
|
76
|
-
[Spec metrics on all environments](https://dashboards.
|
|
74
|
+
[Spec metrics on all environments](https://dashboards.devex.gitlab.net/d/739c1bdd-a436-452b-bddc-fccb4d055768/single-test-overview?var-file_path=#{formatted_path})
|
|
77
75
|
MKDOWN
|
|
78
76
|
end
|
|
79
77
|
|
|
@@ -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
|
-
| [Testcase](#{spec['testcase']}) | [Spec metrics](#{context.single_spec_metrics_link(spec['
|
|
48
|
+
| [Testcase](#{spec['testcase']}) | [Spec metrics](#{context.single_spec_metrics_link(spec['file_path'])})
|
|
49
49
|
#{failure_issue_text(spec)}
|
|
50
50
|
MARKDOWN
|
|
51
51
|
end.join("\n")
|
|
@@ -348,11 +348,11 @@ module GitlabQuality
|
|
|
348
348
|
|
|
349
349
|
# Returns the link to the Grafana dashboard for single spec metrics
|
|
350
350
|
#
|
|
351
|
-
# @param [String]
|
|
351
|
+
# @param [String] file_path the full path of spec
|
|
352
352
|
# @return [String]
|
|
353
|
-
def single_spec_metrics_link(
|
|
354
|
-
base_url = "https://dashboards.
|
|
355
|
-
base_url + CGI.escape(
|
|
353
|
+
def single_spec_metrics_link(file_path)
|
|
354
|
+
base_url = "https://dashboards.devex.gitlab.net/d/739c1bdd-a436-452b-bddc-fccb4d055768/single-test-overview?var-file_path="
|
|
355
|
+
base_url + CGI.escape(file_path)
|
|
356
356
|
end
|
|
357
357
|
|
|
358
358
|
# Returns any test description string within single or double quotes
|
|
@@ -52,6 +52,7 @@ module GitlabQuality
|
|
|
52
52
|
:skip_record_proc,
|
|
53
53
|
:test_retried_proc,
|
|
54
54
|
:custom_metrics_proc,
|
|
55
|
+
:spec_file_path_prefix,
|
|
55
56
|
:logger
|
|
56
57
|
|
|
57
58
|
# rubocop:disable Style/TrivialAccessors -- allows documenting that setting config enables the export as well as document input class type
|
|
@@ -108,6 +109,13 @@ module GitlabQuality
|
|
|
108
109
|
@extra_rspec_metadata_keys ||= []
|
|
109
110
|
end
|
|
110
111
|
|
|
112
|
+
# Extra path prefix for constructing full file path within mono-repository setups
|
|
113
|
+
#
|
|
114
|
+
# @return [String]
|
|
115
|
+
def spec_file_path_prefix
|
|
116
|
+
@spec_file_path_prefix ||= ""
|
|
117
|
+
end
|
|
118
|
+
|
|
111
119
|
# A lambda that determines whether to skip recording a test result
|
|
112
120
|
#
|
|
113
121
|
# This is useful when you would want to skip initial failure when retrying specs is set up in a separate process
|
|
@@ -46,12 +46,16 @@ module GitlabQuality
|
|
|
46
46
|
status: example.execution_result.status,
|
|
47
47
|
run_time: (example.execution_result.run_time * 1000).round,
|
|
48
48
|
location: example_location,
|
|
49
|
-
|
|
49
|
+
# TODO: remove exception_class once migration to exception_classes is fully complete on clickhouse side
|
|
50
|
+
exception_class: example.execution_result.exception&.class&.to_s,
|
|
51
|
+
exception_classes: exception_classes.map { |e| e.class.to_s }.uniq,
|
|
50
52
|
failure_exception: failure_exception,
|
|
51
53
|
quarantined: quarantined?,
|
|
54
|
+
quarantine_issue_url: quarantine_issue_url || "",
|
|
52
55
|
feature_category: example.metadata[:feature_category] || "",
|
|
53
56
|
test_retried: config.test_retried_proc.call(example),
|
|
54
|
-
run_type: run_type
|
|
57
|
+
run_type: run_type,
|
|
58
|
+
spec_file_path_prefix: config.spec_file_path_prefix
|
|
55
59
|
}
|
|
56
60
|
end
|
|
57
61
|
|
|
@@ -95,6 +99,25 @@ module GitlabQuality
|
|
|
95
99
|
example.execution_result.status == :pending
|
|
96
100
|
end
|
|
97
101
|
|
|
102
|
+
# Extract quarantine issue URL from metadata
|
|
103
|
+
#
|
|
104
|
+
# @return [String, nil]
|
|
105
|
+
def quarantine_issue_url
|
|
106
|
+
return nil unless example.metadata.key?(:quarantine)
|
|
107
|
+
|
|
108
|
+
metadata = example.metadata[:quarantine]
|
|
109
|
+
case metadata
|
|
110
|
+
when String
|
|
111
|
+
# Direct URL: quarantine: 'https://gitlab.com/.../issues/123'
|
|
112
|
+
metadata if metadata.start_with?('http')
|
|
113
|
+
when Hash
|
|
114
|
+
# Hash format: quarantine: { issue: 'https://...', reason: '...' }
|
|
115
|
+
issue = metadata[:issue] || metadata['issue']
|
|
116
|
+
# Handle array of URLs (take the first one)
|
|
117
|
+
issue.is_a?(Array) ? issue.first : issue
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
98
121
|
# Base ci job name
|
|
99
122
|
#
|
|
100
123
|
# @return [String]
|
|
@@ -127,22 +150,25 @@ module GitlabQuality
|
|
|
127
150
|
@file_path ||= example_location.gsub(/:\d+$/, "")
|
|
128
151
|
end
|
|
129
152
|
|
|
130
|
-
# Failure exception
|
|
153
|
+
# Failure exception classes
|
|
131
154
|
#
|
|
132
|
-
# @return [
|
|
133
|
-
def
|
|
134
|
-
example.execution_result.exception
|
|
155
|
+
# @return [Array<Exception>]
|
|
156
|
+
def exception_classes
|
|
157
|
+
exception = example.execution_result.exception
|
|
158
|
+
return [] unless exception
|
|
159
|
+
return [exception] unless exception.respond_to?(:all_exceptions)
|
|
160
|
+
|
|
161
|
+
exception.all_exceptions.flatten
|
|
135
162
|
end
|
|
136
163
|
|
|
137
164
|
# Truncated exception stacktrace
|
|
138
165
|
#
|
|
139
166
|
# @return [String]
|
|
140
167
|
def failure_exception
|
|
141
|
-
example.execution_result.exception
|
|
142
|
-
|
|
168
|
+
exception = example.execution_result.exception
|
|
169
|
+
return unless exception
|
|
143
170
|
|
|
144
|
-
|
|
145
|
-
end
|
|
171
|
+
exception.to_s.tr("\n", " ").slice(0, 1000)
|
|
146
172
|
end
|
|
147
173
|
|
|
148
174
|
# Test run type | suite name
|
|
@@ -65,6 +65,7 @@ module GitlabQuality
|
|
|
65
65
|
test_retried Bool,
|
|
66
66
|
feature_category LowCardinality(String) DEFAULT 'unknown',
|
|
67
67
|
run_type LowCardinality(String) DEFAULT 'unknown',
|
|
68
|
+
spec_file_path_prefix LowCardinality(String) DEFAULT '',
|
|
68
69
|
ci_project_id UInt32,
|
|
69
70
|
ci_job_name LowCardinality(String),
|
|
70
71
|
ci_job_id UInt64,
|
|
@@ -75,6 +76,7 @@ module GitlabQuality
|
|
|
75
76
|
ci_target_branch LowCardinality(String),
|
|
76
77
|
ci_server_url LowCardinality(String) DEFAULT 'https://gitlab.com',
|
|
77
78
|
exception_class String DEFAULT '',
|
|
79
|
+
exception_classes Array(String) DEFAULT [],
|
|
78
80
|
failure_exception String DEFAULT ''
|
|
79
81
|
)
|
|
80
82
|
ENGINE = MergeTree()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rspec/core/formatters/base_formatter"
|
|
4
|
+
|
|
5
|
+
module GitlabQuality
|
|
6
|
+
module TestTooling
|
|
7
|
+
module TestQuarantine
|
|
8
|
+
class QuarantineFormatter < ::RSpec::Core::Formatters::BaseFormatter
|
|
9
|
+
include QuarantineHelper
|
|
10
|
+
|
|
11
|
+
::RSpec::Core::Formatters.register(
|
|
12
|
+
self,
|
|
13
|
+
:example_group_started,
|
|
14
|
+
:example_started
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# Starts example group
|
|
18
|
+
# @param [RSpec::Core::Notifications::GroupNotification] example_group_notification
|
|
19
|
+
# @return [void]
|
|
20
|
+
def example_group_started(example_group_notification)
|
|
21
|
+
group = example_group_notification.group
|
|
22
|
+
|
|
23
|
+
skip_or_run_quarantined_tests_or_contexts(group)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Starts example
|
|
27
|
+
# @param [RSpec::Core::Notifications::ExampleNotification] example_notification
|
|
28
|
+
# @return [void]
|
|
29
|
+
def example_started(example_notification)
|
|
30
|
+
example = example_notification.example
|
|
31
|
+
|
|
32
|
+
# if skip propagated from example_group, do not reset skip metadata
|
|
33
|
+
skip_or_run_quarantined_tests_or_contexts(example) unless example.metadata[:skip]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rspec/core'
|
|
4
|
+
|
|
5
|
+
module GitlabQuality
|
|
6
|
+
module TestTooling
|
|
7
|
+
module TestQuarantine
|
|
8
|
+
module QuarantineHelper
|
|
9
|
+
include ::RSpec::Core::Pending
|
|
10
|
+
|
|
11
|
+
extend self
|
|
12
|
+
|
|
13
|
+
# Skip tests in quarantine unless we explicitly focus on them or quarantine disabled
|
|
14
|
+
def skip_or_run_quarantined_tests_or_contexts(example)
|
|
15
|
+
return if Runtime::Env.quarantine_disabled?
|
|
16
|
+
|
|
17
|
+
if filters.key?(:quarantine)
|
|
18
|
+
included_filters = filters_other_than_quarantine
|
|
19
|
+
|
|
20
|
+
# If :quarantine is focused, skip the test/context unless its metadata
|
|
21
|
+
# includes quarantine and any other filters
|
|
22
|
+
# E.g., Suppose a test is tagged :smoke and :quarantine, and another is tagged
|
|
23
|
+
# :ldap and :quarantine. If we wanted to run just quarantined smoke tests
|
|
24
|
+
# using `--tag quarantine --tag smoke`, without this check we'd end up
|
|
25
|
+
# running that ldap test as well because of the :quarantine metadata.
|
|
26
|
+
# We could use an exclusion filter, but this way the test report will list
|
|
27
|
+
# the quarantined tests when they're not run so that we're aware of them
|
|
28
|
+
if should_skip_when_focused?(example.metadata, included_filters)
|
|
29
|
+
example.metadata[:skip] = "Only running tests tagged with :quarantine and any of #{included_filters.keys}"
|
|
30
|
+
end
|
|
31
|
+
elsif example.metadata.key?(:quarantine)
|
|
32
|
+
quarantine_tag = example.metadata[:quarantine]
|
|
33
|
+
|
|
34
|
+
example.metadata[:skip] = quarantine_message(quarantine_tag)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def filters_other_than_quarantine
|
|
39
|
+
filters.except(:quarantine)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def quarantine_message(quarantine_tag)
|
|
43
|
+
quarantine_message = %w[In quarantine]
|
|
44
|
+
quarantine_message << case quarantine_tag
|
|
45
|
+
when String
|
|
46
|
+
": #{quarantine_tag}"
|
|
47
|
+
when Hash
|
|
48
|
+
quarantine_tag.key?(:issue) ? ": #{quarantine_tag[:issue]}" : ''
|
|
49
|
+
else
|
|
50
|
+
''
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
quarantine_message.join(' ').strip
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Checks if a test or context should be skipped.
|
|
57
|
+
#
|
|
58
|
+
# Returns true if
|
|
59
|
+
# - the metadata does not includes the :quarantine tag
|
|
60
|
+
# or if
|
|
61
|
+
# - the metadata includes the :quarantine tag
|
|
62
|
+
# - and the filter includes other tags that aren't in the metadata
|
|
63
|
+
def should_skip_when_focused?(metadata, included_filters)
|
|
64
|
+
return true unless metadata.key?(:quarantine)
|
|
65
|
+
return false if included_filters.empty?
|
|
66
|
+
|
|
67
|
+
!metadata.keys.intersect?(included_filters.keys)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def filters
|
|
71
|
+
@filters ||= ::RSpec.configuration.inclusion_filter.rules
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -8,11 +8,13 @@ module GitlabQuality
|
|
|
8
8
|
"Net::ReadTimeout",
|
|
9
9
|
"403 Forbidden - Your account has been blocked",
|
|
10
10
|
"API failed (502) with `GitLab is not responding",
|
|
11
|
+
"Error Code: 502",
|
|
11
12
|
"unexpected token at 'GitLab is not responding'",
|
|
12
13
|
"GitLab: Internal API error (502).",
|
|
13
14
|
"could not be found (502)",
|
|
14
15
|
"Error reference number: 502",
|
|
15
16
|
"(502): `GitLab is not responding`",
|
|
17
|
+
"(502): `502 Bad Gateway`",
|
|
16
18
|
"<head><title>502 Bad Gateway</title></head>",
|
|
17
19
|
"14:connections to all backends failing",
|
|
18
20
|
"gitlab_canary=true cookie was set in browser but 'Next' badge was not shown on UI"
|
|
@@ -127,14 +129,26 @@ module GitlabQuality
|
|
|
127
129
|
end
|
|
128
130
|
|
|
129
131
|
def full_stacktrace
|
|
132
|
+
page_error_failure = ""
|
|
133
|
+
first_non_ignored_failure = ""
|
|
134
|
+
|
|
130
135
|
failures.each do |failure|
|
|
131
136
|
message = failure['message'] || ""
|
|
132
137
|
message_lines = failure['message_lines'] || []
|
|
133
138
|
|
|
134
139
|
next if IGNORED_FAILURES.any? { |e| message.include?(e) }
|
|
135
140
|
|
|
136
|
-
|
|
141
|
+
formatted_failure = message_lines.empty? ? message : message_lines.join("\n")
|
|
142
|
+
|
|
143
|
+
if message.include?("PageErrorChecker")
|
|
144
|
+
page_error_failure = formatted_failure
|
|
145
|
+
elsif first_non_ignored_failure.empty?
|
|
146
|
+
first_non_ignored_failure = formatted_failure
|
|
147
|
+
end
|
|
137
148
|
end
|
|
149
|
+
|
|
150
|
+
# Return PageErrorChecker failure if found, otherwise first non-ignored failure
|
|
151
|
+
page_error_failure.empty? ? first_non_ignored_failure : page_error_failure
|
|
138
152
|
end
|
|
139
153
|
|
|
140
154
|
def calls_shared_examples?
|
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.7.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:
|
|
11
|
+
date: 2026-02-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: climate_control
|
|
@@ -227,9 +227,6 @@ dependencies:
|
|
|
227
227
|
- - ">="
|
|
228
228
|
- !ruby/object:Gem::Version
|
|
229
229
|
version: '7.0'
|
|
230
|
-
- - "<"
|
|
231
|
-
- !ruby/object:Gem::Version
|
|
232
|
-
version: '7.3'
|
|
233
230
|
type: :runtime
|
|
234
231
|
prerelease: false
|
|
235
232
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -237,9 +234,6 @@ dependencies:
|
|
|
237
234
|
- - ">="
|
|
238
235
|
- !ruby/object:Gem::Version
|
|
239
236
|
version: '7.0'
|
|
240
|
-
- - "<"
|
|
241
|
-
- !ruby/object:Gem::Version
|
|
242
|
-
version: '7.3'
|
|
243
237
|
- !ruby/object:Gem::Dependency
|
|
244
238
|
name: amatch
|
|
245
239
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -308,20 +302,6 @@ dependencies:
|
|
|
308
302
|
- - "~>"
|
|
309
303
|
- !ruby/object:Gem::Version
|
|
310
304
|
version: '5.0'
|
|
311
|
-
- !ruby/object:Gem::Dependency
|
|
312
|
-
name: influxdb-client
|
|
313
|
-
requirement: !ruby/object:Gem::Requirement
|
|
314
|
-
requirements:
|
|
315
|
-
- - "~>"
|
|
316
|
-
- !ruby/object:Gem::Version
|
|
317
|
-
version: '3.1'
|
|
318
|
-
type: :runtime
|
|
319
|
-
prerelease: false
|
|
320
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
321
|
-
requirements:
|
|
322
|
-
- - "~>"
|
|
323
|
-
- !ruby/object:Gem::Version
|
|
324
|
-
version: '3.1'
|
|
325
305
|
- !ruby/object:Gem::Dependency
|
|
326
306
|
name: nokogiri
|
|
327
307
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -436,12 +416,10 @@ email:
|
|
|
436
416
|
executables:
|
|
437
417
|
- detect-infrastructure-failures
|
|
438
418
|
- epic-readiness-notification
|
|
439
|
-
- existing-test-health-issue
|
|
440
419
|
- failed-test-issues
|
|
441
420
|
- feature-readiness-checklist
|
|
442
421
|
- feature-readiness-evaluation
|
|
443
422
|
- flaky-test-issues
|
|
444
|
-
- generate-test-session
|
|
445
423
|
- knapsack-report-issues
|
|
446
424
|
- post-to-slack
|
|
447
425
|
- prepare-stage-reports
|
|
@@ -449,6 +427,7 @@ executables:
|
|
|
449
427
|
- report-results
|
|
450
428
|
- slow-test-issues
|
|
451
429
|
- slow-test-merge-request-report-note
|
|
430
|
+
- sync-category-owners
|
|
452
431
|
- test-coverage
|
|
453
432
|
- update-screenshot-paths
|
|
454
433
|
- update-test-meta
|
|
@@ -471,12 +450,10 @@ files:
|
|
|
471
450
|
- Rakefile
|
|
472
451
|
- exe/detect-infrastructure-failures
|
|
473
452
|
- exe/epic-readiness-notification
|
|
474
|
-
- exe/existing-test-health-issue
|
|
475
453
|
- exe/failed-test-issues
|
|
476
454
|
- exe/feature-readiness-checklist
|
|
477
455
|
- exe/feature-readiness-evaluation
|
|
478
456
|
- exe/flaky-test-issues
|
|
479
|
-
- exe/generate-test-session
|
|
480
457
|
- exe/knapsack-report-issues
|
|
481
458
|
- exe/post-to-slack
|
|
482
459
|
- exe/prepare-stage-reports
|
|
@@ -484,21 +461,27 @@ files:
|
|
|
484
461
|
- exe/report-results
|
|
485
462
|
- exe/slow-test-issues
|
|
486
463
|
- exe/slow-test-merge-request-report-note
|
|
464
|
+
- exe/sync-category-owners
|
|
487
465
|
- exe/test-coverage
|
|
488
466
|
- exe/update-screenshot-paths
|
|
489
467
|
- exe/update-test-meta
|
|
490
468
|
- lefthook.yml
|
|
491
469
|
- lib/gitlab_quality/test_tooling.rb
|
|
492
470
|
- lib/gitlab_quality/test_tooling/click_house/client.rb
|
|
471
|
+
- lib/gitlab_quality/test_tooling/code_coverage/README.md
|
|
493
472
|
- lib/gitlab_quality/test_tooling/code_coverage/artifacts.rb
|
|
494
473
|
- lib/gitlab_quality/test_tooling/code_coverage/category_owners.rb
|
|
495
474
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/category_owners_table.rb
|
|
496
475
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/coverage_metrics_table.rb
|
|
497
476
|
- lib/gitlab_quality/test_tooling/code_coverage/click_house/table.rb
|
|
477
|
+
- lib/gitlab_quality/test_tooling/code_coverage/click_house/test_file_mappings_table.rb
|
|
498
478
|
- lib/gitlab_quality/test_tooling/code_coverage/coverage_data.rb
|
|
499
479
|
- lib/gitlab_quality/test_tooling/code_coverage/lcov_file.rb
|
|
480
|
+
- lib/gitlab_quality/test_tooling/code_coverage/responsibility_classifier.rb
|
|
481
|
+
- lib/gitlab_quality/test_tooling/code_coverage/responsibility_patterns_config.rb
|
|
500
482
|
- lib/gitlab_quality/test_tooling/code_coverage/rspec_report.rb
|
|
501
483
|
- lib/gitlab_quality/test_tooling/code_coverage/source_file_classifier.rb
|
|
484
|
+
- lib/gitlab_quality/test_tooling/code_coverage/test_file_mapping_data.rb
|
|
502
485
|
- lib/gitlab_quality/test_tooling/code_coverage/test_map.rb
|
|
503
486
|
- lib/gitlab_quality/test_tooling/code_coverage/test_report.rb
|
|
504
487
|
- lib/gitlab_quality/test_tooling/code_coverage/utils.rb
|
|
@@ -541,7 +524,6 @@ files:
|
|
|
541
524
|
- lib/gitlab_quality/test_tooling/report/failed_test_issue.rb
|
|
542
525
|
- lib/gitlab_quality/test_tooling/report/feature_readiness/report_on_epic.rb
|
|
543
526
|
- lib/gitlab_quality/test_tooling/report/flaky_test_issue.rb
|
|
544
|
-
- lib/gitlab_quality/test_tooling/report/generate_test_session.rb
|
|
545
527
|
- lib/gitlab_quality/test_tooling/report/group_issues/error_message_normalizer.rb
|
|
546
528
|
- lib/gitlab_quality/test_tooling/report/group_issues/error_pattern_matcher.rb
|
|
547
529
|
- lib/gitlab_quality/test_tooling/report/group_issues/failure_processor.rb
|
|
@@ -564,7 +546,6 @@ files:
|
|
|
564
546
|
- lib/gitlab_quality/test_tooling/report/results_in_issues.rb
|
|
565
547
|
- lib/gitlab_quality/test_tooling/report/results_in_test_cases.rb
|
|
566
548
|
- lib/gitlab_quality/test_tooling/report/slow_test_issue.rb
|
|
567
|
-
- lib/gitlab_quality/test_tooling/report/test_health_issue_finder.rb
|
|
568
549
|
- lib/gitlab_quality/test_tooling/report/update_screenshot_path.rb
|
|
569
550
|
- lib/gitlab_quality/test_tooling/runtime/env.rb
|
|
570
551
|
- lib/gitlab_quality/test_tooling/runtime/logger.rb
|
|
@@ -595,6 +576,8 @@ files:
|
|
|
595
576
|
- lib/gitlab_quality/test_tooling/test_metrics_exporter/formatter.rb
|
|
596
577
|
- lib/gitlab_quality/test_tooling/test_metrics_exporter/test_metrics.rb
|
|
597
578
|
- lib/gitlab_quality/test_tooling/test_metrics_exporter/utils.rb
|
|
579
|
+
- lib/gitlab_quality/test_tooling/test_quarantine/quarantine_formatter.rb
|
|
580
|
+
- lib/gitlab_quality/test_tooling/test_quarantine/quarantine_helper.rb
|
|
598
581
|
- lib/gitlab_quality/test_tooling/test_result/base_test_result.rb
|
|
599
582
|
- lib/gitlab_quality/test_tooling/test_result/j_unit_test_result.rb
|
|
600
583
|
- lib/gitlab_quality/test_tooling/test_result/json_test_result.rb
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require "bundler/setup"
|
|
5
|
-
require "optparse"
|
|
6
|
-
|
|
7
|
-
require_relative "../lib/gitlab_quality/test_tooling"
|
|
8
|
-
|
|
9
|
-
params = {}
|
|
10
|
-
HEALTH_PROBLEM_TYPES = GitlabQuality::TestTooling::Report::TestHealthIssueFinder::HEALTH_PROBLEM_TYPE_TO_LABEL.keys
|
|
11
|
-
|
|
12
|
-
options = OptionParser.new do |opts|
|
|
13
|
-
opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
|
|
14
|
-
|
|
15
|
-
opts.on('-i', '--input-files INPUT_FILES', String, 'JSON rspec-retry report files') do |input_files|
|
|
16
|
-
params[:input_files] = input_files
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
opts.on('-p', '--project PROJECT', String, 'Can be an integer or a group/project string') do |project|
|
|
20
|
-
params[:project] = project
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
opts.on('-t', '--token TOKEN', String, 'A valid access token with `api` scope and Maintainer permission in PROJECT') do |token|
|
|
24
|
-
params[:token] = token
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
opts.on("--health-problem-type PROBLEM_TYPE", String, "Look for the given health problem type (#{HEALTH_PROBLEM_TYPES.join(', ')})") do |value|
|
|
28
|
-
raise ArgumentError, "Invalid health problem type: #{value}. Valid options are: #{HEALTH_PROBLEM_TYPES.join(', ')}" unless HEALTH_PROBLEM_TYPES.include?(value)
|
|
29
|
-
|
|
30
|
-
params[:health_problem_type] = value
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
opts.on_tail('-v', '--version', 'Show the version') do
|
|
34
|
-
require_relative "../lib/gitlab_quality/test_tooling/version"
|
|
35
|
-
puts "#{$PROGRAM_NAME} : #{GitlabQuality::TestTooling::VERSION}"
|
|
36
|
-
exit
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
opts.on_tail('-h', '--help', 'Show the usage') do
|
|
40
|
-
puts "Purpose: Checks whether tests coming from the rspec JSON report files has an existing test health issue opened."
|
|
41
|
-
puts opts
|
|
42
|
-
exit
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
opts.parse(ARGV)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
if params.any?
|
|
49
|
-
raise ArgumentError, "No health problem type given. Valid options are: #{HEALTH_PROBLEM_TYPES.join(', ')}" unless params.key?(:health_problem_type)
|
|
50
|
-
|
|
51
|
-
if GitlabQuality::TestTooling::Report::TestHealthIssueFinder.new(**params).found_existing_unhealthy_test_issue?
|
|
52
|
-
exit 0
|
|
53
|
-
else
|
|
54
|
-
exit 1
|
|
55
|
-
end
|
|
56
|
-
else
|
|
57
|
-
puts options
|
|
58
|
-
exit 1
|
|
59
|
-
end
|
data/exe/generate-test-session
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require "bundler/setup"
|
|
5
|
-
require "optparse"
|
|
6
|
-
|
|
7
|
-
require_relative "../lib/gitlab_quality/test_tooling"
|
|
8
|
-
|
|
9
|
-
params = {}
|
|
10
|
-
|
|
11
|
-
options = OptionParser.new do |opts|
|
|
12
|
-
opts.banner = "Usage: #{$PROGRAM_NAME} [options]"
|
|
13
|
-
|
|
14
|
-
opts.on('-i', '--input-files INPUT_FILES', String, 'RSpec report files (JSON or JUnit XML)') do |input_files|
|
|
15
|
-
params[:input_files] = input_files
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
opts.on('-p', '--project PROJECT', String, 'Can be an integer or a group/project string') do |project|
|
|
19
|
-
params[:project] = project
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
opts.on('-t', '--token TOKEN', String, 'A valid access token with `api` scope and Reporter permission in PROJECT') do |token|
|
|
23
|
-
params[:token] = token
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
opts.on('-c', '--ci-project-token CI_PROJECT_TOKEN', String, 'A valid access token with `read_api` scope permission in current ENV["CI_PROJECT_ID"]') do |ci_project_token|
|
|
27
|
-
params[:ci_project_token] = ci_project_token
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
opts.on('-f', '--issue-url-file ISSUE_URL_FILE', 'Output the created test session issue URL') do |issue_url_file|
|
|
31
|
-
params[:issue_url_file] = issue_url_file
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
opts.on('--pipeline-stages STAGES', String, 'Comma-separated list of pipeline stages to include in test session issue') do |pipeline_stages|
|
|
35
|
-
params[:pipeline_stages] = pipeline_stages.split(',')
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
opts.on('--confidential', "Makes test session issue confidential") do
|
|
39
|
-
params[:confidential] = true
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
opts.on('--dry-run', "Perform a dry-run (don't create or update issues or test cases)") do
|
|
43
|
-
params[:dry_run] = true
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
opts.on_tail('-v', '--version', 'Show the version') do
|
|
47
|
-
require_relative "../lib/gitlab_quality/test_tooling/version"
|
|
48
|
-
puts "#{$PROGRAM_NAME} : #{GitlabQuality::TestTooling::VERSION}"
|
|
49
|
-
exit
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
opts.on_tail('-h', '--help', 'Show the usage') do
|
|
53
|
-
puts "Purpose: Generate test session report based on RSpec report files (JSON or JUnit XML)"
|
|
54
|
-
puts opts
|
|
55
|
-
exit
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
opts.parse(ARGV)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
issue_url_file = params.delete(:issue_url_file)
|
|
62
|
-
|
|
63
|
-
if params.any?
|
|
64
|
-
issue_url = GitlabQuality::TestTooling::Report::GenerateTestSession.new(**params).invoke!
|
|
65
|
-
|
|
66
|
-
File.write(issue_url_file, issue_url) if issue_url_file && issue_url
|
|
67
|
-
else
|
|
68
|
-
puts options
|
|
69
|
-
exit 1
|
|
70
|
-
end
|