gitlab_quality-test_tooling 1.30.0 → 1.31.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/lib/gitlab_quality/test_tooling/knapsack_reports/spec_run_time.rb +4 -3
- data/lib/gitlab_quality/test_tooling/knapsack_reports/spec_run_time_report.rb +4 -2
- data/lib/gitlab_quality/test_tooling/report/failed_test_issue.rb +1 -5
- data/lib/gitlab_quality/test_tooling/report/health_problem_reporter.rb +2 -4
- data/lib/gitlab_quality/test_tooling/report/knapsack_report_issue.rb +1 -0
- data/lib/gitlab_quality/test_tooling/report/merge_request_slow_tests_report.rb +2 -2
- data/lib/gitlab_quality/test_tooling/report/relate_failure_issue.rb +1 -1
- data/lib/gitlab_quality/test_tooling/report/report_as_issue.rb +3 -2
- data/lib/gitlab_quality/test_tooling/report/report_results.rb +4 -2
- data/lib/gitlab_quality/test_tooling/runtime/env.rb +1 -4
- data/lib/gitlab_quality/test_tooling/test_result/base_test_result.rb +14 -4
- data/lib/gitlab_quality/test_tooling/test_result/j_unit_test_result.rb +0 -8
- data/lib/gitlab_quality/test_tooling/test_result/json_test_result.rb +0 -4
- data/lib/gitlab_quality/test_tooling/test_results/base_test_results.rb +4 -2
- data/lib/gitlab_quality/test_tooling/test_results/builder.rb +6 -4
- data/lib/gitlab_quality/test_tooling/test_results/j_unit_test_results.rb +1 -1
- data/lib/gitlab_quality/test_tooling/test_results/json_test_results.rb +1 -1
- 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: 5d848eed10080ffc5f609ba56a75e7baf6f60cef5792d66c9c1bf9fdb8dbd2b9
|
4
|
+
data.tar.gz: 5d799f1628b689fda63e0ca68fb70c5f2e6e37d20d867d6ade61e4ff04ea7e57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e881613627b3fb87abf0c00895a8b44919769b222aa1a42c60c81b8f77a79a99232145e60c798f0296d24f53f761cb6a5fd4c7d00d1cb982dcc3c58fd68a833
|
7
|
+
data.tar.gz: 90b1345308d5f4abb94ab81f16520bf79870de753f570223c5bc45ade1fdb7d2ca099004d682bdbcfe106c3557ebdd093ce0461b493fd98e6e687bb9930b293e
|
data/Gemfile.lock
CHANGED
@@ -4,13 +4,14 @@ module GitlabQuality
|
|
4
4
|
module TestTooling
|
5
5
|
module KnapsackReports
|
6
6
|
class SpecRunTime
|
7
|
-
attr_reader :file, :expected, :actual, :expected_suite_duration, :actual_suite_duration
|
7
|
+
attr_reader :project, :file, :expected, :actual, :expected_suite_duration, :actual_suite_duration
|
8
8
|
|
9
9
|
ACTUAL_TO_EXPECTED_SPEC_RUN_TIME_RATIO_THRESHOLD = 1.5 # actual run time is longer than expected by 50% +
|
10
10
|
SPEC_WEIGHT_PERCENTAGE_TRESHOLD = 15 # a spec file takes 15%+ of the total test suite run time
|
11
11
|
SUITE_DURATION_THRESHOLD = 70 * 60 # if test suite takes more than 70 minutes, job risks timing out
|
12
12
|
|
13
|
-
def initialize(file:, expected:, actual:, expected_suite_duration:, actual_suite_duration:)
|
13
|
+
def initialize(project:, file:, expected:, actual:, expected_suite_duration:, actual_suite_duration:)
|
14
|
+
@project = project
|
14
15
|
@file = file
|
15
16
|
@expected = expected.to_f
|
16
17
|
@actual = actual.to_f
|
@@ -77,7 +78,7 @@ module GitlabQuality
|
|
77
78
|
end
|
78
79
|
|
79
80
|
def file_link
|
80
|
-
"
|
81
|
+
"https://gitlab.com/#{project}/-/blob/#{Runtime::Env.ci_commit_ref_name}/#{file}"
|
81
82
|
end
|
82
83
|
end
|
83
84
|
end
|
@@ -6,9 +6,10 @@ module GitlabQuality
|
|
6
6
|
module TestTooling
|
7
7
|
module KnapsackReports
|
8
8
|
class SpecRunTimeReport
|
9
|
-
attr_reader :expected_report, :actual_report
|
9
|
+
attr_reader :project, :expected_report, :actual_report
|
10
10
|
|
11
|
-
def initialize(expected_report_path:, actual_report_path:)
|
11
|
+
def initialize(project:, expected_report_path:, actual_report_path:)
|
12
|
+
@project = project
|
12
13
|
@expected_report = parse(expected_report_path)
|
13
14
|
@actual_report = parse(actual_report_path)
|
14
15
|
end
|
@@ -24,6 +25,7 @@ module GitlabQuality
|
|
24
25
|
end
|
25
26
|
|
26
27
|
spec_run_time = SpecRunTime.new(
|
28
|
+
project: project,
|
27
29
|
file: spec_file,
|
28
30
|
expected: expected_run_time,
|
29
31
|
actual: actual_run_time,
|
@@ -19,8 +19,6 @@ module GitlabQuality
|
|
19
19
|
ISSUE_STACKTRACE_REGEX = /##### Stack trace\s*(```)#{FAILURE_STACKTRACE_REGEX}(```)\n*/m
|
20
20
|
DEFAULT_MAX_DIFF_RATIO_FOR_DETECTION = 0.15
|
21
21
|
|
22
|
-
MultipleNotesFound = Class.new(StandardError)
|
23
|
-
|
24
22
|
def initialize(
|
25
23
|
base_issue_labels: nil,
|
26
24
|
max_diff_ratio: DEFAULT_MAX_DIFF_RATIO_FOR_DETECTION,
|
@@ -73,9 +71,7 @@ module GitlabQuality
|
|
73
71
|
relevant_notes = find_relevant_failure_discussion_note(issue: issue, test: test, reports_discussion: reports_discussion)
|
74
72
|
return if relevant_notes.empty?
|
75
73
|
|
76
|
-
best_matching_note,
|
77
|
-
|
78
|
-
raise(MultipleNotesFound, %(Too many issues found for test '#{test.name}' (`#{test.file}`)!)) unless relevant_notes.values.count(smaller_diff_ratio) == 1
|
74
|
+
best_matching_note, _ = relevant_notes.min_by { |_, diff_ratio| diff_ratio }
|
79
75
|
|
80
76
|
# Re-instantiate a `Gitlab::ObjectifiedHash` object after having converted it to a hash in #find_relevant_failure_issues above.
|
81
77
|
best_matching_note = Gitlab::ObjectifiedHash.new(best_matching_note)
|
@@ -16,7 +16,7 @@ module GitlabQuality
|
|
16
16
|
include Concerns::GroupAndCategoryLabels
|
17
17
|
include Concerns::IssueReports
|
18
18
|
|
19
|
-
BASE_SEARCH_LABELS
|
19
|
+
BASE_SEARCH_LABELS = ['test'].freeze
|
20
20
|
FOUND_IN_MR_LABEL = '~"found:in MR"'
|
21
21
|
FOUND_IN_MASTER_LABEL = '~"found:master"'
|
22
22
|
|
@@ -65,7 +65,7 @@ module GitlabQuality
|
|
65
65
|
def run!
|
66
66
|
puts "Reporting tests in `#{files.join(',')}` as issues in project `#{project}` via the API at `#{Runtime::Env.gitlab_api_base}`."
|
67
67
|
|
68
|
-
TestResults::Builder.new(file_glob: files).test_results_per_file do |test_results|
|
68
|
+
TestResults::Builder.new(file_glob: files, token: token, project: project).test_results_per_file do |test_results|
|
69
69
|
puts "=> Reporting #{test_results.count} tests in #{test_results.path}"
|
70
70
|
|
71
71
|
process_test_results(test_results)
|
@@ -133,8 +133,6 @@ module GitlabQuality
|
|
133
133
|
else
|
134
134
|
gitlab.create_issue_note(iid: issue.iid, note: note_body)
|
135
135
|
end
|
136
|
-
rescue MultipleNotesFound => e
|
137
|
-
warn(e.message)
|
138
136
|
end
|
139
137
|
|
140
138
|
def find_or_create_reports_discussion(issue:)
|
@@ -25,12 +25,12 @@ module GitlabQuality
|
|
25
25
|
|
26
26
|
private
|
27
27
|
|
28
|
-
attr_reader :
|
28
|
+
attr_reader :token, :project, :gitlab_merge_request, :files, :merge_request_iid, :slow_tests
|
29
29
|
|
30
30
|
def run!
|
31
31
|
puts "Reporting slow tests in MR #{merge_request_iid}"
|
32
32
|
|
33
|
-
TestResults::Builder.new(file_glob: files).test_results_per_file do |test_results|
|
33
|
+
TestResults::Builder.new(token: token, project: project, file_glob: files).test_results_per_file do |test_results|
|
34
34
|
puts "=> Reporting #{test_results.count} tests in #{test_results.path}"
|
35
35
|
|
36
36
|
@slow_tests += slow_related_tests(find_slow_tests(test_results))
|
@@ -52,7 +52,7 @@ module GitlabQuality
|
|
52
52
|
def run!
|
53
53
|
puts "Reporting test failures in `#{files.join(',')}` as issues in project `#{project}` via the API at `#{Runtime::Env.gitlab_api_base}`."
|
54
54
|
|
55
|
-
TestResults::Builder.new(file_glob: files).test_results_per_file do |test_results|
|
55
|
+
TestResults::Builder.new(token: token, project: project, file_glob: files).test_results_per_file do |test_results|
|
56
56
|
puts "=> Reporting #{test_results.count} tests in #{test_results.path}"
|
57
57
|
process_test_results(test_results)
|
58
58
|
end
|
@@ -9,6 +9,7 @@ module GitlabQuality
|
|
9
9
|
include Concerns::Utils
|
10
10
|
|
11
11
|
def initialize(token:, input_files:, related_issues_file: nil, project: nil, confidential: false, dry_run: false, **_kwargs)
|
12
|
+
@token = token
|
12
13
|
@project = project
|
13
14
|
@gitlab = (dry_run ? GitlabClient::IssuesDryClient : GitlabClient::IssuesClient).new(token: token, project: project)
|
14
15
|
@files = Array(input_files)
|
@@ -28,7 +29,7 @@ module GitlabQuality
|
|
28
29
|
|
29
30
|
private
|
30
31
|
|
31
|
-
attr_reader :gitlab, :files, :project, :issue_type, :confidential, :issue_logger
|
32
|
+
attr_reader :token, :gitlab, :files, :project, :issue_type, :confidential, :issue_logger
|
32
33
|
|
33
34
|
def run!
|
34
35
|
raise NotImplementedError
|
@@ -58,7 +59,7 @@ module GitlabQuality
|
|
58
59
|
| ------ | ------ |
|
59
60
|
| File URL | #{test.test_file_link} |
|
60
61
|
| Filename | `#{test.relative_file}` |
|
61
|
-
| Description |
|
62
|
+
| Description | `` #{test.name} `` |
|
62
63
|
| Test level | `#{test.level}` |
|
63
64
|
| Hash | `#{test_hash(test)}` |
|
64
65
|
| Max expected duration | < #{test.max_duration_for_test} seconds |
|
@@ -14,7 +14,7 @@ module GitlabQuality
|
|
14
14
|
def initialize(
|
15
15
|
test_case_project_token:, results_issue_project_token:, input_files:, test_case_project: nil, results_issue_project: nil, dry_run: false,
|
16
16
|
**kwargs)
|
17
|
-
@
|
17
|
+
@test_case_project_token = test_case_project_token
|
18
18
|
@testcase_project_reporter = GitlabQuality::TestTooling::Report::ResultsInTestCases.new(
|
19
19
|
token: test_case_project_token, input_files: input_files, project: test_case_project, dry_run: dry_run, **kwargs)
|
20
20
|
@results_issue_project_reporter = GitlabQuality::TestTooling::Report::ResultsInIssues.new(
|
@@ -32,12 +32,14 @@ module GitlabQuality
|
|
32
32
|
|
33
33
|
private
|
34
34
|
|
35
|
+
attr_reader :test_case_project_token
|
36
|
+
|
35
37
|
# rubocop:disable Metrics/AbcSize
|
36
38
|
def run!
|
37
39
|
puts "Reporting test results in `#{files.join(',')}` as test cases in project `#{test_case_project}` " \
|
38
40
|
"and issues in project `#{results_issue_project}` via the API at `#{Runtime::Env.gitlab_api_base}`."
|
39
41
|
|
40
|
-
TestResults::Builder.new(file_glob: files).test_results_per_file do |test_results|
|
42
|
+
TestResults::Builder.new(token: test_case_project_token, project: test_case_project, file_glob: files).test_results_per_file do |test_results|
|
41
43
|
puts "Reporting tests in #{test_results.path}"
|
42
44
|
|
43
45
|
test_results.each do |test|
|
@@ -17,6 +17,7 @@ module GitlabQuality
|
|
17
17
|
'CI_JOB_URL' => :ci_job_url,
|
18
18
|
'CI_PROJECT_ID' => :ci_project_id,
|
19
19
|
'CI_PROJECT_NAME' => :ci_project_name,
|
20
|
+
'CI_PROJECT_PATH' => :ci_project_path,
|
20
21
|
'CI_PIPELINE_ID' => :ci_pipeline_id,
|
21
22
|
'CI_PIPELINE_URL' => :ci_pipeline_url,
|
22
23
|
'SLACK_QA_CHANNEL' => :slack_qa_channel,
|
@@ -90,10 +91,6 @@ module GitlabQuality
|
|
90
91
|
"#{ci_project_name}-#{test_subset}"
|
91
92
|
end
|
92
93
|
|
93
|
-
def file_base_url
|
94
|
-
env_var_value_if_defined('FILE_BASE_URL') || "https://gitlab.com/gitlab-org/gitlab/-/blob/master/"
|
95
|
-
end
|
96
|
-
|
97
94
|
private
|
98
95
|
|
99
96
|
def enabled?(value, default: true)
|
@@ -13,8 +13,10 @@ module GitlabQuality
|
|
13
13
|
|
14
14
|
attr_reader :report
|
15
15
|
|
16
|
-
def initialize(report:,
|
16
|
+
def initialize(report:, token: '', project: Runtime::Env.ci_project_path, ref: Runtime::Env.ci_commit_ref_name)
|
17
17
|
@report = report
|
18
|
+
@token = token
|
19
|
+
@project = project
|
18
20
|
@ref = ref
|
19
21
|
end
|
20
22
|
|
@@ -58,6 +60,14 @@ module GitlabQuality
|
|
58
60
|
@file ||= relative_file.start_with?('qa/') ? "qa/#{relative_file}" : relative_file
|
59
61
|
end
|
60
62
|
|
63
|
+
def file_base_url
|
64
|
+
@file_base_url ||= "https://gitlab.com/#{project}/-/blob/#{ref}/"
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_file_link
|
68
|
+
"[`#{file}#L#{line_number}`](#{file_base_url}#{file}#L#{line_number})"
|
69
|
+
end
|
70
|
+
|
61
71
|
def full_stacktrace
|
62
72
|
failures.each do |failure|
|
63
73
|
message = failure['message'] || ""
|
@@ -79,15 +89,15 @@ module GitlabQuality
|
|
79
89
|
|
80
90
|
def files_client
|
81
91
|
@files_client ||= GitlabClient::RepositoryFilesClient.new(
|
82
|
-
token:
|
83
|
-
project:
|
92
|
+
token: token,
|
93
|
+
project: project,
|
84
94
|
file_path: file,
|
85
95
|
ref: ref)
|
86
96
|
end
|
87
97
|
|
88
98
|
private
|
89
99
|
|
90
|
-
attr_reader :ref
|
100
|
+
attr_reader :token, :project, :ref
|
91
101
|
end
|
92
102
|
end
|
93
103
|
end
|
@@ -98,14 +98,6 @@ module GitlabQuality
|
|
98
98
|
def failure_issue=(new_failure_issue)
|
99
99
|
report['failure_issue'] = new_failure_issue
|
100
100
|
end
|
101
|
-
|
102
|
-
def test_file_link
|
103
|
-
return "" if file.nil?
|
104
|
-
|
105
|
-
path_prefix = file.start_with?('qa/') ? 'qa/' : ''
|
106
|
-
|
107
|
-
"[`#{path_prefix}#{file}#L#{line_number}`](#{Runtime::Env.file_base_url}#{path_prefix}#{file}#L#{line_number})"
|
108
|
-
end
|
109
101
|
end
|
110
102
|
end
|
111
103
|
end
|
@@ -8,8 +8,10 @@ module GitlabQuality
|
|
8
8
|
|
9
9
|
attr_reader :path
|
10
10
|
|
11
|
-
def initialize(path:, ref: 'master')
|
11
|
+
def initialize(path:, token: nil, project: nil, ref: 'master')
|
12
12
|
@path = path
|
13
|
+
@token = token
|
14
|
+
@project = project
|
13
15
|
@ref = ref
|
14
16
|
@results = parse
|
15
17
|
@testcases = process
|
@@ -25,7 +27,7 @@ module GitlabQuality
|
|
25
27
|
|
26
28
|
private
|
27
29
|
|
28
|
-
attr_reader :results, :testcases, :ref
|
30
|
+
attr_reader :results, :testcases, :token, :project, :ref
|
29
31
|
|
30
32
|
def parse
|
31
33
|
raise NotImplementedError
|
@@ -4,8 +4,10 @@ module GitlabQuality
|
|
4
4
|
module TestTooling
|
5
5
|
module TestResults
|
6
6
|
class Builder
|
7
|
-
def initialize(file_glob:, ref: 'master')
|
7
|
+
def initialize(file_glob:, token: nil, project: nil, ref: 'master')
|
8
8
|
@file_glob = file_glob
|
9
|
+
@token = token
|
10
|
+
@project = project
|
9
11
|
@ref = ref
|
10
12
|
end
|
11
13
|
|
@@ -16,9 +18,9 @@ module GitlabQuality
|
|
16
18
|
test_results =
|
17
19
|
case extension
|
18
20
|
when '.json'
|
19
|
-
TestResults::JsonTestResults.new(path: path, ref: ref)
|
21
|
+
TestResults::JsonTestResults.new(path: path, token: token, project: project, ref: ref)
|
20
22
|
when '.xml'
|
21
|
-
TestResults::JUnitTestResults.new(path: path, ref: ref)
|
23
|
+
TestResults::JUnitTestResults.new(path: path, token: token, project: project, ref: ref)
|
22
24
|
else
|
23
25
|
raise "Unknown extension #{extension}"
|
24
26
|
end
|
@@ -29,7 +31,7 @@ module GitlabQuality
|
|
29
31
|
|
30
32
|
private
|
31
33
|
|
32
|
-
attr_reader :file_glob, :ref
|
34
|
+
attr_reader :file_glob, :token, :project, :ref
|
33
35
|
end
|
34
36
|
end
|
35
37
|
end
|
@@ -18,7 +18,7 @@ module GitlabQuality
|
|
18
18
|
|
19
19
|
def process
|
20
20
|
results.xpath('//testcase').map do |test|
|
21
|
-
GitlabQuality::TestTooling::TestResult::JUnitTestResult.new(report: test)
|
21
|
+
GitlabQuality::TestTooling::TestResult::JUnitTestResult.new(report: test, project: project, token: token)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -20,7 +20,7 @@ module GitlabQuality
|
|
20
20
|
|
21
21
|
def process
|
22
22
|
results['examples'].map do |test|
|
23
|
-
GitlabQuality::TestTooling::TestResult::JsonTestResult.new(report: test)
|
23
|
+
GitlabQuality::TestTooling::TestResult::JsonTestResult.new(report: test, project: project, token: token)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
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.
|
4
|
+
version: 1.31.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-
|
11
|
+
date: 2024-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: climate_control
|