gitlab-qa 5.17.1 → 6.0.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: d14680b847d514a92a3db02e62d17566d165c3aa2fa7772cbf4cdb5eb3746d6f
4
- data.tar.gz: f8669ae124311588e59bd52f743b5aafb41a2f7ca40073f12eae28f860e7f54a
3
+ metadata.gz: 87249baf75070cf8c5362c34b9995f6163370e9b6e353a393104beefe62d4bd8
4
+ data.tar.gz: 6e00eee6993c9f5c6aeb4cb187c708941bfd27cb9b59340165b23b02c30f583a
5
5
  SHA512:
6
- metadata.gz: be1aa1c90f7bbfe3e9fab71640f14517d212d5dbfcd5d412e2576b1c6553ad445a2530088f9999fee9fa02cf3bc813f3ee23ae1f2474b2d48a4e2979710163c6
7
- data.tar.gz: 138a8b071f801af2bf9db1bed412976ba29be624352bef902f97d5a041ecb6cb45e1e1e32373af6c17e47847900aef791fe3e7219a53736781035fa143425449
6
+ metadata.gz: 6d621d51ca18fa402e397b13c86dda6d52039a11ca259c6a46f3e9caffeab0faa68b6b9ff58ec4f727b2dae82c386442655122571936a47c366647b3ad895a50
7
+ data.tar.gz: 73bbcc44b560368e64d8bd335b3fac6d52128e8c05f6ddf582ea6139032f570d80563b6fbc9c96f41598fee2c2c345ec9155f5990f3ea4df1bde2167bede9a27
@@ -94,7 +94,7 @@ release:
94
94
  - exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS || test_run_exit_code=$?
95
95
  - exe/gitlab-qa-report --update-screenshot-path "gitlab-qa-run-*/**/rspec-*.xml"
96
96
  - export GITLAB_QA_ACCESS_TOKEN="$GITLAB_QA_PRODUCTION_ACCESS_TOKEN"
97
- - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ]; then $(exe/gitlab-qa-report --report-in-issues "gitlab-qa-run-*/**/rspec-*.xml" --project "$QA_TESTCASES_REPORTING_PROJECT") || true; fi
97
+ - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ]; then exe/gitlab-qa-report --report-in-issues "gitlab-qa-run-*/**/rspec-*.xml" --project "$QA_TESTCASES_REPORTING_PROJECT" || true; fi
98
98
  - exit $test_run_exit_code
99
99
 
100
100
  .ce-qa:
@@ -251,8 +251,7 @@ of a Gitaly Cluster.
251
251
 
252
252
  To run tests against the GitLab container, a GitLab QA (`gitlab/gitlab-qa`)
253
253
  container is spun up and tests are run from it by running the
254
- `Test::Integration::GitalyHA` scenario, which includes tests written
255
- specifically to test Gitaly Cluster features.
254
+ `Test::Instance::All` scenario with the `:gitaly_cluster` tag.
256
255
 
257
256
  Example:
258
257
 
@@ -97,9 +97,12 @@ module Gitlab
97
97
  end
98
98
 
99
99
  module Report
100
+ autoload :JsonTestResults, 'gitlab/qa/report/json_test_results'
101
+ autoload :JUnitTestResults, 'gitlab/qa/report/junit_test_results'
100
102
  autoload :PrepareStageReports, 'gitlab/qa/report/prepare_stage_reports'
101
103
  autoload :ResultsInIssues, 'gitlab/qa/report/results_in_issues'
102
104
  autoload :SummaryTable, 'gitlab/qa/report/summary_table'
105
+ autoload :TestResult, 'gitlab/qa/report/test_result'
103
106
  autoload :UpdateScreenshotPath, 'gitlab/qa/report/update_screenshot_path'
104
107
  end
105
108
 
@@ -41,26 +41,16 @@ module Gitlab
41
41
  raise NotImplementedError, "#{self.class.name} must specify a docker image tag as DOCKER_IMAGE_TAG"
42
42
  end
43
43
 
44
- def instance
44
+ def instance(skip_teardown: false)
45
45
  instance_no_teardown do
46
46
  yield self if block_given?
47
47
  end
