gitlab-qa 7.27.2 → 7.30.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: 888a15b623b94cf6a072af7edf18d11952ff971a661d1fd4d154b28a627c9509
4
- data.tar.gz: c5e6cb25a0ecda8f4237186249ec44b246254df78b26e1372569500c00901c6c
3
+ metadata.gz: 04b20a54aa036ec24fb463e50ad5b4be00f81a054cdae02dee966b38c0538c56
4
+ data.tar.gz: d8c1715674a879d58359d8f8293452f68ae4d516e4c19d4ad888f34ac018498d
5
5
  SHA512:
6
- metadata.gz: 17a2b9f2863cf42a36f5e72e39a90b17ad00367be81ec2f5e61b35299086e470f227d46c5e1b186abb52c49bab82d6289010a0e4e1410f74d51e779a1cfadec0
7
- data.tar.gz: cfb21124fbd588d157ce8f93fb83300fdb521ddfbfde2e1fd4853aa966cf418075607496671aa5a739656d33acead7524e607076945b305279fa4db94d61a80c
6
+ metadata.gz: 5ccf3ee587dfef9f148fa98aa47b043bb6e2487aca12eb699f489f86fdf05f3939e5ece80ddde46a4e01b9b183dfb24742b287ac616ebc0939665786e8bbeba0
7
+ data.tar.gz: bc1a167d1b2500974abe0b3ec7f7966debe7b7f211f79324f87685f2e0906606e0c2799164f03adfff69d1af97697cf10128c6fe45eec46534832ad4b4ff0fb5
data/.gitignore CHANGED
@@ -1,12 +1,10 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
- /Gemfile.lock
4
3
  /_yardoc/
5
4
  /coverage/
6
5
  /doc/
7
6
  /pkg/
8
7
  /spec/reports/
9
- /tmp/
10
8
  /.idea
11
9
  .ruby-version
12
10
  .ruby-gemset
@@ -70,6 +70,8 @@ workflow:
70
70
  variables:
71
71
  DOCKER_DRIVER: overlay2
72
72
  DOCKER_HOST: tcp://docker:2375
73
+ COLORIZED_LOGS: "true"
74
+ QA_DEBUG: "false"
73
75
  QA_CAN_TEST_GIT_PROTOCOL_V2: "true"
74
76
  QA_CAN_TEST_PRAEFECT: "false"
75
77
  QA_GENERATE_ALLURE_REPORT: "true"
@@ -10,7 +10,6 @@ ce:ci_decomposition:
10
10
  parallel: 5
11
11
  variables:
12
12
  GITLAB_QA_OPTIONS_COMBINED: "$GITLAB_QA_OPTIONS --omnibus-config ci_decomposition"
13
- allow_failure: true # https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/1329
14
13
 
15
14
  ee:ci_decomposition:
16
15
  extends:
@@ -24,4 +23,3 @@ ee:ci_decomposition:
24
23
  parallel: 5
25
24
  variables:
26
25
  GITLAB_QA_OPTIONS_COMBINED: "$GITLAB_QA_OPTIONS --omnibus-config ci_decomposition"
27
- allow_failure: true # https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/1329
@@ -7,7 +7,6 @@ ce:gitaly-cluster:
7
7
  - .rspec-report-opts
8
8
  variables:
9
9
  QA_SCENARIO: "Test::Integration::GitalyCluster"
10
- QA_LOG_PATH: "tmp/gitaly_cluster.log"
11
10
 
12
11
  ce:gitaly-cluster-quarantine:
13
12
  extends:
@@ -19,7 +18,6 @@ ce:gitaly-cluster-quarantine:
19
18
  - .rspec-report-opts
20
19
  variables:
21
20
  QA_SCENARIO: "Test::Integration::GitalyCluster"
22
- QA_LOG_PATH: "tmp/gitaly_cluster.log"
23
21
 
24
22
  ee:gitaly-cluster:
25
23
  extends:
@@ -30,7 +28,6 @@ ee:gitaly-cluster:
30
28
  - .rspec-report-opts
31
29
  variables:
32
30
  QA_SCENARIO: "Test::Integration::GitalyCluster"
33
- QA_LOG_PATH: "tmp/gitaly_cluster.log"
34
31
 
35
32
  ee:gitaly-cluster-quarantine:
36
33
  extends:
@@ -42,4 +39,3 @@ ee:gitaly-cluster-quarantine:
42
39
  - .rspec-report-opts
43
40
  variables:
44
41
  QA_SCENARIO: "Test::Integration::GitalyCluster"
45
- QA_LOG_PATH: "tmp/gitaly_cluster.log"
data/.rubocop.yml CHANGED
@@ -36,3 +36,6 @@ Style/SignalException:
36
36
 
37
37
  Layout/SpaceBeforeFirstArg:
38
38
  Enabled: false
39
+
40
+ RSpec/MultipleMemoizedHelpers:
41
+ Enabled: false
data/.rubocop_todo.yml CHANGED
@@ -89,11 +89,6 @@ RSpec/LeakyConstantDeclaration:
89
89
  Exclude:
90
90
  - 'spec/gitlab/qa/scenario/test/instance/deployment_base_spec.rb'
91
91
 
92
- # Offense count: 221
93
- # Configuration parameters: AllowSubject.
94
- RSpec/MultipleMemoizedHelpers:
95
- Max: 22
96
-
97
92
  # Offense count: 1
98
93
  # Cop supports --auto-correct.
99
94
  Style/ExplicitBlockArgument:
