gitlab-qa 14.5.0 → 14.7.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: 7b273b35fb530099bd344db6ad9f21b56476f4e5b341677e74f22a52a4fcbcad
4
- data.tar.gz: f2712bf79d9fbfa72c89c3fb9d63bce0e4e8b82a164d435be79af21f167d81b6
3
+ metadata.gz: aca8f96e30555fcac3d968c580f1393b87d2114a3616e8ab6dbb98f913f852d4
4
+ data.tar.gz: 566a628d9587a7eeb6e6bcb530bed7170aa689aaadc50cecb28eaba17096e26e
5
5
  SHA512:
6
- metadata.gz: ca2c75c3082c7b613e3ca3ef6f439b0873b23842d200643864cbdbb4f4d264002c8630c8f3879c28a47dbe512f7e3560e223218718faad177502104977fdb254
7
- data.tar.gz: bb1aa0fd9f7f850d8b441fd56e0c1691d4cac6aaee03793fc6b4b944c945b9cfb6cf8f79b10811da2a2536262d70d9bd954fdbbf01c152f17e9b633d33c03d57
6
+ metadata.gz: 4304f800c1430834f7b335ddae6627e51e6126d883359feefb2863662abe274c8b3de2fadca9328c6f6e9815aeb5df2798a1e839a24cf372ee66cdd5db9bea84
7
+ data.tar.gz: 1a8325bf53f232d5db6292a63107b15f0acf19a04acb7dc0186474656dbd12744ab429030eb53a4e3f83acc5f9655a7159fc14d89cf81b373650b4045904e95c
data/.gitlab-ci.yml CHANGED
@@ -133,9 +133,11 @@ package-and-test:
133
133
  RUN_WITH_BUNDLE: "true"
134
134
  SKIP_OMNIBUS_TRIGGER: "true"
135
135
  SKIP_REPORT_IN_ISSUES: "true"
136
- ALLURE_JOB_NAME: gitlab-qa
137
136
  UPDATE_QA_CACHE: $UPDATE_QA_CACHE
138
137
  GITLAB_QA_CACHE_KEY: $GITLAB_QA_CACHE_KEY
138
+ QA_RETRY_FAILED_SPECS: "true"
139
+ QA_RUN_TYPE: gitlab-qa
140
+ QA_EXPORT_TEST_METRICS: "false" # skip metrics export as this pipeline is only used to validate gitlab-qa changes
139
141
  inherit:
140
142
  variables:
141
143
  - RUBY_VERSION
@@ -153,4 +155,4 @@ package-and-test:
153
155
  - if: '$CI_MERGE_REQUEST_IID'
154
156
  when: manual
155
157
  allow_failure: true
