gitlab-qa 14.6.0 → 14.8.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: d16aa0d0e3acf2f78c85344345d2d7a1637fa9c16154446020d0ffd5649687f9
4
- data.tar.gz: 68bbb672fecd7bd17113fd7485cbacf547477cd64362e250296316a897868974
3
+ metadata.gz: 3632783614831ceda0acb1c2fa312dcea081c8e878dfe2ce41bdb6f9ac70253b
4
+ data.tar.gz: 5af7c287d9820b050feb5944a9bf93561ef33442f0120bb71e6c7d0c33528ed3
5
5
  SHA512:
6
- metadata.gz: 260445e5a526267392c3d91d81eee2baa37df00c6981acecef40f64d17ebf7a10d608d9eb3eae61a287633ca5e7446fdd4e8da70bc70d1de8a2c915065910248
7
- data.tar.gz: fcb5cf3c6a4aa914bb089316cb1f3f1b6d8c666fc7dccf7621c79a90d92dc5dcfb6bb5aa77631059f1c841321baf898471f0e35f09ad7a6d831394badc983a67
6
+ metadata.gz: 46a5d0fd06137c2f41f8f504f1b3afea1e82ba010f86f704a5991f859c555a45e74e1ad6eaa320e916ed6c8fa9227ef20e47e7da03441f8bc3ec6e6ef2aa2352
7
+ data.tar.gz: 8ccadd90b943ca72ccd967fabfd70ae26a834ff8b949456eecdda333af3a7e6754b46a956e0dc029b7b70847c9134fb11dcd54a202299d64cbfe2902620c7ca1
data/.gitlab-ci.yml CHANGED
@@ -10,7 +10,7 @@
10
10
  include:
11
11
  - component: gitlab.com/gitlab-org/components/danger-review/danger-review@~latest
12
12
  inputs:
13
- job_image: "${CI_REGISTRY}/gitlab-org/gitlab-build-images/debian-bullseye-ruby-${RUBY_VERSION}:bundler-2.4"
13
+ job_image: "${CI_REGISTRY}/gitlab-org/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}:bundler-${BUNDLER_VERSION}"
14
14
  - component: gitlab.com/gitlab-org/components/gem-release/gem-release@~latest
15
15
 
16
16
  stages:
@@ -20,7 +20,7 @@ stages:
20
20
  - deploy
21
21
 
22
22
  default:
23
- image: ${CI_REGISTRY}/gitlab-org/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}:bundler-2.3
23
+ image: ${CI_REGISTRY}/gitlab-org/gitlab-build-images/debian-${DEBIAN_VERSION}-ruby-${RUBY_VERSION}:bundler-${BUNDLER_VERSION}
24
24
  tags:
25
25
  - gitlab-org
26
26
  cache:
@@ -41,8 +41,10 @@ workflow:
41
41
  - if: '$CI_PIPELINE_SOURCE == "web"'
42
42
 
43
43
  variables:
44
- DEBIAN_VERSION: bullseye
45
- RUBY_VERSION: "3.0"
44
+ DEBIAN_VERSION: bookworm
45
+ DOCKER_VERSION: "24.0.5"
46
+ BUNDLER_VERSION: "2.5"
47
+ RUBY_VERSION: "3.1"
46
48
  BUNDLE_PATH: vendor
47
49
  BUNDLE_SILENCE_ROOT_WARNING: "true"
48
50
  BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES: "true"
@@ -133,13 +135,17 @@ package-and-test:
133
135
  RUN_WITH_BUNDLE: "true"
134
136
  SKIP_OMNIBUS_TRIGGER: "true"
135
137
  SKIP_REPORT_IN_ISSUES: "true"
136
- ALLURE_JOB_NAME: gitlab-qa
137
138
  UPDATE_QA_CACHE: $UPDATE_QA_CACHE
138
139
  GITLAB_QA_CACHE_KEY: $GITLAB_QA_CACHE_KEY
