gitlab_quality-test_tooling 0.9.3 → 1.1.0

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: fa16a309741761cbce53a73d541cef1c6bb587cd790492cddc02face87e4338b
4
- data.tar.gz: 9cdba5b6c53c83adba07ce9cc0316568b4e8137955fe46faef7705b4b577a5d9
3
+ metadata.gz: 57cea55a73290299387eff651dac61af423656f7404afb4bd954d08d6f5d71f1
4
+ data.tar.gz: 4ef22d91d38fa5f85fe71d022e5a77a6081b4c9d536310e1f37d614d1b672d81
5
5
  SHA512:
6
- metadata.gz: dbb5472b2c4a5d70b26806c2467faae4a8b6770a2cf0ddc61f27e2c082f51459f5f8f7a4d640ec93ee3a8da0a126f5effdbae174d7aaf71d2054eddee0854529
7
- data.tar.gz: 98bdef30f3db77c15256ed2ef02e9b3550d8ed6d653e932f0550b35ba3b4f99bd899cedd518dd9a3e0e422ad07e232b2ee1eb1a3abfa2713927312a788c17ad5
6
+ metadata.gz: be4e9f1eea90fa1407058e8fe9cc1bf7dc02e86d9cbe4c3d69a30919e989505fe6ef882abdfdc6a29a3c5a0dbdfb61588c1e359fa800366f38e8f67355230a8f
7
+ data.tar.gz: 36419f06e594ff1d9c39b307d3868d1265bf4cbd68cfbc3e2ea991b594958b8d1e7280380e44526beaf4866376e8493722e2f564744c874824ce783f15b83b24
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab_quality-test_tooling (0.9.3)
4
+ gitlab_quality-test_tooling (1.1.0)
5
5
  activesupport (>= 6.1, < 7.1)
6
6
  gitlab (~> 4.19)
7
7
  http (~> 5.0)
data/README.md CHANGED
@@ -85,6 +85,9 @@ Usage: exe/relate-failure-issue [options]
85
85
  -t, --token TOKEN A valid access token with `api` scope and Maintainer permission in PROJECT
86
86
  --system-log-files SYSTEM_LOG_FILES
87
87
  Include errors from system logs in failure issues
88
+ --base-issue-labels BASE_ISSUE_LABELS
89
+ Labels to add to new failure issues
90
+ --confidential Makes created new issues confidential
88
91
  --dry-run Perform a dry-run (don't create or update issues)
89
92
  -v, --version Show the version
90
93
  -h, --help Show the usage
@@ -128,11 +131,28 @@ Purpose: Create slow test issues from JSON RSpec report files
128
131
  Usage: exe/slow-test-issue [options]
129
132
  -i, --input-files INPUT_FILES JSON RSpec report files JSON
130
133
  -p, --project PROJECT Can be an integer or a group/project string
134
+ -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)
136
+ -v, --version Show the version
137
+ -h, --help Show the usage
138
+ ```
139
+
140
+ ### `slow-test-merge-request-report-note`
141
+
142
+ ```shell
143
+ $ exe/slow-test-merge-request-report-note -h
144
+ Purpose: Create slow test note on merge requests from JSON RSpec report files
145
+ Usage: exe/slow-test-merge-request-report-note [options]
146
+ -i, --input-files INPUT_FILES JSON RSpec report files JSON
147
+ --project PROJECT Can be an integer or a group/project string
148
+ -m MERGE_REQUEST_IID, An integer merge request IID
149
+ --merge_request_iid
131
150
  -t, --token TOKEN A valid access token with `api` scope and Maintainer permission in PROJECT