48
48
  ensure
49
- teardown
49
+ teardown unless skip_teardown
50
50
  end
51
51
 
52
52
  alias_method :launch_and_teardown_instance, :instance
53
53
 
54
- def instance_no_teardown
55
- prepare
56
- start
57
- reconfigure
58
- wait_until_ready
59
- process_exec_commands
60
-
61
- yield self if block_given?
62
- end
63
-
64
54
  def prepare
65
55
  prepare_docker_image
66
56
  prepare_network
@@ -147,6 +137,16 @@ module Gitlab
147
137
  raise 'Invalid instance name!' unless name
148
138
  end
149
139
 
140
+ def instance_no_teardown
141
+ prepare
142
+ start
143
+ reconfigure
144
+ wait_until_ready
145
+ process_exec_commands
146
+
147
+ yield self if block_given?
148
+ end
149
+
150
150
  def teardown?
151
151
  !Runtime::Scenario.attributes.include?(:teardown) || Runtime::Scenario.teardown
152
152
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Gitlab
6
+ module QA
7
+ module Report
8
+ class JsonTestResults
9
+ include Enumerable
10
+
11
+ def initialize(file)
12
+ @testcases = JSON.parse(File.read(file))['examples'].map { |test| TestResult.from_json(test) }
13
+ end
14
+
15
+ def each(&block)
16
+ @testcases.each(&block)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+
5
+ module Gitlab
6
+ module QA
7
+ module Report
8
+ class JUnitTestResults
9
+ include Enumerable
10
+
11
+ def initialize(file)
12
+ @testcases = Nokogiri::XML(File.read(file)).xpath('//testcase').map { |test| TestResult.from_junit(test) }
13
+ end
14
+
15
+ def each(&block)
16
+ @testcases.each(&block)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -30,11 +30,12 @@ module Gitlab
30
30
  RETRY_BACK_OFF_DELAY = 60
31
31
  MAX_RETRY_ATTEMPTS = 3
32
32
 
33
- def initialize(token:, input_files:, project: nil)
33
+ def initialize(token:, input_files:, project: nil, input_format: :junit)
34
34
  @token = token
35
35
  @files = Array(input_files)
36
36
  @project = project
37
37
  @retry_backoff = 0
38
+ @input_format = input_format.to_sym
38
39
  end
39
40
 
40
41
  def invoke!
@@ -46,7 +47,14 @@ module Gitlab
46
47
 
47
48
  Dir.glob(files).each do |file|
48
49
  puts "Reporting tests in #{file}"
49
- Nokogiri::XML(File.open(file)).xpath('//testcase').each do |test|
50
+ case input_format
51
+ when :json
52
+ test_results = Report::JsonTestResults.new(file)
53
+ when :junit
54
+ test_results = Report::JUnitTestResults.new(file)
55
+ end
56
+
57
+ test_results.each do |test|
50
58
  report_test(test)
51
59
  end
52
60
  end
@@ -54,7 +62,7 @@ module Gitlab
54
62
 
55
63
  private
56
64
 
57
- attr_reader :files, :token, :project
65
+ attr_reader :files, :token, :project, :input_format
58
66
 
59
67
  def validate_input!
60
68
  assert_project!
@@ -99,9 +107,9 @@ module Gitlab
99
107
  end
100
108
 
101
109
  def report_test(test)
102
- return if test.search('skipped').any?
110
+ return if test.skipped
103
111
 
104
- puts "Reporting test: #{test['file']} | #{test['name']}"
112
+ puts "Reporting test: #{test.file} | #{test.name}"
105
113
 
106
114
  issue = find_issue(test)
107
115
  if issue
@@ -124,7 +132,7 @@ module Gitlab
124
132
  Gitlab.create_issue(
125
133
  project,
126
134
  title_from_test(test),
127
- { description: "### Full description\n\n#{search_safe(test['name'])}\n\n### File path\n\n#{test['file']}", labels: 'status::automated' }
135
+ { description: "### Full description\n\n#{search_safe(test.name)}\n\n### File path\n\n#{test.file}", labels: 'status::automated' }
128
136
  )
129
137
  end
130
138
  end
