gitlab-qa 4.3.3 → 4.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -20,9 +20,6 @@ Metrics/MethodLength:
20
20
  Rails:
21
21
  Enabled: false
22
22
 
23
- Style/ExtendSelf:
24
- Enabled: false
25
-
26
23
  Style/ModuleFunction:
27
24
  Enabled: false
28
25
 
@@ -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)
@@ -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
- "The [`gitlab-qa` downstream pipeline](#{ENV['CI_PIPELINE_URL']}) #{status_with_icon}")
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[0].to_s.strip
46
- if status != ''
47
- CommitComment.post!(status.to_sym)
48
- else
49
- puts "Please provide a status!"
50
- end
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)
@@ -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 replace `host: localhost` with
10
- `host: 192.168.0.12`.
11
- 1. Also replace `ssh_host: localhost` (found under `gitlab_shell`) with
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
- 1. Enable the `sshd` service by uncommenting the relevant line in your
14
- `Procfile`.
15
- 1. Edit `openssh/sshd_config` and
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
@@ -1,4 +1,4 @@
1
- lib = File.expand_path('../lib', __FILE__)
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.2.0'
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.52.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
@@ -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
@@ -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.sub(/[-\.]([ce]e)(\.(\d+))?\z/, '-\1')
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
@@ -8,7 +8,6 @@ module Gitlab
8
8
 
9
9
  ##
10
10
  # rubocop:disable Lint/MissingCopEnableDirective
11
- # rubocop:disable Metrics/MethodLength
12
11
  # rubocop:disable Metrics/AbcSize
13
12
  #
14
13
  def perform(release, *rspec_args)
@@ -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