gitlab-qa 4.3.3 → 4.4.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.yml +434 -284
- data/.rubocop.yml +0 -3
- data/bin/merge_html_reports +86 -0
- data/bin/notify_upstream_commit +16 -8
- data/docs/run_qa_against_gdk.md +10 -8
- data/docs/what_tests_can_be_run.md +8 -0
- data/gitlab-qa.gemspec +3 -3
- data/lib/gitlab/qa.rb +6 -0
- data/lib/gitlab/qa/component/gitlab.rb +11 -0
- data/lib/gitlab/qa/component/specs.rb +11 -0
- data/lib/gitlab/qa/component/staging.rb +4 -89
- data/lib/gitlab/qa/release.rb +20 -1
- data/lib/gitlab/qa/scenario/test/instance/deployment_base.rb +0 -11
- data/lib/gitlab/qa/scenario/test/integration/geo.rb +0 -1
- data/lib/gitlab/qa/scenario/test/integration/object_storage.rb +0 -2
- data/lib/gitlab/qa/support/dev_ee_qa_image.rb +52 -0
- data/lib/gitlab/qa/support/get_request.rb +39 -0
- data/lib/gitlab/qa/support/invalid_response_error.rb +9 -0
- data/lib/gitlab/qa/version.rb +1 -1
- metadata +12 -8
data/.rubocop.yml
CHANGED
@@ -0,0 +1,86 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
main_report_file = ARGV.shift
|
6
|
+
unless main_report_file
|
7
|
+
puts 'usage: merge_html_reports <main-report> <base-artifact-url> [parallel reports...]'
|
8
|
+
exit 1
|
9
|
+
end
|
10
|
+
|
11
|
+
base_artifact_url = ARGV.shift
|
12
|
+
unless base_artifact_url
|
13
|
+
puts 'usage: merge_html_reports <main-report> <base-artifact-url> [parallel reports...]'
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
|
17
|
+
# Create the base report with empty body tag
|
18
|
+
new_report = Nokogiri::HTML.parse(File.read(ARGV[0]))
|
19
|
+
new_report.at_css('body').remove
|
20
|
+
empty_body = Nokogiri::XML::Node.new('body', new_report)
|
21
|
+
new_report.at_css('head').add_next_sibling(empty_body)
|
22
|
+
|
23
|
+
ARGV.each do |report_file|
|
24
|
+
report = Nokogiri::HTML.parse(File.read(report_file))
|
25
|
+
|
26
|
+
report.css('a').each do |link|
|
27
|
+
link_suffix = link['href'].slice(19..-1)
|
28
|
+
link['href'] = base_artifact_url + link_suffix
|
29
|
+
end
|
30
|
+
|
31
|
+
header = report.css('div #rspec-header')
|
32
|
+
tests = report.css('dt[id^="example_group_"]')
|
33
|
+
|
34
|
+
header.search("//h1/text()").first.content = "Test results for job: #{report_file.slice(/rspec-(.*)\.htm/, 1)}"
|
35
|
+
|
36
|
+
tests.each do |test|
|
37
|
+
title = test.parent
|
38
|
+
group = title.parent
|
39
|
+
script = title.css('script')
|
40
|
+
|
41
|
+
if script.inner_html.include? 'makeYellow'
|
42
|
+
test.remove_class('passed')
|
43
|
+
test.add_class('not_implemented')
|
44
|
+
|
45
|
+
group.remove_class('passed')
|
46
|
+
group.add_class('not_implemented')
|
47
|
+
header.add_class('not_implemented')
|
48
|
+
|
49
|
+
script.remove
|
50
|
+
test.next_sibling.remove
|
51
|
+
test.next_sibling.remove
|
52
|
+
|
53
|
+
elsif script.inner_html.include? 'makeRed'
|
54
|
+
test.remove_class('passed')
|
55
|
+
test.add_class('failed')
|
56
|
+
|
57
|
+
group.remove_class('passed')
|
58
|
+
group.add_class('failed')
|
59
|
+
header.add_class('failed')
|
60
|
+
|
61
|
+
script.remove
|
62
|
+
test.next_sibling.remove
|
63
|
+
test.next_sibling.remove
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
duration = report.at_css('p#duration')
|
68
|
+
totals = report.at_css('p#totals')
|
69
|
+
|
70
|
+
duration_script = report.css('div.results script')[-2]
|
71
|
+
totals_script = report.css('div.results script')[-1]
|
72
|
+
|
73
|
+
duration_text = duration_script.text.slice(49..-3)
|
74
|
+
totals_text = totals_script.text.slice(47..-3)
|
75
|
+
|
76
|
+
duration.inner_html = duration_text
|
77
|
+
totals.inner_html = totals_text
|
78
|
+
|
79
|
+
duration_script.remove
|
80
|
+
totals_script.remove
|
81
|
+
|
82
|
+
# Add the new result after the last one to keep the test order
|
83
|
+
new_report.css('body')[-1].add_next_sibling(report.at_css('body'))
|
84
|
+
end
|
85
|
+
|
86
|
+
File.write(main_report_file, new_report)
|
data/bin/notify_upstream_commit
CHANGED
@@ -10,7 +10,7 @@ Gitlab.configure do |config|
|
|
10
10
|
end
|
11
11
|
|
12
12
|
class CommitComment
|
13
|
-
def self.post!(status)
|
13
|
+
def self.post!(status, report_file_name)
|
14
14
|
unless ENV['TOP_UPSTREAM_SOURCE_SHA']
|
15
15
|
puts "The 'TOP_UPSTREAM_SOURCE_SHA' environment variable is missing, cannot post a comment on a missing upstream commit."
|
16
16
|
return
|
@@ -33,18 +33,26 @@ class CommitComment
|
|
33
33
|
"failed! :boom:"
|
34
34
|
end
|
35
35
|
|
36
|
+
# The HTML report can't be opened as a web page so we're forced to
|
37
|
+
# download it. See https://gitlab.com/gitlab-org/gitlab/issues/25192
|
36
38
|
Gitlab.create_commit_comment(
|
37
39
|
top_upstream_source_project,
|
38
40
|
top_upstream_source_sha,
|
39
|
-
|
41
|
+
<<~COMMENT
|
42
|
+
The [`gitlab-qa` downstream pipeline](#{ENV['CI_PIPELINE_URL']}) #{status_with_icon}.
|
43
|
+
|
44
|
+
You can download a report of the test results: [`#{report_file_name}`](#{ENV['CI_JOB_URL']}/artifacts/raw/#{report_file_name})
|
45
|
+
COMMENT
|
46
|
+
)
|
40
47
|
rescue Gitlab::Error::Error => error
|
41
48
|
puts "Ignoring the following error: #{error}"
|
42
49
|
end
|
43
50
|
end
|
44
51
|
|
45
|
-
status = ARGV
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
52
|
+
status = ARGV.shift.to_s.strip
|
53
|
+
report_file_name = ARGV.shift.to_s.strip
|
54
|
+
|
55
|
+
abort "Please provide a status!" if status == ''
|
56
|
+
abort "Please provide a file name for the report!" if report_file_name == ''
|
57
|
+
|
58
|
+
CommitComment.post!(status.to_sym, report_file_name)
|
data/docs/run_qa_against_gdk.md
CHANGED
@@ -5,16 +5,18 @@ make a few changes to your `gdk/gitlab/config/gitlab.yml` file.
|
|
5
5
|
|
6
6
|
1. Retrieve your current local IP with `ifconfig`, e.g. `192.168.0.12`.
|
7
7
|
1. Create a file named `host` in your GDK directory containing your IP. E.g.:
|
8
|
-
`echo 192.168.0.12 > host`
|
9
|
-
1. Edit `gdk/gitlab/config/gitlab.yml` and
|
10
|
-
`host: 192.168.0.12`.
|
11
|
-
|
8
|
+
`echo "192.168.0.12" > host`
|
9
|
+
1. Edit `gdk/gitlab/config/gitlab.yml` and
|
10
|
+
- replace `host: localhost` under `production:gitlab` with `host: 192.168.0.12`.
|
11
|
+
- replace `ssh_host: localhost` under `production:gitlab_shell` with
|
12
12
|
`ssh_host: 192.168.0.12`.
|
13
|
-
|
14
|
-
`
|
15
|
-
1. Edit `
|
13
|
+
- replace `host: localhost` under `production:webpack:dev_server` with
|
14
|
+
`host: 192.168.0.12`.
|
15
|
+
1. Edit `Procfile` in your GDK directory and
|
16
|
+
- enable the `sshd` service by uncommenting the relevant line
|
17
|
+
1. Edit `openssh/sshd_config` in your GDK directory and
|
16
18
|
- set `ListenAddress` to `192.168.0.12:2222`
|
17
|
-
- add `AcceptEnv GIT_PROTOCOL` to allow use of [Git protocol v2][Git protocol]
|
19
|
+
- add `AcceptEnv GIT_PROTOCOL` to allow the use of the [Git protocol v2][Git protocol]
|
18
20
|
1. Restart your GDK
|
19
21
|
1. Run the QA scenario as follows:
|
20
22
|
|
@@ -36,6 +36,14 @@ For more details on the internals, please read the
|
|
36
36
|
* `GITLAB_QA_PASSWORD_1` - password for `GITLAB_QA_USERNAME_1` available in environments where signup is disabled (e.g. staging.gitlab.com)
|
37
37
|
* `GITLAB_QA_USERNAME_2` - another username available in environments where signup is disabled
|
38
38
|
* `GITLAB_QA_PASSWORD_2` - password for `GITLAB_QA_USERNAME_2` available in environments where signup is disabled (e.g. staging.gitlab.com)
|
39
|
+
* `GITLAB_QA_USERNAME_3` - another username available in environments where signup is disabled
|
40
|
+
* `GITLAB_QA_PASSWORD_3` - password for `GITLAB_QA_USERNAME_3` available in environments where signup is disabled (e.g. staging.gitlab.com)
|
41
|
+
* `GITLAB_QA_USERNAME_4` - another username available in environments where signup is disabled
|
42
|
+
* `GITLAB_QA_PASSWORD_4` - password for `GITLAB_QA_USERNAME_4` available in environments where signup is disabled (e.g. staging.gitlab.com)
|
43
|
+
* `GITLAB_QA_USERNAME_5` - another username available in environments where signup is disabled
|
44
|
+
* `GITLAB_QA_PASSWORD_5` - password for `GITLAB_QA_USERNAME_5` available in environments where signup is disabled (e.g. staging.gitlab.com)
|
45
|
+
* `GITLAB_QA_USERNAME_6` - another username available in environments where signup is disabled
|
46
|
+
* `GITLAB_QA_PASSWORD_6` - password for `GITLAB_QA_USERNAME_6` available in environments where signup is disabled (e.g. staging.gitlab.com)
|
39
47
|
* `GITLAB_LDAP_USERNAME` - LDAP username to use when signing into GitLab
|
40
48
|
* `GITLAB_LDAP_PASSWORD` - LDAP password to use when signing into GitLab
|
41
49
|
* `GITLAB_ADMIN_USERNAME` - Admin username to use when adding a license
|
data/gitlab-qa.gemspec
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
lib = File.expand_path('
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
3
|
require 'gitlab/qa/version'
|
4
4
|
|
@@ -20,11 +20,11 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
# Some dependencies are pinned, to prevent new cops from breaking the CI pipelines
|
22
22
|
spec.add_development_dependency 'climate_control', '~> 0.2'
|
23
|
-
spec.add_development_dependency 'gitlab-styles', '2.
|
23
|
+
spec.add_development_dependency 'gitlab-styles', '2.4.0'
|
24
24
|
spec.add_development_dependency 'pry', '~> 0.11'
|
25
25
|
spec.add_development_dependency 'rake', '~> 12.2'
|
26
26
|
spec.add_development_dependency 'rspec', '~> 3.7'
|
27
|
-
spec.add_development_dependency 'rubocop', '0.
|
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
30
|
end
|
data/lib/gitlab/qa.rb
CHANGED
@@ -64,6 +64,12 @@ module Gitlab
|
|
64
64
|
autoload :Elasticsearch, 'gitlab/qa/component/elasticsearch'
|
65
65
|
end
|
66
66
|
|
67
|
+
module Support
|
68
|
+
autoload :GetRequest, 'gitlab/qa/support/get_request'
|
69
|
+
autoload :DevEEQAImage, 'gitlab/qa/support/dev_ee_qa_image'
|
70
|
+
autoload :InvalidResponseError, 'gitlab/qa/support/invalid_response_error'
|
71
|
+
end
|
72
|
+
|
67
73
|
module Docker
|
68
74
|
autoload :Command, 'gitlab/qa/docker/command'
|
69
75
|
autoload :Engine, 'gitlab/qa/docker/engine'
|
@@ -97,6 +97,17 @@ module Gitlab
|
|
97
97
|
def start # rubocop:disable Metrics/AbcSize
|
98
98
|
ensure_configured!
|
99
99
|
|
100
|
+
if release.dev_gitlab_org?
|
101
|
+
Docker::Command.execute(
|
102
|
+
[
|
103
|
+
'login',
|
104
|
+
'--username gitlab-qa-bot',
|
105
|
+
%(--password "#{Runtime::Env.dev_access_token_variable}"),
|
106
|
+
Release::DEV_REGISTRY
|
107
|
+
]
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
100
111
|
docker.run(image, tag) do |command|
|
101
112
|
command << "-d -p #{port}"
|
102
113
|
command << "--name #{name}"
|
@@ -18,6 +18,17 @@ module Gitlab
|
|
18
18
|
def perform # rubocop:disable Metrics/AbcSize
|
19
19
|
raise ArgumentError unless [suite, release].all?
|
20
20
|
|
21
|
+
if release.dev_gitlab_org?
|
22
|
+
Docker::Command.execute(
|
23
|
+
[
|
24
|
+
'login',
|
25
|
+
'--username gitlab-qa-bot',
|
26
|
+
%(--password "#{Runtime::Env.dev_access_token_variable}"),
|
27
|
+
Release::DEV_REGISTRY
|
28
|
+
]
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
21
32
|
puts "Running test suite `#{suite}` for #{release.project_name}"
|
22
33
|
|
23
34
|
name = "#{release.project_name}-qa-#{SecureRandom.hex(4)}"
|
@@ -8,19 +8,9 @@ module Gitlab
|
|
8
8
|
class Staging
|
9
9
|
ADDRESS = 'https://staging.gitlab.com'.freeze
|
10
10
|
|
11
|
-
class InvalidResponseError < StandardError
|
12
|
-
attr_reader :response
|
13
|
-
|
14
|
-
def initialize(address, response)
|
15
|
-
@response = response
|
16
|
-
|
17
|
-
super "Invalid response received from #{address}"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
11
|
def self.release
|
22
12
|
Release.new(image)
|
23
|
-
rescue InvalidResponseError => ex
|
13
|
+
rescue Support::InvalidResponseError => ex
|
24
14
|
warn ex.message
|
25
15
|
warn "#{ex.response.code} #{ex.response.message}: #{ex.response.body}"
|
26
16
|
exit 1
|
@@ -40,7 +30,7 @@ module Gitlab
|
|
40
30
|
# - https://gitlab.com/gitlab-org/quality/staging/issues/56
|
41
31
|
# - https://gitlab.com/gitlab-org/release/framework/issues/421
|
42
32
|
# - https://gitlab.com/gitlab-org/gitlab-qa/issues/398
|
43
|
-
DevEEQAImage.new.retrieve_image_from_container_registry!(staging_revision)
|
33
|
+
Support::DevEEQAImage.new.retrieve_image_from_container_registry!(staging_revision)
|
44
34
|
else
|
45
35
|
# Auto-deploy builds have a tag formatted like 12.0.12345+5159f2949cb.59c9fa631
|
46
36
|
# but the version api returns a semver version like 12.0.1
|
@@ -84,88 +74,13 @@ module Gitlab
|
|
84
74
|
private
|
85
75
|
|
86
76
|
def api_get!
|
87
|
-
@response_body ||=
|
77
|
+
@response_body ||= # rubocop:disable Naming/MemoizedInstanceVariableName
|
88
78
|
begin
|
89
|
-
response = GetRequest.new(uri, Runtime::Env.qa_access_token).execute!
|
79
|
+
response = Support::GetRequest.new(uri, Runtime::Env.qa_access_token).execute!
|
90
80
|
JSON.parse(response.body)
|
91
81
|
end
|
92
82
|
end
|
93
83
|
end
|
94
|
-
|
95
|
-
class DevEEQAImage
|
96
|
-
attr_reader :base_url
|
97
|
-
|
98
|
-
DEV_ADDRESS = 'https://dev.gitlab.org'.freeze
|
99
|
-
GITLAB_EE_QA_REPOSITORY_ID = 55
|
100
|
-
QAImageNotFoundError = Class.new(StandardError)
|
101
|
-
|
102
|
-
def initialize
|
103
|
-
@base_url = "#{DEV_ADDRESS}/api/v4/projects/gitlab%2Fomnibus-gitlab/registry/repositories/#{GITLAB_EE_QA_REPOSITORY_ID}/tags?per_page=100"
|
104
|
-
|
105
|
-
Runtime::Env.require_qa_dev_access_token!
|
106
|
-
end
|
107
|
-
|
108
|
-
def retrieve_image_from_container_registry!(revision)
|
109
|
-
request_url = base_url
|
110
|
-
|
111
|
-
begin
|
112
|
-
response = api_get!(URI.parse(request_url))
|
113
|
-
tags = JSON.parse(response.body)
|
114
|
-
|
115
|
-
matching_qa_image_tag = find_matching_qa_image_tag(tags, revision)
|
116
|
-
return matching_qa_image_tag['location'] if matching_qa_image_tag
|
117
|
-
|
118
|
-
request_url = next_page_url_from_response(response)
|
119
|
-
end while request_url
|
120
|
-
|
121
|
-
raise QAImageNotFoundError, "No `gitlab-ee-qa` image could be found for the revision `#{revision}`."
|
122
|
-
end
|
123
|
-
|
124
|
-
private
|
125
|
-
|
126
|
-
def api_get!(uri)
|
127
|
-
GetRequest.new(uri, Runtime::Env.qa_dev_access_token).execute!
|
128
|
-
end
|
129
|
-
|
130
|
-
def next_page_url_from_response(response)
|
131
|
-
response['x-next-page'].to_s != '' ? "#{base_url}&page=#{response['x-next-page']}" : nil
|
132
|
-
end
|
133
|
-
|
134
|
-
def find_matching_qa_image_tag(tags, revision)
|
135
|
-
tags.find { |tag| tag['name'].end_with?(revision) }
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
class GetRequest
|
140
|
-
attr_reader :uri, :token
|
141
|
-
|
142
|
-
def initialize(uri, token)
|
143
|
-
@uri = uri
|
144
|
-
@token = token
|
145
|
-
end
|
146
|
-
|
147
|
-
def execute!
|
148
|
-
response =
|
149
|
-
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
150
|
-
http.request(build_request)
|
151
|
-
end
|
152
|
-
|
153
|
-
case response
|
154
|
-
when Net::HTTPSuccess
|
155
|
-
response
|
156
|
-
else
|
157
|
-
raise InvalidResponseError.new(uri.to_s, response)
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
private
|
162
|
-
|
163
|
-
def build_request
|
164
|
-
Net::HTTP::Get.new(uri).tap do |req|
|
165
|
-
req['PRIVATE-TOKEN'] = token
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
84
|
end
|
170
85
|
end
|
171
86
|
end
|
data/lib/gitlab/qa/release.rb
CHANGED
@@ -20,6 +20,21 @@ module Gitlab
|
|
20
20
|
(:(?<tag>.+))?
|
21
21
|
\z
|
22
22
|
}xi
|
23
|
+
|
24
|
+
# Dev tag example:
|
25
|
+
# 12.1.201906121026-325a6632895.b340d0bd35d
|
26
|
+
# |----|------------|-----------|-----------|
|
27
|
+
# | | | |
|
28
|
+
# | | | omnibus-ref
|
29
|
+
# | | gitlab-ee ref
|
30
|
+
# | timestamp
|
31
|
+
# version
|
32
|
+
DEV_TAG_REGEX = /
|
33
|
+
\A
|
34
|
+
(?<version>\d+\.\d+(.\d+)?)\.(?<timestamp>\d+)\-(?<gitlab_ref>[A-Za-z0-9]+)\.(?<omnibus_ref>[A-Za-z0-9]+)
|
35
|
+
\z
|
36
|
+
/xi
|
37
|
+
|
23
38
|
DEFAULT_TAG = 'latest'.freeze
|
24
39
|
DEFAULT_CANONICAL_TAG = 'nightly'.freeze
|
25
40
|
DEV_REGISTRY = 'dev.gitlab.org:5005'.freeze
|
@@ -98,7 +113,11 @@ module Gitlab
|
|
98
113
|
|
99
114
|
# Tag scheme for gitlab-{ce,ee}-qa images is like 11.1.0-rc12-ee
|
100
115
|
def qa_tag
|
101
|
-
tag.
|
116
|
+
if dev_gitlab_org? && (match_data = tag.match(DEV_TAG_REGEX))
|
117
|
+
"#{match_data[:version]}-#{match_data[:gitlab_ref]}"
|
118
|
+
else
|
119
|
+
tag.sub(/[-\.]([ce]e)(\.(\d+))?\z/, '-\1')
|
120
|
+
end
|
102
121
|
end
|
103
122
|
|
104
123
|
def dev_gitlab_org?
|
@@ -18,17 +18,6 @@ module Gitlab
|
|
18
18
|
|
19
19
|
args.unshift(release_name) if release_name&.start_with?('--')
|
20
20
|
|
21
|
-
if release.dev_gitlab_org?
|
22
|
-
Docker::Command.execute(
|
23
|
-
[
|
24
|
-
'login',
|
25
|
-
'--username gitlab-qa-bot',
|
26
|
-
%(--password "#{Runtime::Env.dev_access_token_variable}"),
|
27
|
-
Release::DEV_REGISTRY
|
28
|
-
]
|
29
|
-
)
|
30
|
-
end
|
31
|
-
|
32
21
|
Component::Specs.perform do |specs|
|
33
22
|
specs.suite = 'Test::Instance::All'
|
34
23
|
specs.release = release
|
@@ -6,7 +6,6 @@ module Gitlab
|
|
6
6
|
module Test
|
7
7
|
module Integration
|
8
8
|
class ObjectStorage < Scenario::Template
|
9
|
-
# rubocop:disable Metrics/AbcSize
|
10
9
|
def perform(release, *rspec_args)
|
11
10
|
Component::Gitlab.perform do |gitlab|
|
12
11
|
gitlab.release = release
|
@@ -41,7 +40,6 @@ module Gitlab
|
|
41
40
|
end
|
42
41
|
end
|
43
42
|
end
|
44
|
-
# rubocop:enable Metrics/AbcSize
|
45
43
|
end
|
46
44
|
end
|
47
45
|
end
|