gitlab-qa 4.20.0 → 5.0.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: 066aa882ca586d0186ec53fb1cb7e55276a5081280993568e681c73ffa760bfb
4
- data.tar.gz: 11b473e0b82f5842de908b43dad5699dcdd07fd2d444228548bdd7b21cde2639
3
+ metadata.gz: cbeeb65a1b5a859f9908822611d61985da8ba9dd3118a56fe9e52ce0e645e09b
4
+ data.tar.gz: 78f96fa6fe4c8d7e4139e689ff08fd8c71df18d3d111917c9c672b36b6376936
5
5
  SHA512:
6
- metadata.gz: d9298cbb9e265a96d9f969919992920046f8566452af76252008b2ae7500350965168844bf7bca0d9632163ad34b457dc21b623912b32091f8c6c683932dcf54
7
- data.tar.gz: b7cc0ebfd6b6c35085ab94ada285238e68b5577318d16b559fbb2c28b884d9e9135093749627d7fd02a27543ab4d343a26616cc694027146ab9b5997b0bfb6e9
6
+ metadata.gz: 1b43e0971ca42b9a1fe77475ee94c92c164e3f0a3d8f6a45129f899f67a4708d469b36509df84614d33763d6f469d9702d86ab498aa1151fadfc4297c0b96b5f
7
+ data.tar.gz: cbbd9b29c55a243614d127b9e6840f6b8a1241e8984d87b05c0c728ac445f0c6e4b8d3cdb85f0a8dc45e1cb6dd82350eb52237354792f292a63a3e6cbd3806ff
data/.gitlab-ci.yml CHANGED
@@ -1,7 +1,12 @@
1
- image: ruby:2.6
1
+ .default-rules:
2
+ rules:
3
+ - if: '$CI_COMMIT_TAG || $RELEASE'
4
+ when: never
5
+ - if: '$RELEASE == null && $CI_JOB_NAME =~ /staging/'
6
+ when: manual
7
+ - if: '$CI_MERGE_REQUEST_ID || $CI_COMMIT_REF_NAME == "master"'
2
8
 
3
- services:
4
- - docker:19.03.0-dind
9
+ image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-ruby-2.6
5
10
 
6
11
  stages:
7
12
  - check
@@ -10,11 +15,10 @@ stages:
10
15
  - notify
11
16
 
12
17
  variables:
13
- TEST_IMAGE: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-qa-ruby-2.6
14
- DOCKER_DRIVER: overlay
18
+ DOCKER_DRIVER: overlay2
15
19
  DOCKER_HOST: tcp://docker:2375
16
20
  QA_ARTIFACTS_DIR: $CI_PROJECT_DIR
17
- QA_CAN_TEST_GIT_PROTOCOL_V2: 'false'
21
+ QA_CAN_TEST_GIT_PROTOCOL_V2: 'true'
18
22
 
19
23
  cache:
20
24
  key: "ruby:2.6"
@@ -29,27 +33,37 @@ before_script:
29
33
  fi
30
34
  - export LANG=C.UTF-8
31
35
 
32
- check:rubocop:
36
+ .check-base:
37
+ extends: .default-rules
33
38
  stage: check
34
- image: $TEST_IMAGE
35
- script: bundle exec rubocop
36
- except:
37
- - triggers
38
- tags:
39
- - docker
39
+ script:
40
+ - bundle exec $CI_JOB_NAME
40
41
 
41
- check:rspec:
42
- stage: check
43
- image: $TEST_IMAGE
44
- script: bundle exec rspec
45
- except:
46
- - triggers
47
- tags:
48
- - docker
42
+ rubocop:
43
+ extends: .check-base
44
+
45
+ rspec:
46
+ extends: .check-base
47
+
48
+ release:
49
+ stage: release
50
+ rules:
51
+ - if: '$CI_COMMIT_TAG'
52
+ script:
53
+ - gem update --system
54
+ - ruby --version
55
+ - gem env version
56
+ - gem build gitlab-qa.gemspec
57
+ - gem push gitlab-qa*.gem
58
+ artifacts:
59
+ paths:
60
+ - gitlab-qa*.gem
61
+ expire_in: 30 days
49
62
 