156
- - when: always
158
+ - when: always
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-qa (14.5.0)
4
+ gitlab-qa (14.7.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
data/README.md CHANGED
@@ -121,6 +121,7 @@ All the scenarios you can run are described in the
121
121
 
122
122
  Note: The GitLab QA tool requires that [Docker](https://docs.docker.com/install/) is installed.
123
123
 
124
+
124
125
  ### Command-line options
125
126
 
126
127
  In addition to the [arguments you can use to specify the scenario and
@@ -166,6 +167,25 @@ useful if you want to run and debug a specific test, for example:
166
167
  $ bundle exec bin/qa Test::Instance::All http://localhost:32768 -- qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
167
168
  ```
168
169
 
170
+ ### Lefthook
171
+
172
+ [Lefthook](https://github.com/evilmartians/lefthook) is a Git hooks manager that allows
173
+ custom logic to be executed prior to Git committing or pushing. This project comes with
174
+ Lefthook configuration checked in (`lefthook.yml`), but it must be installed.
175
+
176
+ #### Install Lefthook
177
+
178
+ ```shell
179
+ # Install the `lefthook` Ruby gem:
180
+ bundle install
181
+ # Initialize the lefthook config and adds to .git/hooks dir
182
+ bundle exec lefthook install
183
+ # Verify hook execution works as expected
184
+ bundle exec lefthook run pre-push
185
+ ```
186
+
187
+ For a detailed guide on `lefthook` configuration see https://github.com/evilmartians/lefthook/blob/master/docs/configuration.md
188
+
169
189
  ### How to add new tests
170
190
 
171
191
  Please see the [Beginner's guide to writing end-to-end tests](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/beginners_guide.html).
@@ -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
@@ -6,17 +6,27 @@ module Gitlab
6
6
  class AiGateway < Base
7
7
  DOCKER_IMAGE = 'registry.gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/model-gateway'
8
8
  DOCKER_IMAGE_TAG = 'latest'
9
+ LOG_DIR = '/var/log'
9
10
 
10
11
  def name
11
12
  @name ||= 'ai-gateway'
12
13
  end
13
14
 
15
+ def log_volume
16
+ @log_volume ||= {
17
+ src: File.join(Runtime::Env.host_artifacts_dir, @name, 'logs'),
18
+ dest: LOG_DIR
19
+ }
20
+ end
21
+
14
22
  def configure_environment(gitlab_hostname:)
15
23
  @environment = {
16
24
  'AIGW_GITLAB_URL' => "http://#{gitlab_hostname}",
17
25
  'AIGW_GITLAB_API_URL' => "http://#{gitlab_hostname}/api/v4",
18
26
  'AIGW_CUSTOMER_PORTAL_URL' => Runtime::Env.customer_portal_url,
19
- 'AIGW_USE_FAKE_MODELS' => true
27
+ 'AIGW_MOCK_MODEL_RESPONSES' => true,
28
+ 'AIGW_LOGGING__LEVEL' => 'debug',
29
+ 'AIGW_LOGGING__TO_FILE' => "..#{LOG_DIR}/modelgateway_debug.log"
20
30
  }
21
31
  end
22
32
  end
@@ -1,6 +1,5 @@
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'
@@ -13,7 +12,18 @@ module Gitlab
13
12
  # the `qa/` directory located in GitLab CE / EE repositories.
14
13
  #
15
14
  class Specs < Scenario::Template
16
- attr_accessor :suite, :release, :network, :args, :volumes, :env, :runner_network, :hostname, :additional_hosts
15
+ LAST_RUN_FILE = "examples.txt"
16
+
17
+ attr_accessor :suite,
18
+ :release,
19
+ :network,
20
+ :args,
21
+ :volumes,
22
+ :env,
23
+ :runner_network,
24
+ :hostname,
25
+ :additional_hosts,
26
+ :retry_failed_specs
17
27
 
18
28
  def initialize
19
29
  @docker = Docker::Engine.new(stream_output: true) # stream test output directly instead of through logger
@@ -21,6 +31,7 @@ module Gitlab
21
31
  @volumes = {}
22
32
  @additional_hosts = []
23
33
  @volumes = { '/var/run/docker.sock' => '/var/run/docker.sock' }
34
+ @retry_failed_specs = Runtime::Env.retry_failed_specs?
24
35
 
25
36
  include_optional_volumes(
26
37
  Runtime::Env.qa_rspec_report_path => 'rspec',
@@ -51,9 +62,30 @@ module Gitlab
51
62
  Runtime::Logger.info("Running test suite `#{suite}` for #{release.project_name}")
52
63
 
53
64
  name = "#{release.project_name}-qa-#{SecureRandom.hex(4)}"
65
+ run_specs(name)
66
+ rescue Support::ShellCommand::StatusError => e
67
+ raise e unless retry_failed_specs
54
68
 
55
- feature_flag_sets = []
69
+ results_file = File.join(host_artifacts_dir(name), LAST_RUN_FILE)
70
+ raise "Failed to find initial run results file #{results_file}" unless File.exist?(results_file)
71
+
72
+ Runtime::Logger.warn("Initial test run failed, retrying failed specs in new process!")
73
+ run_specs(name, retry_process: true, initial_run_results_host_path: results_file)
74
+ end
75
+
76
+ private
77
+
78
+ # Ful path to tmp dir inside container
79
+ #
80
+ # @return [String]
81
+ def tmp_dir
82
+ @tmp_dir ||= File.join(Docker::Volumes::QA_CONTAINER_WORKDIR, 'tmp')
83
+ end
84
+
85
+ def feature_flag_sets
86
+ return @feature_flag_sets if defined?(@feature_flag_sets)
56
87
 
88
+ feature_flag_sets = []
57
89
  # When `args` includes:
58
90
  # `[..., "--disable-feature", "a", "--enable-feature", "b", "--set-feature-flags", "c=enable", ...]`
59
91
  # `feature_flag_sets` will be set to:
@@ -62,14 +94,36 @@ module Gitlab
62
94
  while (index = args&.index { |x| x =~ /--.*-feature/ })
63
95
  feature_flag_sets << args.slice!(index, 2)
64
96
  end
65
-
66
97
  # When `args` do not have any feature flag options, we add [] so that test is run exactly once.
67
98
  feature_flag_sets << [] unless feature_flag_sets.any?
68
99
 
100
+ @feature_flag_sets = feature_flag_sets
101
+ end
102
+
103
+ def run_specs(name, retry_process: false, initial_run_results_host_path: nil)
104
+ container_name = retry_process ? "#{name}-retry" : name
105
+
106
+ env_vars = if retry_process
107
+ Runtime::Env.variables.merge({
108
+ **env,
109
+ "QA_RSPEC_RETRIED" => "true",
110
+ "NO_KNAPSACK" => "true"
111
+ })
112
+ else
113
+ Runtime::Env.variables.merge(env)
114
+ end
115
+
116
+ env_vars["RSPEC_LAST_RUN_RESULTS_FILE"] = last_run_results_file
117
+ # TODO: remove once rspec-retry gem is removed
118
+ env_vars["QA_DISABLE_RSPEC_RETRY"] = "true" if retry_failed_specs
119
+
120
+ run_volumes = volumes.to_h.merge({ host_artifacts_dir(container_name) => tmp_dir })
121
+ run_volumes[initial_run_results_host_path] = last_run_results_file if retry_process
122
+
69
123
  feature_flag_sets.each do |feature_flag_set|
70
124
  @docker.run(
71
125
  image: qa_image,
72
- args: [suite, *args_with_flags(args, feature_flag_set)],
126
+ args: [suite, *args_with_flags(feature_flag_set, retry_process: retry_process)],
73
127
  mask_secrets: Runtime::Env.variables_to_mask
74
128
  ) do |command|
75
129
  command << "-t --rm --net=#{network || 'bridge'}"
@@ -84,37 +138,40 @@ module Gitlab
84
138
  command << hosts # override /etc/hosts in docker container when test runs
85
139
  end
86
140
 
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
- )
95
-
96
- volumes.to_h.each { |to, from| command.volume(to, from) }
141
+ env_vars.each { |key, value| command.env(key, value) }
142
+ run_volumes.each { |to, from| command.volume(to, from) }
97
143
 
98
- command.name(name)
144
+ command.name(container_name)
99
145
  end
100
146
  end
101
147
  end
102
148
 
103
- private
104
-
105
149
  def docker_pull_qa_image_if_needed
106
150
  @docker.login(**release.login_params) if release.login_params
107
151
 
108
152
  @docker.pull(image: qa_image) unless Runtime::Env.skip_pull?
109
153
  end
110
154
 
111
- def args_with_flags(args, feature_flag_set)
112
- return args if feature_flag_set.empty?
155
+ def args_with_flags(feature_flag_set, retry_process: false)
156
+ return args if feature_flag_set.empty? && !retry_process
113
157
 
114
- Runtime::Logger.info("Running with feature flag: #{feature_flag_set.join(' ')}")
158
+ run_args = args.dup
159
+
160
+ if retry_process
161
+ if run_args.include?("--")
162
+ run_args.push("--only-failures")
163
+ first_rspec_arg_index = run_args.index("--") + 1
164
+ # if first arg after `--` is a not a flag, it's a specific spec/folder which needs to be removed
165
+ run_args.delete_at(first_rspec_arg_index) unless run_args[first_rspec_arg_index].start_with?("--")
166
+ else
167
+ run_args.push("--", "--only-failures")
168
+ end
169
+ end
115
170
 
116
- args_with_f = args.dup
117
- args_with_f.insert(1, *feature_flag_set)
171
+ return run_args if feature_flag_set.empty?
172
+
173
+ Runtime::Logger.info("Running with feature flag: #{feature_flag_set.join(' ')}")
174
+ run_args.insert(1, *feature_flag_set)
118
175
  end
119
176
 
120
177
  def skip_tests?
@@ -138,9 +195,23 @@ module Gitlab
138
195
  host_path.present? && volumes[host_path] = File.join(Docker::Volumes::QA_CONTAINER_WORKDIR, container_path)
139
196
  end
140
197
  end
198
+
199
+ # Full path to host artifacts dir
200
+ #
201
+ # @param [String] name
202
+ # @return [String]
203
+ def host_artifacts_dir(name)
204
+ File.join(Runtime::Env.host_artifacts_dir, name)
205
+ end
206
+
207
+ # Path to save or read run results file within container
208
+ #
209
+ # @return [String]
210
+ def last_run_results_file
211
+ File.join(tmp_dir, LAST_RUN_FILE)
212
+ end
141
213
  end
142
214
  end
143
215
  end
144
216
  end
145
- # rubocop:enable Metrics/CyclomaticComplexity
146
217
  # 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,
@@ -106,6 +107,7 @@ module Gitlab
106
107
  'CI_PROJECT_NAME' => :ci_project_name,
107
108
  'CI_PROJECT_PATH' => :ci_project_path,
108
109
  'CI_PIPELINE_SOURCE' => :ci_pipeline_source,
110
+ 'CI_PIPELINE_ID' => :ci_pipeline_id,
109
111
  'CI_PIPELINE_URL' => :ci_pipeline_url,
110
112
  'CI_PIPELINE_CREATED_AT' => :ci_pipeline_created_at,
111
113
  'CI_MERGE_REQUEST_IID' => :ci_merge_request_iid,
@@ -277,20 +279,29 @@ module Gitlab
277
279
 
278
280
  def require_aws_s3_environment!
279
281
  %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)
282
+ unless ENV.key?(env_key)
283
+ raise ArgumentError,
284
+ "Environment variable #{env_key} must be set to run AWS S3 object storage specs"
285
+ end
281
286
  end
282
287
  end
283
288
 
284
289
  def require_gcs_environment!
285
290
  %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)