132
151
  --dry-run Perform a dry-run (don't create issues)
133
152
  -v, --version Show the version
134
153
  -h, --help Show the usage
135
154
  ```
155
+
136
156
  ## Development
137
157
 
138
158
  ### Initial setup
@@ -37,6 +37,10 @@ options = OptionParser.new do |opts|
37
37
  params[:base_issue_labels] = base_issue_labels.split(',')
38
38
  end
39
39
 
40
+ opts.on('--confidential', "Makes created new issues confidential") do
41
+ params[:confidential] = true
42
+ end
43
+
40
44
  opts.on('--dry-run', "Perform a dry-run (don't create or update issues)") do
41
45
  params[:dry_run] = true
42
46
  end
@@ -0,0 +1,54 @@
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, 'JSON RSpec report files JSON') 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('-m', '--merge_request_iid MERGE_REQUEST_IID', String, 'An integer merge request IID') do |merge_request_iid|
23
+ params[:merge_request_iid] = merge_request_iid
24
+ end
25
+
26
+ opts.on('-t', '--token TOKEN', String, 'A valid access token with `api` scope and Maintainer permission in PROJECT') do |token|
27
+ params[:token] = token
28
+ end
29
+
30
+ opts.on('--dry-run', "Perform a dry-run (don't create note)") do
31
+ params[:dry_run] = true
32
+ end
33
+
34
+ opts.on_tail('-v', '--version', 'Show the version') do
35
+ require_relative "../lib/gitlab_quality/test_tooling/version"
36
+ puts "#{$PROGRAM_NAME} : #{GitlabQuality::TestTooling::VERSION}"
37
+ exit
38
+ end
39
+
40
+ opts.on_tail('-h', '--help', 'Show the usage') do
41
+ puts "Purpose: Create slow test note on merge requests from JSON RSpec report files"
42
+ puts opts
43
+ exit
44
+ end
45
+
46
+ opts.parse(ARGV)
47
+ end
48
+
49
+ if params.any?
50
+ GitlabQuality::TestTooling::Report::MergeRequestSlowTestsReport.new(**params).invoke!
51
+ else
52
+ puts options
53
+ exit 1
54
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gitlab'
4
+
5
+ module GitlabQuality
6
+ module TestTooling
7
+ module GitlabClient
8
+ class MergeRequest
9
+ def initialize(token:, project:, merge_request_iid:)
10
+ @token = token
11
+ @project = project
12
+ @merge_request_iid = merge_request_iid
13
+ end
14
+
15
+ def find_merge_request
16
+ client.merge_request_changes(project, merge_request_iid)
17
+ end
18
+
19
+ def merge_request_changed_files
20
+ find_merge_request["changes"].map do |change|
21
+ change["new_path"]
22
+ end
23
+ end
24
+
25
+ def find_note(body:)
26
+ client.merge_request_notes(project, merge_request_iid, per_page: 100).auto_paginate.find do |mr_note|
27
+ mr_note['body'] =~ /#{body}/
28
+ end
29
+ end
30
+
31
+ def create_note(note:)
32
+ client.create_merge_request_note(project, merge_request_iid, note)
33
+ end
34
+
35
+ def update_note(id:, note:)
36
+ client.edit_merge_request_note(project, merge_request_iid, id, note)
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :project, :token, :merge_request_iid
42
+
43
+ def client
44
+ @client ||= Gitlab.client(
45
+ endpoint: Runtime::Env.gitlab_api_base,
46
+ private_token: token
47
+ )
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitlabQuality
4
+ module TestTooling
5
+ module GitlabClient
6
+ class MergeRequestDryClient < MergeRequest
7
+ def find_merge_request
8
+ puts "Finding merge_request_id #{merge_request_iid}"
9
+ puts "project: #{project}"
10
+ end
11
+
12
+ def merge_request_changed_files
13
+ puts "Changed files for #{merge_request_iid}"
14
+ []
15
+ end
16
+
17
+ def find_note(body:)
18
+ puts "Find note for #{merge_request_iid} with body: #{body}"
19
+ end
20
+
21
+ def create_note(note:)
22
+ puts "The following note would have been created with body: #{note}"
23
+ end
24
+
25
+ def update_note(id:, note:)
26
+ puts "The following note would have been update id: #{id} with body: #{note}"
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -61,13 +61,14 @@ module GitlabQuality
61
61
  end
62
62
  end
63
63
 
64
- def create_issue(title:, description:, labels:, issue_type: 'issue', assignee_id: nil, due_date: nil)
64
+ def create_issue(title:, description:, labels:, issue_type: 'issue', assignee_id: nil, due_date: nil, confidential: false)
65
65
  attrs = {
66
66
  issue_type: issue_type,
67
67
  description: description,
68
68
  labels: labels,
69
69
  assignee_id: assignee_id,
70
- due_date: due_date
70
+ due_date: due_date,
71
+ confidential: confidential
71
72
  }.compact
72
73
 
73
74
  handle_gitlab_client_exceptions do
@@ -39,9 +39,7 @@ module GitlabQuality
39
39
 
40
40
  def fetch_group_sets(product_group)
41
41
  @group_sets = @stage_sets.select do |user|
42
- user['role'].include?(product_group.split("_").map do |word|
43
- word == 'and' ? word : word.capitalize
44
- end.join(" "))
42
+ user['role'].downcase.tr(' ', '_').include?(product_group)
45
43
  end
46
44
  end
47
45
  end
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GitlabQuality
4
+ module TestTooling
5
+ module Report
6
+ class MergeRequestSlowTestsReport
7
+ SLOW_TEST_MESSAGE = '<!-- slow-test -->'
8
+ SLOW_TEST_LABEL = '/label ~"rspec:slow test detected"'
9
+ SLOW_TEST_NOTE_SOURCE_CODE = 'Generated by [`gitlab_quality-test_tooling`](https://gitlab.com/gitlab-org/ruby/gems/gitlab_quality-test_tooling/-/blob/main/lib/gitlab_quality/test_tooling/report/merge_request_slow_tests_report.rb).'
10
+ SLOW_TEST_NOTE_FEEDBACK = 'Please [share your feedback and suggestions](https://gitlab.com/gitlab-org/quality/engineering-productivity/team/-/issues/289).'
11
+
12
+ def initialize(token:, input_files:, merge_request_iid:, project: nil, dry_run: false, **_kwargs)
13
+ @project = project
14
+ @gitlab_merge_request = (dry_run ? GitlabClient::MergeRequestDryClient : GitlabClient::MergeRequest).new(token: token, project: project,
15
+ merge_request_iid: merge_request_iid)
16
+ @files = Array(input_files)
17
+ @merge_request_iid = merge_request_iid
18
+ end
19
+
20
+ def invoke!
21
+ validate_input!
22
+
23
+ run!
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :gitlab_merge_request, :files, :project, :merge_request_iid
29
+
30
+ def run!
31
+ puts "Reporting slow tests in MR #{merge_request_iid}"
32
+
33
+ TestResults::Builder.new(files).test_results_per_file do |test_results|
34
+ puts "=> Reporting #{test_results.count} tests in #{test_results.path}"
35
+
36
+ upsert_mr_note(slow_related_tests(slow_tests(test_results))) if should_create_mr_note?(test_results)
37
+ end
38
+ end
39
+
40
+ def should_create_mr_note?(test_results)
41
+ gitlab_merge_request.merge_request_changed_files.any? &&
42
+ slow_tests(test_results).any? &&
43
+ slow_related_tests(slow_tests(test_results)).any?
44
+ end
45
+
46
+ def slow_related_tests(slow_test_results)
47
+ slow_test_results.select do |slow_test_result|
48
+ base_file = slow_test_result.file.split('/').last.gsub('_spec.rb', '')
49
+
50
+ merge_request_changed_files.any? { |change| change =~ /#{base_file}/ }
51
+ end
52
+ end
53
+
54
+ def merge_request_changed_files
55
+ @merge_request_changed_files ||= gitlab_merge_request.merge_request_changed_files
56
+ end
57
+
58
+ def slow_tests(test_results)
59
+ test_results.select(&:slow_test?)
60
+ end
61
+
62
+ def note_header
63
+ [
64
+ SLOW_TEST_MESSAGE,
65
+ SLOW_TEST_LABEL,
66
+ ":tools: #{SLOW_TEST_NOTE_SOURCE_CODE}\n",
67
+ ":recycle: #{SLOW_TEST_NOTE_FEEDBACK}\n",
68
+ "---\n",
69
+ ':snail: Slow tests detected in this merge request, might be related with changed RSpec files.',
70
+ '| Job | File | Name | Duration | Expected duration |',
71
+ '| --- | --- | --- | --- | --- |'
72
+ ]
73
+ end
74
+
75
+ def slow_test_rows(slow_test)
76
+ rows = []
77
+
78
+ slow_test.each do |test|
79
+ rows << slow_test_table_row(test)
80
+ end
81
+
82
+ rows
83
+ end
84
+
85
+ def build_note(slow_test)
86
+ rows = note_header + slow_test_rows(slow_test)
87
+
88
+ rows.join("\n")
89
+ end
90
+
91
+ def note_comment_includes_slow_test?(gitlab_note, slow_test)
92
+ gitlab_note.include?("[##{slow_test.ci_job_id}](#{slow_test.ci_job_url}) | #{slow_test.test_file_link}")
93
+ end
94
+
95
+ def slow_test_table_row(slow_test)
96
+ row = [
97
+ "[##{slow_test.ci_job_id}](#{slow_test.ci_job_url})",
98
+ slow_test.test_file_link,
99
+ slow_test.name,
100
+ "#{slow_test.run_time} s",
101
+ "< #{slow_test.max_duration_for_test} s"
102
+ ]
103
+
104
+ "| #{row.join(' | ')} |"
105
+ end
106
+
107
+ def add_slow_test_rows(gitlab_note, slow_tests)
108
+ slow_tests.each do |slow_test|
109
+ gitlab_note += "\n#{slow_test_table_row(slow_test)}" unless note_comment_includes_slow_test?(gitlab_note, slow_test)
110
+ end
111
+
112
+ gitlab_note
113
+ end
114
+
115
+ def upsert_mr_note(slow_tests)
116
+ existing_note = gitlab_merge_request.find_note(body: SLOW_TEST_MESSAGE)
117
+
118
+ if existing_note
119
+ puts "Update note for merge request: #{merge_request_iid}"
120
+
121
+ up_to_date_note = add_slow_test_rows(existing_note.body, slow_tests)
122
+
123
+ gitlab_merge_request.update_note(id: existing_note['id'], note: up_to_date_note) if existing_note.body != up_to_date_note
124
+ else
125
+ up_to_date_note = build_note(slow_tests)
126
+
127
+ puts "Create note for merge request: #{merge_request_iid}"
128
+
129
+ gitlab_merge_request.create_note(note: up_to_date_note)
130
+ end
131
+ end
132
+
133
+ def validate_input!
134
+ assert_project!
135
+ assert_input_files!(files)
136
+ end
137
+
138
+ def assert_project!
139
+ return if project
140
+
141
+ abort "Please provide a valid project ID or path with the `-p/--project` option!"
142
+ end
143
+
144
+ def assert_input_files!(files)
145
+ return if Dir.glob(files).any?
146
+
147
+ abort "Please provide valid JUnit report files. No files were found matching `#{files.join(',')}`"
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -8,23 +8,11 @@ module GitlabQuality
8
8
  class ReportAsIssue
9
9
  include Concerns::Utils
10
10
 
11
- FILE_BASE_URL = "https://gitlab.com/gitlab-org/gitlab/-/blob/master/"
12
-
13
- OTHER_TESTS_MAX_DURATION = 45.40 # seconds
14
-
15
- TestLevelSpecification = Struct.new(:regex, :max_duration)
16
-
17
- TEST_LEVEL_SPECIFICATIONS = [
18
- TestLevelSpecification.new(%r{spec/features/}, 50.13),
19
- TestLevelSpecification.new(%r{spec/(controllers|requests)/}, 19.20),
20
- TestLevelSpecification.new(%r{spec/lib/}, 27.12),
21
- TestLevelSpecification.new(%r{qa/specs/features/}, 240)
22
- ].freeze
23
-
24
- def initialize(token:, input_files:, project: nil, dry_run: false, **_kwargs)
11
+ def initialize(token:, input_files:, project: nil, confidential: false, dry_run: false, **_kwargs)
25
12
  @project = project
26
13
  @gitlab = (dry_run ? GitlabIssueDryClient : GitlabIssueClient).new(token: token, project: project)
27
14
  @files = Array(input_files)
15
+ @confidential = confidential
28
16
  end
29
17
 
30
18
  def invoke!
@@ -35,7 +23,7 @@ module GitlabQuality
35
23
 
36
24
  private
37
25
 
38
- attr_reader :gitlab, :files, :project, :issue_type
26
+ attr_reader :gitlab, :files, :project, :issue_type, :confidential
39
27
 
40
28
  def run!
41
29
  raise NotImplementedError
@@ -51,22 +39,16 @@ module GitlabQuality
51
39
 
52
40
  | Field | Value |
53
41
  | ------ | ------ |
54
- | File | #{test_file_link(test)} |
42
+ | File | #{test.test_file_link} |
55
43
  | Description | `#{test.name}` |
56
44
  | Test level | #{test.level} |
57
45
  | Hash | `#{test_hash(test)}` |
58
46
  | Duration | #{test.run_time} seconds |
59
- | Expected duration | < #{max_duration_for_test(test)} seconds |
47
+ | Expected duration | < #{test.max_duration_for_test} seconds |
60
48
  #{"| Test case | #{test.testcase} |" if test.testcase}
61
49
  DESCRIPTION
62
50
  end
63
51
 
64
- def test_file_link(test)
65
- path_prefix = test.file.start_with?('qa/') ? 'qa/' : ''
66
-
67
- "[`#{path_prefix}#{test.file}#L#{test.line_number}`](#{FILE_BASE_URL}#{path_prefix}#{test.file}#L#{test.line_number})"
68
- end
69
-
70
52
  def new_issue_labels(_test)
71
53
  []
72
54
  end
@@ -104,7 +86,8 @@ module GitlabQuality
104
86
  labels: new_issue_labels(test).to_a,
105
87
  issue_type: issue_type,
106
88
  assignee_id: new_issue_assignee_id(test),
107
- due_date: new_issue_due_date(test)
89
+ due_date: new_issue_due_date(test),
90
+ confidential: confidential
108
91
  }.compact