50
63
  .test:
51
64
  stage: test
52
- image: $TEST_IMAGE
65
+ services:
66
+ - docker:19.03.0-dind
53
67
  tags:
54
68
  - docker
55
69
  artifacts:
@@ -63,23 +77,33 @@ check:rspec:
63
77
  .ce-qa:
64
78
  variables:
65
79
  DEFAULT_RELEASE: "CE"
66
- only:
67
- variables:
68
- - $RELEASE == null
69
- - $RELEASE =~ /gitlab-ce/
80
+ rules:
81
+ - if: '$CI_COMMIT_TAG || $RELEASE =~ /gitlab-ee/'
82
+ when: never
83
+ - if: '$RELEASE == null && $CI_JOB_NAME =~ /quarantine|praefect|custom/'
84
+ when: manual
85
+ - if: '$RELEASE =~ /gitlab-ce/ && $CI_JOB_NAME =~ /quarantine|praefect|custom/'
86
+ when: manual
87
+ - if: '$CI_MERGE_REQUEST_ID && $CI_JOB_NAME =~ /quarantine|praefect|custom/'
88
+ when: manual
89
+ - if: '$RELEASE == null || $RELEASE =~ /gitlab-ce/ || $CI_MERGE_REQUEST_ID || $CI_COMMIT_REF_NAME == "master"'
70
90
 
71
91
  .ee-qa:
72
92
  variables:
73
93
  DEFAULT_RELEASE: "EE"
74
- only:
75
- variables:
76
- - $RELEASE == null
77
- - $RELEASE =~ /gitlab-ee/
94
+ rules:
95
+ - if: '$CI_COMMIT_TAG || $RELEASE =~ /gitlab-ce/'
96
+ when: never
97
+ - if: '$RELEASE == null && $CI_JOB_NAME =~ /quarantine|praefect|custom/'
98
+ when: manual
99
+ - if: '$RELEASE =~ /gitlab-ee/ && $CI_JOB_NAME =~ /quarantine|praefect|custom/'
100
+ when: manual
101
+ - if: '$CI_MERGE_REQUEST_ID && $CI_JOB_NAME =~ /quarantine|praefect|custom/'
102
+ when: manual
103
+ - if: '$RELEASE == null || $RELEASE =~ /gitlab-ee/ || $CI_MERGE_REQUEST_ID || $CI_COMMIT_REF_NAME == "master"'
78
104
 
79
105
  .only-qa:
80
- except:
81
- variables:
82
- - $RELEASE
106
+ extends: .default-rules
83
107
 
84
108
  .high-capacity:
85
109
  tags:
@@ -100,7 +124,6 @@ check:rspec:
100
124
 
101
125
  .quarantine:
102
126
  allow_failure: true
103
- when: manual
104
127
 
105
128
  .echo-custom-variables-before-calling-gitlab-qa:
106
129
  script:
@@ -133,7 +156,7 @@ ce:custom-parallel:
133
156
  - .ce-qa
134
157
  - .rspec-report-opts
135
158
  - .echo-custom-variables-before-calling-gitlab-qa
136
- when: manual
159
+ allow_failure: true
137
160
  parallel: 10
138
161
 
139
162
  ee:custom-parallel:
@@ -143,7 +166,7 @@ ee:custom-parallel:
143
166
  - .ee-qa
144
167
  - .rspec-report-opts
145
168
  - .echo-custom-variables-before-calling-gitlab-qa
146
- when: manual
169
+ allow_failure: true
147
170
  parallel: 10
148
171
 
149
172
  ce:instance:
@@ -188,24 +211,6 @@ ee:instance-quarantine:
188
211
  - .quarantine
189
212
  - .rspec-report-opts
190
213
 
