gitlab-qa 4.20.0 → 5.0.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 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