109
92
  issue = gitlab.create_issue(**attrs)
110
93
 
@@ -161,6 +144,8 @@ module GitlabQuality
161
144
  'found:pre.gitlab.com'
162
145
  when 'nightly', Runtime::Env.default_branch, 'staging-ref', 'release'
163
146
  "found:#{pipeline}"
147
+ when 'customers-gitlab-com'
148
+ 'found:customers.stg.gitlab.com'
164
149
  else
165
150
  raise "No `found:*` label for the `#{pipeline}` pipeline!"
166
151
  end
@@ -169,15 +154,6 @@ module GitlabQuality
169
154
  def ee_test?(test)
170
155
  test.file =~ %r{features/ee/(api|browser_ui)}
171
156
  end
172
-
173
- def max_duration_for_test(test)
174
- test_level_specification = TEST_LEVEL_SPECIFICATIONS.find do |test_level_specification|
175
- test.example_id =~ test_level_specification.regex
176
- end
177
- return OTHER_TESTS_MAX_DURATION unless test_level_specification
178
-
179
- test_level_specification.max_duration
180
- end
181
157
  end
182
158
  end
183
159
  end
@@ -27,7 +27,7 @@ module GitlabQuality
27
27
  puts "=> Reporting #{test_results.count} tests in #{test_results.path}"