191
- ce:docker:
192
- script:
193
- - exe/gitlab-qa Test::Instance::Image ${RELEASE:=CE} -- --tag docker $RSPEC_REPORT_OPTS
194
- extends:
195
- - .test
196
- - .high-capacity
197
- - .ce-qa
198
- - .rspec-report-opts
199
-
200
- ee:docker:
201
- script:
202
- - exe/gitlab-qa Test::Instance::Image ${RELEASE:=EE} -- --tag docker $RSPEC_REPORT_OPTS
203
- extends:
204
- - .test
205
- - .high-capacity
206
- - .ee-qa
207
- - .rspec-report-opts
208
-
209
214
  ce:relative_url:
210
215
  script:
211
216
  - exe/gitlab-qa Test::Instance::RelativeUrl ${RELEASE:=CE} -- $RSPEC_REPORT_OPTS
@@ -753,7 +758,7 @@ ce:praefect:
753
758
  - .knapsack-variables
754
759
  - .rspec-report-opts
755
760
  parallel: 5
756
- when: manual
761
+ allow_failure: true
757
762
 
758
763
  ee:praefect:
759
764
  script:
@@ -765,7 +770,7 @@ ee:praefect:
765
770
  - .knapsack-variables
766
771
  - .rspec-report-opts
767
772
  parallel: 5
768
- when: manual
773
+ allow_failure: true
769
774
 
770
775
  ce:smtp:
771
776
  script:
@@ -785,29 +790,6 @@ ee:smtp:
785
790
  - .ee-qa
786
791
  - .rspec-report-opts
787
792
 
788
- .notify_upstream_commit:
789
- stage: notify
790
- except:
791
- variables:
792
- - $TOP_UPSTREAM_SOURCE_PROJECT == null
793
- - $TOP_UPSTREAM_SOURCE_SHA == null
794
- before_script:
795
- - gem install gitlab --no-document
796
-
797
- notify_upstream_commit:success:
798
- extends:
799
- - .notify_upstream_commit
800
- script:
801
- - bin/notify_upstream_commit success
802
- when: on_success
803
-
804
- notify_upstream_commit:failure:
805
- extends:
806
- - .notify_upstream_commit
807
- script:
808
- - bin/notify_upstream_commit failure
809
- when: on_failure
810
-
811
793
  # This job requires the `GITLAB_QA_ACCESS_TOKEN` and `GITLAB_QA_DEV_ACCESS_TOKEN`
812
794
  # variable to be passed when triggered.
813
795
  staging:
@@ -818,23 +800,29 @@ staging:
818
800
  - .test
819
801
  - .high-capacity
820
802
  - .only-qa
821
- when: manual
803
+ allow_failure: true
822
804
 
823
- release:
824
- stage: release
805
+ .notify_upstream_commit:
806
+ stage: notify
807
+ image: ruby:2.6
808
+ before_script:
809
+ - gem install gitlab --no-document
810
+
811
+ notify_upstream_commit:success:
812
+ extends: .notify_upstream_commit
813
+ script:
814
+ - bin/notify_upstream_commit success
825
815
  rules:
826
- - if: '$CI_COMMIT_TAG'
816
+ - if: '$TOP_UPSTREAM_SOURCE_PROJECT && $TOP_UPSTREAM_SOURCE_SHA'
827
817
  when: on_success
818
+
819
+ notify_upstream_commit:failure:
820
+ extends: .notify_upstream_commit
828
821
  script:
829
- - gem update --system
830
- - ruby --version
831
- - gem env version
832
- - gem build gitlab-qa.gemspec
833
- - gem push gitlab-qa*.gem
834
- artifacts:
835
- paths:
836
- - gitlab-qa*.gem
837
- expire_in: 30 days
822
+ - bin/notify_upstream_commit failure
823
+ rules:
824
+ - if: '$TOP_UPSTREAM_SOURCE_PROJECT && $TOP_UPSTREAM_SOURCE_SHA'
825
+ when: on_failure
838
826
 
839
827
  .notify_slack:
840
828
  image: alpine
@@ -847,10 +835,11 @@ release:
847
835
  notify_slack:
848
836
  extends:
849
837
  - .notify_slack
