gitlab-qa 5.15.0 → 6.1.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: 32ae85f17e98b415ac5fddd505d5cf9d37462bbcc5b0eabee7584c3a26803542
4
- data.tar.gz: 62ea7475a8d3eddb193a975c440fc19b2177ea612ecf8a02d9bbf9a8c926f177
3
+ metadata.gz: 960a5ea5f4f964cf9e9a237d75e96350bd611e9c6b9c1e1721c3dd2df1476104
4
+ data.tar.gz: 4c42c1a2652f8f6d49565e849bbb6e3ecdce24d1d11662478cdd511424d7a020
5
5
  SHA512:
6
- metadata.gz: 35e187728145ac187fda0dbe3b41b24d44adc52a3cb8718083736ccf0e36f06a089c74e97db983b4b40f2eb432fa847c440208e083df24d8f9a5df76a495b0d7
7
- data.tar.gz: a7e08091352126ada545f61b6d7a940e0eb87f4ec9d9753fa0521244c2f35b209a0474eb158b7e82486ee7fe5ae59047d3748fd6aadd36922d96b9520081b177
6
+ metadata.gz: 3e09dabf4c89b97a6a92d7d78a4bccaa57605f85ff0559c9423cc55b1bb3e6fb5f926ba1ccad193ee7e04c17b774502b47862011abc674cc00e84a323590a611
7
+ data.tar.gz: c88cd735d53a3c1d17c4aaf28b7af47a1a0ac827d6f3012d187e43b1f897616472f35618cfe9f419b87ff1e88cfb6d5922e49ec53db9cc4c2d3b154f8ab3a786
@@ -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"; fi
97
+ - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ]; then exe/gitlab-qa-report --report-in-issues "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_TESTCASES_REPORTING_PROJECT" || true; fi
98
98
  - exit $test_run_exit_code
99
99
 
100
100
  .ce-qa:
@@ -143,7 +143,7 @@ release:
143
143
  .rspec-report-opts:
144
144
  variables:
145
145
  FILE_SAFE_JOB_NAME: $(echo $CI_JOB_NAME | sed 's/[ /]/_/g')
146
- RSPEC_REPORT_OPTS: "--format RspecJunitFormatter --out \"tmp/rspec-${CI_JOB_ID}.xml\" --format html --out \"tmp/rspec-${FILE_SAFE_JOB_NAME}.htm\" --color --format documentation"
146
+ RSPEC_REPORT_OPTS: "--format QA::Support::JsonFormatter --out \"tmp/rspec-${CI_JOB_ID}.json\" --format RspecJunitFormatter --out \"tmp/rspec-${CI_JOB_ID}.xml\" --format html --out \"tmp/rspec-${FILE_SAFE_JOB_NAME}.htm\" --color --format documentation"
147
147
 
148
148
  .quarantine:
149
149
  allow_failure: true
@@ -832,6 +832,44 @@ ee:praefect-quarantine:
832
832
  QA_CAN_TEST_PRAEFECT: "true"
833
833
  QA_RSPEC_TAGS: "--tag quarantine --tag ~orchestrated"
834
834
 
835
+ ce:gitaly-cluster:
836
+ extends:
837
+ - .test
838
+ - .high-capacity
839
+ - .ce-qa
840
+ - .rspec-report-opts
841
+ variables:
842
+ QA_SCENARIO: "Test::Integration::GitalyCluster"
843
+
844
+ ce:gitaly-cluster-quarantine:
845
+ extends:
846
+ - .test
847
+ - .high-capacity
848
+ - .ce-qa
849
+ - .quarantine
850
+ - .rspec-report-opts
851
+ variables:
852
+ QA_SCENARIO: "Test::Integration::GitalyCluster"
853
+
854
+ ee:gitaly-cluster:
855
+ extends:
856
+ - .test
857
+ - .high-capacity
858
+ - .ee-qa
859
+ - .rspec-report-opts
860
+ variables:
861
+ QA_SCENARIO: "Test::Integration::GitalyCluster"
862
+
863
+ ee:gitaly-cluster-quarantine:
864
+ extends:
865
+ - .test
866
+ - .high-capacity
867
+ - .ee-qa
868
+ - .quarantine
869
+ - .rspec-report-opts
870
+ variables:
871
+ QA_SCENARIO: "Test::Integration::GitalyCluster"
872
+
835
873
  ce:smtp:
836
874
  extends:
837
875
  - .test
@@ -893,7 +931,8 @@ ee:jira-quarantine:
893
931
  staging:
894
932
  script:
895
933
  - unset EE_LICENSE
896
- - exe/gitlab-qa Test::Instance::Staging
934
+ - 'echo "Running: exe/gitlab-qa Test::Instance::Staging ${RELEASE:=$DEFAULT_RELEASE} -- $QA_TESTS $QA_RSPEC_TAGS"'
935
+ - exe/gitlab-qa Test::Instance::Staging ${RELEASE:=$DEFAULT_RELEASE} -- $QA_TESTS $QA_RSPEC_TAGS
897
936
  extends:
898
937
  - .test
899
938
  - .high-capacity
@@ -1,5 +1,6 @@
1
- # What tests can be run?
2
1
 
2
+ # What tests can be run?
3
+ [[_TOC_]]
3
4
  ## The two types of QA tests
4
5
 
5
6
  First of all, the first thing to choose is whether you want to run orchestrated
@@ -28,6 +29,8 @@ For more details on the internals, please read the
28
29
 
29
30
  ## Supported GitLab environment variables
30
31
 
32
+ All environment variables used by GitLab QA should be defined in [`lib/gitlab/qa/runtime/env.rb`](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/lib/gitlab/qa/runtime/env.rb).
33
+
31
34
  | Variable | Default | Description | Required |
32
35
  |-----------------------|-----------|-----------------------|----------|
33
36
  | `GITLAB_USERNAME` | `root` | Username to use when signing into GitLab. | Yes|
@@ -53,7 +56,8 @@ For more details on the internals, please read the
53
56
  | `GITLAB_SANDBOX_NAME` | `gitlab-qa-sandbox` | The sandbox group name the test suite is going to use. | No|