data/Gemfile.lock ADDED
@@ -0,0 +1,248 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ gitlab-qa (7.30.0)
5
+ activesupport (~> 6.1)
6
+ gitlab (~> 4.18.0)
7
+ http (~> 5.0)
8
+ nokogiri (~> 1.10)
9
+ rainbow (~> 3.0.0)
10
+ table_print (= 1.5.7)
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ activesupport (6.1.6)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ zeitwerk (~> 2.3)
21
+ addressable (2.8.0)
22
+ public_suffix (>= 2.0.2, < 5.0)
23
+ ast (2.4.2)
24
+ backport (1.2.0)
25
+ benchmark (0.2.0)
26
+ claide (1.1.0)
27
+ claide-plugins (0.9.2)
28
+ cork
29
+ nap
30
+ open4 (~> 1.3)
31
+ climate_control (1.0.1)
32
+ coderay (1.1.3)
33
+ colored2 (3.1.2)
34
+ concurrent-ruby (1.1.10)
35
+ cork (0.3.0)
36
+ colored2 (~> 3.1)
37
+ crack (0.4.5)
38
+ rexml
39
+ danger (8.6.1)
40
+ claide (~> 1.0)
41
+ claide-plugins (>= 0.9.2)
42
+ colored2 (~> 3.1)
43
+ cork (~> 0.1)
44
+ faraday (>= 0.9.0, < 2.0)
45
+ faraday-http-cache (~> 2.0)
46
+ git (~> 1.7)
47
+ kramdown (~> 2.3)
48
+ kramdown-parser-gfm (~> 1.0)
49
+ no_proxy_fix
50
+ octokit (~> 4.7)
51
+ terminal-table (>= 1, < 4)
52
+ danger-gitlab (8.0.0)
53
+ danger
54
+ gitlab (~> 4.2, >= 4.2.0)
55
+ diff-lcs (1.5.0)
56
+ domain_name (0.5.20190701)
57
+ unf (>= 0.0.5, < 1.0.0)
58
+ e2mmap (0.1.0)
59
+ faraday (1.10.0)
60
+ faraday-em_http (~> 1.0)
61
+ faraday-em_synchrony (~> 1.0)
62
+ faraday-excon (~> 1.1)
63
+ faraday-httpclient (~> 1.0)
64
+ faraday-multipart (~> 1.0)
65
+ faraday-net_http (~> 1.0)
66
+ faraday-net_http_persistent (~> 1.0)
67
+ faraday-patron (~> 1.0)
68
+ faraday-rack (~> 1.0)
69
+ faraday-retry (~> 1.0)
70
+ ruby2_keywords (>= 0.0.4)
71
+ faraday-em_http (1.0.0)
72
+ faraday-em_synchrony (1.0.0)
73
+ faraday-excon (1.1.0)
74
+ faraday-http-cache (2.2.0)
75
+ faraday (>= 0.8)
76
+ faraday-httpclient (1.0.1)
77
+ faraday-multipart (1.0.3)
78
+ multipart-post (>= 1.2, < 3)
79
+ faraday-net_http (1.0.1)
80
+ faraday-net_http_persistent (1.2.0)
81
+ faraday-patron (1.0.0)
82
+ faraday-rack (1.0.0)
83
+ faraday-retry (1.0.3)
84
+ ffi (1.15.5)
85
+ ffi-compiler (1.0.1)
86
+ ffi (>= 1.0.0)
87
+ rake
88
+ git (1.11.0)
89
+ rchardet (~> 1.8)
90
+ gitlab (4.18.0)
91
+ httparty (~> 0.18)
92
+ terminal-table (>= 1.5.1)
93
+ gitlab-dangerfiles (2.11.0)
94
+ danger (>= 8.4.5)
95
+ danger-gitlab (>= 8.0.0)
96
+ gitlab-styles (6.2.1)
97
+ rubocop (~> 0.91, >= 0.91.1)
98
+ rubocop-gitlab-security (~> 0.1.1)
99
+ rubocop-performance (~> 1.9.2)
100
+ rubocop-rails (~> 2.9)
101
+ rubocop-rspec (~> 1.44)
102
+ hashdiff (1.0.1)
103
+ http (5.0.4)
104
+ addressable (~> 2.8)
105
+ http-cookie (~> 1.0)
106
+ http-form_data (~> 2.2)
107
+ llhttp-ffi (~> 0.4.0)
108
+ http-cookie (1.0.5)
109
+ domain_name (~> 0.5)
110
+ http-form_data (2.3.0)
111
+ httparty (0.20.0)
112
+ mime-types (~> 3.0)
113
+ multi_xml (>= 0.5.2)
114
+ i18n (1.10.0)
115
+ concurrent-ruby (~> 1.0)
116
+ jaro_winkler (1.5.4)
117
+ kramdown (2.4.0)
118
+ rexml
119
+ kramdown-parser-gfm (1.1.0)
120
+ kramdown (~> 2.0)
121
+ llhttp-ffi (0.4.0)
122
+ ffi-compiler (~> 1.0)
123
+ rake (~> 13.0)
124
+ method_source (1.0.0)
125
+ mime-types (3.4.1)
126
+ mime-types-data (~> 3.2015)
127
+ mime-types-data (3.2022.0105)
128
+ mini_portile2 (2.8.0)
129
+ minitest (5.15.0)
130
+ multi_xml (0.6.0)
131
+ multipart-post (2.1.1)
132
+ nap (1.1.0)
133
+ no_proxy_fix (0.1.2)
134
+ nokogiri (1.13.6)
135
+ mini_portile2 (~> 2.8.0)
136
+ racc (~> 1.4)
137
+ octokit (4.22.0)
138
+ faraday (>= 0.9)
139
+ sawyer (~> 0.8.0, >= 0.5.3)
140
+ open4 (1.3.4)
141
+ parallel (1.22.1)
142
+ parser (3.1.2.0)
143
+ ast (~> 2.4.1)
144
+ pry (0.14.1)
145
+ coderay (~> 1.1)
146
+ method_source (~> 1.0)
147
+ public_suffix (4.0.7)
148
+ racc (1.6.0)
149
+ rack (2.2.3)
150
+ rainbow (3.0.0)
151
+ rake (13.0.6)
152
+ rchardet (1.8.0)
153
+ regexp_parser (2.4.0)
154
+ reverse_markdown (2.1.1)
155
+ nokogiri
156
+ rexml (3.2.5)
157
+ rspec (3.11.0)
158
+ rspec-core (~> 3.11.0)
159
+ rspec-expectations (~> 3.11.0)
160
+ rspec-mocks (~> 3.11.0)
161
+ rspec-core (3.11.0)
162
+ rspec-support (~> 3.11.0)
163
+ rspec-expectations (3.11.0)
164
+ diff-lcs (>= 1.2.0, < 2.0)
165
+ rspec-support (~> 3.11.0)
166
+ rspec-mocks (3.11.1)
167
+ diff-lcs (>= 1.2.0, < 2.0)
168
+ rspec-support (~> 3.11.0)
169
+ rspec-support (3.11.0)
170
+ rubocop (0.93.1)
171
+ parallel (~> 1.10)
172
+ parser (>= 2.7.1.5)
173
+ rainbow (>= 2.2.2, < 4.0)
174
+ regexp_parser (>= 1.8)
175
+ rexml
176
+ rubocop-ast (>= 0.6.0)
177
+ ruby-progressbar (~> 1.7)
178
+ unicode-display_width (>= 1.4.0, < 2.0)
179
+ rubocop-ast (1.18.0)
180
+ parser (>= 3.1.1.0)
181
+ rubocop-gitlab-security (0.1.1)
182
+ rubocop (>= 0.51)
183
+ rubocop-performance (1.9.2)
184
+ rubocop (>= 0.90.0, < 2.0)
185
+ rubocop-ast (>= 0.4.0)
186
+ rubocop-rails (2.9.1)
187
+ activesupport (>= 4.2.0)
188
+ rack (>= 1.1)
189
+ rubocop (>= 0.90.0, < 2.0)
190
+ rubocop-rspec (1.44.1)
191
+ rubocop (~> 0.87)
192
+ rubocop-ast (>= 0.7.1)
193
+ ruby-progressbar (1.11.0)
194
+ ruby2_keywords (0.0.5)
195
+ sawyer (0.8.2)
196
+ addressable (>= 2.3.5)
197
+ faraday (> 0.8, < 2.0)
198
+ solargraph (0.45.0)
199
+ backport (~> 1.2)
200
+ benchmark
201
+ bundler (>= 1.17.2)
202
+ diff-lcs (~> 1.4)
203
+ e2mmap
204
+ jaro_winkler (~> 1.5)
205
+ kramdown (~> 2.3)
206
+ kramdown-parser-gfm (~> 1.1)
207
+ parser (~> 3.0)
208
+ reverse_markdown (>= 1.0.5, < 3)
209
+ rubocop (>= 0.52)
210
+ thor (~> 1.0)
211
+ tilt (~> 2.0)
212
+ yard (~> 0.9, >= 0.9.24)
213
+ table_print (1.5.7)
214
+ terminal-table (3.0.2)
215
+ unicode-display_width (>= 1.1.1, < 3)
216
+ thor (1.2.1)
217
+ tilt (2.0.10)
218
+ tzinfo (2.0.4)
219
+ concurrent-ruby (~> 1.0)
220
+ unf (0.1.4)
221
+ unf_ext
222
+ unf_ext (0.0.8.2)
223
+ unicode-display_width (1.8.0)
224
+ webmock (3.7.0)
225
+ addressable (>= 2.3.6)
226
+ crack (>= 0.3.2)
227
+ hashdiff (>= 0.4.0, < 2.0.0)
228
+ webrick (1.7.0)
229
+ yard (0.9.27)
230
+ webrick (~> 1.7.0)
231
+ zeitwerk (2.5.4)
232
+
233
+ PLATFORMS
234
+ ruby
235
+
236
+ DEPENDENCIES
237
+ climate_control (~> 1.0.1)
238
+ gitlab-dangerfiles (~> 2.11)
239
+ gitlab-qa!
240
+ gitlab-styles (~> 6.2.1)
241
+ pry (~> 0.11)
242
+ rake (~> 13.0)
243
+ rspec (~> 3.7)
244
+ solargraph (~> 0.41)
245
+ webmock (= 3.7.0)
246
+
247
+ BUNDLED WITH
248
+ 2.2.33
@@ -68,7 +68,7 @@ All environment variables used by GitLab QA should be defined in [`lib/gitlab/qa
68
68
  | `QA_PRAEFECT_REPOSITORY_STORAGE` |- | The name of repository storage using Praefect. Note: Admin access is required to change repository storage. | No|
69
69
  | `QA_COOKIES` |- | Optionally set to "cookie1=value;cookie2=value" in order to add a cookie to every request. This can be used to set the canary cookie by setting it to "gitlab_canary=true". | No|
70
70
  | `QA_DEBUG` |- | Set to `true` to verbosely log page object actions. Note: if enabled be aware that sensitive data might be logged. If an input element has a QA selector with `password` in the name, data entered into the input element will be masked. If the element doesn't have `password` in its name it won't be masked. | No|
71
- | `QA_LOG_PATH` |- | Path to output debug logging to. If not set logging will be output to STDOUT. | No|
71
+ | `QA_LOG_PATH` |- | Path to output debug logging to. By default `QA_ARTIFACTS_DIR` is used | No|
72
72
  | `QA_CAN_TEST_GIT_PROTOCOL_V2` | `true` | Set to `false` to skip tests that require Git protocol v2 if your environment doesn't support it. | No|
73
73
  | `QA_CAN_TEST_ADMIN_FEATURES` | `true` | Set to `false` to skip tests that require admin access. | No|
74
74
  | `QA_CAN_TEST_PRAEFECT` | `true` | Set to `false` to skip tests that require Praefect to be running. | No|
@@ -712,6 +712,23 @@ in the GitLab project).
712
712
  This is used to retrieve the version that staging is currently running.
713
713
  This can be found in the shared 1Password vault.
714
714
 
715
+ - `GITLAB_USERNAME`: An existing user.
716
+
717
+ - `GITLAB_PASSWORD`: The user's password.
718
+
719
+ **Required by specific tests:**
720
+
721
+ - `QA_PRAEFECT_REPOSITORY_STORAGE`: The name of a Gitaly Cluster storage.
722
+
723
+ - `GITLAB_ADMIN_USERNAME`: An existing user with administrator access. Required by tests that set feature flags or
724
+ perform other admin actions.
725
+
726
+ - `GITLAB_ADMIN_PASSWORD`: The administrator user's password.
727
+
728
+ - `GITLAB_QA_USERNAME_X`: The username of a pre-generated test user, where `X` is `1` to `6`.
729
+
730
+ - `GITLAB_QA_PASSWORD_X`: The pre-generated test user's password.
731
+
715
732
  **Optional environment variables:**
716
733
 
717
734
  - `GITLAB_QA_DEV_ACCESS_TOKEN`: A valid personal access token for the
@@ -719,17 +736,24 @@ in the GitLab project).
719
736
  This is used to pull the QA Docker image from the Omnibus GitLab `dev` Container Registry.
720
737
  If the variable isn't present, the QA image from Docker Hub will be used.
721
738
  This can be found in the shared 1Password vault.
739
+ Please note that this variable must be provided when you need to be sure the version of the
740
+ tests matches the version of GitLab on Staging. If the version from Docker Hub is used it might not include changes deployed to Staging very recently.
722
741
 
723
- Example:
742
+ An example of how to run the smoke tests:
724
743
 
725
744
  ```
726
- $ export GITLAB_QA_USER_AGENT="$GITLAB_QA_USER_AGENT"
727
- $ export GITLAB_QA_ACCESS_TOKEN=your_api_access_token
728
- $ export GITLAB_QA_DEV_ACCESS_TOKEN=your_dev_registry_access_token
745
+ $ export GITLAB_QA_USER_AGENT="<value from 1Password>"
746
+ $ export GITLAB_QA_ACCESS_TOKEN="<value from 1Password>"
747
+ $ export GITLAB_QA_DEV_ACCESS_TOKEN="<value from 1Password>"
729
748
  $ export GITLAB_USERNAME="gitlab-qa"
730
- $ export GITLAB_PASSWORD="$GITLAB_QA_PASSWORD"
749
+ $ export GITLAB_PASSWORD="<value from 1Password>"
750
+ $ export GITLAB_ADMIN_USERNAME="<value from 1Password>"
751
+ $ export GITLAB_ADMIN_PASSWORD="<value from 1Password>"
752
+ $ export GITLAB_QA_USERNAME_1="gitlab-qa-user1"
753
+ $ export GITLAB_QA_PASSWORD_1="<value from 1Password>"
754
+ $ export QA_PRAEFECT_REPOSITORY_STORAGE="nfs-file22"
731
755
 
732
- $ gitlab-qa Test::Instance::Staging
756
+ $ gitlab-qa Test::Instance::Staging -- --tag smoke
733
757
  ```
734
758
 
735
759
  ### `Test::Instance::StagingRef`
@@ -828,6 +852,52 @@ by setting `QA_COOKIES=gitlab_canary=true`. This adds a cookie
828
852
  to all web requests which will result in them being routed
829
853
  to the canary fleet.
830
854
 
855
+ **Required environment variables:**
856
+
857
+ - `GITLAB_QA_USER_AGENT`: The browser user-agent to use instead of the default Chrome user-agent.
858
+ This is needed for the automated tests to bypass the WAF
859
+
860
+ - `GITLAB_QA_ACCESS_TOKEN`: A valid personal access token with the `api` scope.
861
+ This is used to retrieve the version that staging is currently running.
862
+ This can be found in the shared 1Password vault.
863
+
864
+ - `GITLAB_USERNAME`: An existing user.
865
+
866
+ - `GITLAB_PASSWORD`: The user's password.
867
+
868
+ **Required by specific tests:**
869
+
870
+ - `GITLAB_QA_USERNAME_X`: The username of a pre-generated test user, where `X` is `1` to `6`.
871
+
872
+ - `GITLAB_QA_PASSWORD_X`: The pre-generated test user's password.
873
+
874
+ **Optional environment variables:**
875
+
876
+ - `GITLAB_QA_DEV_ACCESS_TOKEN`: A valid personal access token for the
877
+ `gitlab-qa-bot` on `dev.gitlab.org` with the `registry` scope.
878
+ This is used to pull the QA Docker image from the Omnibus GitLab `dev` Container Registry.
879
+ If the variable isn't present, the QA image from Docker Hub will be used.
880
+ This can be found in the shared 1Password vault.
881
+ Please note that this variable should be provided when you need to be sure the version of the
882
+ tests matches the version of GitLab on Staging. If the version from Docker Hub is used it might not include changes deployed to Staging very recently.
883
+
884
+ An example of how to run the smoke tests:
885
+
886
+ ```
887
+ $ export GITLAB_QA_USER_AGENT="<value from 1Password>"
888
+ $ export GITLAB_QA_ACCESS_TOKEN="<value from 1Password>"
889
+ $ export GITLAB_QA_DEV_ACCESS_TOKEN="<value from 1Password>"
890
+ $ export GITLAB_USERNAME="gitlab-qa"
891
+ $ export GITLAB_PASSWORD="<value from 1Password>"
892
+ $ export GITLAB_QA_USERNAME_1="gitlab-qa-user1"
893
+ $ export GITLAB_QA_PASSWORD_1="<value from 1Password>"
894
+ $ export QA_CAN_TEST_GIT_PROTOCOL_V2="false"
895
+ $ export QA_CAN_TEST_ADMIN_FEATURES="false"
896
+ $ export QA_CAN_TEST_PRAEFECT="false"
897
+
898
+ $ gitlab-qa Test::Instance::Production -- --tag smoke
899
+ ```
900
+
831
901
  ### `Test::Instance::Preprod`
832
902
 
833
903
  This scenario functions the same as `Test::Instance::Staging`
@@ -15,8 +15,7 @@ module Gitlab
15
15
  @environment = {}
16
16
  @volumes = {}
17
17
  @network_aliases = []
18
-
19
- self.exec_commands = []
18
+ @exec_commands = []
20
19
  end
21
20
 
22
21
  def add_network_alias(name)
@@ -155,7 +155,6 @@ module Gitlab
155
155
  setup_omnibus
156
156
 
157
157
  @docker.attach(name) do |line, wait|
158
- puts line
159
158
  # TODO, workaround which allows to detach from the container
160
159
  break if /gitlab Reconfigured!/.match?(line)
161
160
  end
@@ -174,22 +173,29 @@ module Gitlab
174
173
  def process_exec_commands
175
174
  @docker.copy(name, DATA_SEED_PATH, DATA_PATH) if seed_admin_token || seed_db
176
175
 
177
- self.exec_commands += seed_admin_token_command if seed_admin_token
178
- self.exec_commands += seed_test_data_command if seed_db
179
- self.exec_commands += Runtime::Scenario.omnibus_exec_commands
176
+ exec_commands << seed_admin_token_command if seed_admin_token
177
+ exec_commands << seed_test_data_command if seed_db
178
+ exec_commands << Runtime::Scenario.omnibus_exec_commands
179
+ exec_commands << add_git_server_hooks unless Runtime::Scenario.skip_server_hooks
180
+
181
+ commands = exec_commands.flatten.uniq
182
+ return if commands.empty?
180
183
 
181
184
  Runtime::Logger.info("Running exec_commands...")
182
- exec_commands.flatten.uniq.each { |command| @docker.exec(name, command) }
185
+ commands.each { |command| @docker.exec(name, command) }
183
186
  end
184
187
 
185
- def sha_version
188
+ def rails_version
186
189
  json = @docker.read_file(
187
190
  @release.image, @release.tag,
188
191
  '/opt/gitlab/version-manifest.json'
189
192
  )
190
193
 
191
194
  manifest = JSON.parse(json)
192
- manifest['software']['gitlab-rails']['locked_version']
195
+ {
196
+ sha: manifest['software']['gitlab-rails']['locked_version'],
197
+ source: manifest['software']['gitlab-rails']['locked_source']['git']
198
+ }
193
199
  end
194
200
 
195
201
  def copy_key_file(env_key)
@@ -241,6 +247,25 @@ module Gitlab
241
247
  ["gitlab-rails runner #{DATA_PATH}/admin_access_token_seed.rb"]
242
248
  end
243
249
 
250
+ def add_git_server_hooks
251
+ global_server_prereceive_hook = <<~SCRIPT
252
+ #!/usr/bin/env bash
253
+
254
+ if [[ \\\$GL_PROJECT_PATH =~ 'reject-prereceive' ]]; then
255
+ echo 'GL-HOOK-ERR: Custom error message rejecting prereceive hook for projects with GL_PROJECT_PATH matching pattern reject-prereceive'
256
+ exit 1
257
+ fi
258
+ SCRIPT
259
+
260
+ [
261
+ @docker.exec(name, 'mkdir -p /opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d'),
262
+ @docker.write_files(name) do |f|
263
+ f.write('/opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d/pre-receive.d', global_server_prereceive_hook, false)
264
+ end,
265
+ @docker.exec(name, 'chmod +x /opt/gitlab/embedded/service/gitlab-shell/hooks/pre-receive.d/*')
266
+ ]
267
+ end
268
+
244
269
  class Availability
245
270
  def initialize(name, relative_path: '', scheme: 'http', protocol_port: 80)
246
271
  @docker = Docker::Engine.new
@@ -11,7 +11,7 @@ module Gitlab
11
11
  attr_accessor :suite, :release, :network, :args, :volumes, :env, :runner_network, :hostname
12
12
 
13
13
  def initialize
14
- @docker = Docker::Engine.new
14
+ @docker = Docker::Engine.new(stream_output: true) # stream test output directly instead of through logger
15
15
  @volumes = {}
16
16
  @env = {}
17
17
  end
@@ -2,11 +2,17 @@ module Gitlab
2
2
  module QA
3
3
  module Docker
4
4
  class Command
5
- attr_reader :args
5
+ attr_reader :args, :stream_output
6
6
 
7
- def initialize(cmd = nil, mask_secrets: nil)
7
+ # Shell command
8
+ #
9
+ # @param [<String, Array>] cmd
10
+ # @param [<String, Array>] mask_secrets
11
+ # @param [Boolean] stream_output stream command output to stdout directly instead of logger
12
+ def initialize(cmd = nil, mask_secrets: nil, stream_output: false)
8
13
  @args = Array(cmd)
9
14
  @mask_secrets = Array(mask_secrets)
15
+ @stream_output = stream_output
10
16
  end
11
17
 
12
18
  def <<(*args)
@@ -7,6 +7,12 @@ module Gitlab
7
7
  DOCKER_HOST = ENV['DOCKER_HOST'] || 'http://localhost'
8
8
  PRIVILEGED_COMMANDS = [/^iptables.*/].freeze
9
9
 
10
+ attr_reader :stream_output
11
+
12
+ def initialize(stream_output: false)
13
+ @stream_output = stream_output
14
+ end
15
+
10
16
  def hostname
11
17
  URI(DOCKER_HOST).host
12
18
  end
@@ -15,12 +21,17 @@ module Gitlab
15
21
  Docker::Command.execute(%(login --username "#{username}" --password "#{password}" #{registry}), mask_secrets: password)
16
22
  end
17
23
 
18
- def pull(image:, tag: nil)
19
- Docker::Command.execute("pull #{full_image_name(image, tag)}")
24
+ def pull(image:, tag: nil, quiet: true)
25
+ Docker::Command.new("pull").tap do |command|
26
+ command << "-q" if quiet
27
+ command << full_image_name(image, tag)
28
+
29
+ command.execute!
30
+ end
20
31
  end
21
32
 
22
33
  def run(image:, tag: nil, args: [])
23
- Docker::Command.new('run').tap do |command|
34
+ Docker::Command.new('run', stream_output: stream_output).tap do |command|
24
35
  yield command if block_given?
25
36
 
26
37
  command << full_image_name(image, tag)
@@ -50,8 +61,15 @@ module Gitlab
50
61
  def write_files(name)
51
62
  exec(name, yield(
52
63
  Class.new do
53
- def self.write(file, contents)
54
- %(echo "#{contents}" > #{file};)
64
+ # @param file The name of the file
65
+ # @param contents The content of the file to write
66
+ # @param expand_vars Set false if you need to write an environment variable '$' to a file. The variable should be escaped \\\$
67
+ def self.write(file, contents, expand_vars = true)
68
+ if expand_vars
69
+ %(echo "#{contents}" > #{file};)
70
+ else
71
+ %(echo '#{contents}' > #{file};)
72
+ end
55
73
  end
56
74
 
57
75
  def self.append(file, contents)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'open3'
2
4
  require 'rainbow/refinement'
3
5
 
@@ -6,35 +8,57 @@ module Gitlab
6
8
  module Docker
7
9
  class Shellout
8
10
  using Rainbow
11
+
9
12
  StatusError = Class.new(StandardError)
10
13
 
11
14
  def initialize(command)
12
15
  @command = command
13
16
  @output = []
14
-
15
- Rainbow.enabled = Runtime::Env.colorized_logs?
16
- Runtime::Logger.info("Docker shell command: `#{@command.mask_secrets}`".cyan)
17
+ @logger = Runtime::Logger.logger
17
18
  end
18
19
 
20
+ attr_reader :command, :logger
21
+
19
22
  def execute! # rubocop:disable Metrics/AbcSize
20
23
  raise StatusError, 'Command already executed' if @output.any?
21
24
 
25
+ logger.info("Docker shell command: `#{@command.mask_secrets.cyan}`")
26
+
22
27
  Open3.popen2e(@command.to_s) do |_in, out, wait|
23
28
  out.each do |line|
24
29
  @output.push(line)
25
30
 
26
- if block_given?
27
- yield line, wait
28
- else
31
+ if stream_progress
32
+ print "."
33
+ elsif command.stream_output
29
34
  puts line
30
35
  end
36
+
37
+ yield line, wait if block_given?
31
38
  end
39
+ puts if stream_progress
32
40
 
33
- if wait.value.exited? && wait.value.exitstatus.nonzero? # rubocop:disable Style/IfUnlessModifier
34
- raise StatusError, "Docker command `#{@command.mask_secrets}` failed! ✘"
41
+ if wait.value.exited? && wait.value.exitstatus.nonzero?
42
+ logger.error("Docker shell command output:\n#{output}") unless command.stream_output
43
+ raise StatusError, "Docker command `#{@command.mask_secrets[0..100]}` failed! ✘"
35
44
  end
45
+
46
+ logger.debug("Docker shell command output:\n#{output}") unless command.stream_output || output.empty?
36
47
  end
37
48
 
49
+ output
50
+ end
51
+
52
+ private
53
+
54
+ # Stream only command execution progress and log output when command finished
55
+ #
56
+ # @return [Boolean]
57
+ def stream_progress
58
+ !(Runtime::Env.ci || command.stream_output)
59
+ end
60
+
61
+ def output
38
62
  @output.join.chomp
39
63
  end
40
64
  end
@@ -210,10 +210,10 @@ module Gitlab
210
210
 
211
211
  failure = full_stacktrace(test)
212
212
 
213
- if test.screenshot? && !failure.include?('500 Internal Server Error') && !failure.include?('fabricate_via_api!')
213
+ if test.screenshot? && !['500 Internal Server Error', 'fabricate_via_api!', 'Error Code 500'].any? { |e| failure.include?(e) }
214
214
  relative_url = gitlab.upload_file(file_fullpath: test.failure_screenshot)
215
215
 
216
- section = "### Screenshot: #{relative_url.markdown}"
216
+ section = "### Screenshot: #{relative_url.markdown}" if relative_url
217
217
  end
218
218
 
219
219
  section
@@ -7,7 +7,9 @@ module Gitlab
7
7
  class ReportResults < ReportAsIssue
8
8
  attr_accessor :testcase_project_reporter, :results_issue_project_reporter, :files, :test_case_project, :results_issue_project, :gitlab
9
9
 
10
- def initialize(token:, input_files:, test_case_project:, results_issue_project:, dry_run: false, **kwargs)
10
+ IGNORE_EXCEPTIONS = ['Net::ReadTimeout'].freeze
11
+
12
+ def initialize(token:, input_files:, test_case_project: nil, results_issue_project: nil, dry_run: false, **kwargs)
11
13
  @testcase_project_reporter = Gitlab::QA::Report::ResultsInTestCases.new(token: token, input_files: input_files, project: test_case_project, dry_run: dry_run, **kwargs)
12
14
  @results_issue_project_reporter = Gitlab::QA::Report::ResultsInIssues.new(token: token, input_files: input_files, project: results_issue_project, dry_run: dry_run, **kwargs)
13
15
  @test_case_project = test_case_project
@@ -32,7 +34,7 @@ module Gitlab
32
34
  test_results.each do |test|
33
35
  puts "Reporting test: #{test.file} | #{test.name}\n"
34
36
 
35
- report_test(test) unless test.skipped
37
+ report_test(test) if should_report?(test)
36
38
  end
37
39
 
38
40
  test_results.write
@@ -54,6 +56,40 @@ module Gitlab
54
56
  testcase_project_reporter.update_testcase(testcase, test)
55
57
  results_issue_project_reporter.update_issue(issue, test)
56
58
  end
59
+
60
+ # Checks if a test result should be reported.
61
+ #
62
+ # @return [Boolean] false if the test was skipped or failed because of a transient error that can be ignored.
63
+ # Otherwise returns true.
64
+ def should_report?(test)
65
+ return false if test.skipped
66
+
67
+ if test.report.key?('exceptions')
68
+ reason = ignore_failure_reason(test.report['exceptions'])
69
+
70
+ if reason
71
+ puts "Issue update skipped because #{reason}"
72
+
73
+ return false
74
+ end
75
+ end
76
+
77
+ true
78
+ end
79
+
80
+ # Determine any reason to ignore a failure.
81
+ #
82
+ # @param [Array<Hash>] exceptions the exceptions associated with the failure.
83
+ # @return [String] the reason to ignore the exceptions, or `nil` if any exceptions should not be ignored.
84
+ def ignore_failure_reason(exceptions)
85
+ exception_classes = exceptions
86
+ .filter_map { |exception| exception['class'] if IGNORE_EXCEPTIONS.include?(exception['class']) }
87
+ .compact
88
+ return if exception_classes.empty? || exception_classes.size < exceptions.size
89
+
90
+ msg = exception_classes.many? ? 'the errors were' : 'the error was'
91
+ "#{msg} #{exception_classes.join(', ')}"
92
+ end
57
93
  end
58
94
  end
59
95
  end
@@ -35,7 +35,7 @@ module Gitlab
35
35
  note_posted = note_status(issue, test)
36
36
 
37
37
  if labels_updated || note_posted
38
- puts "Issue updated."
38
+ puts "Issue updated: #{issue.web_url}"
39
39
  else
40
40
  puts "Test passed, no results issue update needed."
41
41
  end
@@ -15,6 +15,7 @@ module Gitlab
15
15
  Runtime::Scenario.define(:seed_db, false)
16
16
  Runtime::Scenario.define(:seed_admin_token, true) # Create an admin access token for root user by default
17
17
  Runtime::Scenario.define(:omnibus_exec_commands, [])
18
+ Runtime::Scenario.define(:skip_server_hooks, false)
18
19
 
19
20
  # Omnibus Configurators specified by flags
20
21
  @active_configurators = []
@@ -37,6 +38,10 @@ module Gitlab
37
38
  Runtime::Scenario.define(:seed_admin_token, false)
38
39
  end
39
40
 
41
+ opts.on('--skip-server-hooks', 'Skip adding global git server hooks') do
42
+ Runtime::Scenario.define(:skip_server_hooks, true)
43
+ end
44
+
40
45
  opts.on('--qa-image QA_IMAGE', String, 'Specifies a QA image to be used instead of inferring it from the GitLab image. See Gitlab::QA::Release#qa_image') do |value|
41
46
  Runtime::Scenario.define(:qa_image, value)
42
47
  end
@@ -27,7 +27,6 @@ module Gitlab
27
27
  'QA_COOKIES' => :qa_cookie,
28
28
  'QA_DEBUG' => :qa_debug,
29
29
  'QA_DEFAULT_BRANCH' => :qa_default_branch,
30
- 'QA_LOG_PATH' => :qa_log_path,
31
30
  'QA_CAN_TEST_ADMIN_FEATURES' => :qa_can_test_admin_features,
32
31
  'QA_CAN_TEST_GIT_PROTOCOL_V2' => :qa_can_test_git_protocol_v2,
33
32
  'QA_CAN_TEST_PRAEFECT' => :qa_can_test_praefect,
@@ -168,6 +167,14 @@ module Gitlab
168
167
  enabled?(ENV['QA_DEBUG'], default: true)
169
168
  end
170
169
 
170
+ def log_level
171
+ env_var_value_if_defined('QA_LOG_LEVEL')&.upcase || 'INFO'
172
+ end
173
+
174
+ def log_path
175
+ env_var_value_if_defined('QA_LOG_PATH') || host_artifacts_dir
176
+ end
177
+
171
178
  def default_branch
172
179
  env_var_value_if_defined('QA_DEFAULT_BRANCH') || 'main'
173
180
  end
@@ -11,7 +11,12 @@ module Gitlab
11
11
  def_delegators :logger, :debug, :info, :warn, :error, :fatal, :unknown
12
12
 
13
13
  def self.logger
14
- @logger ||= QA::TestLogger.logger(level: Runtime::Env.debug? ? ::Logger::DEBUG : ::Logger::INFO)
14
+ @logger ||= begin
15
+ log_path = Env.log_path
16
+ ::FileUtils.mkdir_p(log_path) unless File.exist?(log_path)
17
+
18
+ TestLogger.logger(level: Env.debug? ? "DEBUG" : Env.log_level, path: log_path)
19
+ end
15
20
  end
16
21
  end
17
22
  end
@@ -22,7 +22,8 @@ module Gitlab
22
22
  "gitlab-psql -c 'create database gitlabhq_production_ci owner gitlab'",
23
23
  "gitlab-psql -d gitlabhq_production_ci -c 'create extension btree_gist'",
24
24
  "gitlab-psql -d gitlabhq_production_ci -c 'create extension pg_trgm'",
25
- "gitlab-rake db:structure:load:ci"
25
+ "gitlab-rake db:structure:load:ci",
26
+ "gitlab-ctl restart"
26
27
  ].freeze