850
- only:
851
- variables:
852
- - $TOP_UPSTREAM_SOURCE_JOB && $NOTIFY_CHANNEL
853
- - $TOP_UPSTREAM_SOURCE_JOB && $TOP_UPSTREAM_SOURCE_REF == 'master'
838
+ rules:
839
+ - if: '$TOP_UPSTREAM_SOURCE_JOB && $NOTIFY_CHANNEL'
840
+ when: on_failure
841
+ - if: '$TOP_UPSTREAM_SOURCE_JOB && $TOP_UPSTREAM_SOURCE_REF == "master"'
842
+ when: on_failure
854
843
  script:
855
844
  - export RELEASE=${TOP_UPSTREAM_SOURCE_REF:-$RELEASE}
856
845
  - echo "NOTIFY_CHANNEL is ${NOTIFY_CHANNEL:=qa-$TOP_UPSTREAM_SOURCE_REF}"
@@ -858,4 +847,3 @@ notify_slack:
858
847
  - echo "CI_PIPELINE_URL is $CI_PIPELINE_URL"
859
848
  - echo "TOP_UPSTREAM_SOURCE_JOB is $TOP_UPSTREAM_SOURCE_JOB"
860
849
  - bin/slack $NOTIFY_CHANNEL "☠️ QA against $RELEASE failed! ☠️ See $CI_PIPELINE_URL (triggered from $TOP_UPSTREAM_SOURCE_JOB)" ci_failing
861
- when: on_failure
@@ -613,6 +613,24 @@ Example:
613
613
  $ gitlab-qa Test::Instance::Smoke ee:<tag> https://staging.gitlab.com
