gitlab_quality-test_tooling 1.14.2 → 1.15.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14bec41f34b3f27d3e5c1c6fe900e918a78d1fbf2e2e44f05e18abb68e533e35
4
- data.tar.gz: 2613da07d940b2b4c9ee096600417a963fbf670bd5b9b3ecb44263f50775e486
3
+ metadata.gz: 8364acd36abab9ce89c0846c346b893ca041a6a740ced7dc5c784da5990ea74c
4
+ data.tar.gz: 9468d8b559aeec587f9c3722e4f6e9d539d790828f9ecc7f815cc39ca22f2657
5
5
  SHA512:
6
- metadata.gz: 220ca8d8ced57c9a2294f83ae4bfaacdf293ed4945bd5c986075001a0c302c98b8ddc1aa27bd735b9df8c474a56b9795f8fb44e2a35396d5900799dca0720237
7
- data.tar.gz: 90af1e3e738f9196bbd8dfa20b4bb973e875e1b1d24eb1e2b6a4de5186e2fb17cfe3eff2b76e02c683e7509a806daf34b71bd8fff0499e23ca0ad0959cc54176
6
+ metadata.gz: 4d287ca74d5fe7bc1bd9acd25541eb6f150f717f95f9e8c0bdf7a53ac139f3dab5186565ec74f2f7279e50dd47268d22121eb94ba2e3955cc5f6de33e7a952c0
7
+ data.tar.gz: e2954fea3d65bdce6e72f26a201965f45cc3aab583a34af9835f4d42f71540ad21582f4f8a96a12cd377a949644ab458ea213febfb2e6e90fbdc25c1867ddb72
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab_quality-test_tooling (1.14.2)
4
+ gitlab_quality-test_tooling (1.15.0)
5
5
  activesupport (>= 6.1, < 7.1)
6
6
  amatch (~> 0.4.1)
7
7
  gitlab (~> 4.19)
@@ -10,7 +10,7 @@ module GitlabQuality
10
10
  end
11
11
  end
12
12
 
13
- def create_merge_request(title:, source_branch:, target_branch:, description:, labels:, assignee_id: nil)
13
+ def create_merge_request(title:, source_branch:, target_branch:, description:, labels:, assignee_id: nil, reviewer_ids: [])
14
14
  attrs = {
15
15
  source_branch: source_branch,
16
16
  target_branch: target_branch,
@@ -18,7 +18,8 @@ module GitlabQuality
18
18
  labels: labels,
19
19
  assignee_id: assignee_id,
20
20
  squash: true,
21
- remove_source_branch: true
21
+ remove_source_branch: true,
22
+ reviewer_ids: reviewer_ids
22
23
  }.compact
23
24
 
24
25
  merge_request = handle_gitlab_client_exceptions do
@@ -26,10 +26,11 @@ module GitlabQuality
26
26
  puts "The following note would have been updated id: #{id} with body: #{note} for mr_iid: #{merge_request_iid}"
27
27
  end
28
28
 
29
- def create_merge_request(title:, source_branch:, target_branch:, description:, labels:, assignee_id:)
29
+ def create_merge_request(title:, source_branch:, target_branch:, description:, labels:, assignee_id:, reviewer_ids:)
30
30
  puts "A merge request would be created with title: #{title} " \
31
31
  "source_branch: #{source_branch} target_branch: #{target_branch} " \
32
- "description: #{description} labels: #{labels}, assignee_id: #{assignee_id}"
32
+ "description: #{description} labels: #{labels}, assignee_id: #{assignee_id}" \
33
+ "reviewer_ids: #{reviewer_ids}"
33
34
  end
34
35
  end
35
36
  end
@@ -268,7 +268,7 @@ module GitlabQuality
268
268
  if stacktrace_match