27
28
  end
28
29
  end
@@ -12,22 +12,43 @@ module Gitlab
12
12
  # the window defined by the `weekday_hours` method.
13
13
  # We perform a single API call to get the commit
14
14
  class Version < Scenario::Template
15
+ SOURCE_MAP = {
16
+ 'git@dev.gitlab.org:gitlab/gitlab-ee.git' => {
17
+ host: 'dev.gitlab.org',
18
+ project: 'gitlab/gitlab-ee'
19
+ },
20
+ 'git@dev.gitlab.org:gitlab/gitlabhq.git' => {
21
+ host: 'dev.gitlab.org',
22
+ project: 'gitlab/gitlabhq'
23
+ },
24
+ 'git@gitlab.com:gitlab-org/gitlab.git' => {
25
+ host: 'gitlab.com',
26
+ project: 'gitlab-org/gitlab'
27
+ },
28
+ 'git@gitlab.com:gitlab-org/gitlab-foss.git' => {
29
+ host: 'gitlab.com',
30
+ project: 'gitlab-org/gitlab-foss'
31
+ }
32
+ }.freeze
33
+
15
34
  def perform(release = 'ce')
16
35
  version = Component::Gitlab.perform do |gitlab|
17
36
  gitlab.release = release
18
37
  gitlab.act do