614
614
  ```
615
615
 
616
+ ### `Test::Instance::RepositoryStorage`
617
+
618
+ This scenario will run a limited number of tests that are tagged with `:repository_storage`.
619
+
620
+ These tests verify features related to multiple repository storages.
621
+
622
+ **Required environment variables:**
623
+
624
+ - `QA_ADDITIONAL_REPOSITORY_STORAGE`: The name of the non-default repository storage.
625
+
626
+ Example:
627
+
628
+ ```
629
+ $ export QA_ADDITIONAL_REPOSITORY_STORAGE=secondary
630
+
631
+ $ gitlab-qa Test::Instance::RepositoryStorage
632
+ ```
633
+
616
634
  ----
617
635
 
618
636
  [Back to README.md](../README.md)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../lib', __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'gitlab/qa'
7
+
8
+ Gitlab::QA::Reporter.invoke(ARGV)
data/gitlab-qa.gemspec CHANGED
@@ -27,5 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency 'rubocop', '~> 0.54.0'
28
28
  spec.add_development_dependency 'rubocop-rspec', '1.20.1'
29
29
  spec.add_development_dependency 'webmock', '3.7.0'
30
+ spec.add_runtime_dependency 'activesupport', '~> 6.0.2'
31
+ spec.add_runtime_dependency 'gitlab', '~> 4.11.0'
30
32
  spec.add_runtime_dependency 'nokogiri', '~> 1.10'
31
33
  end
data/lib/gitlab/qa.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  module Gitlab
2
2
  module QA
3
3
  autoload :Release, 'gitlab/qa/release'
4
+ autoload :Reporter, 'gitlab/qa/reporter'
4
5
  autoload :Runner, 'gitlab/qa/runner'
5
6
 
6
7
  module Runtime
7
8
  autoload :Env, 'gitlab/qa/runtime/env'
9
+ autoload :TokenFinder, 'gitlab/qa/runtime/token_finder'
8
10
  end
9
11
 
10
12
  module Scenario
@@ -86,6 +88,7 @@ module Gitlab
86
88
 
87
89
  module Report
88
90
  autoload :PrepareStageReports, 'gitlab/qa/report/prepare_stage_reports'
91
+ autoload :ResultsInIssues, 'gitlab/qa/report/results_in_issues'
89
92
  end
90
93
  end
91
94
  end
@@ -0,0 +1,191 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'nokogiri'
4
+ require 'gitlab'
5
+ require 'active_support/core_ext/enumerable'
6
+
7
+ module Gitlab
8
+ # Monkey patch the Gitlab client to use the correct API path
9
+ class Client
10
+ def team_member(project, id)
11
+ get("/projects/#{url_encode project}/members/all/#{id}")
12
+ end
13
+ end
14
+
15
+ module QA
16
+ module Report
17
+ # Uses the API to create or update GitLab issues with the results of tests from RSpec report files.
18
+ # The GitLab client is used for API access: https://github.com/NARKOZ/gitlab
19
+ class ResultsInIssues
20
+ MAINTAINER_ACCESS_LEVEL = 40
21
+ MAX_TITLE_LENGTH = 255
22
+
23
+ def initialize(token:, input_files:, project: nil)
24
+ @token = token
25
+ @files = Array(input_files)
26
+ @project = project
27
+ end
28
+
29
+ def invoke!
30
+ configure_gitlab_client
31
+
32
+ validate_input!
33
+
34
+ puts "Reporting test results in `#{files.join(',')}` as issues in project `#{project}` via the API at `#{Runtime::Env.gitlab_api_base}`."
35
+
36
+ Dir.glob(files).each do |file|
37
+ puts "Reporting tests in #{file}"
38
+ Nokogiri::XML(File.open(file)).xpath('//testcase').each do |test|
39
+ report_test(test)
40
+ end
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :files, :token, :project
47
+
48
+ def validate_input!
49
+ assert_project!
50
+ assert_input_files!(files)
51
+ assert_user_permission!
52
+ end
53
+
54
+ def assert_project!
55
+ return if project
56
+
57
+ abort "Please provide a valid project ID or path with the `-p/--project` option!"
58
+ end
59
+
60
+ def assert_input_files!(files)
61
+ return if Dir.glob(files).any?
62
+
63
+ abort "Please provide valid JUnit report files. No files were found matching `#{files.join(',')}`"
64
+ end
65
+
66
+ def assert_user_permission!
67
+ user = Gitlab.user
68
+ member = Gitlab.team_member(project, user.id)
69
+
70
+ abort_not_permitted if member.access_level < MAINTAINER_ACCESS_LEVEL
71
+ rescue Gitlab::Error::NotFound
72
+ abort_not_permitted
73
+ end
74
+
75
+ def abort_not_permitted
76
+ abort "You must have at least Maintainer access to the project to use this feature."
77
+ end
78
+
79
+ def configure_gitlab_client
80
+ Gitlab.configure do |config|
81
+ config.endpoint = Runtime::Env.gitlab_api_base
82
+ config.private_token = token
83
+ end
84
+ end
85
+
86
+ def report_test(test)
87
+ return if test.search('skipped').any?
88
+
89
+ puts "Reporting test name: #{test['name']} | #{test['file']}"
90
+
91
+ issue = find_issue(test)
92
+ if issue
93
+ puts "Found existing issue: #{issue.web_url}"
94
+ else
95
+ issue = create_issue(test)
96
+ puts "Created new issue: #{issue.web_url}"
97
+ end
98
+
99
+ update_labels(issue, test)
100
+ note_status(issue, test)
101
+
102
+ puts "Issue updated"
103
+ end
104
+
105
+ def create_issue(test)
106
+ puts "Creating issue for file: #{test['file']} | name: #{test['name']}"
107
+
108
+ Gitlab.create_issue(
109
+ project,
110
+ title_from_test(test),
111
+ { description: "### Full description\n\n#{search_safe(test['name'])}\n\n### File path\n\n#{test['file']}", labels: 'status::automated' }
112
+ )
113
+ end
114
+
115
+ def find_issue(test)
116
+ issues = Gitlab.search_in_project(project, 'issues', search_term(test))
117
+ .auto_paginate
118
+ .select { |issue| issue.state == 'opened' && issue.title.strip == title_from_test(test) }
119
+
120
+ warn(%(Too many issues found with the file path "#{test['file']}" and name "#{test['name']}")) if issues.many?
121
+
122
+ issues.first
123
+ end
124
+
125
+ def search_term(test)
126
+ %("#{test['file']}" "#{search_safe(test['name'])}")
127
+ end
128
+
129
+ def title_from_test(test)
130
+ title = "Results for #{test['file']} | #{search_safe(test['name'])}".strip
131
+
132
+ return title unless title.length > MAX_TITLE_LENGTH
133
+
134
+ "#{title[0...MAX_TITLE_LENGTH - 3]}..."
135
+ end
136
+
137
+ def search_safe(value)
138
+ value.delete('"')
139
+ end
140
+
141
+ def note_status(issue, test)
142
+ return if failures(test).empty?
143
+
144
+ errors = failures(test).each_with_object([]) do |failure, text|
145
+ text << <<~TEXT
146
+ Error:
147
+ ```
148
+ #{failure['message']}
149
+ ```
150
+
151
+ Stacktrace:
152
+ ```
153
+ #{failure.content}
154
+ ```
155
+ TEXT
156
+ end.join("\n\n")
157
+
158
+ Gitlab.create_issue_note(project, issue.iid, ":x: ~\"#{pipeline}::failed\" in job `#{Runtime::Env.ci_job_name}` in #{Runtime::Env.ci_job_url}\n\n#{errors}")
159
+ end
160
+
161
+ def update_labels(issue, test)
162
+ labels = issue.labels
163
+ labels.delete_if { |label| label.start_with?("#{pipeline}::") }
164
+ labels << (failures(test).empty? ? "#{pipeline}::passed" : "#{pipeline}::failed")
165
+
166
+ Gitlab.edit_issue(project, issue.iid, labels: labels)
167
+ end
168
+
169
+ def failures(test)
170
+ test.search('failure')
171
+ end
172
+
173
+ def pipeline
174
+ # Gets the name of the pipeline the test was run in, to be used as the key of a scoped label
175
+ #
176
+ # Tests can be run in several pipelines:
177
+ # gitlab-qa, nightly, master, staging, canary, production, preprod, and MRs
178
+ #
179
+ # Some of those run in their own project, so CI_PROJECT_NAME is the name we need. Those are:
180
+ # nightly, staging, canary, production, and preprod
181
+ #
182
+ # MR, master, and gitlab-qa tests run in gitlab-qa, but we only want to report tests run on master
183
+ # because the other pipelines will be monitored by the author of the MR that triggered them.
184
+ # So we assume that we're reporting a master pipeline if the project name is 'gitlab-qa'.
185
+
186
+ Runtime::Env.ci_project_name == 'gitlab-qa' ? 'master' : Runtime::Env.ci_project_name
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,68 @@
1
+ require 'optparse'
2
+
3
+ module Gitlab
4
+ module QA
5
+ class Reporter
6
+ # rubocop:disable Metrics/AbcSize
7
+ def self.invoke(args)
8
+ report_options = {}
9
+
10
+ options = OptionParser.new do |opts|
11
+ opts.banner = 'Usage: gitlab-qa-reporter [options]'
12
+
13
+ opts.on('--prepare-stage-reports FILES', 'Prepare separate reports for each Stage from the provided JUnit XML files') do |files|
14
+ report_options[:prepare_stage_reports] = true
15
+ report_options[:input_files] = files if files
16
+ end
17
+
18
+ opts.on('--report-in-issues FILES', String, 'Report test results from JUnit XML files in GitLab issues') do |files|
19
+ report_options[:report_in_issues] = true
20
+ report_options[:input_files] = files if files
21
+ end
22
+
23
+ opts.on('-p', '--project PROJECT_ID', String, 'A valid project ID. Can be an integer or a group/project string. Required by --report-in-issues') do |value|
24
+ report_options[:project] = value
25
+ end
26
+
27
+ opts.on('-t', '--token ACCESS_TOKEN', String, 'A valid access token. Used by --report-in-issues') do |value|
28
+ report_options[:token] = value
29
+ end
30
+
31
+ opts.on_tail('-v', '--version', 'Show the version') do
32
+ require 'gitlab/qa/version'
33
+ puts "#{$PROGRAM_NAME} : #{VERSION}"
34
+ exit
35
+ end
36
+
37
+ opts.on_tail('-h', '--help', 'Show the usage') do
38
+ puts opts
39
+ exit
40
+ end
41
+
42
+ opts.parse(args)
43
+ end
44
+
45
+ if args.any?
46
+ if report_options[:prepare_stage_reports]
47
+ report_options.delete(:prepare_stage_reports)
48
+ Gitlab::QA::Report::PrepareStageReports.new(**report_options).invoke!
49
+
50
+ exit
51
+ end
52
+
53
+ if report_options[:report_in_issues]
54
+ report_options.delete(:report_in_issues)
55
+ report_options[:token] = Runtime::TokenFinder.find_token!(report_options[:token])
56
+ Gitlab::QA::Report::ResultsInIssues.new(**report_options).invoke!
57
+
58
+ exit
59
+ end
60
+ else
61
+ puts options
62
+ exit 1
63
+ end
64
+ end
65
+ # rubocop:enable Metrics/AbcSize
66
+ end
67
+ end
68
+ end
@@ -2,6 +2,7 @@ require 'optparse'
2
2
 