291
+ unless ENV.key?(env_key)
292
+ raise ArgumentError,
293
+ "Environment variable #{env_key} must be set to run GCS object storage specs"
294
+ end
287
295
  end
288
296
  end
289
297
 
290
298
  def require_gcs_with_cdn_environment!
291
299
  %w[GOOGLE_CDN_JSON_KEY GCS_CDN_BUCKET_NAME GOOGLE_CDN_LB GOOGLE_CDN_SIGNURL_KEY
292
300
  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)
301
+ unless ENV.key?(env_key)
302
+ raise ArgumentError,
303
+ "Environment variable #{env_key} must be set to run GCS with CDN enabled scenario"
304
+ end
294
305
  end
295
306
  end
296
307
 
@@ -359,7 +370,7 @@ module Gitlab
359
370
  end
360
371
 
361
372
  def video_recorder_image
362
- env_var_value_if_defined('QA_VIDEO_RECORDER_IMAGE') || 'presidenten/selenoid-manual-video-recorder'
373
+ env_var_value_if_defined('QA_VIDEO_RECORDER_IMAGE') || 'registry.gitlab.com/gitlab-org/gitlab-qa/selenoid-manual-video-recorder'
363
374
  end
364
375
 
365
376
  def video_recorder_version
@@ -455,6 +466,10 @@ module Gitlab
455
466
  enabled?(env_var_value_if_defined('QA_MOCK_GITHUB'), default: true)
456
467
  end
457
468
 
469
+ def retry_failed_specs?
470
+ enabled?(env_var_value_if_defined('QA_RETRY_FAILED_SPECS'), default: false)
471
+ end
472
+
458
473
  private
459
474
 
460
475
  def enabled?(value, default: true)
@@ -111,8 +111,9 @@ 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
116
117
  end
117
118
  rescue Support::ShellCommand::StatusError => e
118
119
  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.5.0'
5
+ VERSION = '14.7.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.5.0
4
+ version: 14.7.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-03-22 00:00:00.000000000 Z
11
+ date: 2024-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control