54
57
  | `GITLAB_QA_ACCESS_TOKEN`|- | A valid personal access token with the `api` scope. This is used for API access during tests, and is used in the version that staging is currently running. An existing token that is valid on [`Test::Instance::Staging`](#testinstancestaging) scenario to retrieve the staging can be found in the shared 1Password vault. |No|
55
58
  | `GITLAB_QA_ADMIN_ACCESS_TOKEN` |- | A valid personal access token with the `api` scope from a user with admin access. Used for API access as an admin during tests. | No|
56
- | `EE_LICESEN` |- | Enterprise Edition license. | No|
59
+ | `GITLAB_QA_CONTAINER_REGISTRY_ACCESS_TOKEN` | - | A valid personal access token with the `read_registry` scope. Used to [access the container registry on `registry.gitlab.com` when tests run in a CI job that _is not_ triggered via another pipeline](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/364addb83e7b136ff0f9d8719ca9553d290aa9ab/lib/gitlab/qa/release.rb#L152). For example, if you manually run a [new Staging pipeline](https://ops.gitlab.net/gitlab-org/quality/staging/-/pipelines/new), this token will be used. | No |
60
+ | `EE_LICENSE` |- | Enterprise Edition license. | No|
57
61
  | `QA_ARTIFACTS_DIR` |`/tmp/gitlab-qa`| Path to a directory where artifacts (logs and screenshots) for failing tests will be saved. | No|
58
62
  | `DOCKER_HOST` |`http://localhost`| Docker host to run tests against. | No|
59
63
  | `CHROME_HEADLESS` |- | When running locally, set to `false` to allow Chrome tests to be visible - watch your tests being run. | No|
@@ -83,8 +87,27 @@ For more details on the internals, please read the
83
87
 
84
88
  ## Running tests with a feature flag enabled
85
89
 
86
- It is possible to enable a feature flag before running tests. See the [QA
87
- framework documentation](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/qa/README.md#running-tests-with-a-feature-flag-enabled) for details.
90
+ It is possible to enable or disable a feature flag before running tests.
91
+ To test a Gitlab image with a feature flag enabled, run this command:
92
+ ```
93
+ $ gitlab-qa Test::Instance::Image gitlab/gitlab-ee:12.4.0-ee.0 --enable-feature feature_flag_name
94
+ ```
95
+
96
+ To run a test with feature flag disabled, run this command:
97
+ ```
98
+ $ gitlab-qa Test::Instance::Image gitlab/gitlab-ee:12.4.0-ee.0 --disable-feature feature_flag_name
99
+ ```
100
+
101
+ You an also test a GitLab image multiple times with different feature flag settings:
102
+ ```
103
+ $ gitlab-qa Test::Instance::Image gitlab/gitlab-ee:12.4.0-ee.0 --disable-feature feature_flag_name --enable-feature feature_flag_name
104
+ ```
105
+ This will first disable `feature_flag_name` flag and run the tests and then enable it and run the tests again.
106
+
107
+ You can pass any number of feature flag settings. The tests will run once for each setting.
108
+
109
+ See the [QA framework documentation](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/qa/README.md#running-tests-with-a-feature-flag-enabled)
110
+ for information on running the tests with different feature flag settings from the QA framework.
88
111
 
89
112
  ## Specifying the GitLab version
90
113
 
@@ -217,6 +240,25 @@ $ gitlab-qa Test::Integration::Geo EE
217
240
 
218
241
  [test-geo]: https://gitlab.com/gitlab-org/gitlab-ee/blob/master/qa/qa/ee/scenario/test/geo.rb
219
242
 
243
+ ### `Test::Integration::GitalyCluster CE|EE|<full image address>`
244
+
245
+ This tests [Gitaly Cluster](https://docs.gitlab.com/ee/administration/gitaly/praefect.html),
246
+ a clustered configuration of the Gitaly repository storage service.
247
+
248
+ The scenario configures and starts several docker containers to
249
+ represent the [recommended minimum configuration](https://docs.gitlab.com/ee/administration/gitaly/praefect.html#requirements-for-configuring-a-gitaly-cluster)
250
+ of a Gitaly Cluster.
251
+
252
+ To run tests against the GitLab container, a GitLab QA (`gitlab/gitlab-qa`)
253
+ container is spun up and tests are run from it by running the
254
+ `Test::Instance::All` scenario with the `:gitaly_cluster` tag.
255
+
256
+ Example:
257
+
258
+ ```
259
+ $ gitlab-qa Test::Integration::GitalyCluster EE
260
+ ```
261
+
220
262
  ### `Test::Integration::LDAPNoTLS CE|EE|<full image address>`
221
263
 
222
264
  This tests that a GitLab instance works as expected with an external
@@ -545,7 +587,7 @@ in the GitLab CE project).
545
587
 
546
588
  - `GITLAB_QA_DEV_ACCESS_TOKEN`: A valid personal access token for the
547
589
  `gitlab-qa-bot` on `dev.gitlab.org` with the `registry` scope.
548
- This is used to pull the QA Docker from the Omnibus GitLab `dev` Container Registry.
590
+ This is used to pull the QA Docker image from the Omnibus GitLab `dev` Container Registry.
549
591
  If the variable isn't present, the QA image from Docker Hub will be used.
550
592
  This can be found in the shared 1Password vault.
551
593
 
@@ -560,6 +602,41 @@ $ export GITLAB_PASSWORD="$GITLAB_QA_PASSWORD"
560
602
  $ gitlab-qa Test::Instance::Staging
561
603
  ```
562
604
 
605
+ ### `Test::Instance::StagingGeo`
606
+
607
+ This scenario tests that the Geo staging deployment (with [`staging.gitlab.com`](https://staging.gitlab.com) as the primary site and [`geo.staging.gitlab.com`](https://geo.staging.gitlab.com) as the secondary site) works as expected by running tests tagged `:geo` against it. This is done by spinning up a GitLab QA (`gitlab/gitlab-qa`) container and running the `QA::EE::Scenario::Test::Geo` scenario. Note that the Geo setup steps in the `QA::EE::Scenario::Test::Geo` scenario are skipped when testing a live Geo deployment.
608
+
609
+ **Required user properties:**
610
+
611
+ - The user must provide OAuth authorization on the secondary site before running Geo tests. This can be done via the authorization modal that appears after logging into the secondary node for the first time.
612
+
613
+ - Some Geo tests require the user to have Admin access level (for example, the Geo Nodes API tests)
614
+
615
+ **Required environment variables:**
616
+
617
+ - `GITLAB_QA_ACCESS_TOKEN`: A valid personal access token with the `api` scope.
618
+ This is used to retrieve the version that staging is currently running.
619
+ This can be found in the shared 1Password vault.
620
+
621
+ **Optional environment variables:**
622
+
623
+ - `GITLAB_QA_DEV_ACCESS_TOKEN`: A valid personal access token for the
624
+ `gitlab-qa-bot` on `dev.gitlab.org` with the `registry` scope.
625
+ This is used to pull the QA Docker image from the Omnibus GitLab `dev` Container Registry.
626
+ If the variable isn't present, the QA image from Docker Hub will be used.
627
+ This can be found in the shared 1Password vault.
628
+
629
+ Example:
630
+
631
+ ```
632
+ $ export GITLAB_QA_ACCESS_TOKEN=your_api_access_token
633
+ $ export GITLAB_QA_DEV_ACCESS_TOKEN=your_dev_registry_access_token
634
+ $ export GITLAB_USERNAME="gitlab-qa"
635
+ $ export GITLAB_PASSWORD="$GITLAB_QA_PASSWORD"
636
+
637
+ $ gitlab-qa Test::Instance::StagingGeo
638
+ ```
639
+
563
640
  ### `Test::Instance::Production`
564
641
 
565
642
  This scenario functions the same as `Test::Instance::Staging`
@@ -633,6 +710,25 @@ $ export EE_LICENSE=$(cat /path/to/gitlab_license)
633
710
  $ gitlab-qa Test::Instance::Airgapped EE -- --tag smoke
634
711
  ```
635
712
 
713
+ ### `Test::Instance::Geo EE|<full image address>:nightly|latest|any_tag http://geo-primary.gitlab http://geo-secondary.gitlab`
714
+
715
+ This scenario will run tests tagged `:geo` against a live Geo deployment, by spinning up a GitLab QA (`gitlab/gitlab-qa`)
716
+ container and running the `QA::EE::Scenario::Test::Geo` scenario. Note that the Geo setup steps in the `QA::EE::Scenario::Test::Geo` scenario are skipped when testing a live Geo deployment. The URLs for the primary site and secondary site of the live Geo deployment must be provided as command line arguments.
717
+
718
+ **Required user properties:**
719
+
720
+ - The user must provide OAuth authorization on the secondary site before running Geo tests. This can be done via the authorization modal that appears after signing into the secondary node for the first time.
721
+
722
+ - Some Geo tests require the user to have Admin access level (for example, the Geo Nodes API tests)
723
+
724
+ Example:
725
+
726
+ ```
727
+ $ export GITLAB_USERNAME="gitlab-qa"
728
+ $ export GITLAB_PASSWORD="$GITLAB_QA_PASSWORD"
729
+
730
+ $ gitlab-qa Test::Instance::Geo EE https://primary.gitlab.com https://secondary.gitlab.com
731
+ ```
636
732
  ----
637
733
 
638
734
  [Back to README.md](../README.md)
@@ -54,7 +54,7 @@ module Gitlab
54
54
  autoload :Praefect, 'gitlab/qa/scenario/test/integration/praefect'
55
55
  autoload :Elasticsearch, 'gitlab/qa/scenario/test/integration/elasticsearch'
56
56
  autoload :SMTP, 'gitlab/qa/scenario/test/integration/smtp'
57
- autoload :GitalyHA, 'gitlab/qa/scenario/test/integration/gitaly_ha'
57
+ autoload :GitalyCluster, 'gitlab/qa/scenario/test/integration/gitaly_cluster'
58
58
  autoload :Jira, 'gitlab/qa/scenario/test/integration/jira'
59
59
  end
60
60
 
@@ -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,16 +41,12 @@ 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
45
- prepare
46
- start
47
- reconfigure
48
- wait_until_ready
49
- process_exec_commands
50
-
51
- yield self if block_given?
44
+ def instance(skip_teardown: false)
45
+ instance_no_teardown do
46
+ yield self if block_given?
47
+ end
52
48
  ensure
53
- teardown
49
+ teardown unless skip_teardown
54
50
  end
55
51
 
56
52
  alias_method :launch_and_teardown_instance, :instance
@@ -141,6 +137,16 @@ module Gitlab
141
137
  raise 'Invalid instance name!' unless name
142
138
  end
143
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
+
144
150
  def teardown?
145
151
  !Runtime::Scenario.attributes.include?(:teardown) || Runtime::Scenario.teardown
146
152
  end
@@ -27,26 +27,50 @@ module Gitlab
27
27
 
28
28
  name = "#{release.project_name}-qa-#{SecureRandom.hex(4)}"
29
29
 
30
- @docker.run(release.qa_image, release.qa_tag, suite, *args) do |command|
31
- command << "-t --rm --net=#{network || 'bridge'}"
30
+ feature_flag_sets = []
32
31
 
33
- env.merge(Runtime::Env.variables).each do |key, value|
34
- command.env(key, value)
35
- end
32
+ # When `args` includes `[..., "--disable-feature", "a", "--enable-feature", "b", ...]`
33
+ # `feature_flag_sets` will be set to `[["--disable-feature", "a"], ["--enable-feature", "b"]]`
34
+ # This will result in tests running twice, once with each feature.
35
+ while (index = args&.index { |x| x =~ /--.*-feature/ })
36
+ feature_flag_sets << args.slice!(index, 2)
37
+ end
36
38
 
37
- command.volume('/var/run/docker.sock', '/var/run/docker.sock')
38
- command.volume(File.join(Runtime::Env.host_artifacts_dir, name), File.join(Docker::Volumes::QA_CONTAINER_WORKDIR, 'tmp'))
39
+ # When `args` do not have either "--disable-feature" or "--enable-feature", we
40
+ # add [] so that test is run exactly once.
41
+ feature_flag_sets << [] unless feature_flag_sets.any?
39
42
 
40
- @volumes.to_h.each do |to, from|
41
- command.volume(to, from)
42
- end
43
+ feature_flag_sets.each do |feature_flag_set|
44
+ @docker.run(release.qa_image, release.qa_tag, suite, *args_with_flags(args, feature_flag_set)) do |command|
45
+ command << "-t --rm --net=#{network || 'bridge'}"
46
+
47
+ env.merge(Runtime::Env.variables).each do |key, value|
48
+ command.env(key, value)
49
+ end
50
+
51
+ command.volume('/var/run/docker.sock', '/var/run/docker.sock')
52
+ command.volume(File.join(Runtime::Env.host_artifacts_dir, name), File.join(Docker::Volumes::QA_CONTAINER_WORKDIR, 'tmp'))
53
+
54
+ @volumes.to_h.each do |to, from|
55
+ command.volume(to, from)
56
+ end
43
57
 
44
- command.name(name)
58
+ command.name(name)
59
+ end
45
60
  end
46
61
  end
47
62
 
48
63
  private
49
64
 
65
+ def args_with_flags(args, feature_flag_set)
66
+ return args if feature_flag_set.empty?
67
+
68
+ puts "Running with feature flag: #{feature_flag_set.join(' ')}"
69
+
70
+ args_with_f = args.dup
71
+ args_with_f.insert(1, *feature_flag_set)
72
+ end
73
+
50
74
  def skip_tests?
51
75
  Runtime::Scenario.attributes.include?(:run_tests) && !Runtime::Scenario.run_tests
52
76
  end
@@ -4,8 +4,9 @@ module Gitlab
4
4
  class Command
5
5
  attr_reader :args
6
6
 
7
- def initialize(cmd = nil)
7
+ def initialize(cmd = nil, mask_secrets: nil)
8
8
  @args = Array(cmd)
9
+ @mask_secrets = Array(mask_secrets)
9
10
  end
10
11
 
11
12
  def <<(*args)
@@ -28,6 +29,17 @@ module Gitlab
28
29
  "docker #{@args.join(' ')}"
29
30
  end
30
31
 
32
+ # Returns a masked string form of a Command
33
+ #
34
+ # @example
35
+ # Command.new('a docker command', mask_secrets: 'command').mask_secrets #=> 'a docker *****'
36
+ # Command.new('a docker command', mask_secrets: %w[docker command]).mask_secrets #=> 'a ***** *****'
37
+ #
38
+ # @return [String] The masked command string
39
+ def mask_secrets
40
+ @mask_secrets.each_with_object(to_s) { |secret, s| s.gsub!(secret, '*****') }
41
+ end
42
+
31
43
  def ==(other)
32
44
  to_s == other.to_s
33
45
  end
@@ -36,8 +48,8 @@ module Gitlab
36
48
  Docker::Shellout.new(self).execute!(&block)
37
49
  end
38
50
 
39
- def self.execute(cmd, &block)
40
- new(cmd).execute!(&block)
51
+ def self.execute(cmd, mask_secrets: nil, &block)
52
+ new(cmd, mask_secrets: mask_secrets).execute!(&block)
41
53
  end
42
54
  end
43
55
  end
@@ -10,7 +10,7 @@ module Gitlab
10
10
  end
11
11
 
12
12
  def login(username:, password:, registry:)
13
- Docker::Command.execute(%(login --username "#{username}" --password "#{password}" #{registry}))
13
+ Docker::Command.execute(%(login --username "#{username}" --password "#{password}" #{registry}), mask_secrets: password)
14
14
  end
15
15
 
16
16
  def pull(image, tag)
@@ -10,7 +10,7 @@ module Gitlab
10
10
  @command = command
11
11
  @output = []
12
12
 
13
- puts "Docker shell command: `#{@command}`"
13
+ puts "Docker shell command: `#{@command.mask_secrets}`"
14
14
  end
15
15
 
16
16
  def execute!
@@ -28,7 +28,7 @@ module Gitlab
28
28
  end
29
29
 
30
30
  if wait.value.exited? && wait.value.exitstatus.nonzero?
31
- raise StatusError, "Docker command `#{@command}` failed!"
31
+ raise StatusError, "Docker command `#{@command.mask_secrets}` failed!"
32
32
  end
33
33
  end
34
34
 
@@ -147,14 +147,15 @@ module Gitlab
147
147
  registry: DEV_REGISTRY
148
148
  }
149
149
  elsif omnibus_mirror?
150
- username, password = if Runtime::Env.ci_job_token
150
+ username, password = if Runtime::Env.ci_job_token && Runtime::Env.ci_pipeline_source == 'pipeline'
151
151
  ['gitlab-ci-token', Runtime::Env.ci_job_token]
152
+ elsif Runtime::Env.qa_container_registry_access_token
153
+ [Runtime::Env.gitlab_username, Runtime::Env.qa_container_registry_access_token]
152
154
  else
153
155
  Runtime::Env.require_qa_access_token!
154
156
 
155
157
  [Runtime::Env.gitlab_username, Runtime::Env.qa_access_token]
156
158
  end
157
-
158
159
  {
159
160
  username: username,
160
161
  password: password,
@@ -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
@@ -46,7 +46,18 @@ module Gitlab
46
46
 
47
47
  Dir.glob(files).each do |file|
48
48
  puts "Reporting tests in #{file}"
49
- Nokogiri::XML(File.open(file)).xpath('//testcase').each do |test|
49
+ extension = File.extname(file)
50
+
51
+ case extension
52
+ when '.json'
53
+ test_results = Report::JsonTestResults.new(file)
54
+ when '.xml'
55
+ test_results = Report::JUnitTestResults.new(file)
56
+ else
57
+ raise "Unknown extension #{extension}"
58
+ end
59
+
60
+ test_results.each do |test|
50
61
  report_test(test)
51
62
  end
52
63
  end
@@ -99,9 +110,9 @@ module Gitlab
99
110
  end
100
111
 
101
112
  def report_test(test)
102
- return if test.search('skipped').any?
113
+ return if test.skipped
103
114
 
104
- puts "Reporting test: #{test['file']} | #{test['name']}"
115
+ puts "Reporting test: #{test.file} | #{test.name}"
105
116
 
106
117
  issue = find_issue(test)
107
118
  if issue
@@ -124,29 +135,37 @@ module Gitlab
124
135
  Gitlab.create_issue(
125
136
  project,
126
137
  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' }
138
+ { description: "### Full description\n\n#{search_safe(test.name)}\n\n### File path\n\n#{test.file}", labels: 'status::automated' }
128
139
  )
129
140
  end
130
141
  end
131
142
 
143
+ # rubocop:disable Metrics/AbcSize
132
144
  def find_issue(test)
133
145
  handle_gitlab_client_exceptions do
146
+ return Gitlab.issue(project, id_from_status_issue_url(test.status_issue)) if test.status_issue
147
+
134
148
  issues = Gitlab.issues(project, { search: search_term(test) })
135
149
  .auto_paginate
136
150
  .select { |issue| issue.state == 'opened' && issue.title.strip == title_from_test(test) }
137
151
 
138
- warn(%(Too many issues found with the file path "#{test['file']}" and name "#{test['name']}")) if issues.many?
152
+ warn(%(Too many issues found with the file path "#{test.file}" and name "#{test.name}")) if issues.many?
139
153
 
140
154
  issues.first
141
155
  end
142
156
  end
157
+ # rubocop:enable Metrics/AbcSize
158
+
159
+ def id_from_status_issue_url(url)
160
+ url.split('/').last.to_i
161
+ end
143
162
 
144
163
  def search_term(test)
145
- %("#{test['file']}" "#{search_safe(test['name'])}")
164
+ %("#{test.file}" "#{search_safe(test.name)}")
146
165
  end
147
166
 
148
167
  def title_from_test(test)
149
- title = "#{partial_file_path(test['file'])} | #{search_safe(test['name'])}".strip
168
+ title = "#{partial_file_path(test.file)} | #{search_safe(test.name)}".strip
150
169
 
151
170
  return title unless title.length > MAX_TITLE_LENGTH
152
171
 
@@ -162,7 +181,7 @@ module Gitlab
162
181
  end
163
182
 
164
183
  def note_status(issue, test)
165
- return if failures(test).empty?
184
+ return if test.failures.empty?
166
185
 
167
186
  note = note_content(test)
168
187
 
@@ -176,7 +195,7 @@ module Gitlab
176
195
  end
177
196
 
178
197
  def note_content(test)
179
- errors = failures(test).each_with_object([]) do |failure, text|
198
+ errors = test.failures.each_with_object([]) do |failure, text|
180
199
  text << <<~TEXT
181
200
  Error:
182
201
  ```
@@ -185,7 +204,7 @@ module Gitlab
185
204
 
186
205
  Stacktrace:
187
206
  ```
188
- #{failure.content}
207
+ #{failure['stacktrace']}
189
208
  ```
190
209
  TEXT
191
210
  end.join("\n\n")
@@ -231,7 +250,7 @@ module Gitlab
231
250
  def update_labels(issue, test)
232
251
  labels = issue.labels
233
252
  labels.delete_if { |label| label.start_with?("#{pipeline}::") }
234
- labels << (failures(test).empty? ? "#{pipeline}::passed" : "#{pipeline}::failed")
253
+ labels << (test.failures.empty? ? "#{pipeline}::passed" : "#{pipeline}::failed")
235
254
  labels << "Enterprise Edition" if ee_test?(test)
236
255
  quarantine_job? ? labels << "quarantine" : labels.delete("quarantine")
237
256
 
@@ -242,11 +261,7 @@ module Gitlab
242
261
  # rubocop:enable Metrics/AbcSize
243
262
 
244
263
  def ee_test?(test)
245
- test['file'] =~ %r{features/ee/(api|browser_ui)}
246
- end
247
-
248
- def failures(test)
249
- test.search('failure')
264
+ test.file =~ %r{features/ee/(api|browser_ui)}
250
265
  end
251
266
 
252
267
  def pipeline
@@ -0,0 +1,64 @@
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, :status_issue
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
+ test_result.status_issue = test['status_issue']
16
+ end
17
+ end
18
+
19
+ def self.from_junit(test)
20
+ new.tap do |test_result|
21
+ test_result.name = test['name']
22
+ test_result.file = test['file']
23
+ test_result.skipped = test.search('skipped').any?
24
+ test_result.failures = failures_from_junit_exceptions(test)
25
+ end
26
+ end
27
+
28
+ def self.failures_from_json_exceptions(test)
29
+ return [] unless test.key?('exceptions')
30
+
31
+ test['exceptions'].map do |exception|
32
+ spec_file_first_index = exception['backtrace'].rindex do |line|
33
+ line.include?(File.basename(test['file_path']))
34
+ end
35
+
36
+ {
37
+ 'message' => "#{exception['class']}: #{exception['message']}",
38
+ 'stacktrace' => exception['backtrace'].slice(0..spec_file_first_index).join("\n")
39
+ }
40
+ end
41
+ end
42
+ private_class_method :failures_from_json_exceptions
43
+
44
+ def self.failures_from_junit_exceptions(test)
45
+ failures = test.search('failure')
46
+ return [] if failures.empty?
47
+
48
+ failures.map do |exception|
49
+ trace = exception.content.split("\n").map(&:strip)
50
+ spec_file_first_index = trace.rindex do |line|
51
+ line.include?(File.basename(test['file']))
52
+ end
53
+
54
+ {
55
+ 'message' => "#{exception['type']}: #{exception['message']}",
56
+ 'stacktrace' => trace.slice(0..spec_file_first_index).join("\n")
57
+ }
58
+ end
59
+ end
60
+ private_class_method :failures_from_junit_exceptions
61
+ end
62
+ end
63
+ end
64
+ end
@@ -6,6 +6,8 @@ module Gitlab
6
6
  module Env
7
7
  extend self
8
8
 
9
+ # Variables that are used in tests and are passed through to the docker container that executes the tests.
10
+ # These variables should be listed in /docs/what_tests_can_be_run.md#supported-gitlab-environment-variables
9
11
  ENV_VARIABLES = {
10
12
  'QA_REMOTE_GRID' => :remote_grid,
11
13
  'QA_REMOTE_GRID_USERNAME' => :remote_grid_username,
@@ -38,6 +40,7 @@ module Gitlab
38
40
  'SIGNUP_DISABLED' => :signup_disabled,
39
41
  'QA_ADDITIONAL_REPOSITORY_STORAGE' => :qa_additional_repository_storage,
40
42
  'QA_PRAEFECT_REPOSITORY_STORAGE' => :qa_praefect_repository_storage,
43
+ 'QA_GITALY_NON_CLUSTER_STORAGE' => :qa_gitaly_non_cluster_storage,
41
44
  'QA_COOKIES' => :qa_cookie,
42
45
  'QA_DEBUG' => :qa_debug,
43
46
  'QA_LOG_PATH' => :qa_log_path,
@@ -112,6 +115,10 @@ module Gitlab
112
115
  ENV['CI_JOB_URL']
113
116
  end
114
117
 
118
+ def ci_pipeline_source
119
+ ENV['CI_PIPELINE_SOURCE']
120
+ end
121
+
115
122
  def ci_project_name
116
123
  ENV['CI_PROJECT_NAME']
117
124
  end
@@ -148,6 +155,10 @@ module Gitlab
148
155
  ENV['GITLAB_QA_DEV_ACCESS_TOKEN']
149
156
  end
150
157
 
158
+ def qa_container_registry_access_token
159
+ ENV['GITLAB_QA_CONTAINER_REGISTRY_ACCESS_TOKEN']
160
+ end
161
+
151
162
  def host_artifacts_dir
152
163
  @host_artifacts_dir ||= File.join(ENV['QA_ARTIFACTS_DIR'] || '/tmp/gitlab-qa', Runtime::Env.run_id)
153
164
  end
@@ -8,9 +8,6 @@ module Gitlab
8
8
 
9
9
  class Geo < Scenario::Template
10
10
  def perform(release, primary_address, secondary_address, *rspec_args)
11
- # Geo requires an EE license
12
- Runtime::Env.require_license!
13
-
14
11
  Component::Specs.perform do |specs|
15
12
  specs.suite = 'QA::EE::Scenario::Test::Geo'
16
13
  specs.release = QA::Release.new(release)
@@ -27,13 +27,14 @@ module Gitlab
27
27
  gitlab_rails['db_pool'] = 5;
28
28
  gitlab_rails['geo_node_name'] = '#{primary.name}';
29
29
  gitlab_rails['monitoring_whitelist'] = ['0.0.0.0/0'];
30
+ gitlab_rails['packages_enabled'] = true;
30
31
  postgresql['listen_address'] = '0.0.0.0';
31
32
  postgresql['max_replication_slots'] = 1;
32
33
  postgresql['md5_auth_cidr_addresses'] = ['0.0.0.0/0'];
33
34
  postgresql['sql_user_password'] = 'e1d1469ec5f533651918b4567a3ed1ae';
34
35
  postgresql['trust_auth_cidr_addresses'] = ['0.0.0.0/0','0.0.0.0/0'];
35
36
  sidekiq['concurrency'] = 2;
36
- unicorn['worker_processes'] = 2;
37
+ puma['worker_processes'] = 2;
37
38
  OMNIBUS
38
39
  primary.exec_commands = fast_ssh_key_lookup_commands + git_lfs_install_commands
39
40
 
@@ -50,11 +51,12 @@ module Gitlab
50
51
  gitlab_rails['db_pool'] = 5;
51
52
  gitlab_rails['geo_node_name'] = '#{secondary.name}';
52
53
  gitlab_rails['monitoring_whitelist'] = ['0.0.0.0/0'];
54
+ gitlab_rails['packages_enabled'] = true;
53
55
  postgresql['listen_address'] = '0.0.0.0';
54
56
  postgresql['md5_auth_cidr_addresses'] = ['0.0.0.0/0'];
55
57
  postgresql['sql_user_password'] = 'e1d1469ec5f533651918b4567a3ed1ae';
56
58
  sidekiq['concurrency'] = 2;
57
- unicorn['worker_processes'] = 2;
59
+ puma['worker_processes'] = 2;
58
60
  OMNIBUS
59
61
  secondary.exec_commands = fast_ssh_key_lookup_commands + git_lfs_install_commands
60
62
 
@@ -0,0 +1,204 @@
1
+ module Gitlab
2
+ module QA
3
+ module Scenario
4
+ module Test
5
+ module Integration
6
+ class GitalyCluster < Scenario::Template
7
+ attr_reader :gitlab_name, :spec_suite
8
+
9
+ def initialize
10
+ @gitlab_name = 'gitlab-gitaly-cluster'
11
+ @primary_node_name = 'gitaly1'
12
+ @secondary_node_name = 'gitaly2'
13
+ @tertiary_node_name = 'gitaly3'
14
+ @praefect_node_name = 'praefect'
15
+ @database = 'postgres'
16
+ @spec_suite = 'Test::Instance::All'
17
+ @network = 'test'
18
+ end
19
+
20
+ # rubocop:disable Metrics/AbcSize
21
+ def perform(release, *rspec_args)
22
+ gitaly_primary_node = gitaly(@primary_node_name, release)
23
+ gitaly_secondary_node = gitaly(@secondary_node_name, release)
24
+ gitaly_tertiary_node = gitaly(@tertiary_node_name, release)
25
+
26
+ sql_node = Component::PostgreSQL.new.tap do |sql|
27
+ sql.name = @database
28
+ sql.network = @network
29
+ sql.instance(skip_teardown: true) do
30
+ sql.run_psql '-d template1 -c "CREATE DATABASE praefect_production OWNER postgres"'
31
+ end
32
+ end
33
+
34
+ praefect_node = Component::Gitlab.new.tap do |praefect|
35
+ praefect.release = QA::Release.new(release)
36
+ praefect.name = @praefect_node_name
37
+ praefect.network = @network
38
+ praefect.skip_availability_check = true
39
+
40
+ praefect.omnibus_config = praefect_omnibus_configuration
41
+
42
+ praefect.instance(skip_teardown: true)
43
+ end
44
+
45
+ Component::Gitlab.perform do |gitlab|
46
+ gitlab.release = QA::Release.new(release)
47
+ gitlab.name = gitlab_name
48
+ gitlab.network = @network
49
+
50
+ gitlab.omnibus_config = gitlab_omnibus_configuration
51
+ gitlab.instance do
52
+ puts "Running Gitaly Cluster specs!"
53
+
54
+ rspec_args << "--" unless rspec_args.include?('--')
55
+ rspec_args << %w[--tag gitaly_cluster]
56
+
57
+ Component::Specs.perform do |specs|
58
+ specs.suite = spec_suite
59
+ specs.release = gitlab.release
60
+ specs.network = gitlab.network
61
+ specs.args = [gitlab.address, *rspec_args]
62
+ end
63
+ end
64
+ end
65
+ ensure
66
+ praefect_node&.teardown
67
+ sql_node&.teardown
68
+ gitaly_primary_node&.teardown
69
+ gitaly_secondary_node&.teardown
70
+ gitaly_tertiary_node&.teardown
71
+ end
72
+ # rubocop:enable Metrics/AbcSize
73
+
74
+ private
75
+
76
+ def disable_other_services
77
+ <<~OMNIBUS
78
+ postgresql['enable'] = false;
79
+ redis['enable'] = false;
80
+ nginx['enable'] = false;
81
+ prometheus['enable'] = false;
82
+ grafana['enable'] = false;
83
+ puma['enable'] = false;
84
+ sidekiq['enable'] = false;
85
+ gitlab_workhorse['enable'] = false;
86
+ gitlab_rails['rake_cache_clear'] = false;
87
+ gitlab_rails['auto_migrate'] = false;
88
+ OMNIBUS
89
+ end
90
+
91
+ def praefect_omnibus_configuration
92
+ <<~OMNIBUS
93
+ #{disable_other_services}
94
+ gitaly['enable'] = false;
95
+ praefect['enable'] = true;
96
+ praefect['listen_addr'] = '0.0.0.0:2305';
97
+ praefect['prometheus_listen_addr'] = '0.0.0.0:9652';
98
+ praefect['auth_token'] = 'PRAEFECT_EXTERNAL_TOKEN';
99
+ praefect['database_host'] = '#{@database}.#{@network}';
100
+ praefect['database_user'] = 'postgres';
101
+ praefect['database_port'] = 5432;
102
+ praefect['database_password'] = 'SQL_PASSWORD';
103
+ praefect['database_dbname'] = 'praefect_production';
104
+ praefect['database_sslmode'] = 'disable';
105
+ praefect['postgres_queue_enabled'] = true;
106
+ praefect['failover_enabled'] = true;
107
+ praefect['virtual_storages'] = {
108
+ 'default' => {
109
+ '#{@primary_node_name}' => {
110
+ 'address' => 'tcp://#{@primary_node_name}.#{@network}:8075',
111
+ 'token' => 'PRAEFECT_INTERNAL_TOKEN',
112
+ 'primary' => true
113
+ },
114
+ '#{@secondary_node_name}' => {
115
+ 'address' => 'tcp://#{@secondary_node_name}.#{@network}:8075',
116
+ 'token' => 'PRAEFECT_INTERNAL_TOKEN'
117
+ },
118
+ '#{@tertiary_node_name}' => {
119
+ 'address' => 'tcp://#{@tertiary_node_name}.#{@network}:8075',
120
+ 'token' => 'PRAEFECT_INTERNAL_TOKEN'
121
+ }
122
+ }
123
+ };
124
+ OMNIBUS
125
+ end
126
+
127
+ def gitaly_omnibus_configuration
128
+ <<~OMNIBUS
129
+ #{disable_other_services}
130
+ prometheus['enable'] = true;
131
+ prometheus_monitoring['enable'] = false;
132
+ gitaly['enable'] = true;
133
+ gitaly['listen_addr'] = '0.0.0.0:8075';
134
+ gitaly['prometheus_listen_addr'] = '0.0.0.0:9236';
135
+ gitaly['auth_token'] = 'PRAEFECT_INTERNAL_TOKEN';
136
+ gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN';
137
+ gitlab_rails['internal_api_url'] = 'http://#{@gitlab_name}.#{@network}';
138
+ git_data_dirs({
139
+ '#{@primary_node_name}' => {
140
+ 'path' => '/var/opt/gitlab/git-data'
141
+ },
142
+ '#{@secondary_node_name}' => {
143
+ 'path' => '/var/opt/gitlab/git-data'
144
+ },
145
+ '#{@tertiary_node_name}' => {
146
+ 'path' => '/var/opt/gitlab/git-data'
147
+ }
148
+ });
149
+ OMNIBUS
150
+ end
151
+
152
+ def gitlab_omnibus_configuration
153
+ <<~OMNIBUS
154
+ external_url 'http://#{@gitlab_name}.#{@network}';
155
+
156
+ git_data_dirs({
157
+ 'default' => {
158
+ 'gitaly_address' => 'tcp://#{@praefect_node_name}.#{@network}:2305',
159
+ 'gitaly_token' => 'PRAEFECT_EXTERNAL_TOKEN'
160
+ }
161
+ });
162
+ gitaly['listen_addr'] = '0.0.0.0:8075';
163
+ gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN';
164
+ prometheus['scrape_configs'] = [
165
+ {
166
+ 'job_name' => 'praefect',
167
+ 'static_configs' => [
168
+ 'targets' => [
169
+ '#{@praefect_node_name}.#{@network}:9652'
170
+ ]
171
+ ]
172
+ },
173
+ {
174
+ 'job_name' => 'praefect-gitaly',
175
+ 'static_configs' => [
176
+ 'targets' => [
177
+ '#{@primary_node_name}.#{@network}:9236',
178
+ '#{@secondary_node_name}.#{@network}:9236',
179
+ '#{@tertiary_node_name}.#{@network}:9236'
180
+ ]
181
+ ]
182
+ }
183
+ ];
184
+ grafana['disable_login_form'] = false;
185
+ grafana['admin_password'] = 'GRAFANA_ADMIN_PASSWORD';
186
+ OMNIBUS
187
+ end
188
+
189
+ def gitaly(name, release)
190
+ Component::Gitlab.new.tap do |gitaly|
191
+ gitaly.release = QA::Release.new(release)
192
+ gitaly.name = name
193
+ gitaly.network = @network
194
+ gitaly.skip_availability_check = true
195
+ gitaly.omnibus_config = gitaly_omnibus_configuration
196
+ gitaly.instance(skip_teardown: true)
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
@@ -65,6 +65,7 @@ module Gitlab
65
65
  def omnibus_config_with_praefect
66
66
  <<~OMNIBUS
67
67
  gitaly['enable'] = true;
68
+ gitaly['listen_addr'] = '0.0.0.0:8075';
68
69
  gitaly['auth_token'] = 'secret-token';
69
70
  gitaly['storage'] = [
70
71
  {
@@ -82,7 +83,7 @@ module Gitlab
82
83
  praefect['virtual_storages'] = {
83
84
  'default' => {
84
85
  'praefect-gitaly-0' => {
85
- 'address' => 'unix:/var/opt/gitlab/gitaly/gitaly.socket',
86
+ 'address' => 'tcp://localhost:8075',
86
87
  'token' => 'secret-token',
87
88
  'primary' => true
88
89
  }
@@ -1,5 +1,5 @@
1
1
  module Gitlab
2
2
  module QA
3
- VERSION = '5.15.0'.freeze
3
+ VERSION = '6.1.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.15.0
4
+ version: 6.1.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-07-06 00:00:00.000000000 Z
11
+ date: 2020-08-21 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
@@ -284,7 +287,7 @@ files:
284
287
  - lib/gitlab/qa/scenario/test/instance/staging_geo.rb
285
288
  - lib/gitlab/qa/scenario/test/integration/elasticsearch.rb
286
289
  - lib/gitlab/qa/scenario/test/integration/geo.rb
287
- - lib/gitlab/qa/scenario/test/integration/gitaly_ha.rb
290
+ - lib/gitlab/qa/scenario/test/integration/gitaly_cluster.rb
288
291
  - lib/gitlab/qa/scenario/test/integration/group_saml.rb
289
292
  - lib/gitlab/qa/scenario/test/integration/instance_saml.rb
290
293
  - lib/gitlab/qa/scenario/test/integration/jira.rb
@@ -1,166 +0,0 @@
1
- module Gitlab
2
- module QA
3
- module Scenario
4
- module Test
5
- module Integration
6
- class GitalyHA < Scenario::Template
7
- attr_reader :gitlab_name, :spec_suite
8
-
9
- def initialize
10
- @gitlab_name = 'gitlab-gitaly-ha'
11
- @primary_node = 'gitaly1'
12
- @secondary_node = 'gitaly2'
13
- @praefect_node = 'praefect'
14
- @database = 'postgres'
15
- @spec_suite = 'Test::Integration::GitalyHA'
16
- @network = 'test'
17
- end
18
-
19
- # rubocop:disable Metrics/AbcSize
20
- def perform(release, *rspec_args)
21
- gitaly(@primary_node, release) do
22
- gitaly(@secondary_node, release) do
23
- Component::PostgreSQL.perform do |sql|
24
- sql.name = @database
25
- sql.network = @network
26
-
27
- sql.instance do
28
- sql.run_psql '-d template1 -c "CREATE DATABASE praefect_production OWNER postgres"'
29
-
30
- Component::Gitlab.perform do |praefect|
31
- praefect.release = QA::Release.new(release)
32
- praefect.name = @praefect_node
33
- praefect.network = @network
34
- praefect.skip_availability_check = true
35
-
36
- praefect.omnibus_config = praefect_omnibus_configuration
37
-
38
- praefect.instance do
39
- Component::Gitlab.perform do |gitlab|
40
- gitlab.release = QA::Release.new(release)
41
- gitlab.name = gitlab_name
42
- gitlab.network = @network
43
-
44
- gitlab.omnibus_config = gitlab_omnibus_configuration
45
- gitlab.instance do
46
- puts "Running Gitaly HA specs!"
47
-
48
- Component::Specs.perform do |specs|
49
- specs.suite = spec_suite
50
- specs.release = gitlab.release
51
- specs.network = gitlab.network
52
- specs.args = [gitlab.address, *rspec_args]
53
- end
54
- end
55
- end
56
- end
57
- end
58
- end
59
- end
60
- end
61
- end
62
- end
63
- # rubocop:enable Metrics/AbcSize
64
-
65
- private
66
-
67
- def disable_other_services
68
- <<~OMNIBUS
69
- postgresql['enable'] = false;
70
- redis['enable'] = false;
71
- nginx['enable'] = false;
72
- prometheus['enable'] = false;
73
- grafana['enable'] = false;
74
- unicorn['enable'] = false;
75
- sidekiq['enable'] = false;
76
- gitlab_workhorse['enable'] = false;
77
- gitlab_rails['rake_cache_clear'] = false;
78
- gitlab_rails['auto_migrate'] = false;
79
- OMNIBUS
80
- end
81
-
82
- def praefect_omnibus_configuration
83
- <<~OMNIBUS
84
- #{disable_other_services}
85
- gitaly['enable'] = false;
86
- praefect['enable'] = true;
87
- praefect['listen_addr'] = '0.0.0.0:2305';
88
- praefect['prometheus_listen_addr'] = '0.0.0.0:9652';
89
- praefect['auth_token'] = 'PRAEFECT_EXTERNAL_TOKEN';
90
- praefect['database_host'] = '#{@database}.#{@network}';
91
- praefect['database_user'] = 'postgres';
92
- praefect['database_port'] = 5432;
93
- praefect['database_password'] = 'SQL_PASSWORD';
94
- praefect['database_dbname'] = 'praefect_production';
95
- praefect['database_sslmode'] = 'disable';
96
- praefect['postgres_queue_enabled'] = true;
97
- praefect['failover_enabled'] = true;
98
- praefect['virtual_storages'] = {
99
- 'default' => {
100
- '#{@primary_node}' => {
101
- 'address' => 'tcp://#{@primary_node}.#{@network}:8075',
102
- 'token' => 'PRAEFECT_INTERNAL_TOKEN',
103
- 'primary' => true
104
- },
105
- '#{@secondary_node}' => {
106
- 'address' => 'tcp://#{@secondary_node}.#{@network}:8075',
107
- 'token' => 'PRAEFECT_INTERNAL_TOKEN'
108
- }
109
- }
110
- };
111
- OMNIBUS
112
- end
113
-
114
- def gitaly_omnibus_configuration
115
- <<~OMNIBUS
116
- #{disable_other_services}
117
- prometheus_monitoring['enable'] = false;
118
- gitaly['enable'] = true;
119
- gitaly['listen_addr'] = '0.0.0.0:8075';
120
- gitaly['prometheus_listen_addr'] = '0.0.0.0:9236';
121
- gitaly['auth_token'] = 'PRAEFECT_INTERNAL_TOKEN';
122
- gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN';
123
- gitlab_rails['internal_api_url'] = 'http://#{@gitlab_name}.#{@network}';
124
- git_data_dirs({
125
- '#{@primary_node}' => {
126
- 'path' => '/var/opt/gitlab/git-data'
127
- },
128
- '#{@secondary_node}' => {
129
- 'path' => '/var/opt/gitlab/git-data'
130
- }
131
- });
132
- OMNIBUS
133
- end
134
-
135
- def gitlab_omnibus_configuration
136
- <<~OMNIBUS
137
- git_data_dirs({
138
- 'default' => {
139
- 'gitaly_address' => 'tcp://#{@praefect_node}.#{@network}:2305',
140
- 'gitaly_token' => 'PRAEFECT_EXTERNAL_TOKEN'
141
- }
142
- });
143
- gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN';
144
- OMNIBUS
145
- end
146
-
147
- def gitaly(name, release)
148
- Component::Gitlab.perform do |gitaly|
149
- gitaly.release = QA::Release.new(release)
150
- gitaly.name = name
151
- gitaly.network = @network
152
- gitaly.skip_availability_check = true
153
-
154
- gitaly.omnibus_config = gitaly_omnibus_configuration
155
-
156
- gitaly.instance do
157
- yield self
158
- end
159
- end
160
- end
161
- end
162
- end
163
- end
164
- end
165
- end
166
- end