140
+ QA_RETRY_FAILED_SPECS: "true"
141
+ QA_RUN_TYPE: gitlab-qa
142
+ QA_EXPORT_TEST_METRICS: "false" # skip metrics export as this pipeline is only used to validate gitlab-qa changes
139
143
  inherit:
140
144
  variables:
141
145
  - RUBY_VERSION
142
146
  - DEBIAN_VERSION
147
+ - DOCKER_VERSION
148
+ - BUNDLER_VERSION
143
149
  trigger:
144
150
  strategy: depend
145
151
  forward:
@@ -153,4 +159,4 @@ package-and-test:
153
159
  - if: '$CI_MERGE_REQUEST_IID'
154
160
  when: manual
155
161
  allow_failure: true
156
- - when: always
162
+ - when: always
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-qa (14.6.0)
4
+ gitlab-qa (14.8.0)
5
5
  activesupport (>= 6.1, < 7.2)
6
6
  gitlab (~> 4.19)
7
7
  http (~> 5.0)
@@ -127,7 +127,7 @@ GEM
127
127
  multi_xml (>= 0.5.2)
128
128
  i18n (1.14.1)
129
129
  concurrent-ruby (~> 1.0)
130
- jaro_winkler (1.5.4)
130
+ jaro_winkler (1.5.6)
131
131
  json (2.6.3)
132
132
  kramdown (2.4.0)
133
133
  rexml
@@ -18,7 +18,7 @@ I.e, if you have a Selenium server set up at http://localhost:4444 or if you hav
18
18
  | QA_SAVE_ALL_VIDEOS | Used with Selenoid. Saves video for both passed and failed tests | false | false, true |
19
19
  | QA_SELENOID_BROWSER_IMAGE | Used with Selenoid. Sets the browser image to use for video recording. | "selenoid/chrome" | "selenoid/chrome", "registry.gitlab.com/gitlab-org/gitlab-qa/selenoid-chrome-gitlab" |
20
20
  | QA_SELENOID_BROWSER_VERSION | Used in conjunction with QA_SELENOID_BROWSER_IMAGE. Version of browser to run against. | "111.0" | "latest" "111.0" "mobile-111.0"|
21
- | QA_VIDEO_RECORDER_IMAGE | Used with Selenoid. Sets the video recorder image to use for video recording. | "presidenten/selenoid-manual-video-recorder" | "presidenten/selenoid-manual-video-recorder" |
21
+ | QA_VIDEO_RECORDER_IMAGE | Used with Selenoid. Sets the video recorder image to use for video recording. | "registry.gitlab.com/gitlab-org/gitlab-qa/selenoid-manual-video-recorder" | "registry.gitlab.com/gitlab-org/gitlab-qa/selenoid-manual-video-recorder", "presidenten/selenoid-manual-video-recorder" |
22
22
  | QA_VIDEO_RECORDER_VERSION | Used with Selenoid. Sets the video recorder image version to use for video recording. | "latest" | "latest" |
23
23
  | QA_REMOTE_GRID_USERNAME | Used with Sauce Labs. Username to specify in the remote grid. "USERNAME@provider:80" | | "gitlab-sl" |
24
24
  | QA_REMOTE_GRID_ACCESS_KEY | Used with Sauce Labs. Key/Token paired with `QA_REMOTE_GRID_USERNAME` | | |
@@ -349,11 +349,13 @@ $ gitlab-qa Test::Omnibus::UpdateFromPrevious gitlab-ee:dev-tag 15.6.0-pre major
349
349
 
350
350
  ### `Test::Integration::Geo EE|<full image address>`
351
351
 
352
- This tests that two GitLab Geo instances work as expected.
352
+ This tests that Geo UI proxying is working as expected.
353
353
 
354
- The scenario spins up a primary and secondary GitLab Geo nodes, and verifies
355
- that the replications (repository, attachments, project rename etc.) work as
356
- expected.
354
+ The scenario spins up primary and secondary GitLab Geo nodes and
355
+ can be used to verify that web requests to secondary Geo site return
356
+ data that is present on the primary.
357
+
358
+ See https://docs.gitlab.com/ee/administration/geo/secondary_proxy
357
359
 