3
3
  module Gitlab
4
4
  module QA
5
+ # rubocop:disable Metrics/AbcSize
5
6
  class Runner
6
7
  # These options are implemented in the QA framework (i.e., in the CE/EE codebase)
7
8
  # They're included here so that gitlab-qa treats them as valid options
@@ -13,10 +14,7 @@ module Gitlab
13
14
  ['--loop', 'Execute tests in a loop']
14
15
  ].freeze
15
16
 
16
- # rubocop:disable Metrics/AbcSize
17
17
  def self.run(args)
18
- report_options = {}
19
-
20
18
  options = OptionParser.new do |opts|
21
19
  opts.banner = 'Usage: gitlab-qa [options] Scenario URL [[--] path] [rspec_options]'
22
20
 
@@ -24,11 +22,6 @@ module Gitlab
24
22
  opts.on(*opt)
25
23
  end
26
24
 
27
- opts.on('--prepare-stage-reports FILES', 'Prepare separate reports for each Stage from the provided JUnit XML files') do |files|
28
- report_options[:prepare_stage_reports] = true
29
- report_options[:input_files] = files if files
30
- end
31
-
32
25
  opts.on_tail('-v', '--version', 'Show the version') do
33
26
  require 'gitlab/qa/version'
34
27
  puts "#{$PROGRAM_NAME} : #{VERSION}"