28
28
 
29
29
  test_results.each do |test|
30
- create_slow_issue(test) if should_create_slow_issue?(test)
30
+ create_slow_issue(test) if test.slow_test?
31
31
  end
32
32
  end
33
33
  end
@@ -59,10 +59,6 @@ module GitlabQuality
59
59
  rescue MultipleIssuesFound => e
60
60
  warn(e.message)
61
61
  end
62
-
63
- def should_create_slow_issue?(test)
64
- !test.allowed_to_be_slow? && test.run_time > max_duration_for_test(test)
65
- end
66
62
  end
67
63
  end
68
64
  end
@@ -4,8 +4,21 @@ module GitlabQuality
4
4
  module TestTooling
5
5
  module TestResult
6
6
  class JsonTestResult < BaseTestResult
7
+ FILE_BASE_URL = "https://gitlab.com/gitlab-org/gitlab/-/blob/master/"
8
+
7
9
  PRIVATE_TOKEN_REGEX = /(private_token=)[\w-]+/
8
10
 
11
+ OTHER_TESTS_MAX_DURATION = 45.40 # seconds
12
+
13
+ TestLevelSpecification = Struct.new(:regex, :max_duration)
14
+
15
+ TEST_LEVEL_SPECIFICATIONS = [
16
+ TestLevelSpecification.new(%r{spec/features/}, 50.13),
17
+ TestLevelSpecification.new(%r{spec/(controllers|requests)/}, 19.20),
18
+ TestLevelSpecification.new(%r{spec/lib/}, 27.12),
19
+ TestLevelSpecification.new(%r{qa/specs/features/}, 240)
20
+ ].freeze
21
+
9
22
  def name