358
360
  To run tests against the GitLab containers, a GitLab QA (`gitlab/gitlab-qa`)
359
361
  container is spun up and tests are run from it by running the
@@ -24,7 +24,7 @@ module Gitlab
24
24
  'AIGW_GITLAB_URL' => "http://#{gitlab_hostname}",
25
25
  'AIGW_GITLAB_API_URL' => "http://#{gitlab_hostname}/api/v4",
26
26
  'AIGW_CUSTOMER_PORTAL_URL' => Runtime::Env.customer_portal_url,
27
- 'AIGW_USE_FAKE_MODELS' => true,
27
+ 'AIGW_MOCK_MODEL_RESPONSES' => true,
28
28
  'AIGW_LOGGING__LEVEL' => 'debug',
29
29
  'AIGW_LOGGING__TO_FILE' => "..#{LOG_DIR}/modelgateway_debug.log"
30
30
  }
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # rubocop:disable Metrics/CyclomaticComplexity
4
3
  # rubocop:disable Metrics/AbcSize
5
4
 
6
5
  require 'securerandom'
6
+ require 'active_support/core_ext/array/grouping'
7
7
 
8
8
  module Gitlab
9
9
  module QA
@@ -13,7 +13,19 @@ module Gitlab
13
13
  # the `qa/` directory located in GitLab CE / EE repositories.
14
14
  #
15
15
  class Specs < Scenario::Template
16
- attr_accessor :suite, :release, :network, :args, :volumes, :env, :runner_network, :hostname, :additional_hosts
16
+ LAST_RUN_FILE = "examples.txt"
17
+
18
+ attr_accessor :suite,
19
+ :release,
20
+ :network,
21
+ :args,
22
+ :volumes,
23
+ :env,
24
+ :runner_network,
25
+ :hostname,
26
+ :additional_hosts,
27
+ :retry_failed_specs,
28
+ :infer_qa_image_from_release
17
29
 
18
30
  def initialize
19
31
  @docker = Docker::Engine.new(stream_output: true) # stream test output directly instead of through logger
@@ -21,6 +33,7 @@ module Gitlab
21
33
  @volumes = {}
22
34
  @additional_hosts = []
23
35
  @volumes = { '/var/run/docker.sock' => '/var/run/docker.sock' }
36
+ @retry_failed_specs = Runtime::Env.retry_failed_specs?
24
37
 