@@ -44,13 +37,6 @@ module Gitlab
44
37
  end
45
38
 
46
39
  if args.size >= 1
47
- if report_options[:prepare_stage_reports]
48
- report_options.delete(:prepare_stage_reports)
49
- Gitlab::QA::Report::PrepareStageReports.new(**report_options).invoke!
50
-
51
- exit
52
- end
53
-
54
40
  Scenario
55
41
  .const_get(args.shift)
56
42
  .perform(*args)
@@ -12,6 +12,7 @@ module Gitlab
12
12
  'QA_REMOTE_GRID_ACCESS_KEY' => :remote_grid_access_key,
13
13
  'QA_REMOTE_GRID_PROTOCOL' => :remote_grid_protocol,
14
14
  'QA_BROWSER' => :browser,
15
+ 'GITLAB_API_BASE' => :api_base,
15
16
  'GITLAB_ADMIN_USERNAME' => :admin_username,
16
17
  'GITLAB_ADMIN_PASSWORD' => :admin_password,
17
18
  'GITLAB_USERNAME' => :user_username,
@@ -22,7 +23,6 @@ module Gitlab
22
23
  'GITLAB_FORKER_PASSWORD' => :forker_password,
23
24
  'GITLAB_USER_TYPE' => :user_type,
24
25
  'GITLAB_SANDBOX_NAME' => :gitlab_sandbox_name,
25
- 'GITLAB_QA_ACCESS_TOKEN' => :qa_access_token,
26
26
  'GITLAB_QA_ADMIN_ACCESS_TOKEN' => :qa_admin_access_token,
27
27
  'GITHUB_ACCESS_TOKEN' => :github_access_token,
28
28
  'GITLAB_URL' => :gitlab_url,
@@ -78,6 +78,22 @@ module Gitlab
78
78
  send(:attr_accessor, accessor) # rubocop:disable GitlabSecurity/PublicSend
79
79
  end
80
80
 