@@ -135,18 +143,18 @@ module Gitlab
135
143
  .auto_paginate
136
144
  .select { |issue| issue.state == 'opened' && issue.title.strip == title_from_test(test) }
137
145
 
138
- warn(%(Too many issues found with the file path "#{test['file']}" and name "#{test['name']}")) if issues.many?
146
+ warn(%(Too many issues found with the file path "#{test.file}" and name "#{test.name}")) if issues.many?
139
147
 
140
148
  issues.first
141
149
  end
142
150
  end
143
151
 
144
152
  def search_term(test)
145
- %("#{test['file']}" "#{search_safe(test['name'])}")
153
+ %("#{test.file}" "#{search_safe(test.name)}")
146
154
  end
147
155
 
148
156
  def title_from_test(test)
149
- title = "#{partial_file_path(test['file'])} | #{search_safe(test['name'])}".strip
157
+ title = "#{partial_file_path(test.file)} | #{search_safe(test.name)}".strip
150
158
 
151
159
  return title unless title.length > MAX_TITLE_LENGTH
152
160
 
@@ -162,7 +170,7 @@ module Gitlab
162
170
  end
163
171
 
164
172
  def note_status(issue, test)
165
- return if failures(test).empty?
173
+ return if test.failures.empty?
166
174
 
167
175
  note = note_content(test)
168
176
 
@@ -176,7 +184,7 @@ module Gitlab
176
184
  end
177
185
 
178
186
  def note_content(test)
179
- errors = failures(test).each_with_object([]) do |failure, text|
187
+ errors = test.failures.each_with_object([]) do |failure, text|
180
188
  text << <<~TEXT
181
189
  Error:
182
190
  ```
@@ -185,7 +193,7 @@ module Gitlab
185
193
 
186
194
  Stacktrace:
187
195
  ```
