gitlab-qa 10.2.1 → 10.3.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: 6a87ce2862d1a1e65107ce6b34b35e9ffdea5dacd3ac8d193d0193ccd70955f2
4
- data.tar.gz: 6b5e54d9aff03e63831b2874076ade24540c164e5391e628c0ab7b6a2a0f19b6
3
+ metadata.gz: 2851a74117f3479437a3e355883c7a407d4f56c41aac2700028cd9686790f0ea
4
+ data.tar.gz: a284df28173a258c4948ead8be3c677df487c585b60cc73ffe88d5c12b6281b5
5
5
  SHA512:
6
- metadata.gz: 617455a03eba3c3e7fb55eed317084851160409105c356d76cfb7c449daa383985a62ae7a4ccac64e2804511aed8a7fe826a4bf3effac7210150c5359fa209d7
7
- data.tar.gz: 9947e70d1176453db67c99223ed72c9f8be9764ffb80985fd94666d758ef5abca7b3d67b294f24988d5d089a6b1f1afc9e30ca2eed9134c944c8ccec2a1216b6
6
+ metadata.gz: 44a1c9743ce4fafbaad0e20f2de55598c4686598a2c3ac50d9da69565e72a477e3a0ab90f909fb32ed2b153129912b365db19ee9af91814bf6db707dc4bc70f4
7
+ data.tar.gz: f2d8e7accf348103ff3f7ab85467186dd11a7c51a5cdb691e3e8999716272ba54a06204257395a7594ea832c60b93d33a11fd198c57b957609599638ab3b2672
@@ -32,4 +32,9 @@ with the latest commit from https://gitlab.com/gitlab-org/gitlab-qa/commits/mast
32
32
  - Checklist after merging:
33
33
  - [ ] [Update the release notes for the newly created tag](docs/release_process.md#how-to).
34
34
 
35
+ - Checklist after gitlab-qa version has been released by the post merge pipeline:
36
+ - [ ] In the pipeline-common project, [update the GITLAB_QA_VERSION](https://gitlab.com/gitlab-org/quality/pipeline-common/-/blob/master/ci/base.gitlab-ci.yml) and [create a release](https://gitlab.com/gitlab-org/quality/pipeline-common#release-process).
37
+ - [ ] In the GitLab project, update the ref for pipeline-common for [package-and-test](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/package-and-test/main.gitlab-ci.yml) and [review-apps](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/ci/review-apps/qa.gitlab-ci.yml).
38
+ - [ ] Unless already done by [renovate-gitlab-bot](https://gitlab.com/dashboard/merge_requests?scope=all&state=opened&author_username=gitlab-dependency-update-bot&label_name[]=Quality), or if you need it sooner, in the GitLab project, [update the gitlab-qa gem version](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/Gemfile) and [`Gemfile.lock`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/Gemfile.lock) (for an example, see: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117054).
39
+
35
40
  /label ~Quality ~"type::maintenance" ~"maintenance::dependency"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-qa (10.2.1)
4
+ gitlab-qa (10.3.0)
5
5
  activesupport (~> 6.1)
6
6
  gitlab (~> 4.18.0)
7
7
  http (~> 5.0)
@@ -9,12 +9,17 @@ I.e, if you have a Selenium server set up at http://localhost:4444 or if you hav
9
9
  | Variable | Description | Default | Example(s) |
10
10
  |---------------------------|----------------------------------------------------------------|----------|--------------------------------|
11
11
  | QA_BROWSER | Browser to run against | "chrome" | "chrome" "firefox" "safari" |
12
+ | QA_BROWSER_VERSION | Version of browser to run against | "latest" | "latest" "111.0" "mobile-111.0"|
12
13
  | QA_REMOTE_GRID_PROTOCOL | Protocol to use | "http" | "http" "https" |
13
- | QA_REMOTE_GRID | Remote grid to run tests against | | "localhost:3000" "provider:80" |
14
- | QA_REMOTE_GRID_USERNAME | Username to specify in the remote grid. "USERNAME@provider:80" | | "gitlab-sl" |
15
- | QA_REMOTE_GRID_ACCESS_KEY | Key/Token paired with `QA_REMOTE_GRID_USERNAME` | | |
16
- | QA_REMOTE_TUNNEL_ID | Name of the remote tunnel to use | "gitlab-sl_tunnel_id" | |
17
- | QA_REMOTE_MOBILE_DEVICE_NAME | Name of mobile device to test against. `QA_BROWSER` must be set to `safari` for iOS devices and `chrome` for Android devices. | | "iPhone 12 Simulator" |
14
+ | QA_REMOTE_GRID | Remote grid to run tests against | | "localhost:3000" "provider:80" "selenoid:4444" |
15
+ | QA_LAYOUT | Used with Selenoid. Tells test nav to expect collapsed menus. "phone" expects collapsed top and left nav bars, "tablet" expects collapsed left nav bar only. | | "phone", "tablet" |
16
+ | SELENOID_DIRECTORY | Used with Selenoid. Directory to save videos to | "<host_artifacts_dir>/selenoid" | |
17
+ | USE_SELENOID | Used with Selenoid. Sets up selenoid containers. | false | false, true |
18
+ | QA_RECORD_VIDEO | Used with Selenoid. Triggers video recording. | false | false, true |
19
+ | QA_REMOTE_GRID_USERNAME | Used with Sauce Labs. Username to specify in the remote grid. "USERNAME@provider:80" | | "gitlab-sl" |
20
+ | QA_REMOTE_GRID_ACCESS_KEY | Used with Sauce Labs. Key/Token paired with `QA_REMOTE_GRID_USERNAME` | | |
21
+ | QA_REMOTE_TUNNEL_ID | Used with Sauce Labs. Name of the remote tunnel to use | "gitlab-sl_tunnel_id" | |
22
+ | QA_REMOTE_MOBILE_DEVICE_NAME | Used with Sauce Labs. Name of mobile device to test against. `QA_BROWSER` must be set to `safari` for iOS devices and `chrome` for Android devices. | | "iPhone 12 Simulator" |
18
23
 
19
24
  ## Testing with Sauce Labs
20
25
 
@@ -0,0 +1,25 @@
1
+ {
2
+ "chrome": {
3
+ "default": "111.0",
4
+ "versions": {
5
+ "111.0": {
6
+ "image": "selenoid/chrome:111.0",
7
+ "port": "4444"
8
+ },
9
+ "mobile-111.0": {
10
+ "image": "registry.gitlab.com/gitlab-org/gitlab-qa/selenoid-chrome-gitlab:mobile-111.0",
11
+ "path": "/wd/hub",
12
+ "port": "4444"
13
+ }
14
+ }
15
+ },
16
+ "MicrosoftEdge": {
17
+ "default": "111.0",
18
+ "versions": {
19
+ "111.0": {
20
+ "image": "browsers/edge:111.0",
21
+ "port": "4444"
22
+ }
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'http'
4
+
5
+ module Gitlab
6
+ module QA
7
+ module Component
8
+ # Component for the Selenoid Grid
9
+ # https://aerokube.com/selenoid/latest/
10
+ class Selenoid < Base
11
+ DOCKER_IMAGE = 'aerokube/selenoid'
12
+ DOCKER_IMAGE_TAG = 'latest-release'
13
+
14
+ def name
15
+ @name ||= 'selenoid'
16
+ end
17
+
18
+ def instance
19
+ Runtime::Env.webdriver_headless = '0'
20
+ Runtime::Env.chrome_disable_dev_shm = 'true'
21
+ Runtime::Env.remote_grid = "#{hostname}:4444"
22
+ Runtime::Env.remote_grid_protocol = 'http'
23
+ raise 'Please provide a block!' unless block_given?
24
+
25
+ super
26
+ end
27
+
28
+ def start
29
+ pull_images
30
+ docker.run(image: image, tag: tag, args: ['-container-network', network]) do |command|
31
+ set_command_args(command)
32
+ set_volumes(command)
33
+ end
34
+
35
+ wait_until_ready
36
+ end
37
+
38
+ def wait_until_ready(max_attempts: 20, wait: 2)
39
+ Runtime::Logger.info("Waiting for Selenoid ...")
40
+
41
+ max_attempts.times do
42
+ return Runtime::Logger.info("Selenoid ready!") if grid_healthy?
43
+
44
+ sleep wait
45
+ end
46
+
47
+ raise "Retried #{max_attempts} times. Selenoid is not responding. Aborting."
48
+ end
49
+
50
+ private
51
+
52
+ def grid_healthy?
53
+ HTTP.get('http://localhost:4444/ping').status&.success?
54
+ rescue HTTP::ConnectionError => _e
55
+ false
56
+ end
57
+
58
+ def pull_images
59
+ docker.pull(image: "selenoid/chrome", tag: Runtime::Env.browser_version) if Runtime::Env.browser == :chrome && !Runtime::Env.mobile_layout?
60
+ docker.pull(image: "selenoid/video-recorder", tag: "latest-release")
61
+ end
62
+
63
+ # Set custom run command arguments
64
+ #
65
+ # @param [Docker::Command] command
66
+ # @return [void]
67
+ def set_command_args(command)
68
+ command << '-d '
69
+ command << "--name #{name}"
70
+ command << "--net #{network}"
71
+ command << "--hostname #{hostname}"
72
+ command << "--publish 4444:4444"
73
+ command << "-e OVERRIDE_VIDEO_OUTPUT_DIR=#{Runtime::Env.selenoid_directory}/video"
74
+ end
75
+
76
+ # Set volumes
77
+ #
78
+ # @param [Docker::Command] command
79
+ # @return [void]
80
+ def set_volumes(command)
81
+ command.volume('/var/run/docker.sock', '/var/run/docker.sock')
82
+ command.volume("#{__dir__}/../../../../fixtures/selenoid", "/etc/selenoid")
83
+ command.volume("#{Runtime::Env.selenoid_directory}/video", '/opt/selenoid/video')
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  # rubocop:disable Metrics/CyclomaticComplexity
3
+ # rubocop:disable Metrics/AbcSize
3
4
 
4
5
  require 'securerandom'
5
6
 
@@ -27,6 +28,19 @@ module Gitlab
27
28
  end
28
29
 
29
30
  def perform
31
+ if Runtime::Env.use_selenoid?
32
+ Component::Selenoid.perform do |selenoid|
33
+ selenoid.network = network
34
+ selenoid.instance do
35
+ internal_perform
36
+ end
37
+ end
38
+ else
39
+ internal_perform
40
+ end
41
+ end
42
+
43
+ def internal_perform
30
44
  return Runtime::Logger.info("Skipping tests.") if skip_tests?
31
45
 
32
46
  raise ArgumentError unless [suite, release].all?
@@ -114,3 +128,4 @@ module Gitlab
114
128
  end
115
129
  end
116
130
  # rubocop:enable Metrics/CyclomaticComplexity
131
+ # rubocop:enable Metrics/AbcSize
@@ -19,7 +19,7 @@ module Gitlab
19
19
  FAILED_JOB_DESCRIPTION_REGEX = %r{First happened in https?:\/\/\S+\.}m.freeze
20
20
  FAILED_JOB_NOTE_REGEX = %r{Failed most recently in \D+ pipeline: https?:\/\/\S+}.freeze
21
21
  NEW_ISSUE_LABELS = Set.new(%w[QA Quality test failure::new priority::2]).freeze
22
- IGNORE_EXCEPTIONS = ['Net::ReadTimeout'].freeze
22
+ IGNORE_EXCEPTIONS = ['Net::ReadTimeout', '403 Forbidden - Your account has been blocked'].freeze
23
23
 
24
24
  MultipleIssuesFound = Class.new(StandardError)
25
25
 
@@ -53,10 +53,10 @@ module Gitlab
53
53
  puts " => Searching issues for test '#{test.name}'..."
54
54
 
55
55
  begin
56
- issue = test.quarantine? ? find_and_link_issue(test) : find_and_link_issue(test) || create_issue(test)
57
- return unless issue
56
+ issue, issue_already_commented = find_and_link_issue(test)
57
+ return create_issue(test) unless issue || test.quarantine?
58
58
 
59
- update_labels(issue, test)
59
+ update_labels(issue, test) unless issue_already_commented
60
60
  rescue MultipleIssuesFound => e
61
61
  warn(e.message)
62
62
  end
@@ -64,19 +64,18 @@ module Gitlab
64
64
 
65
65
  def find_and_link_issue(test)
66
66
  issue, diff_ratio = find_failure_issue(test)
67
- issue_already_commented = issue ? @commented_issue_list.include?(issue.web_url) : nil
67
+ return [false, true] unless issue
68
68
 
69
- if issue && !issue_already_commented
69
+ issue_already_commented = issue_already_commented?(issue)
70
+ if issue_already_commented
71
+ puts " => Failure already commented on issue."
72
+ else
70
73
  puts " => Found issue #{issue.web_url} for test '#{test.name}' with a diff ratio of #{(diff_ratio * 100).round(2)}%."
71
74
  post_or_update_failed_job_note(issue, test)
72
75
  @commented_issue_list.add(issue.web_url)
73
- else
74
- puts " => Failure already commented on issue." if issue_already_commented
75
-
76
- return false
77
76
  end
78
77
 
79
- issue
78
+ [issue, issue_already_commented]
80
79
  end
81
80
 
82
81
  def create_issue(test)
@@ -286,6 +285,8 @@ module Gitlab
286
285
  current_note = "Failed most recently in #{pipeline} pipeline: #{test.ci_job_url}"
287
286
  existing_note = existing_failure_note(issue)
288
287
 
288
+ return if existing_note && current_note == existing_note.body
289
+
289
290
  if existing_note
290
291
  gitlab.edit_issue_note(issue_iid: issue.iid, note_id: existing_note.id, note: current_note)
291
292
  else
@@ -355,13 +356,17 @@ module Gitlab
355
356
  # @param [Array<Hash>] exceptions the exceptions associated with the failure.
356
357
  # @return [String] the reason to ignore the exceptions, or `nil` if any exceptions should not be ignored.
357
358
  def ignore_failure_reason(exceptions)
358
- exception_classes = exceptions
359
- .filter_map { |exception| exception['class'] if IGNORE_EXCEPTIONS.include?(exception['class']) }
359
+ exception_messages = exceptions
360
+ .filter_map { |exception| exception['message'] if IGNORE_EXCEPTIONS.any? { |e| exception['message'].include?(e) } }
360
361
  .compact
361
- return if exception_classes.empty? || exception_classes.size < exceptions.size
362
+ return if exception_messages.empty? || exception_messages.size < exceptions.size
363
+
364
+ msg = exception_messages.many? ? 'the errors were' : 'the error was'
365
+ "#{msg} #{exception_messages.join(', ')}"
366
+ end
362
367
 
363
- msg = exception_classes.many? ? 'the errors were' : 'the error was'
364
- "#{msg} #{exception_classes.join(', ')}"
368
+ def issue_already_commented?(issue)
369
+ @commented_issue_list.include?(issue.web_url)
365
370
  end
366
371
  end
367
372
  end
@@ -41,6 +41,7 @@ module Gitlab
41
41
  'QA_INFLUXDB_TOKEN' => :qa_influxdb_token,
42
42
  'QA_SKIP_PULL' => :qa_skip_pull,
43
43
  'QA_VALIDATE_RESOURCE_REUSE' => :qa_validate_resource_reuse,
44
+ 'WEBDRIVER_HEADLESS' => :webdriver_headless,
44
45
  'GITLAB_API_BASE' => :api_base,
45
46
  'GITLAB_ADMIN_USERNAME' => :admin_username,
46
47
  'GITLAB_ADMIN_PASSWORD' => :admin_password,
@@ -148,7 +149,9 @@ module Gitlab
148
149
  'RELEASE' => :release,
149
150
  'RELEASE_REGISTRY_URL' => :release_registry_url,
150
151
  'RELEASE_REGISTRY_USERNAME' => :release_registry_username,
151
- 'RELEASE_REGISTRY_PASSWORD' => :release_registry_password
152
+ 'RELEASE_REGISTRY_PASSWORD' => :release_registry_password,
153
+ 'SELENOID_DIRECTORY' => :selenoid_directory,
154
+ 'USE_SELENOID' => :use_selenoid
152
155
  }.freeze
153
156
 
154
157
  ENV_VARIABLES.each do |env_name, method_name|
@@ -349,6 +352,22 @@ module Gitlab
349
352
  enabled?(env_var_value_if_defined('QA_EXPORT_TEST_METRICS'), default: true)
350
353
  end
351
354
 
355
+ def selenoid_directory
356
+ env_var_value_if_defined('SELENOID_DIRECTORY') || "#{host_artifacts_dir}/selenoid"
357
+ end
358
+
359
+ def use_selenoid?
360
+ enabled?(env_var_value_if_defined('USE_SELENOID'), default: false)
361
+ end
362
+
363
+ def mobile_layout?
364
+ env_var_value_if_defined('QA_LAYOUT')&.match?(/tablet|phone/i)
365
+ end
366
+
367
+ def browser_version
368
+ env_var_value_if_defined('QA_BROWSER_VERSION')
369
+ end
370
+
352
371
  def qa_run_type
353
372
  return env_var_value_if_defined('QA_RUN_TYPE') if env_var_value_valid?('QA_RUN_TYPE')
354
373
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module QA
5
- VERSION = '10.2.1'
5
+ VERSION = '10.3.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: 10.2.1
4
+ version: 10.3.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: 2023-04-14 00:00:00.000000000 Z
11
+ date: 2023-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -360,6 +360,7 @@ files:
360
360
  - fixtures/ldap/2_add_users.ldif
361
361
  - fixtures/ldap/3_add_groups.ldif
362
362
  - fixtures/ldap/tanuki.ldif
363
+ - fixtures/selenoid/browsers.json
363
364
  - gitlab-qa.gemspec
364
365
  - lefthook.yml
365
366
  - lib/gitlab/qa.rb
@@ -382,6 +383,7 @@ files:
382
383
  - lib/gitlab/qa/component/production.rb
383
384
  - lib/gitlab/qa/component/release.rb
384
385
  - lib/gitlab/qa/component/saml.rb
386
+ - lib/gitlab/qa/component/selenoid.rb
385
387
  - lib/gitlab/qa/component/specs.rb
386
388
  - lib/gitlab/qa/component/staging.rb
387
389
  - lib/gitlab/qa/component/staging_ref.rb