10
23
  report.fetch('full_description')
11
24
  end
@@ -93,6 +106,10 @@ module GitlabQuality
93
106
  report['level']
94
107
  end
95
108
 
109
+ def ci_job_id
110
+ report['ci_job_url'].split('/').last
111
+ end
112
+
96
113
  def failures # rubocop:disable Metrics/AbcSize
97
114
  @failures ||=
98
115
  report.fetch('exceptions', []).filter_map do |exception|
@@ -123,6 +140,25 @@ module GitlabQuality
123
140
  !!report['allowed_to_be_slow']
124
141
  end
125
142
 
143
+ def slow_test?
144
+ !allowed_to_be_slow? && run_time > max_duration_for_test
145
+ end
146
+
147
+ def max_duration_for_test
148
+ test_level_specification = TEST_LEVEL_SPECIFICATIONS.find do |test_level_specification|
149
+ example_id =~ test_level_specification.regex
150
+ end
151
+ return OTHER_TESTS_MAX_DURATION unless test_level_specification
152
+
153
+ test_level_specification.max_duration
154
+ end
155
+
156
+ def test_file_link
157
+ path_prefix = file.start_with?('qa/') ? 'qa/' : ''
158
+
159
+ "[`#{path_prefix}#{file}#L#{line_number}`](#{FILE_BASE_URL}#{path_prefix}#{file}#L#{line_number})"
160
+ end
161
+
126
162
  private