188
- #{failure.content}
196
+ #{failure['stacktrace']}
189
197
  ```
190
198
  TEXT
191
199
  end.join("\n\n")
@@ -231,7 +239,7 @@ module Gitlab
231
239
  def update_labels(issue, test)
232
240
  labels = issue.labels
233
241
  labels.delete_if { |label| label.start_with?("#{pipeline}::") }
234
- labels << (failures(test).empty? ? "#{pipeline}::passed" : "#{pipeline}::failed")
242
+ labels << (test.failures.empty? ? "#{pipeline}::passed" : "#{pipeline}::failed")
235
243
  labels << "Enterprise Edition" if ee_test?(test)
236
244
  quarantine_job? ? labels << "quarantine" : labels.delete("quarantine")
237
245
 
@@ -242,11 +250,7 @@ module Gitlab
242
250
  # rubocop:enable Metrics/AbcSize
243
251
 
244
252
  def ee_test?(test)
245
- test['file'] =~ %r{features/ee/(api|browser_ui)}
246
- end
247
-
248
- def failures(test)
249
- test.search('failure')
253
+ test.file =~ %r{features/ee/(api|browser_ui)}
250
254
  end
251
255
 
252
256
  def pipeline
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Report
6
+ class TestResult
7
+ attr_accessor :name, :file, :skipped, :failures
8
+
9
+ def self.from_json(test)
10
+ new.tap do |test_result|
11
+ test_result.name = test['full_description']
12
+ test_result.file = test['file_path']
13
+ test_result.skipped = test['status'] == 'pending'
14
+ test_result.failures = failures_from_json_exceptions(test)
15
+ end
16
+ end
17
+
18
+ def self.from_junit(test)
19
+ new.tap do |test_result|
20
+ test_result.name = test['name']
21
+ test_result.file = test['file']
22
+ test_result.skipped = test.search('skipped').any?
23
+ test_result.failures = failures_from_junit_exceptions(test)
24
+ end
25
+ end
26
+
27
+ def self.failures_from_json_exceptions(test)
28
+ return [] unless test.key?('exceptions')
29
+
30
+ test['exceptions'].map do |exception|
31
+ {
32
+ 'message' => "#{exception['class']}: #{exception['message']}",
33
+ 'stacktrace' => exception['backtrace'].join('\n')
34
+ }
35
+ end
36
+ end
37
+ private_class_method :failures_from_json_exceptions
38
+
39
+ def self.failures_from_junit_exceptions(test)
40
+ failures = test.search('failure')
41
+ return [] if failures.empty?
42
+
43
+ failures.map do |exception|
44
+ {
45
+ 'message' => "#{exception['type']}: #{exception['message']}",
46
+ 'stacktrace' => exception.content
47
+ }
48
+ end
49
+ end
50
+ private_class_method :failures_from_junit_exceptions
51
+ end
52
+ end
53
+ end
54
+ end
@@ -7,13 +7,13 @@ module Gitlab
7
7
  attr_reader :gitlab_name, :spec_suite
8
8
 
9
9
  def initialize
10
- @gitlab_name = 'gitlab-gitaly-ha'
10
+ @gitlab_name = 'gitlab-gitaly-cluster'
11
11
  @primary_node_name = 'gitaly1'
12
12
  @secondary_node_name = 'gitaly2'
13
13
  @tertiary_node_name = 'gitaly3'
14
14
  @praefect_node_name = 'praefect'
15
15
  @database = 'postgres'
16
- @spec_suite = 'Test::Integration::GitalyHA'
16
+ @spec_suite = 'Test::Instance::All'
17
17
  @network = 'test'
18
18
  end
19
19
 
@@ -26,7 +26,7 @@ module Gitlab
26
26
  sql_node = Component::PostgreSQL.new.tap do |sql|
27
27
  sql.name = @database
28
28
  sql.network = @network
29
- sql.instance_no_teardown do
29
+ sql.instance(skip_teardown: true) do
30
30
  sql.run_psql '-d template1 -c "CREATE DATABASE praefect_production OWNER postgres"'
31
31
  end
32
32
  end
@@ -39,7 +39,7 @@ module Gitlab
39
39
 
40
40
  praefect.omnibus_config = praefect_omnibus_configuration
41
41
 
42
- praefect.instance_no_teardown
42
+ praefect.instance(skip_teardown: true)
43
43
  end
44
44
 
45
45
  Component::Gitlab.perform do |gitlab|
@@ -49,7 +49,10 @@ module Gitlab
49
49
 
50
50
  gitlab.omnibus_config = gitlab_omnibus_configuration
51
51
  gitlab.instance do
52
- puts "Running Gitaly HA specs!"
52
+ puts "Running Gitaly Cluster specs!"
53
+
54
+ rspec_args << "--" unless rspec_args.include?('--')
55
+ rspec_args << %w[--tag gitaly_cluster]
53
56
 
54
57
  Component::Specs.perform do |specs|
55
58
  specs.suite = spec_suite
@@ -190,7 +193,7 @@ module Gitlab
190
193
  gitaly.network = @network
191
194
  gitaly.skip_availability_check = true
192
195
  gitaly.omnibus_config = gitaly_omnibus_configuration
193
- gitaly.instance_no_teardown
196
+ gitaly.instance(skip_teardown: true)
194
197
  end
195
198
  end
196
199
  end
@@ -1,5 +1,5 @@
1
1
  module Gitlab
2
2
  module QA
3
- VERSION = '5.17.1'.freeze
3
+ VERSION = '6.0.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-qa
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.17.1
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Grzegorz Bizon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-10 00:00:00.000000000 Z
11
+ date: 2020-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -257,9 +257,12 @@ files:
257
257
  - lib/gitlab/qa/docker/shellout.rb
258
258
  - lib/gitlab/qa/docker/volumes.rb
259
259
  - lib/gitlab/qa/release.rb
260
+ - lib/gitlab/qa/report/json_test_results.rb
261
+ - lib/gitlab/qa/report/junit_test_results.rb
260
262
  - lib/gitlab/qa/report/prepare_stage_reports.rb
261
263
  - lib/gitlab/qa/report/results_in_issues.rb
262
264
  - lib/gitlab/qa/report/summary_table.rb
265
+ - lib/gitlab/qa/report/test_result.rb
263
266
  - lib/gitlab/qa/report/update_screenshot_path.rb
264
267
  - lib/gitlab/qa/reporter.rb
265
268
  - lib/gitlab/qa/runner.rb