gitlab-qa 7.13.3 → 7.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitlab/ci/rules.gitlab-ci.yml +70 -0
- data/.gitlab-ci.yml +132 -21
- data/docs/run_qa_against_gdk.md +11 -1
- data/docs/what_tests_can_be_run.md +1 -0
- data/lib/gitlab/qa/component/elasticsearch.rb +1 -0
- data/lib/gitlab/qa/report/generate_test_session.rb +5 -0
- data/lib/gitlab/qa/report/gitlab_issue_client.rb +8 -1
- data/lib/gitlab/qa/report/relate_failure_issue.rb +2 -1
- data/lib/gitlab/qa/report/report_as_issue.rb +12 -3
- data/lib/gitlab/qa/report/report_results.rb +71 -0
- data/lib/gitlab/qa/report/results_in_issues.rb +24 -142
- data/lib/gitlab/qa/report/results_in_testcases.rb +67 -0
- data/lib/gitlab/qa/report/results_reporter_shared.rb +65 -0
- data/lib/gitlab/qa/reporter.rb +15 -7
- data/lib/gitlab/qa/runtime/env.rb +2 -1
- data/lib/gitlab/qa/scenario/test/integration/service_ping_disabled.rb +33 -0
- data/lib/gitlab/qa/version.rb +1 -1
- data/lib/gitlab/qa.rb +4 -0
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '090fb8d7830e6cfd3ee6978b9f7ba4ad6eb4ba5ceec37921e5cde75285fd4015'
|
|
4
|
+
data.tar.gz: '058a34d1526fc7ae37df2c8b75e3e0888c15785c5bb2d3954b0b72e6a6d653d8'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: de89ce6d1c4a5cf43aebd3510af3f758dc1e8f2d8063878ec6a74d5530d9af9ffa903ad77267caed55ad77125ecb2aa044523cb9366144c82637f02bb765778f
|
|
7
|
+
data.tar.gz: 9a68591bf7a1a774dbee63a5f0374c0b46df7029e4e90419f184be961cfbddb7d31589e7603299bb1b7f59af20ceb7f2eb5f4071315389dc97958946bc246801
|
|
@@ -37,6 +37,12 @@
|
|
|
37
37
|
.if-set-feature-flag: &if-set-feature-flag
|
|
38
38
|
if: '$GITLAB_QA_OPTIONS =~ /--set-feature-flags/'
|
|
39
39
|
|
|
40
|
+
.if-qa-tests-specified: &if-qa-tests-specified
|
|
41
|
+
if: '$QA_TESTS != null && $QA_TESTS != ""'
|
|
42
|
+
|
|
43
|
+
.if-qa-tests-not-specified: &if-qa-tests-not-specified
|
|
44
|
+
if: '$QA_TESTS == null || $QA_TESTS == ""'
|
|
45
|
+
|
|
40
46
|
#########
|
|
41
47
|
# Rules #
|
|
42
48
|
#########
|
|
@@ -98,3 +104,67 @@
|
|
|
98
104
|
- <<: *if-set-feature-flag
|
|
99
105
|
when: never
|
|
100
106
|
- !reference [".rules:only-qa", rules]
|
|
107
|
+
|
|
108
|
+
# === When QA_TESTS variable has a value ===
|
|
109
|
+
|
|
110
|
+
.rules:ce-never-when-qa-tests-specified:
|
|
111
|
+
rules:
|
|
112
|
+
- <<: *if-qa-tests-specified
|
|
113
|
+
when: never
|
|
114
|
+
- !reference [".rules:ce-qa", rules]
|
|
115
|
+
|
|
116
|
+
.rules:ee-never-when-qa-tests-specified:
|
|
117
|
+
rules:
|
|
118
|
+
- <<: *if-qa-tests-specified
|
|
119
|
+
when: never
|
|
120
|
+
- !reference [".rules:ee-qa", rules]
|
|
121
|
+
|
|
122
|
+
.rules:ce-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-specified:
|
|
123
|
+
rules:
|
|
124
|
+
- <<: *if-qa-tests-specified
|
|
125
|
+
when: never
|
|
126
|
+
- !reference [".rules:ce-never-when-triggered-by-feature-flag-definition-change", rules]
|
|
127
|
+
|
|
128
|
+
.rules:ee-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-specified:
|
|
129
|
+
rules:
|
|
130
|
+
- <<: *if-qa-tests-specified
|
|
131
|
+
when: never
|
|
132
|
+
- !reference [".rules:ee-never-when-triggered-by-feature-flag-definition-change", rules]
|
|
133
|
+
|
|
134
|
+
.rules:only-qa-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-specified:
|
|
135
|
+
rules:
|
|
136
|
+
- <<: *if-qa-tests-specified
|
|
137
|
+
when: never
|
|
138
|
+
- !reference [".rules:only-qa-never-when-triggered-by-feature-flag-definition-change", rules]
|
|
139
|
+
|
|
140
|
+
# === When QA_TESTS variable does not have a value ===
|
|
141
|
+
|
|
142
|
+
.rules:ce-never-when-qa-tests-not-specified:
|
|
143
|
+
rules:
|
|
144
|
+
- <<: *if-qa-tests-not-specified
|
|
145
|
+
when: never
|
|
146
|
+
- !reference [".rules:ce-qa", rules]
|
|
147
|
+
|
|
148
|
+
.rules:ee-never-when-qa-tests-not-specified:
|
|
149
|
+
rules:
|
|
150
|
+
- <<: *if-qa-tests-not-specified
|
|
151
|
+
when: never
|
|
152
|
+
- !reference [".rules:ee-qa", rules]
|
|
153
|
+
|
|
154
|
+
.rules:ce-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-not-specified:
|
|
155
|
+
rules:
|
|
156
|
+
- <<: *if-qa-tests-not-specified
|
|
157
|
+
when: never
|
|
158
|
+
- !reference [".rules:ce-never-when-triggered-by-feature-flag-definition-change", rules]
|
|
159
|
+
|
|
160
|
+
.rules:ee-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-not-specified:
|
|
161
|
+
rules:
|
|
162
|
+
- <<: *if-qa-tests-not-specified
|
|
163
|
+
when: never
|
|
164
|
+
- !reference [".rules:ee-never-when-triggered-by-feature-flag-definition-change", rules]
|
|
165
|
+
|
|
166
|
+
.rules:only-qa-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-not-specified:
|
|
167
|
+
rules:
|
|
168
|
+
- <<: *if-qa-tests-not-specified
|
|
169
|
+
when: never
|
|
170
|
+
- !reference [".rules:only-qa-never-when-triggered-by-feature-flag-definition-change", rules]
|
data/.gitlab-ci.yml
CHANGED
|
@@ -46,7 +46,8 @@ variables:
|
|
|
46
46
|
QA_CAN_TEST_GIT_PROTOCOL_V2: "true"
|
|
47
47
|
QA_CAN_TEST_PRAEFECT: "false"
|
|
48
48
|
QA_GENERATE_ALLURE_REPORT: "true"
|
|
49
|
-
QA_TESTCASES_REPORTING_PROJECT: "gitlab-org/
|
|
49
|
+
QA_TESTCASES_REPORTING_PROJECT: "gitlab-org/gitlab"
|
|
50
|
+
QA_TEST_RESULTS_ISSUES_PROJECT: "gitlab-org/quality/testcases"
|
|
50
51
|
QA_TESTCASE_SESSIONS_PROJECT: "gitlab-org/quality/testcase-sessions"
|
|
51
52
|
# QA_DEFAULT_BRANCH is the default branch name of the instance under test.
|
|
52
53
|
QA_DEFAULT_BRANCH: "master"
|
|
@@ -66,6 +67,7 @@ rspec:
|
|
|
66
67
|
|
|
67
68
|
.test:
|
|
68
69
|
stage: test
|
|
70
|
+
timeout: 1 hour 30 minutes
|
|
69
71
|
services:
|
|
70
72
|
- docker:20.10.5-dind
|
|
71
73
|
tags:
|
|
@@ -83,7 +85,7 @@ rspec:
|
|
|
83
85
|
- bundle exec exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} $GITLAB_QA_OPTIONS -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS || test_run_exit_code=$?
|
|
84
86
|
- bundle exec exe/gitlab-qa-report --update-screenshot-path "gitlab-qa-run-*/**/rspec-*.xml"
|
|
85
87
|
- export GITLAB_QA_ACCESS_TOKEN="$GITLAB_QA_PRODUCTION_ACCESS_TOKEN"
|
|
86
|
-
- if [ "$TOP_UPSTREAM_SOURCE_REF" == $TOP_UPSTREAM_DEFAULT_BRANCH ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --report-
|
|
88
|
+
- if [ "$TOP_UPSTREAM_SOURCE_REF" == $TOP_UPSTREAM_DEFAULT_BRANCH ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --report-results "gitlab-qa-run-*/**/rspec-*.json" --test-case-project "$QA_TESTCASES_REPORTING_PROJECT" --results-issue-project "$QA_TEST_RESULTS_ISSUES_PROJECT" || true; fi
|
|
87
89
|
- exit $test_run_exit_code
|
|
88
90
|
|
|
89
91
|
# For jobs that shouldn't report results in issues, e.g., manually run custom jobs
|
|
@@ -106,7 +108,7 @@ rspec:
|
|
|
106
108
|
- bundle exec exe/gitlab-qa Test::Omnibus::Update ${RELEASE:=$DEFAULT_RELEASE} ${RELEASE:=$DEFAULT_RELEASE} $GITLAB_QA_OPTIONS -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS || test_run_exit_code=$?
|
|
107
109
|
- bundle exec exe/gitlab-qa-report --update-screenshot-path "gitlab-qa-run-*/**/rspec-*.xml"
|
|
108
110
|
- export GITLAB_QA_ACCESS_TOKEN="$GITLAB_QA_PRODUCTION_ACCESS_TOKEN"
|
|
109
|
-
- if [ "$TOP_UPSTREAM_SOURCE_REF" == $TOP_UPSTREAM_DEFAULT_BRANCH ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --report-
|
|
111
|
+
- if [ "$TOP_UPSTREAM_SOURCE_REF" == $TOP_UPSTREAM_DEFAULT_BRANCH ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --report-results "gitlab-qa-run-*/**/rspec-*.json" --test-case-project "$QA_TESTCASES_REPORTING_PROJECT" --results-issue-project "$QA_TEST_RESULTS_ISSUES_PROJECT" || true; fi
|
|
110
112
|
- exit $test_run_exit_code
|
|
111
113
|
|
|
112
114
|
.ce-variables:
|
|
@@ -187,9 +189,9 @@ ee:custom-parallel:
|
|
|
187
189
|
allow_failure: true
|
|
188
190
|
parallel: 10
|
|
189
191
|
|
|
190
|
-
ce:instance:
|
|
192
|
+
ce:instance-parallel:
|
|
191
193
|
extends:
|
|
192
|
-
- .rules:ce-qa
|
|
194
|
+
- .rules:ce-never-when-qa-tests-specified
|
|
193
195
|
- .test
|
|
194
196
|
- .high-capacity
|
|
195
197
|
- .ce-variables
|
|
@@ -197,6 +199,14 @@ ce:instance:
|
|
|
197
199
|
- .rspec-report-opts
|
|
198
200
|
parallel: 5
|
|
199
201
|
|
|
202
|
+
ce:instance:
|
|
203
|
+
extends:
|
|
204
|
+
- .rules:ce-never-when-qa-tests-not-specified
|
|
205
|
+
- .test
|
|
206
|
+
- .high-capacity
|
|
207
|
+
- .ce-variables
|
|
208
|
+
- .rspec-report-opts
|
|
209
|
+
|
|
200
210
|
ce:instance-quarantine:
|
|
201
211
|
extends:
|
|
202
212
|
- .rules:ce-qa
|
|
@@ -208,9 +218,9 @@ ce:instance-quarantine:
|
|
|
208
218
|
variables:
|
|
209
219
|
QA_RSPEC_TAGS: "--tag quarantine --tag ~orchestrated"
|
|
210
220
|
|
|
211
|
-
ee:instance:
|
|
221
|
+
ee:instance-parallel:
|
|
212
222
|
extends:
|
|
213
|
-
- .rules:ee-qa
|
|
223
|
+
- .rules:ee-never-when-qa-tests-specified
|
|
214
224
|
- .test
|
|
215
225
|
- .high-capacity
|
|
216
226
|
- .ee-variables
|
|
@@ -218,6 +228,14 @@ ee:instance:
|
|
|
218
228
|
- .rspec-report-opts
|
|
219
229
|
parallel: 5
|
|
220
230
|
|
|
231
|
+
ee:instance:
|
|
232
|
+
extends:
|
|
233
|
+
- .rules:ee-never-when-qa-tests-not-specified
|
|
234
|
+
- .test
|
|
235
|
+
- .high-capacity
|
|
236
|
+
- .ee-variables
|
|
237
|
+
- .rspec-report-opts
|
|
238
|
+
|
|
221
239
|
ee:instance-quarantine:
|
|
222
240
|
extends:
|
|
223
241
|
- .rules:ee-qa
|
|
@@ -229,9 +247,9 @@ ee:instance-quarantine:
|
|
|
229
247
|
variables:
|
|
230
248
|
QA_RSPEC_TAGS: "--tag quarantine --tag ~orchestrated"
|
|
231
249
|
|
|
232
|
-
ce:relative_url:
|
|
250
|
+
ce:relative_url-parallel:
|
|
233
251
|
extends:
|
|
234
|
-
- .rules:ce-never-when-triggered-by-feature-flag-definition-change
|
|
252
|
+
- .rules:ce-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-specified
|
|
235
253
|
- .test
|
|
236
254
|
- .high-capacity
|
|
237
255
|
- .ce-variables
|
|
@@ -241,6 +259,16 @@ ce:relative_url:
|
|
|
241
259
|
variables:
|
|
242
260
|
QA_SCENARIO: "Test::Instance::RelativeUrl"
|
|
243
261
|
|
|
262
|
+
ce:relative_url:
|
|
263
|
+
extends:
|
|
264
|
+
- .rules:ce-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-not-specified
|
|
265
|
+
- .test
|
|
266
|
+
- .high-capacity
|
|
267
|
+
- .ce-variables
|
|
268
|
+
- .rspec-report-opts
|
|
269
|
+
variables:
|
|
270
|
+
QA_SCENARIO: "Test::Instance::RelativeUrl"
|
|
271
|
+
|
|
244
272
|
ce:relative_url-quarantine:
|
|
245
273
|
extends:
|
|
246
274
|
- .rules:ce-never-when-triggered-by-feature-flag-definition-change
|
|
@@ -253,9 +281,9 @@ ce:relative_url-quarantine:
|
|
|
253
281
|
QA_SCENARIO: "Test::Instance::RelativeUrl"
|
|
254
282
|
QA_RSPEC_TAGS: "--tag quarantine --tag ~orchestrated"
|
|
255
283
|
|
|
256
|
-
ee:relative_url:
|
|
284
|
+
ee:relative_url-parallel:
|
|
257
285
|
extends:
|
|
258
|
-
- .rules:ee-never-when-triggered-by-feature-flag-definition-change
|
|
286
|
+
- .rules:ee-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-specified
|
|
259
287
|
- .test
|
|
260
288
|
- .high-capacity
|
|
261
289
|
- .ee-variables
|
|
@@ -265,6 +293,16 @@ ee:relative_url:
|
|
|
265
293
|
variables:
|
|
266
294
|
QA_SCENARIO: "Test::Instance::RelativeUrl"
|
|
267
295
|
|
|
296
|
+
ee:relative_url:
|
|
297
|
+
extends:
|
|
298
|
+
- .rules:ee-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-not-specified
|
|
299
|
+
- .test
|
|
300
|
+
- .high-capacity
|
|
301
|
+
- .ee-variables
|
|
302
|
+
- .rspec-report-opts
|
|
303
|
+
variables:
|
|
304
|
+
QA_SCENARIO: "Test::Instance::RelativeUrl"
|
|
305
|
+
|
|
268
306
|
ee:relative_url-quarantine:
|
|
269
307
|
extends:
|
|
270
308
|
- .rules:ee-never-when-triggered-by-feature-flag-definition-change
|
|
@@ -336,9 +374,9 @@ ee:image:
|
|
|
336
374
|
- .test
|
|
337
375
|
- .ee-variables
|
|
338
376
|
|
|
339
|
-
ce:update:
|
|
377
|
+
ce:update-parallel:
|
|
340
378
|
extends:
|
|
341
|
-
- .rules:ce-never-when-triggered-by-feature-flag-definition-change
|
|
379
|
+
- .rules:ce-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-specified
|
|
342
380
|
- .test
|
|
343
381
|
- .high-capacity
|
|
344
382
|
- .ce-variables
|
|
@@ -347,6 +385,15 @@ ce:update:
|
|
|
347
385
|
- .update-scenario-script
|
|
348
386
|
parallel: 5
|
|
349
387
|
|
|
388
|
+
ce:update:
|
|
389
|
+
extends:
|
|
390
|
+
- .rules:ce-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-not-specified
|
|
391
|
+
- .test
|
|
392
|
+
- .high-capacity
|
|
393
|
+
- .ce-variables
|
|
394
|
+
- .rspec-report-opts
|
|
395
|
+
- .update-scenario-script
|
|
396
|
+
|
|
350
397
|
ce:update-quarantine:
|
|
351
398
|
extends:
|
|
352
399
|
- .rules:ce-never-when-triggered-by-feature-flag-definition-change
|
|
@@ -359,9 +406,9 @@ ce:update-quarantine:
|
|
|
359
406
|
variables:
|
|
360
407
|
QA_RSPEC_TAGS: "--tag quarantine --tag ~orchestrated"
|
|
361
408
|
|
|
362
|
-
ee:update:
|
|
409
|
+
ee:update-parallel:
|
|
363
410
|
extends:
|
|
364
|
-
- .rules:ee-never-when-triggered-by-feature-flag-definition-change
|
|
411
|
+
- .rules:ee-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-specified
|
|
365
412
|
- .test
|
|
366
413
|
- .high-capacity
|
|
367
414
|
- .ee-variables
|
|
@@ -370,6 +417,15 @@ ee:update:
|
|
|
370
417
|
- .update-scenario-script
|
|
371
418
|
parallel: 10
|
|
372
419
|
|
|
420
|
+
ee:update:
|
|
421
|
+
extends:
|
|
422
|
+
- .rules:ee-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-not-specified
|
|
423
|
+
- .test
|
|
424
|
+
- .high-capacity
|
|
425
|
+
- .ee-variables
|
|
426
|
+
- .rspec-report-opts
|
|
427
|
+
- .update-scenario-script
|
|
428
|
+
|
|
373
429
|
ee:update-quarantine:
|
|
374
430
|
extends:
|
|
375
431
|
- .rules:ee-never-when-triggered-by-feature-flag-definition-change
|
|
@@ -382,17 +438,26 @@ ee:update-quarantine:
|
|
|
382
438
|
QA_RSPEC_TAGS: "--tag quarantine --tag ~orchestrated"
|
|
383
439
|
|
|
384
440
|
# The Test::Omnibus::Upgrade scenario isn't run on master (because it always uses the latest CE/EE image) so we don't report the test results in issues
|
|
385
|
-
ce:upgrade:
|
|
441
|
+
ce:upgrade-parallel:
|
|
386
442
|
script:
|
|
387
443
|
- bundle exec exe/gitlab-qa Test::Omnibus::Upgrade CE -- $RSPEC_REPORT_OPTS
|
|
388
444
|
extends:
|
|
389
|
-
- .rules:only-qa-never-when-triggered-by-feature-flag-definition-change
|
|
445
|
+
- .rules:only-qa-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-specified
|
|
390
446
|
- .test
|
|
391
447
|
- .high-capacity
|
|
392
448
|
- .rspec-report-opts
|
|
393
449
|
- .knapsack-variables
|
|
394
450
|
parallel: 5
|
|
395
451
|
|
|
452
|
+
ce:upgrade:
|
|
453
|
+
script:
|
|
454
|
+
- bundle exec exe/gitlab-qa Test::Omnibus::Upgrade CE -- $RSPEC_REPORT_OPTS
|
|
455
|
+
extends:
|
|
456
|
+
- .rules:only-qa-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-not-specified
|
|
457
|
+
- .test
|
|
458
|
+
- .high-capacity
|
|
459
|
+
- .rspec-report-opts
|
|
460
|
+
|
|
396
461
|
ce:upgrade-quarantine:
|
|
397
462
|
script:
|
|
398
463
|
- bundle exec exe/gitlab-qa Test::Omnibus::Upgrade CE -- --tag quarantine --tag ~orchestrated $RSPEC_REPORT_OPTS
|
|
@@ -464,6 +529,26 @@ ee:mattermost-quarantine:
|
|
|
464
529
|
variables:
|
|
465
530
|
QA_SCENARIO: "Test::Integration::Mattermost"
|
|
466
531
|
|
|
532
|
+
ce:service_ping_disabled:
|
|
533
|
+
extends:
|
|
534
|
+
- .rules:ce-never-when-triggered-by-feature-flag-definition-change
|
|
535
|
+
- .test
|
|
536
|
+
- .high-capacity
|
|
537
|
+
- .ce-variables
|
|
538
|
+
- .rspec-report-opts
|
|
539
|
+
variables:
|
|
540
|
+
QA_SCENARIO: "Test::Integration::ServicePingDisabled"
|
|
541
|
+
|
|
542
|
+
ee:service_ping_disabled:
|
|
543
|
+
extends:
|
|
544
|
+
- .rules:ee-never-when-triggered-by-feature-flag-definition-change
|
|
545
|
+
- .test
|
|
546
|
+
- .high-capacity
|
|
547
|
+
- .ee-variables
|
|
548
|
+
- .rspec-report-opts
|
|
549
|
+
variables:
|
|
550
|
+
QA_SCENARIO: "Test::Integration::ServicePingDisabled"
|
|
551
|
+
|
|
467
552
|
# Disabling geo jobs temporarily due to https://gitlab.com/gitlab-org/gitlab/-/issues/273063
|
|
468
553
|
# ee:geo:
|
|
469
554
|
# extends:
|
|
@@ -920,9 +1005,9 @@ ee:elasticsearch-quarantine:
|
|
|
920
1005
|
variables:
|
|
921
1006
|
QA_SCENARIO: "Test::Integration::Elasticsearch"
|
|
922
1007
|
|
|
923
|
-
ce:praefect:
|
|
1008
|
+
ce:praefect-parallel:
|
|
924
1009
|
extends:
|
|
925
|
-
- .rules:ce-never-when-triggered-by-feature-flag-definition-change
|
|
1010
|
+
- .rules:ce-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-specified
|
|
926
1011
|
- .test
|
|
927
1012
|
- .high-capacity
|
|
928
1013
|
- .ce-variables
|
|
@@ -933,6 +1018,17 @@ ce:praefect:
|
|
|
933
1018
|
QA_SCENARIO: "Test::Integration::Praefect"
|
|
934
1019
|
QA_CAN_TEST_PRAEFECT: "true"
|
|
935
1020
|
|
|
1021
|
+
ce:praefect:
|
|
1022
|
+
extends:
|
|
1023
|
+
- .rules:ce-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-not-specified
|
|
1024
|
+
- .test
|
|
1025
|
+
- .high-capacity
|
|
1026
|
+
- .ce-variables
|
|
1027
|
+
- .rspec-report-opts
|
|
1028
|
+
variables:
|
|
1029
|
+
QA_SCENARIO: "Test::Integration::Praefect"
|
|
1030
|
+
QA_CAN_TEST_PRAEFECT: "true"
|
|
1031
|
+
|
|
936
1032
|
ce:praefect-quarantine:
|
|
937
1033
|
extends:
|
|
938
1034
|
- .rules:ce-never-when-triggered-by-feature-flag-definition-change
|
|
@@ -946,9 +1042,9 @@ ce:praefect-quarantine:
|
|
|
946
1042
|
QA_CAN_TEST_PRAEFECT: "true"
|
|
947
1043
|
QA_RSPEC_TAGS: "--tag quarantine --tag ~orchestrated"
|
|
948
1044
|
|
|
949
|
-
ee:praefect:
|
|
1045
|
+
ee:praefect-parallel:
|
|
950
1046
|
extends:
|
|
951
|
-
- .rules:ee-never-when-triggered-by-feature-flag-definition-change
|
|
1047
|
+
- .rules:ee-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-specified
|
|
952
1048
|
- .test
|
|
953
1049
|
- .high-capacity
|
|
954
1050
|
- .ee-variables
|
|
@@ -959,6 +1055,17 @@ ee:praefect:
|
|
|
959
1055
|
QA_SCENARIO: "Test::Integration::Praefect"
|
|
960
1056
|
QA_CAN_TEST_PRAEFECT: "true"
|
|
961
1057
|
|
|
1058
|
+
ee:praefect:
|
|
1059
|
+
extends:
|
|
1060
|
+
- .rules:ee-never-when-triggered-by-feature-flag-definition-change-and-never-when-qa-tests-not-specified
|
|
1061
|
+
- .test
|
|
1062
|
+
- .high-capacity
|
|
1063
|
+
- .ee-variables
|
|
1064
|
+
- .rspec-report-opts
|
|
1065
|
+
variables:
|
|
1066
|
+
QA_SCENARIO: "Test::Integration::Praefect"
|
|
1067
|
+
QA_CAN_TEST_PRAEFECT: "true"
|
|
1068
|
+
|
|
962
1069
|
ee:praefect-quarantine:
|
|
963
1070
|
extends:
|
|
964
1071
|
- .rules:ee-never-when-triggered-by-feature-flag-definition-change
|
|
@@ -981,6 +1088,7 @@ ce:gitaly-cluster:
|
|
|
981
1088
|
- .rspec-report-opts
|
|
982
1089
|
variables:
|
|
983
1090
|
QA_SCENARIO: "Test::Integration::GitalyCluster"
|
|
1091
|
+
QA_LOG_PATH: "tmp/gitaly_cluster.log"
|
|
984
1092
|
|
|
985
1093
|
ce:gitaly-cluster-quarantine:
|
|
986
1094
|
extends:
|
|
@@ -992,6 +1100,7 @@ ce:gitaly-cluster-quarantine:
|
|
|
992
1100
|
- .rspec-report-opts
|
|
993
1101
|
variables:
|
|
994
1102
|
QA_SCENARIO: "Test::Integration::GitalyCluster"
|
|
1103
|
+
QA_LOG_PATH: "tmp/gitaly_cluster.log"
|
|
995
1104
|
|
|
996
1105
|
ee:gitaly-cluster:
|
|
997
1106
|
extends:
|
|
@@ -1002,6 +1111,7 @@ ee:gitaly-cluster:
|
|
|
1002
1111
|
- .rspec-report-opts
|
|
1003
1112
|
variables:
|
|
1004
1113
|
QA_SCENARIO: "Test::Integration::GitalyCluster"
|
|
1114
|
+
QA_LOG_PATH: "tmp/gitaly_cluster.log"
|
|
1005
1115
|
|
|
1006
1116
|
ee:gitaly-cluster-quarantine:
|
|
1007
1117
|
extends:
|
|
@@ -1013,6 +1123,7 @@ ee:gitaly-cluster-quarantine:
|
|
|
1013
1123
|
- .rspec-report-opts
|
|
1014
1124
|
variables:
|
|
1015
1125
|
QA_SCENARIO: "Test::Integration::GitalyCluster"
|
|
1126
|
+
QA_LOG_PATH: "tmp/gitaly_cluster.log"
|
|
1016
1127
|
|
|
1017
1128
|
ce:mtls:
|
|
1018
1129
|
extends:
|
data/docs/run_qa_against_gdk.md
CHANGED
|
@@ -49,6 +49,16 @@ make a few changes to your `gdk/gitlab/config/gitlab.yml` file.
|
|
|
49
49
|
**Note:** The hostname of the URL provided to `gitlab-qa` must match the hostname configured for GDK.
|
|
50
50
|
If they do not match, a test will be signed out when it visits a page directly because the hostname of the URL visited will be different from the hostname that was used when signing in.
|
|
51
51
|
|
|
52
|
+
**Note:** When you log into your GDK instance of GitLab for the first time, the root password requires a change.
|
|
53
|
+
GitLab QA expects the default initial password to be used in tests; see all default values listed in
|
|
54
|
+
[Supported GitLab environment variables](what_tests_can_be_run.md#supported-gitlab-environment-variables).
|
|
55
|
+
If you have changed your root password, you must set the `GITLAB_INITIAL_ROOT_PASSWORD` environment
|
|
56
|
+
variable.
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
export GITLAB_INITIAL_ROOT_PASSWORD="<GDK root password>"
|
|
60
|
+
```
|
|
61
|
+
|
|
52
62
|
### Running EE tests
|
|
53
63
|
|
|
54
64
|
When running EE tests you'll need to have a license available. GitLab engineers can [request a license](https://about.gitlab.com/handbook/developer-onboarding/#working-on-gitlab-ee).
|
|
@@ -101,7 +111,7 @@ your DNS and point to the IP/port of `dnsdock` application.
|
|
|
101
111
|
|
|
102
112
|
### Docker on macOS caveats
|
|
103
113
|
|
|
104
|
-
When using OS X Docker, you need to go to Preferences > Advanced and allocate at least **5.0 GB**,
|
|
114
|
+
When using OS X Docker, you need to go to Preferences > Resources > Advanced and allocate at least **5.0 GB**,
|
|
105
115
|
otherwise some steps may fail to execute the `chrome-webdriver`.
|
|
106
116
|
|
|
107
117
|
When using docker-machine, see [this StackOverflow link for increasing memory](https://stackoverflow.com/questions/32834082/how-to-increase-docker-machine-memory-mac/36982696#36982696).
|
|
@@ -62,6 +62,7 @@ All environment variables used by GitLab QA should be defined in [`lib/gitlab/qa
|
|
|
62
62
|
| `QA_ARTIFACTS_DIR` |`/tmp/gitlab-qa`| Path to a directory where artifacts (logs and screenshots) for failing tests will be saved. | No|
|
|
63
63
|
| `DOCKER_HOST` |`http://localhost`| Docker host to run tests against. | No|
|
|
64
64
|
| `WEBDRIVER_HEADLESS` |- | When running locally, set to `false` to allow Chrome tests to be visible - watch your tests being run. | No|
|
|
65
|
+
| `CHROME_DISABLE_DEV_SHM` | `false` | Set to `true` to disable `/dev/shm` usage in Chrome on Linux. | No|
|
|
65
66
|
| `QA_ADDITIONAL_REPOSITORY_STORAGE` |- | The name of additional, non-default storage to be used with tests tagged `repository_storage`, run via the `Test::Instance::RepositoryStorage` scenario. Note: Admin access is required to change repository storage. | No|
|
|
66
67
|
| `QA_PRAEFECT_REPOSITORY_STORAGE` |- | The name of repository storage using Praefect. Note: Admin access is required to change repository storage. | No|
|
|
67
68
|
| `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|
|
|
@@ -107,7 +107,14 @@ module Gitlab
|
|
|
107
107
|
retry
|
|
108
108
|
rescue StandardError => e
|
|
109
109
|
pipeline = QA::Runtime::Env.pipeline_from_project_name
|
|
110
|
-
channel =
|
|
110
|
+
channel = case pipeline
|
|
111
|
+
when "canary"
|
|
112
|
+
"qa-production"
|
|
113
|
+
when "staging-canary"
|
|
114
|
+
"qa-staging"
|
|
115
|
+
else
|
|
116
|
+
"qa-#{pipeline}"
|
|
117
|
+
end
|
|
111
118
|
error_msg = warn_exception(e)
|
|
112
119
|
|
|
113
120
|
return unless QA::Runtime::Env.ci_commit_ref_name == QA::Runtime::Env.default_branch
|
|
@@ -19,6 +19,7 @@ module Gitlab
|
|
|
19
19
|
def initialize(max_diff_ratio: DEFAULT_MAX_DIFF_RATIO_FOR_DETECTION, **kwargs)
|
|
20
20
|
super
|
|
21
21
|
@max_diff_ratio = max_diff_ratio.to_f
|
|
22
|
+
@issue_type = 'issue'
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
private
|
|
@@ -63,7 +64,7 @@ module Gitlab
|
|
|
63
64
|
puts " => Found issue #{issue.web_url} for test '#{test.name}' with a diff ratio of #{(diff_ratio * 100).round(2)}%."
|
|
64
65
|
else
|
|
65
66
|
issue = create_issue(test)
|
|
66
|
-
puts "
|
|
67
|
+
puts "for test '#{test.name}'."
|
|
67
68
|
end
|
|
68
69
|
|
|
69
70
|
issue
|
|
@@ -22,7 +22,7 @@ module Gitlab
|
|
|
22
22
|
|
|
23
23
|
private
|
|
24
24
|
|
|
25
|
-
attr_reader :gitlab, :files, :project
|
|
25
|
+
attr_reader :gitlab, :files, :project, :issue_type
|
|
26
26
|
|
|
27
27
|
def run!
|
|
28
28
|
raise NotImplementedError
|
|
@@ -77,11 +77,18 @@ module Gitlab
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def create_issue(test)
|
|
80
|
-
gitlab.create_issue(
|
|
80
|
+
issue = gitlab.create_issue(
|
|
81
81
|
title: title_from_test(test),
|
|
82
82
|
description: new_issue_description(test),
|
|
83
|
-
labels: new_issue_labels(test).to_a
|
|
83
|
+
labels: new_issue_labels(test).to_a,
|
|
84
|
+
issue_type: issue_type
|
|
84
85
|
)
|
|
86
|
+
|
|
87
|
+
new_link = issue_type == 'test_case' ? issue.web_url.sub('/issues/', '/quality/test_cases/') : issue.web_url
|
|
88
|
+
|
|
89
|
+
puts "Created new #{issue_type}: #{new_link}"
|
|
90
|
+
|
|
91
|
+
issue
|
|
85
92
|
end
|
|
86
93
|
|
|
87
94
|
def issue_labels(issue)
|
|
@@ -111,6 +118,8 @@ module Gitlab
|
|
|
111
118
|
'found:gitlab.com'
|
|
112
119
|
when 'canary', 'staging'
|
|
113
120
|
"found:#{pipeline}.gitlab.com"
|
|
121
|
+
when 'staging-canary'
|
|
122
|
+
"found:canary.staging.gitlab.com"
|
|
114
123
|
when 'preprod'
|
|
115
124
|
'found:pre.gitlab.com'
|
|
116
125
|
when 'staging-orchestrated', 'nightly', QA::Runtime::Env.default_branch, 'staging-ref', 'release'
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Gitlab
|
|
4
|
+
module QA
|
|
5
|
+
module Report
|
|
6
|
+
# Uses the API to create or update GitLab test cases and issues with the results of tests from RSpec report files.
|
|
7
|
+
class ReportResults < ReportAsIssue
|
|
8
|
+
# TODO: Remove old_testcase_project_reporter once all test case links are updated to the gitlab project. See https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/1079
|
|
9
|
+
attr_accessor :testcase_project_reporter, :results_issue_project_reporter, :files, :test_case_project, :results_issue_project, :gitlab, :old_testcase_project_reporter
|
|
10
|
+
|
|
11
|
+
def initialize(token:, input_files:, test_case_project:, results_issue_project:, dry_run: false, **kwargs)
|
|
12
|
+
@testcase_project_reporter = Gitlab::QA::Report::ResultsInTestCases.new(token: token, input_files: input_files, project: test_case_project, dry_run: dry_run, **kwargs)
|
|
13
|
+
# TODO: Remove the line below once all test case links are updated to the gitlab project. See https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/1079
|
|
14
|
+
@old_testcase_project_reporter = Gitlab::QA::Report::ResultsInTestCases.new(token: token, input_files: input_files, project: results_issue_project, dry_run: dry_run, **kwargs)
|
|
15
|
+
@results_issue_project_reporter = Gitlab::QA::Report::ResultsInIssues.new(token: token, input_files: input_files, project: results_issue_project, dry_run: dry_run, **kwargs)
|
|
16
|
+
@test_case_project = test_case_project
|
|
17
|
+
@results_issue_project = results_issue_project
|
|
18
|
+
@files = Array(input_files)
|
|
19
|
+
@gitlab = testcase_project_reporter.gitlab
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def assert_project!
|
|
23
|
+
return if test_case_project && results_issue_project
|
|
24
|
+
|
|
25
|
+
abort "Please provide valid project IDs or paths with the `--results-issue-project` and `--test-case-project` options!"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def run!
|
|
29
|
+
puts "Reporting test results in `#{files.join(',')}` as test cases in project `#{test_case_project}`"\
|
|
30
|
+
" and issues in project `#{results_issue_project}` via the API at `#{Runtime::Env.gitlab_api_base}`."
|
|
31
|
+
|
|
32
|
+
test_results_per_file do |test_results|
|
|
33
|
+
puts "Reporting tests in #{test_results.path}"
|
|
34
|
+
|
|
35
|
+
test_results.each do |test|
|
|
36
|
+
puts "Reporting test: #{test.file} | #{test.name}\n"
|
|
37
|
+
|
|
38
|
+
report_test(test) unless test.skipped
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
test_results.write
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def report_test(test)
|
|
48
|
+
# TODO: Remove the line below and replace correct_testcase_project_reporter with testcase_project_reporter
|
|
49
|
+
# once all test case links are updated to the gitlab project. See https://gitlab.com/gitlab-org/quality/team-tasks/-/issues/1079
|
|
50
|
+
correct_testcase_project_reporter = using_old_testcase_link(test) ? old_testcase_project_reporter : testcase_project_reporter
|
|
51
|
+
|
|
52
|
+
testcase = correct_testcase_project_reporter.find_or_create_testcase(test)
|
|
53
|
+
# The API returns the test case with an issue URL since it is technically a type of issue.
|
|
54
|
+
# This updates the URL to a valid test case link.
|
|
55
|
+
test.testcase = testcase.web_url.sub('/issues/', '/quality/test_cases/')
|
|
56
|
+
|
|
57
|
+
issue, is_new = results_issue_project_reporter.get_related_issue(testcase, test)
|
|
58
|
+
|
|
59
|
+
correct_testcase_project_reporter.add_issue_link_to_testcase(testcase, issue, test) if is_new
|
|
60
|
+
|
|
61
|
+
correct_testcase_project_reporter.update_testcase(testcase, test)
|
|
62
|
+
results_issue_project_reporter.update_issue(issue, test)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def using_old_testcase_link(test)
|
|
66
|
+
test.testcase.include?(results_issue_project)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -1,120 +1,62 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'nokogiri'
|
|
4
|
-
require 'active_support/core_ext/enumerable'
|
|
5
|
-
|
|
6
3
|
module Gitlab
|
|
7
4
|
module QA
|
|
8
5
|
module Report
|
|
9
|
-
# Uses the API to create or update GitLab issues with the results of tests from RSpec report files.
|
|
6
|
+
# Uses the API to create or update GitLab test result issues with the results of tests from RSpec report files.
|
|
10
7
|
class ResultsInIssues < ReportAsIssue
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
RESULTS_SECTION_TEMPLATE = "\n\n### DO NOT EDIT BELOW THIS LINE\n\nActive and historical test results:"
|
|
14
|
-
|
|
15
|
-
def run!
|
|
16
|
-
puts "Reporting test results in `#{files.join(',')}` as issues in project `#{project}` via the API at `#{Runtime::Env.gitlab_api_base}`."
|
|
17
|
-
|
|
18
|
-
test_results_per_file do |test_results|
|
|
19
|
-
puts "Reporting tests in #{test_results.path}"
|
|
8
|
+
include ResultsReporterShared
|
|
20
9
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
report_test(test) unless test.skipped
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
test_results.write
|
|
28
|
-
end
|
|
10
|
+
def initialize(**kwargs)
|
|
11
|
+
super
|
|
12
|
+
@issue_type = 'issue'
|
|
29
13
|
end
|
|
30
14
|
|
|
31
|
-
def
|
|
32
|
-
testcase = find_testcase(test) || create_testcase(test)
|
|
33
|
-
test.testcase ||= testcase.web_url.sub('/issues/', '/quality/test_cases/')
|
|
34
|
-
|
|
15
|
+
def get_related_issue(testcase, test)
|
|
35
16
|
issue = find_linked_results_issue_by_iid(testcase, test)
|
|
17
|
+
is_new = false
|
|
36
18
|
|
|
37
19
|
if issue
|
|
38
|
-
issue = update_issue_title(issue, test
|
|
20
|
+
issue = update_issue_title(issue, test) if issue_title_needs_updating?(issue, test)
|
|
39
21
|
else
|
|
40
22
|
puts "No valid issue link found"
|
|
41
23
|
issue = find_or_create_results_issue(test)
|
|
42
|
-
|
|
43
|
-
add_issue_to_testcase(testcase, issue)
|
|
24
|
+
is_new = true
|
|
44
25
|
end
|
|
45
26
|
|
|
46
|
-
|
|
47
|
-
update_issue(issue, test)
|
|
27
|
+
[issue, is_new]
|
|
48
28
|
end
|
|
49
29
|
|
|
50
|
-
def
|
|
51
|
-
|
|
30
|
+
def update_issue(issue, test)
|
|
31
|
+
new_labels = issue_labels(issue)
|
|
32
|
+
new_labels |= ['Testcase Linked']
|
|
52
33
|
|
|
53
|
-
|
|
54
|
-
|
|
34
|
+
labels_updated = update_labels(issue, test, new_labels)
|
|
35
|
+
note_posted = note_status(issue, test)
|
|
36
|
+
|
|
37
|
+
if labels_updated || note_posted
|
|
38
|
+
puts "Issue updated."
|
|
55
39
|
else
|
|
56
|
-
|
|
40
|
+
puts "Test passed, no results issue update needed."
|
|
57
41
|
end
|
|
58
|
-
|
|
59
|
-
testcase
|
|
60
42
|
end
|
|
61
43
|
|
|
62
|
-
|
|
63
|
-
iid = testcase_iid_from_url(test.testcase)
|
|
64
|
-
|
|
65
|
-
return unless iid
|
|
66
|
-
|
|
67
|
-
find_issue_by_iid(iid, 'test_case')
|
|
68
|
-
end
|
|
44
|
+
private
|
|
69
45
|
|
|
70
46
|
def find_linked_results_issue_by_iid(testcase, test)
|
|
71
47
|
iid = issue_iid_from_testcase(testcase)
|
|
72
48
|
|
|
73
49
|
return unless iid
|
|
74
50
|
|
|
75
|
-
find_issue_by_iid(iid
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def find_issue_by_iid(iid, issue_type)
|
|
79
|
-
issues = gitlab.find_issues(iid: iid) do |issue|
|
|
80
|
-
issue.state == 'opened' && issue.issue_type == issue_type
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
warn(%(#{issue_type} iid "#{iid}" not valid)) if issues.empty?
|
|
84
|
-
|
|
85
|
-
issues.first
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def update_issue_title(issue, test, issue_type)
|
|
89
|
-
warn(%(#{issue_type} title needs to be updated from '#{issue.title.strip}' to '#{title_from_test(test)}'))
|
|
90
|
-
|
|
91
|
-
gitlab.edit_issue(iid: issue.iid, options: { title: title_from_test(test) })
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def create_testcase(test)
|
|
95
|
-
title = title_from_test(test)
|
|
96
|
-
puts "Creating test case '#{title}' ..."
|
|
97
|
-
|
|
98
|
-
gitlab.create_issue(
|
|
99
|
-
title: title,
|
|
100
|
-
description: new_testcase_description(test),
|
|
101
|
-
labels: new_issue_labels(test),
|
|
102
|
-
issue_type: 'test_case'
|
|
103
|
-
)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def testcase_iid_from_url(url)
|
|
107
|
-
return warn(%(\nPlease update #{url} to test case url")) if url&.include?('/-/issues/')
|
|
108
|
-
|
|
109
|
-
url && url.split('/').last.to_i
|
|
51
|
+
find_issue_by_iid(iid)
|
|
110
52
|
end
|
|
111
53
|
|
|
112
|
-
def
|
|
113
|
-
|
|
54
|
+
def find_or_create_results_issue(test)
|
|
55
|
+
find_issue(test) || create_issue(test)
|
|
114
56
|
end
|
|
115
57
|
|
|
116
58
|
def issue_iid_from_testcase(testcase)
|
|
117
|
-
results = testcase.description.partition(
|
|
59
|
+
results = testcase.description.partition(TEST_CASE_RESULTS_SECTION_TEMPLATE).last if testcase.description.include?(TEST_CASE_RESULTS_SECTION_TEMPLATE)
|
|
118
60
|
|
|
119
61
|
return puts "No issue link found" unless results
|
|
120
62
|
|
|
@@ -123,66 +65,6 @@ module Gitlab
|
|
|
123
65
|
issue_iid&.to_i
|
|
124
66
|
end
|
|
125
67
|
|
|
126
|
-
def find_or_create_results_issue(test)
|
|
127
|
-
issue = find_issue(test, 'issue')
|
|
128
|
-
|
|
129
|
-
if issue
|
|
130
|
-
puts "Found existing issue: #{issue.web_url}"
|
|
131
|
-
else
|
|
132
|
-
issue = create_issue(test)
|
|
133
|
-
puts "Created new issue: #{issue.web_url}"
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
issue
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def find_issue(test, issue_type)
|
|
140
|
-
issues = gitlab.find_issues(options: { search: search_term(test) }) do |issue|
|
|
141
|
-
issue.state == 'opened' && issue.issue_type == issue_type && issue.title.strip == title_from_test(test)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
warn(%(Too many #{issue_type}s found with the file path "#{test.file}" and name "#{test.name}")) if issues.many?
|
|
145
|
-
|
|
146
|
-
issues.first
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
def add_issue_to_testcase(testcase, issue)
|
|
150
|
-
results_section = testcase.description.include?(RESULTS_SECTION_TEMPLATE) ? '' : RESULTS_SECTION_TEMPLATE
|
|
151
|
-
|
|
152
|
-
gitlab.edit_issue(iid: testcase.iid, options: { description: (testcase.description + results_section + "\n\n#{issue.web_url}") })
|
|
153
|
-
|
|
154
|
-
puts "Added issue #{issue.web_url} to testcase #{testcase.web_url}"
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def update_issue(issue, test)
|
|
158
|
-
new_labels = issue_labels(issue)
|
|
159
|
-
new_labels |= ['Testcase Linked']
|
|
160
|
-
|
|
161
|
-
labels_updated = update_labels(issue, test, new_labels)
|
|
162
|
-
note_posted = note_status(issue, test)
|
|
163
|
-
|
|
164
|
-
if labels_updated || note_posted
|
|
165
|
-
puts "Issue updated."
|
|
166
|
-
else
|
|
167
|
-
puts "Test passed, no update needed."
|
|
168
|
-
end
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
def new_issue_labels(test)
|
|
172
|
-
['Quality', "devops::#{test.stage}", 'status::automated']
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def up_to_date_labels(test:, issue: nil, new_labels: Set.new)
|
|
176
|
-
labels = super
|
|
177
|
-
labels |= new_issue_labels(test).to_set
|
|
178
|
-
labels.delete_if { |label| label.start_with?("#{pipeline}::") }
|
|
179
|
-
labels << (test.failures.empty? ? "#{pipeline}::passed" : "#{pipeline}::failed")
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
def search_term(test)
|
|
183
|
-
%("#{partial_file_path(test.file)}" "#{search_safe(test.name)}")
|
|
184
|
-
end
|
|
185
|
-
|
|
186
68
|
def note_status(issue, test)
|
|
187
69
|
return false if test.skipped
|
|
188
70
|
return false if test.failures.empty?
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Gitlab
|
|
4
|
+
module QA
|
|
5
|
+
module Report
|
|
6
|
+
# Uses the API to create or update GitLab test cases with the results of tests from RSpec report files.
|
|
7
|
+
class ResultsInTestCases < ReportAsIssue
|
|
8
|
+
attr_reader :issue_type, :gitlab
|
|
9
|
+
|
|
10
|
+
include ResultsReporterShared
|
|
11
|
+
|
|
12
|
+
def initialize(**kwargs)
|
|
13
|
+
super
|
|
14
|
+
@issue_type = 'test_case'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def find_or_create_testcase(test)
|
|
18
|
+
find_testcase(test) || create_issue(test)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add_issue_link_to_testcase(testcase, issue, test)
|
|
22
|
+
results_section = testcase.description.include?(TEST_CASE_RESULTS_SECTION_TEMPLATE) ? '' : TEST_CASE_RESULTS_SECTION_TEMPLATE
|
|
23
|
+
|
|
24
|
+
gitlab.edit_issue(iid: testcase.iid, options: { description: (testcase.description + results_section + "\n\n#{issue.web_url}") })
|
|
25
|
+
# We are using test.testcase for the url here instead of testcase.web_url since it has the updated test case path
|
|
26
|
+
puts "Added results issue #{issue.web_url} link to test case #{test.testcase}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def update_testcase(testcase, test)
|
|
30
|
+
puts "Test case labels updated." if update_labels(testcase, test)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def find_testcase(test)
|
|
36
|
+
testcase = find_testcase_by_iid(test)
|
|
37
|
+
|
|
38
|
+
if testcase
|
|
39
|
+
testcase = update_issue_title(testcase, test) if issue_title_needs_updating?(testcase, test)
|
|
40
|
+
else
|
|
41
|
+
testcase = find_issue(test)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
testcase
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def find_testcase_by_iid(test)
|
|
48
|
+
iid = testcase_iid_from_url(test.testcase)
|
|
49
|
+
|
|
50
|
+
return unless iid
|
|
51
|
+
|
|
52
|
+
find_issue_by_iid(iid)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def testcase_iid_from_url(url)
|
|
56
|
+
return warn(%(\nPlease update #{url} to test case url")) if url&.include?('/-/issues/')
|
|
57
|
+
|
|
58
|
+
url && url.split('/').last.to_i
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def new_issue_description(test)
|
|
62
|
+
"#{super}#{TEST_CASE_RESULTS_SECTION_TEMPLATE}"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'active_support/core_ext/enumerable'
|
|
4
|
+
|
|
5
|
+
module Gitlab
|
|
6
|
+
module QA
|
|
7
|
+
module Report
|
|
8
|
+
module ResultsReporterShared
|
|
9
|
+
TEST_CASE_RESULTS_SECTION_TEMPLATE = "\n\n### DO NOT EDIT BELOW THIS LINE\n\nActive and historical test results:"
|
|
10
|
+
|
|
11
|
+
def find_issue(test)
|
|
12
|
+
issues = search_for_issues(test)
|
|
13
|
+
|
|
14
|
+
warn(%(Too many #{issue_type}s found with the file path "#{test.file}" and name "#{test.name}")) if issues.many?
|
|
15
|
+
puts "Found existing #{issue_type}: #{issues.first.web_url}" unless issues.empty?
|
|
16
|
+
|
|
17
|
+
issues.first
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def find_issue_by_iid(iid)
|
|
21
|
+
issues = gitlab.find_issues(iid: iid) do |issue|
|
|
22
|
+
issue.state == 'opened' && issue.issue_type == issue_type
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
warn(%(#{issue_type} iid "#{iid}" not valid)) if issues.empty?
|
|
26
|
+
|
|
27
|
+
issues.first
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def issue_title_needs_updating?(issue, test)
|
|
31
|
+
issue.title.strip != title_from_test(test) && !%w[canary production preprod release].include?(pipeline)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def new_issue_labels(test)
|
|
35
|
+
['Quality', "devops::#{test.stage}", 'status::automated']
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def search_term(test)
|
|
39
|
+
%("#{partial_file_path(test.file)}" "#{search_safe(test.name)}")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def up_to_date_labels(test:, issue: nil, new_labels: Set.new)
|
|
43
|
+
labels = super
|
|
44
|
+
labels |= new_issue_labels(test).to_set
|
|
45
|
+
labels.delete_if { |label| label.start_with?("#{pipeline}::") }
|
|
46
|
+
labels << (test.failures.empty? ? "#{pipeline}::passed" : "#{pipeline}::failed")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def update_issue_title(issue, test)
|
|
50
|
+
warn(%(#{issue_type} title needs to be updated from '#{issue.title.strip}' to '#{title_from_test(test)}'))
|
|
51
|
+
|
|
52
|
+
gitlab.edit_issue(iid: issue.iid, options: { title: title_from_test(test) })
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def search_for_issues(test)
|
|
58
|
+
gitlab.find_issues(options: { search: search_term(test) }) do |issue|
|
|
59
|
+
issue.state == 'opened' && issue.issue_type == issue_type && issue.title.strip == title_from_test(test)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
data/lib/gitlab/qa/reporter.rb
CHANGED
|
@@ -17,8 +17,8 @@ module Gitlab
|
|
|
17
17
|
report_options[:input_files] = files if files
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
opts.on('--report-
|
|
21
|
-
report_options[:
|
|
20
|
+
opts.on('--report-results FILES', String, 'Report test results from JUnit XML files in GitLab test cases and results issues') do |files|
|
|
21
|
+
report_options[:report_results] = true
|
|
22
22
|
report_options[:input_files] = files if files
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -31,16 +31,24 @@ module Gitlab
|
|
|
31
31
|
report_options[:max_diff_ratio] = value
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
opts.on('-p', '--project PROJECT_ID', String, 'A valid project ID. Can be an integer or a group/project string. Required by --
|
|
34
|
+
opts.on('-p', '--project PROJECT_ID', String, 'A valid project ID. Can be an integer or a group/project string. Required by --relate-failure-issue') do |value|
|
|
35
35
|
report_options[:project] = value
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
opts.on('--results-issue-project RESULTS_ISSUE_PROJECT_ID', String, 'A valid project ID. Can be an integer or a group/project string. Required by --report-results') do |value|
|
|
39
|
+
report_options[:results_issue_project] = value
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
opts.on('--test-case-project TEST_CASE_PROJECT_ID', String, 'A valid project ID. Can be an integer or a group/project string. Required by --report-results') do |value|
|
|
43
|
+
report_options[:test_case_project] = value
|
|
44
|
+
end
|
|
45
|
+
|
|
38
46
|
opts.on('--generate-test-session FILES', String, 'Generate test session report') do |files|
|
|
39
47
|
report_options[:generate_test_session] = true
|
|
40
48
|
report_options[:input_files] = files if files
|
|
41
49
|
end
|
|
42
50
|
|
|
43
|
-
opts.on('-t', '--token ACCESS_TOKEN', String, 'A valid access token. Required by --report-
|
|
51
|
+
opts.on('-t', '--token ACCESS_TOKEN', String, 'A valid access token. Required by --report-results and --relate-failure-issue') do |value|
|
|
44
52
|
report_options[:token] = value
|
|
45
53
|
end
|
|
46
54
|
|
|
@@ -60,7 +68,7 @@ module Gitlab
|
|
|
60
68
|
report_options[:files] = files
|
|
61
69
|
end
|
|
62
70
|
|
|
63
|
-
opts.on('--dry-run', "Perform a dry-run (don't create or update issues)") do |files|
|
|
71
|
+
opts.on('--dry-run', "Perform a dry-run (don't create or update issues or test cases)") do |files|
|
|
64
72
|
report_options[:dry_run] = true
|
|
65
73
|
end
|
|
66
74
|
|
|
@@ -86,9 +94,9 @@ module Gitlab
|
|
|
86
94
|
report_options[:token] = Runtime::TokenFinder.find_token!(report_options[:token])
|
|
87
95
|
Gitlab::QA::Report::RelateFailureIssue.new(**report_options).invoke!
|
|
88
96
|
|
|
89
|
-
elsif report_options.delete(:
|
|
97
|
+
elsif report_options.delete(:report_results)
|
|
90
98
|
report_options[:token] = Runtime::TokenFinder.find_token!(report_options[:token])
|
|
91
|
-
Gitlab::QA::Report::
|
|
99
|
+
Gitlab::QA::Report::ReportResults.new(**report_options).invoke!
|
|
92
100
|
|
|
93
101
|
elsif report_options.delete(:generate_test_session)
|
|
94
102
|
report_options[:token] = Runtime::TokenFinder.find_token!(report_options[:token])
|
|
@@ -123,7 +123,8 @@ module Gitlab
|
|
|
123
123
|
'GOOGLE_JSON_KEY' => :google_json_key,
|
|
124
124
|
'GCS_BUCKET_NAME' => :gcs_bucket_name,
|
|
125
125
|
'SMOKE_ONLY' => :smoke_only,
|
|
126
|
-
'NO_ADMIN' => :no_admin
|
|
126
|
+
'NO_ADMIN' => :no_admin,
|
|
127
|
+
'CHROME_DISABLE_DEV_SHM' => :chrome_disable_dev_shm
|
|
127
128
|
}.freeze
|
|
128
129
|
|
|
129
130
|
ENV_VARIABLES.each do |env_name, method_name|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Gitlab
|
|
4
|
+
module QA
|
|
5
|
+
module Scenario
|
|
6
|
+
module Test
|
|
7
|
+
module Integration
|
|
8
|
+
class ServicePingDisabled < Scenario::Template
|
|
9
|
+
def perform(release, *rspec_args)
|
|
10
|
+
Component::Gitlab.perform do |gitlab|
|
|
11
|
+
gitlab.release = release
|
|
12
|
+
gitlab.network = 'test'
|
|
13
|
+
|
|
14
|
+
gitlab.omnibus_configuration << <<~OMNIBUS
|
|
15
|
+
gitlab_rails['usage_ping_enabled'] = false;
|
|
16
|
+
OMNIBUS
|
|
17
|
+
|
|
18
|
+
gitlab.instance do
|
|
19
|
+
Component::Specs.perform do |specs|
|
|
20
|
+
specs.suite = 'Test::Integration::ServicePingDisabled'
|
|
21
|
+
specs.release = gitlab.release
|
|
22
|
+
specs.network = gitlab.network
|
|
23
|
+
specs.args = [gitlab.address, *rspec_args]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/gitlab/qa/version.rb
CHANGED
data/lib/gitlab/qa.rb
CHANGED
|
@@ -72,6 +72,7 @@ module Gitlab
|
|
|
72
72
|
autoload :ClientSSL, 'gitlab/qa/scenario/test/integration/client_ssl'
|
|
73
73
|
autoload :Registry, 'gitlab/qa/scenario/test/integration/registry'
|
|
74
74
|
autoload :RegistryTLS, 'gitlab/qa/scenario/test/integration/registry_tls'
|
|
75
|
+
autoload :ServicePingDisabled, 'gitlab/qa/scenario/test/integration/service_ping_disabled'
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
module Sanity
|
|
@@ -122,7 +123,10 @@ module Gitlab
|
|
|
122
123
|
autoload :JUnitTestResults, 'gitlab/qa/report/junit_test_results'
|
|
123
124
|
autoload :PrepareStageReports, 'gitlab/qa/report/prepare_stage_reports'
|
|
124
125
|
autoload :ReportAsIssue, 'gitlab/qa/report/report_as_issue'
|
|
126
|
+
autoload :ReportResults, 'gitlab/qa/report/report_results'
|
|
125
127
|
autoload :ResultsInIssues, 'gitlab/qa/report/results_in_issues'
|
|
128
|
+
autoload :ResultsInTestCases, 'gitlab/qa/report/results_in_testcases'
|
|
129
|
+
autoload :ResultsReporterShared, 'gitlab/qa/report/results_reporter_shared'
|
|
126
130
|
autoload :GenerateTestSession, 'gitlab/qa/report/generate_test_session'
|
|
127
131
|
autoload :SummaryTable, 'gitlab/qa/report/summary_table'
|
|
128
132
|
autoload :TestResult, 'gitlab/qa/report/test_result'
|
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.
|
|
4
|
+
version: 7.16.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: 2021-
|
|
11
|
+
date: 2021-12-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: climate_control
|
|
@@ -256,7 +256,10 @@ files:
|
|
|
256
256
|
- lib/gitlab/qa/report/prepare_stage_reports.rb
|
|
257
257
|
- lib/gitlab/qa/report/relate_failure_issue.rb
|
|
258
258
|
- lib/gitlab/qa/report/report_as_issue.rb
|
|
259
|
+
- lib/gitlab/qa/report/report_results.rb
|
|
259
260
|
- lib/gitlab/qa/report/results_in_issues.rb
|
|
261
|
+
- lib/gitlab/qa/report/results_in_testcases.rb
|
|
262
|
+
- lib/gitlab/qa/report/results_reporter_shared.rb
|
|
260
263
|
- lib/gitlab/qa/report/summary_table.rb
|
|
261
264
|
- lib/gitlab/qa/report/test_result.rb
|
|
262
265
|
- lib/gitlab/qa/report/update_screenshot_path.rb
|
|
@@ -309,6 +312,7 @@ files:
|
|
|
309
312
|
- lib/gitlab/qa/scenario/test/integration/registry.rb
|
|
310
313
|
- lib/gitlab/qa/scenario/test/integration/registry_tls.rb
|
|
311
314
|
- lib/gitlab/qa/scenario/test/integration/saml.rb
|
|
315
|
+
- lib/gitlab/qa/scenario/test/integration/service_ping_disabled.rb
|
|
312
316
|
- lib/gitlab/qa/scenario/test/integration/smtp.rb
|
|
313
317
|
- lib/gitlab/qa/scenario/test/integration/ssh_tunnel.rb
|
|
314
318
|
- lib/gitlab/qa/scenario/test/omnibus/image.rb
|