127
163
 
128
164
  def quarantine
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GitlabQuality
4
4
  module TestTooling
5
- VERSION = "0.9.3"
5
+ VERSION = "1.1.0"
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: 0.9.3
4
+ version: 1.1.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: 2023-07-26 00:00:00.000000000 Z
11
+ date: 2023-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -324,6 +324,7 @@ executables:
324
324
  - relate-failure-issue
325
325
  - report-results
326
326
  - slow-test-issues
327
+ - slow-test-merge-request-report-note
327
328
  - update-screenshot-paths
328
329
  extensions: []
329
330
  extra_rdoc_files: []
@@ -348,9 +349,12 @@ files:
348
349
  - exe/relate-failure-issue
349
350
  - exe/report-results
350
351
  - exe/slow-test-issues
352
+ - exe/slow-test-merge-request-report-note
351
353
  - exe/update-screenshot-paths
352
354
  - lefthook.yml
353
355
  - lib/gitlab_quality/test_tooling.rb
356
+ - lib/gitlab_quality/test_tooling/gitlab_client/merge_request.rb
357
+ - lib/gitlab_quality/test_tooling/gitlab_client/merge_request_dry_client.rb
354
358
  - lib/gitlab_quality/test_tooling/gitlab_issue_client.rb
355
359
  - lib/gitlab_quality/test_tooling/gitlab_issue_dry_client.rb
356
360
  - lib/gitlab_quality/test_tooling/labels_inference.rb
@@ -359,6 +363,7 @@ files:
359
363
  - lib/gitlab_quality/test_tooling/report/concerns/results_reporter.rb
360
364
  - lib/gitlab_quality/test_tooling/report/concerns/utils.rb
361
365
  - lib/gitlab_quality/test_tooling/report/generate_test_session.rb
366
+ - lib/gitlab_quality/test_tooling/report/merge_request_slow_tests_report.rb
362
367
  - lib/gitlab_quality/test_tooling/report/prepare_stage_reports.rb
363
368
  - lib/gitlab_quality/test_tooling/report/relate_failure_issue.rb
364
369
  - lib/gitlab_quality/test_tooling/report/report_as_issue.rb