19
38
  pull
20
- sha_version
39
+ rails_version
21
40
  end
22
41
  end
23
42
 
24
- project = "gitlab-org/#{QA::Release.new(release).api_project_name}"
25
- commit = api_commit_detail(project, version)
43
+ project = SOURCE_MAP[version[:source]][:project]
44
+ host = SOURCE_MAP[version[:source]][:host]
45
+ sha = version[:sha]
46
+ commit = api_commit_detail(host, project, sha)
26
47
 
27
48
  if commit_within_hours?(commit['created_at'], weekday_hours(commit['created_at']))
28
- puts "Found commit #{version} in recent history of #{project}"
49
+ puts "Found commit #{sha} in recent history of #{project} on #{host}"
29
50
  else
30
- puts "Did not find #{version} in recent history of #{project}"
51
+ puts "Did not find #{sha} in recent history of #{project} on #{host}"
31
52
  exit 1
32
53
  end
33
54
  end
@@ -51,9 +72,14 @@ module Gitlab
51
72
  Time.at(Time.parse(commit_time_string).utc).to_datetime > Time.at((Time.now - hours * 60 * 60).utc).to_datetime
52
73
  end
53
74
 
54
- def api_commit_detail(project, commit_id)
55
- api = 'https://gitlab.com/api/v4'
56
- url = "#{api}/projects/#{CGI.escape(project)}/repository/commits/#{commit_id}"
75
+ def api_commit_detail(host, project, sha)
76
+ url = "https://#{host}/api/v4/projects/#{CGI.escape(project)}/repository/commits/#{sha}"
77
+
78
+ if host == 'dev.gitlab.org'
79
+ Runtime::Env.require_qa_dev_access_token!
80
+
81
+ url = "#{url}?private_token=#{Runtime::Env.qa_dev_access_token}"
82
+ end
57
83
 