25
38
  include_optional_volumes(
26
39
  Runtime::Env.qa_rspec_report_path => 'rspec',
@@ -51,9 +64,30 @@ module Gitlab
51
64
  Runtime::Logger.info("Running test suite `#{suite}` for #{release.project_name}")
52
65
 
53
66
  name = "#{release.project_name}-qa-#{SecureRandom.hex(4)}"
67
+ run_specs(name)
68
+ rescue Support::ShellCommand::StatusError => e
69
+ raise e unless retry_failed_specs
54
70
 
55
- feature_flag_sets = []
71
+ results_file = File.join(host_artifacts_dir(name), LAST_RUN_FILE)
72
+ raise "Failed to find initial run results file #{results_file}" unless File.exist?(results_file)
73
+
74
+ Runtime::Logger.warn("Initial test run failed, retrying failed specs in new process!")
75
+ run_specs(name, retry_process: true, initial_run_results_host_path: results_file)
76
+ end
77
+
78
+ private
56
79
 
80
+ # Ful path to tmp dir inside container
81
+ #
82
+ # @return [String]
83
+ def tmp_dir
84
+ @tmp_dir ||= File.join(Docker::Volumes::QA_CONTAINER_WORKDIR, 'tmp')
85
+ end
86
+
87
+ def feature_flag_sets
88
+ return @feature_flag_sets if defined?(@feature_flag_sets)
89
+
90
+ feature_flag_sets = []
57
91
  # When `args` includes:
58
92
  # `[..., "--disable-feature", "a", "--enable-feature", "b", "--set-feature-flags", "c=enable", ...]`
59
93
  # `feature_flag_sets` will be set to:
@@ -62,14 +96,36 @@ module Gitlab
62
96
  while (index = args&.index { |x| x =~ /--.*-feature/ })
63
97
  feature_flag_sets << args.slice!(index, 2)
64
98
  end
65
-
66
99
  # When `args` do not have any feature flag options, we add [] so that test is run exactly once.
67
100
  feature_flag_sets << [] unless feature_flag_sets.any?
68
101
 
102
+ @feature_flag_sets = feature_flag_sets
103
+ end
104
+
105
+ def run_specs(name, retry_process: false, initial_run_results_host_path: nil)
106
+ container_name = retry_process ? "#{name}-retry" : name
107
+
108
+ env_vars = if retry_process
109
+ Runtime::Env.variables.merge({
110
+ **env,
111
+ "QA_RSPEC_RETRIED" => "true",
112
+ "NO_KNAPSACK" => "true"
113
+ })
114
+ else
115
+ Runtime::Env.variables.merge(env)
116
+ end
117
+
118
+ env_vars["RSPEC_LAST_RUN_RESULTS_FILE"] = last_run_results_file
119
+ # TODO: remove once rspec-retry gem is removed
120
+ env_vars["QA_DISABLE_RSPEC_RETRY"] = "true" if retry_failed_specs
121
+
122
+ run_volumes = volumes.to_h.merge({ host_artifacts_dir(container_name) => tmp_dir })
123
+ run_volumes[initial_run_results_host_path] = last_run_results_file if retry_process
124
+
69
125
  feature_flag_sets.each do |feature_flag_set|
70
126
  @docker.run(
71
127
  image: qa_image,
72
- args: [suite, *args_with_flags(args, feature_flag_set)],
128
+ args: [suite, *args_with_flags(feature_flag_set, retry_process: retry_process)],
73
129
  mask_secrets: Runtime::Env.variables_to_mask
74
130
  ) do |command|
75
131
  command << "-t --rm --net=#{network || 'bridge'}"
@@ -84,37 +140,50 @@ module Gitlab
84
140
  command << hosts # override /etc/hosts in docker container when test runs
85
141
  end
86
142
 
87
- Runtime::Env.variables.merge(env).each do |key, value|
88
- command.env(key, value)
89
- end
90
-
91
- command.volume(
92
- File.join(Runtime::Env.host_artifacts_dir, name),
93
- File.join(Docker::Volumes::QA_CONTAINER_WORKDIR, 'tmp')
94
- )
143
+ env_vars.each { |key, value| command.env(key, value) }
144
+ run_volumes.each { |to, from| command.volume(to, from) }
95
145
 
96
- volumes.to_h.each { |to, from| command.volume(to, from) }
97
-
98
- command.name(name)
146
+ command.name(container_name)
99
147
  end
100
148
  end
101
149
  end
102
150
 
103
- private
104
-
105
151
  def docker_pull_qa_image_if_needed
106
152
  @docker.login(**release.login_params) if release.login_params
107
153
 
108
154
  @docker.pull(image: qa_image) unless Runtime::Env.skip_pull?
109
155
  end
110
156
 
111
- def args_with_flags(args, feature_flag_set)
112
- return args if feature_flag_set.empty?
157
+ def args_with_flags(feature_flag_set, retry_process: false)
158
+ return args if feature_flag_set.empty? && !retry_process
159
+
160
+ run_args = if !retry_process
161
+ args.dup
162
+ elsif args.include?("--")
163
+ qa_args, rspec_args = args.split("--")
164
+ [*qa_args, "--"] + args_without_spec_arguments(rspec_args).push("--only-failures")
165
+ else
166
+ args.dup.push("--", "--only-failures")
167
+ end
168
+
169
+ return run_args if feature_flag_set.empty?
113
170
 
114
171
  Runtime::Logger.info("Running with feature flag: #{feature_flag_set.join(' ')}")
172
+ run_args.insert(1, *feature_flag_set)
173
+ end
174
+
175
+ # Remove particular spec argument like specific spec/folder or specific tags
176
+ #
177
+ # @param [Array] rspec_args
178
+ # @return [Array]
179
+ def args_without_spec_arguments(rspec_args)
180
+ arg_pairs = rspec_args.each_with_object([]) do |arg, new_args|
181
+ next new_args.push([arg]) if new_args.last.nil? || arg.start_with?("--") || new_args.last.size == 2
182
+
183
+ new_args.last.push(arg)
184
+ end
115
185
 
116
- args_with_f = args.dup
117
- args_with_f.insert(1, *feature_flag_set)
186
+ arg_pairs.reject { |pair| pair.first == "--tag" || !pair.first.start_with?("--") }.flatten
118
187
  end
119
188
 
120
189
  def skip_tests?
@@ -122,11 +191,10 @@ module Gitlab
122
191
  end
123
192
 
124
193
  def qa_image
125
- if Runtime::Scenario.attributes.include?(:qa_image)
126
- Runtime::Scenario.qa_image
127
- else
128
- "#{release.qa_image}:#{release.qa_tag}"
129
- end
194
+ infered_qa_image = "#{release.qa_image}:#{release.qa_tag}"
195
+ return infered_qa_image if infer_qa_image_from_release || !Runtime::Scenario.attributes.include?(:qa_image)
196
+
197
+ Runtime::Scenario.qa_image
130
198
  end
131
199
 
132
200
  # Adds volumes to the volumes hash if the relevant host paths exist
@@ -138,9 +206,23 @@ module Gitlab
138
206
  host_path.present? && volumes[host_path] = File.join(Docker::Volumes::QA_CONTAINER_WORKDIR, container_path)
139
207
  end
140
208
  end
209
+
210
+ # Full path to host artifacts dir
211
+ #
212
+ # @param [String] name
213
+ # @return [String]
214
+ def host_artifacts_dir(name)
215
+ File.join(Runtime::Env.host_artifacts_dir, name)
216
+ end
217
+
218
+ # Path to save or read run results file within container
219
+ #
220
+ # @return [String]
221
+ def last_run_results_file
222
+ File.join(tmp_dir, LAST_RUN_FILE)
223
+ end
141
224
  end
142
225
  end
143
226
  end
144
227
  end
145
- # rubocop:enable Metrics/CyclomaticComplexity
146
228
  # rubocop:enable Metrics/AbcSize
@@ -96,6 +96,7 @@ module Gitlab
96
96
  'CI' => :ci,
97
97
  'CI_JOB_NAME' => :ci_job_name,
98
98
  'CI_JOB_NAME_SLUG' => :ci_job_name_slug,
99
+ 'CI_JOB_ID' => :ci_job_id,
99
100
  'CI_JOB_URL' => :ci_job_url,
100
101
  'CI_JOB_TOKEN' => :ci_job_token,
101
102
  'CI_RUNNER_ID' => :ci_runner_id,
@@ -105,7 +106,9 @@ module Gitlab
105
106
  'CI_NODE_TOTAL' => :ci_node_total,
106
107
  'CI_PROJECT_NAME' => :ci_project_name,
107
108
  'CI_PROJECT_PATH' => :ci_project_path,
109
+ 'CI_PROJECT_PATH_SLUG' => :ci_project_path_slug,
108
110
  'CI_PIPELINE_SOURCE' => :ci_pipeline_source,
111
+ 'CI_PIPELINE_ID' => :ci_pipeline_id,
109
112
  'CI_PIPELINE_URL' => :ci_pipeline_url,
110
113
  'CI_PIPELINE_CREATED_AT' => :ci_pipeline_created_at,
111
114
  'CI_MERGE_REQUEST_IID' => :ci_merge_request_iid,
@@ -277,20 +280,29 @@ module Gitlab
277
280
 
278
281
  def require_aws_s3_environment!
279
282
  %w[AWS_S3_REGION AWS_S3_KEY_ID AWS_S3_ACCESS_KEY AWS_S3_BUCKET_NAME].each do |env_key|
280
- raise ArgumentError, "Environment variable #{env_key} must be set to run AWS S3 object storage specs" unless ENV.key?(env_key)
283
+ unless ENV.key?(env_key)
284
+ raise ArgumentError,
285
+ "Environment variable #{env_key} must be set to run AWS S3 object storage specs"
286
+ end
281
287
  end
282
288
  end
283
289
 
284
290
  def require_gcs_environment!
285
291
  %w[GOOGLE_PROJECT GOOGLE_CLIENT_EMAIL GOOGLE_JSON_KEY GCS_BUCKET_NAME].each do |env_key|
286
- raise ArgumentError, "Environment variable #{env_key} must be set to run GCS object storage specs" unless ENV.key?(env_key)
292
+ unless ENV.key?(env_key)
293
+ raise ArgumentError,
294
+ "Environment variable #{env_key} must be set to run GCS object storage specs"
295
+ end
287
296
  end
288
297
  end
289
298
 
290
299
  def require_gcs_with_cdn_environment!
291
300
  %w[GOOGLE_CDN_JSON_KEY GCS_CDN_BUCKET_NAME GOOGLE_CDN_LB GOOGLE_CDN_SIGNURL_KEY
292
301
  GOOGLE_CDN_SIGNURL_KEY_NAME].each do |env_key|
293
- raise ArgumentError, "Environment variable #{env_key} must be set to run GCS with CDN enabled scenario" unless ENV.key?(env_key)
302
+ unless ENV.key?(env_key)
303
+ raise ArgumentError,
304
+ "Environment variable #{env_key} must be set to run GCS with CDN enabled scenario"
305
+ end
294
306
  end
295
307
  end
296
308
 
@@ -359,7 +371,7 @@ module Gitlab
359
371
  end
360
372
 
361
373
  def video_recorder_image
362
- env_var_value_if_defined('QA_VIDEO_RECORDER_IMAGE') || 'presidenten/selenoid-manual-video-recorder'
374
+ env_var_value_if_defined('QA_VIDEO_RECORDER_IMAGE') || 'registry.gitlab.com/gitlab-org/gitlab-qa/selenoid-manual-video-recorder'
363
375
  end
364
376
 
365
377
  def video_recorder_version
@@ -455,6 +467,10 @@ module Gitlab
455
467
  enabled?(env_var_value_if_defined('QA_MOCK_GITHUB'), default: true)
456
468
  end
457
469
 
470
+ def retry_failed_specs?
471
+ enabled?(env_var_value_if_defined('QA_RETRY_FAILED_SPECS'), default: false)
472
+ end
473
+
458
474
  private
459
475
 
460
476
  def enabled?(value, default: true)
@@ -111,8 +111,11 @@ module Gitlab
111
111
  specs.args = [gitlab.address, *rspec_args]
112
112
  next if release == current_release
113
113
 
114
- # do not generate reports and metrics artifacts for non release runs
114
+ # do not generate reports and metrics artifacts for non release runs or retry failures
115
115
  specs.env = { 'QA_GENERATE_ALLURE_REPORT' => false, 'QA_SAVE_TEST_METRICS' => false }
116
+ specs.retry_failed_specs = false
117
+ # if qa-image was set explicitly, make sure it is not used on initial run for release
118
+ specs.infer_qa_image_from_release = true
116
119
  end
117
120
  rescue Support::ShellCommand::StatusError => e
118
121
  if release == current_release # only fail on current release
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module QA
5
- VERSION = '14.6.0'
5
+ VERSION = '14.8.0'
6
6
  end
7
7
  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: 14.6.0
4
+ version: 14.8.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-04-02 00:00:00.000000000 Z
11
+ date: 2024-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control