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 +4 -4
- data/.gitlab-ci.yml +42 -3
- data/docs/what_tests_can_be_run.md +101 -5
- data/lib/gitlab/qa.rb +4 -1
- data/lib/gitlab/qa/component/base.rb +15 -9
- data/lib/gitlab/qa/component/specs.rb +35 -11
- data/lib/gitlab/qa/docker/command.rb +15 -3
- data/lib/gitlab/qa/docker/engine.rb +1 -1
- data/lib/gitlab/qa/docker/shellout.rb +2 -2
- data/lib/gitlab/qa/release.rb +3 -2
- data/lib/gitlab/qa/report/json_test_results.rb +21 -0
- data/lib/gitlab/qa/report/junit_test_results.rb +21 -0
- data/lib/gitlab/qa/report/results_in_issues.rb +31 -16
- data/lib/gitlab/qa/report/test_result.rb +64 -0
- data/lib/gitlab/qa/runtime/env.rb +11 -0
- data/lib/gitlab/qa/scenario/test/instance/geo.rb +0 -3
- data/lib/gitlab/qa/scenario/test/integration/geo.rb +4 -2
- data/lib/gitlab/qa/scenario/test/integration/gitaly_cluster.rb +204 -0
- data/lib/gitlab/qa/scenario/test/integration/praefect.rb +2 -1
- data/lib/gitlab/qa/version.rb +1 -1
- metadata +6 -3
- data/lib/gitlab/qa/scenario/test/integration/gitaly_ha.rb +0 -166
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 960a5ea5f4f964cf9e9a237d75e96350bd611e9c6b9c1e1721c3dd2df1476104
|
4
|
+
data.tar.gz: 4c42c1a2652f8f6d49565e849bbb6e3ecdce24d1d11662478cdd511424d7a020
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3e09dabf4c89b97a6a92d7d78a4bccaa57605f85ff0559c9423cc55b1bb3e6fb5f926ba1ccad193ee7e04c17b774502b47862011abc674cc00e84a323590a611
|
7
|
+
data.tar.gz: c88cd735d53a3c1d17c4aaf28b7af47a1a0ac827d6f3012d187e43b1f897616472f35618cfe9f419b87ff1e88cfb6d5922e49ec53db9cc4c2d3b154f8ab3a786
|
data/.gitlab-ci.yml
CHANGED
@@ -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-*.
|
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
|
-
| `
|
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.
|
87
|
-
|
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)
|
data/lib/gitlab/qa.rb
CHANGED
@@ -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 :
|
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
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
31
|
-
command << "-t --rm --net=#{network || 'bridge'}"
|
30
|
+
feature_flag_sets = []
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
38
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
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
|
|
data/lib/gitlab/qa/release.rb
CHANGED
@@ -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
|
-
|
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.
|
113
|
+
return if test.skipped
|
103
114
|
|
104
|
-
puts "Reporting test: #{test
|
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
|
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
|
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
|
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
|
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
|
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 =
|
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
|
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 << (
|
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
|
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
|
-
|
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
|
-
|
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' => '
|
86
|
+
'address' => 'tcp://localhost:8075',
|
86
87
|
'token' => 'secret-token',
|
87
88
|
'primary' => true
|
88
89
|
}
|
data/lib/gitlab/qa/version.rb
CHANGED
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:
|
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-
|
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/
|
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
|