58
84
  JSON.parse(Net::HTTP.get(URI(url)))
59
85
  end
@@ -1,13 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'logger'
4
3
  require 'rainbow'
4
+ require 'active_support/logger'
5
5
 
6
6
  module Gitlab
7
7
  module QA
8
8
  # Common test logger implementation
9
9
  #
10
10
  class TestLogger
11
+ TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
11
12
  LEVEL_COLORS = {
12
13
  "DEBUG" => :magenta,
13
14
  "INFO" => :green,
@@ -18,17 +19,62 @@ module Gitlab
18
19
 
19
20
  Rainbow.enabled = Runtime::Env.colorized_logs?
20
21
 
21
- def self.logger(level: ::Logger::INFO, source: 'Gitlab QA')
22
- ::Logger.new($stdout).tap do |logger|
23
- logger.level = level
22
+ class << self
23
+ # Combined logger instance
24
+ #
25
+ # @param [<Symbol, String>] level
26
+ # @param [String] source
27
+ # @return [ActiveSupport::Logger]
28
+ def logger(level: :info, source: 'Gitlab QA', path: 'tmp')
29
+ console_log = console_logger(level: level, source: source)
30
+ file_log = file_logger(source: source, path: path)
24
31
 
25
- logger.formatter = proc do |severity, datetime, progname, msg|
26
- date_format = datetime.strftime("%Y-%m-%d %H:%M:%S")
27
- msg_prefix = "[date=#{date_format} from=#{source}] #{severity.ljust(5)} -- "
32
+ console_log.extend(ActiveSupport::Logger.broadcast(file_log))
33
+ end
34
+
35
+ private
36
+
37
+ # Console logger instance
38
+ #
39
+ # @param [<Symbol, String>] level
40
+ # @param [String] source
41
+ # @return [ActiveSupport::Logger]
42
+ def console_logger(level:, source:)
43
+ ActiveSupport::Logger.new($stdout, level: level, datetime_format: TIME_FORMAT).tap do |logger|
44
+ logger.formatter = proc do |severity, datetime, progname, msg|
45
+ msg_prefix = message_prefix(datetime, source, severity)
46
+
47
+ Rainbow(msg_prefix).public_send(LEVEL_COLORS.fetch(severity, :silver)) + "#{msg}\n" # rubocop:disable GitlabSecurity/PublicSend
48
+ end
49
+ end
50
+ end
51
+
52
+ # File logger
53
+ #
54
+ # @param [String] source
55
+ # @param [String] path
56
+ # @return [ActiveSupport::Logger]
57
+ def file_logger(source:, path:)
58
+ log_file = "#{path}/#{source.downcase.tr(' ', '-')}.log"
59
+
60
+ ActiveSupport::Logger.new(log_file, level: :debug, datetime_format: TIME_FORMAT).tap do |logger|
61
+ logger.formatter = proc do |severity, datetime, progname, msg|
62
+ msg_prefix = message_prefix(datetime, source, severity)
28
63
 
29
- Rainbow(msg_prefix).public_send(LEVEL_COLORS.fetch(severity, :silver)) + "#{msg}\n" # rubocop:disable GitlabSecurity/PublicSend
64
+ "#{msg_prefix}#{msg}\n"
65
+ end
30
66
  end
31
67
  end
68
+
69
+ # Log message prefix
70
+ #
71
+ # @param [DateTime] date
72
+ # @param [String] source
73
+ # @param [String] severity
74
+ # @return [String]
75
+ def message_prefix(date, source, severity)
76
+ "[date=#{date} from=#{source}] #{severity.ljust(5)} -- "
77
+ end
32
78
  end
33
79
  end
34
80
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module QA
5
- VERSION = '7.27.2'
5
+ VERSION = '7.30.0'
6
6
  end
7
7
  end
data/tmp/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ **
2
+
3
+ !.gitignore
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: 7.27.2
4
+ version: 7.30.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab Quality
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-05-23 00:00:00.000000000 Z
11
+ date: 2022-06-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -264,6 +264,7 @@ files:
264
264
  - CONTRIBUTING.md
265
265
  - Dangerfile
266
266
  - Gemfile
267
+ - Gemfile.lock
267
268
  - LICENSE
268
269
  - README.md
269
270
  - Rakefile
@@ -409,6 +410,7 @@ files:
409
410
  - tls_certificates/gitlab/gitlab.test.crt
410
411
  - tls_certificates/gitlab/gitlab.test.csr
411
412
  - tls_certificates/gitlab/gitlab.test.key
413
+ - tmp/.gitignore
412
414
  homepage: http://about.gitlab.com/
413
415
  licenses:
414
416
  - MIT