81
+ def gitlab_api_base
82
+ ENV['GITLAB_API_BASE'] || 'https://gitlab.com/api/v4'
83
+ end
84
+
85
+ def ci_job_name
86
+ ENV['CI_JOB_NAME']
87
+ end
88
+
89
+ def ci_job_url
90
+ ENV['CI_JOB_URL']
91
+ end
92
+
93
+ def ci_project_name
94
+ ENV['CI_PROJECT_NAME']
95
+ end
96
+
81
97
  def run_id
82
98
  @run_id ||= "gitlab-qa-run-#{Time.now.strftime('%Y-%m-%d-%H-%M-%S')}-#{SecureRandom.hex(4)}"
83
99
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Runtime
6
+ class TokenFinder
7
+ def self.find_token!(token, suffix: nil)
8
+ new(token, suffix).find_token!
9
+ end
10
+
11
+ attr_reader :token, :suffix
12
+
13
+ def initialize(token, suffix)
14
+ @token = token
15
+ @suffix = suffix
16
+ end
17
+
18
+ def find_token!
19
+ find_token_from_attrs || find_token_from_env || find_token_from_file
20
+ end
21
+
22
+ def find_token_from_attrs
23
+ token
24
+ end
25
+
26
+ def find_token_from_env
27
+ Env.qa_access_token
28
+ end
29
+
30
+ def find_token_from_file
31
+ @token_from_file ||= File.read(token_file_path).strip
32
+ rescue Errno::ENOENT
33
+ fail "Please provide a valid access token with the `-t/--token` option, the `GITLAB_QA_ACCESS_TOKEN` environment variable, or in the `#{token_file_path}` file!"
34
+ end
35
+
36
+ private
37
+
38
+ def token_file_path
39
+ @token_file_path ||= File.expand_path("../api_token#{"_#{suffix}" if suffix}", __dir__)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,5 +1,5 @@
1
1
  module Gitlab
2
2
  module QA
3
- VERSION = '4.20.0'.freeze
3
+ VERSION = '5.0.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-qa
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.20.0
4
+ version: 5.0.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-02-17 00:00:00.000000000 Z
11
+ date: 2020-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -122,6 +122,34 @@ dependencies:
122
122
  - - '='
123
123
  - !ruby/object:Gem::Version
124
124
  version: 3.7.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: activesupport
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 6.0.2
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 6.0.2
139
+ - !ruby/object:Gem::Dependency
140
+ name: gitlab
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 4.11.0
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 4.11.0
125
153
  - !ruby/object:Gem::Dependency
126
154
  name: nokogiri
127
155
  requirement: !ruby/object:Gem::Requirement
@@ -141,6 +169,7 @@ email:
141
169
  - grzesiek.bizon@gmail.com
142
170
  executables:
143
171
  - gitlab-qa
172
+ - gitlab-qa-report
144
173
  extensions: []
145
174
  extra_rdoc_files: []
146
175
  files:
@@ -172,6 +201,7 @@ files:
172
201
  - docs/waits.md
173
202
  - docs/what_tests_can_be_run.md
174
203
  - exe/gitlab-qa
204
+ - exe/gitlab-qa-report
175
205
  - fixtures/ldap/1_add_nodes.ldif
176
206
  - fixtures/ldap/2_add_users.ldif
177
207
  - fixtures/ldap/3_add_groups.ldif
@@ -195,8 +225,11 @@ files:
195
225
  - lib/gitlab/qa/docker/volumes.rb
196
226
  - lib/gitlab/qa/release.rb
197
227
  - lib/gitlab/qa/report/prepare_stage_reports.rb
228
+ - lib/gitlab/qa/report/results_in_issues.rb
229
+ - lib/gitlab/qa/reporter.rb
198
230
  - lib/gitlab/qa/runner.rb
199
231
  - lib/gitlab/qa/runtime/env.rb
232
+ - lib/gitlab/qa/runtime/token_finder.rb
200
233
  - lib/gitlab/qa/scenario/actable.rb
201
234
  - lib/gitlab/qa/scenario/cli_commands.rb
202
235
  - lib/gitlab/qa/scenario/template.rb