gitlab_quality-test_tooling 1.14.2 → 1.15.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: 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