269
269
  stacktrace_match[:stacktrace].gsub(/^\s*#.*$/, '').gsub(/^[[:space:]]+/, '').strip
270
270
  else
271
- puts " => [DEBUG] Stacktrace doesn't match the regex (#{regex}):\n----------------\n#{stacktrace}\n----------------\n"
271
+ puts " => [DEBUG] Stacktrace doesn't match the regex (#{regex})!"
272
272
  end
273
273
  end
274
274
 
@@ -33,6 +33,10 @@ module GitlabQuality
33
33
  env_var_value_if_defined('QA_LOG_LEVEL')&.upcase || 'INFO'
34
34
  end
35
35
 
36
+ def gitlab_bot_username
37
+ env_var_value_if_defined('GITLAB_BOT_USERNAME') || 'gitlab-bot'
38
+ end
39
+
36
40
  def log_path
37
41
  env_var_value_if_defined('QA_LOG_PATH') || host_artifacts_dir
38
42
  end
@@ -14,38 +14,39 @@ module GitlabQuality
14
14
  # @param [TestMetaUpdater] context instance of TestMetaUpdater
15
15
  def execute(spec, context) # rubocop:disable Metrics/AbcSize
16
16
  @context = context
17
-
17
+ @existing_mrs = nil
18
18
  @file_path = spec["file_path"]
19
19
  devops_stage = spec["stage"]
20
20
  product_group = spec["product_group"]
21
21
  @example_name = spec["name"]
22
22
  @mr_title = format("%{prefix} %{example_name}", prefix: '[PROMOTE TO BLOCKING]', example_name: example_name)
23
23
 
24
- return unless proceed_with_merge_request?
25
-
26
24
  @file_contents = context.get_file_contents(file_path)
27
25
 
28
- new_content, changed_line_no = add_blocking_metadata
26
+ new_content, @changed_line_no = add_blocking_metadata
29
27
 
30
- return if changed_line_no.negative?
28
+ return unless proceed_with_merge_request?
31
29
 
32
30
  branch = context.create_branch("blocking-promotion-#{SecureRandom.hex(4)}", example_name, context.ref)
33
31
 
34
32
  context.commit_changes(branch, <<~COMMIT_MESSAGE, file_path, new_content)
35
33
  Promote end-to-end test to blocking
36
34
 
37
- Promote to blocking: #{example_name}
35
+ #{"Promote to blocking: #{example_name}".truncate(72)}
38
36
  COMMIT_MESSAGE
39
37
 
40
- assignee_id, assignee_handle = context.fetch_dri_id(product_group, devops_stage)
38
+ reviewer_id, assignee_handle = context.fetch_dri_id(product_group, devops_stage)
39
+
40
+ gitlab_bot_user_id = context.user_id_for_username(Runtime::Env.gitlab_bot_username)
41
41
 
42
- merge_request = context.create_merge_request(mr_title, branch, assignee_id) do
42
+ merge_request = context.create_merge_request(mr_title, branch, gitlab_bot_user_id, [reviewer_id]) do
43
43
  <<~MARKDOWN
44
44
  ## What does this MR do?
45
45
 
46
46
  Promotes the test [`#{example_name}`](https://gitlab.com/#{context.project}/-/blob/#{context.ref}/#{file_path}#L#{changed_line_no + 1})
47
47
  to the blocking bucket
48
48
 
49
+ This test was identified in the reliable e2e test report: #{context.report_issue}
49
50
 
50
51
  /label ~"Quality" ~"QA" ~"type::maintenance"
51
52
  /label ~"devops::#{devops_stage}"
@@ -62,6 +63,11 @@ module GitlabQuality
62
63
  If you think this MR should not be merged, please close it and add a note of the reason to the blocking report: #{context.report_issue}
63
64
  MARKDOWN
64
65
 
66
+ if merge_request
67
+ context.add_processed_record({ file_path => changed_line_no })
68
+ Runtime::Logger.info(" Created MR for promotion to blocking: #{merge_request.web_url}")
69
+ end
70
+
65
71
  merge_request
66
72
  end
67
73
 
@@ -82,15 +88,20 @@ module GitlabQuality
82
88
 
83
89
  private
84
90
 
85
- attr_reader :context, :file_path, :file_contents, :example_name, :mr_title
91
+ attr_reader :context, :file_path, :file_contents, :example_name, :mr_title, :changed_line_no
86
92
 
87
93
  # Checks if there is already an MR open
88
94
  #
89
95
  # @return [Boolean]
90
- def proceed_with_merge_request?
91
- open_mrs = context.existing_merge_requests(title: mr_title)
92
- if open_mrs&.any?
93
- puts " An open MR already exists for '#{example_name}': #{open_mrs.first['web_url']}. Will not proceed with creating MR."
96
+ def proceed_with_merge_request? # rubocop:disable Metrics/AbcSize
97
+ if changed_line_no.negative?
98
+ Runtime::Logger.info(" No lines were changed in #{file_path}. Will not proceed with creating MR.")
99
+ return false
100
+ elsif context.record_processed?(file_path, changed_line_no)
101
+ Runtime::Logger.info(" Record already processed for #{file_path}:#{changed_line_no}. Will not proceed with creating MR.")
102
+ return false
103
+ elsif existing_mrs&.any?
104
+ Runtime::Logger.info(" An open MR already exists for '#{example_name}': #{existing_mrs.first['web_url']}. Will not proceed with creating MR.")
94
105
  return false
95
106
  end
96
107
 
@@ -24,7 +24,7 @@ module GitlabQuality
24
24
  # @param [TestMetaUpdater] context instance of TestMetaUpdater
25
25
  def execute(spec, context) # rubocop:disable Metrics/AbcSize
26
26
  @context = context
27
-
27
+ @existing_mrs = nil
28
28
  @file_path = spec["file_path"]
29
29
  devops_stage = spec["stage"]
30
30
  @failure_issue_url = spec["failure_issue"]
@@ -33,21 +33,23 @@ module GitlabQuality
33
33
  @mr_title = format("%{prefix} %{example_name}", prefix: '[QUARANTINE]', example_name: example_name)
34
34
  @failure_issue = context.fetch_issue(iid: issue_id)
35
35
 
36
- return unless proceed_with_merge_request?
37
-
38
36
  @file_contents = context.get_file_contents(file_path)
39
37
 
40
- new_content, changed_line_no = add_quarantine_metadata
38
+ new_content, @changed_line_no = add_quarantine_metadata
39
+
40
+ return unless proceed_with_merge_request?
41
41
 
42
42
  branch = context.create_branch("#{issue_id}-quarantine-#{SecureRandom.hex(4)}", example_name, context.ref)
43
43
 
44
44
  context.commit_changes(branch, <<~COMMIT_MESSAGE, file_path, new_content)
45
45
  Quarantine end-to-end test
46
46
 
47
- Quarantine #{example_name}
47
+ #{"Quarantine #{example_name}".truncate(72)}
48
48
  COMMIT_MESSAGE
49
49
 
50
- context.create_merge_request(mr_title, branch) do
50
+ gitlab_bot_user_id = context.user_id_for_username(Runtime::Env.gitlab_bot_username)
51
+
52
+ merge_request = context.create_merge_request(mr_title, branch, gitlab_bot_user_id) do
51
53
  <<~MARKDOWN
52
54
  ## What does this MR do?
53
55
 
@@ -85,6 +87,13 @@ module GitlabQuality
85
87
  </div>
86
88
  MARKDOWN
87
89
  end
90
+
91
+ if merge_request
92
+ context.add_processed_record({ file_path => changed_line_no })
93
+ Runtime::Logger.info(" Created MR for quarantine: #{merge_request.web_url}")
94
+ end
95
+
96
+ merge_request
88
97
  end
89
98
 
90
99
  # Performs post processing. Takes a list of MRs and posts them in a note on report_issue and Slack
@@ -114,20 +123,21 @@ module GitlabQuality
114
123
 
115
124
  private
116
125
 
117
- attr_reader :context, :file_path, :file_contents, :failure_issue_url, :example_name, :issue_id, :mr_title, :failure_issue
126
+ attr_reader :context, :file_path, :file_contents, :failure_issue_url, :example_name,
127
+ :issue_id, :mr_title, :failure_issue, :changed_line_no
118
128
 
119
129
  # Checks if the failure issue is closed or if there is already an MR open
120
130
  #
121
131
  # @return [Boolean]
122
- def proceed_with_merge_request?
132
+ def proceed_with_merge_request? # rubocop:disable Metrics/AbcSize
123
133
  if context.issue_is_closed?(failure_issue)
124
- puts " Failure issue '#{failure_issue_url}' is closed. Will not proceed with creating MR."
134
+ Runtime::Logger.info(" Failure issue '#{failure_issue_url}' is closed. Will not proceed with creating MR.")
125
135
  return false
126
- end
127
-
128
- open_mrs = context.existing_merge_requests(title: mr_title)
129
- if open_mrs.any?
130
- puts " An open MR already exists for '#{example_name}': #{open_mrs.first['web_url']}. Will not proceed with creating MR."
136
+ elsif context.record_processed?(file_path, changed_line_no)
137
+ Runtime::Logger.info(" Record already processed for #{file_path}:#{changed_line_no}. Will not proceed with creating MR.")
138
+ return false
139
+ elsif existing_mrs&.any?
140
+ Runtime::Logger.info(" An open MR already exists for '#{example_name}': #{existing_mrs.first['web_url']}. Will not proceed with creating MR.")
131
141
  return false
132
142
  end
133
143
 
@@ -144,7 +154,7 @@ module GitlabQuality
144
154
  indentation = context.indentation(line)
145
155
 
146
156
  if line.include?(',') && line.split.last != 'do'
147
- line[line.index(',')] = format(QUARANTINE_METADATA.rstrip, issue_url: failure_issue_url, indentation: indentation, suffix: ',', quarantine_type: quarantine_type)
157
+ line[line.rindex(',')] = format(QUARANTINE_METADATA.rstrip, issue_url: failure_issue_url, indentation: indentation, suffix: ',', quarantine_type: quarantine_type)
148
158
  else
149
159
  line[line.rindex(' ')] = format(QUARANTINE_METADATA.rstrip, issue_url: failure_issue_url, indentation: indentation, suffix: ' ', quarantine_type: quarantine_type)
150
160
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/core_ext/string/filters'
4
+
3
5
  module GitlabQuality
4
6
  module TestTooling
5
7
  module TestMeta
@@ -15,6 +17,13 @@ module GitlabQuality
15
17
  end
16
18
 
17
19
  private_class_method :new
20
+
21
+ # Fetch existing MRs for given mr title
22
+ #
23
+ # @return [Array<Gitlab::ObjectifiedHash>]
24
+ def existing_mrs
25
+ @existing_mrs ||= context.existing_merge_requests(title: mr_title)
26
+ end
18
27
  end
19
28
  end
20
29
  end
@@ -8,7 +8,7 @@ module GitlabQuality
8
8
  class TestMetaUpdater
9
9
  include TestTooling::Concerns::FindSetDri
10
10
 
11
- attr_reader :project, :ref, :report_issue
11
+ attr_reader :project, :ref, :report_issue, :processed_records
12
12
 
13
13
  TEST_PLATFORM_MAINTAINERS_SLACK_CHANNEL_ID = 'C0437FV9KBN' # test-platform-maintainers
14
14
 
@@ -19,6 +19,7 @@ module GitlabQuality
19
19
  @ref = ref
20
20
  @dry_run = dry_run
21
21
  @processor = processor
22
+ @processed_records = {}
22
23
  end
23
24
 
24
25
  def invoke!
@@ -33,10 +34,20 @@ module GitlabQuality
33
34
  end
34
35
  end
35
36
 
37
+ # Add processed records
38
+ #
39
+ # @param [Hash<String,Integer>] record the processed record
40
+ # @option record [String] :file_path the path to the spec file
41
+ # @option spec [Intenger] :changed_line_no the line number change in file_path
42
+ # @return [Hash<String,Integer>] processed_records
43
+ def add_processed_record(record)
44
+ @processed_records.merge!(record)
45
+ end
46
+
36
47
  # Fetch contents of file from the repository
37
48
  #
38
- # [String] file_path path to the file
39
- # [String] contents of the file
49
+ # @param [String] file_path path to the file
50
+ # @return [String] contents of the file
40
51
  def get_file_contents(file_path)
41
52
  repository_files = GitlabClient::RepositoryFilesClient.new(token: token, project: project, file_path: file_path)
42
53
  repository_files.file_contents
@@ -110,8 +121,10 @@ module GitlabQuality
110
121
  # @param [String] example_name the example
111
122
  # @param [Gitlab::ObjectifiedHash] branch the branch
112
123
  # @param [Integer] assignee_id
124
+ # @param [Array<Integer>] reviewer_ids
125
+ # @param [String] labels comma seperated list of labels
113
126
  # @return [Gitlab::ObjectifiedHash] the created merge request
114
- def create_merge_request(title, branch, assignee_id = nil, labels = '')
127
+ def create_merge_request(title, branch, assignee_id = nil, reviewer_ids = [], labels = '')
115
128
  description = yield
116
129
 
117
130
  merge_request_client.create_merge_request(
@@ -120,7 +133,8 @@ module GitlabQuality
120
133
  target_branch: ref,
121
134
  description: description,
122
135
  labels: labels,
123
- assignee_id: assignee_id)
136
+ assignee_id: assignee_id,
137
+ reviewer_ids: reviewer_ids)
124
138
  end
125
139
 
126
140
  # Check if issue is closed
@@ -179,7 +193,15 @@ module GitlabQuality
179
193
  def fetch_dri_id(product_group, devops_stage)
180
194
  assignee_handle = ENV.fetch('QA_TEST_DRI_HANDLE', nil) || set_dri_via_group(product_group, devops_stage)
181
195
 
182
- [issue_client.find_user_id(username: assignee_handle), assignee_handle]
196
+ [user_id_for_username(assignee_handle), assignee_handle]
197
+ end
198
+
199
+ # Fetch id for the given GitLab username/handle
200
+ #
201
+ # @param [String] username
202
+ # @return [Integer]
203
+ def user_id_for_username(username)
204
+ issue_client.find_user_id(username: username)
183
205
  end
184
206
 
185
207
  # Post a message on Slack
@@ -221,6 +243,15 @@ module GitlabQuality
221
243
  merge_request_client.find(options: { search: title, in: 'title', state: 'opened' })
222
244
  end
223
245
 
246
+ # Checks if changes has already been made to given file and line number
247
+ #
248
+ # @param [String] file_path path to the file
249
+ # @param [Integer] changed_line_no updated line number
250
+ # @return [Boolean]
251
+ def record_processed?(file_path, changed_line_no)
252
+ processed_records[file_path] && processed_records[file_path] == changed_line_no
253
+ end
254
+
224
255
  private
225
256
 
226
257
  attr_reader :token, :specs_file, :dry_run, :processor
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GitlabQuality
4
4
  module TestTooling
5
- VERSION = "1.14.2"
5
+ VERSION = "1.15.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: 1.14.2
4
+ version: 1.15.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-01-31 00:00:00.000000000 Z
11
+ date: 2024-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control