gitlab-qa 6.4.0 → 6.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +67 -3
- data/.gitlab/merge_request_templates/Release.md +1 -1
- data/.rubocop.yml +2 -0
- data/.rubocop_todo.yml +98 -0
- data/docs/what_tests_can_be_run.md +17 -0
- data/gitlab-qa.gemspec +3 -3
- data/lib/gitlab/qa.rb +4 -0
- data/lib/gitlab/qa/component/base.rb +1 -1
- data/lib/gitlab/qa/component/postgresql.rb +2 -1
- data/lib/gitlab/qa/docker/shellout.rb +1 -1
- data/lib/gitlab/qa/report/base_test_results.rb +6 -3
- data/lib/gitlab/qa/report/generate_test_session.rb +203 -0
- data/lib/gitlab/qa/report/gitlab_issue_client.rb +21 -7
- data/lib/gitlab/qa/report/gitlab_issue_dry_client.rb +28 -0
- data/lib/gitlab/qa/report/json_test_results.rb +2 -2
- data/lib/gitlab/qa/report/junit_test_results.rb +2 -2
- data/lib/gitlab/qa/report/relate_failure_issue.rb +139 -0
- data/lib/gitlab/qa/report/report_as_issue.rb +101 -3
- data/lib/gitlab/qa/report/results_in_issues.rb +16 -84
- data/lib/gitlab/qa/report/test_result.rb +22 -1
- data/lib/gitlab/qa/reporter.rb +30 -2
- data/lib/gitlab/qa/runtime/env.rb +34 -27
- data/lib/gitlab/qa/scenario/test/integration/actioncable.rb +36 -0
- data/lib/gitlab/qa/scenario/test/integration/gitaly_cluster.rb +7 -2
- data/lib/gitlab/qa/scenario/test/integration/praefect.rb +41 -84
- data/lib/gitlab/qa/version.rb +1 -1
- metadata +17 -12
@@ -19,6 +19,10 @@ module Gitlab
|
|
19
19
|
self.failures = failures_from_exceptions
|
20
20
|
end
|
21
21
|
|
22
|
+
def stage
|
23
|
+
@stage ||= file[%r{(?:api|browser_ui)/(?:(?:\d+_)?(\w+))}, 1]
|
24
|
+
end
|
25
|
+
|
22
26
|
def name
|
23
27
|
raise NotImplementedError
|
24
28
|
end
|
@@ -46,8 +50,16 @@ module Gitlab
|
|
46
50
|
report['file_path']
|
47
51
|
end
|
48
52
|
|
53
|
+
def status
|
54
|
+
report['status']
|
55
|
+
end
|
56
|
+
|
57
|
+
def ci_job_url
|
58
|
+
report['ci_job_url']
|
59
|
+
end
|
60
|
+
|
49
61
|
def skipped
|
50
|
-
|
62
|
+
status == 'pending'
|
51
63
|
end
|
52
64
|
|
53
65
|
def testcase
|
@@ -58,6 +70,14 @@ module Gitlab
|
|
58
70
|
report['testcase'] = new_testcase
|
59
71
|
end
|
60
72
|
|
73
|
+
def failure_issue
|
74
|
+
report['failure_issue']
|
75
|
+
end
|
76
|
+
|
77
|
+
def failure_issue=(new_failure_issue)
|
78
|
+
report['failure_issue'] = new_failure_issue
|
79
|
+
end
|
80
|
+
|
61
81
|
private
|
62
82
|
|
63
83
|
# rubocop:disable Metrics/AbcSize
|
@@ -71,6 +91,7 @@ module Gitlab
|
|
71
91
|
|
72
92
|
{
|
73
93
|
'message' => "#{exception['class']}: #{exception['message']}",
|
94
|
+
'message_lines' => exception['message_lines'],
|
74
95
|
'stacktrace' => "#{exception['message_lines'].join("\n")}\n#{exception['backtrace'].slice(0..spec_file_first_index).join("\n")}"
|
75
96
|
}
|
76
97
|
end
|
data/lib/gitlab/qa/reporter.rb
CHANGED
@@ -4,6 +4,7 @@ module Gitlab
|
|
4
4
|
module QA
|
5
5
|
class Reporter
|
6
6
|
# rubocop:disable Metrics/AbcSize
|
7
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
7
8
|
def self.invoke(args)
|
8
9
|
report_options = {}
|
9
10
|
slack_options = {}
|
@@ -21,11 +22,25 @@ module Gitlab
|
|
21
22
|
report_options[:input_files] = files if files
|
22
23
|
end
|
23
24
|
|
24
|
-
opts.on('-
|
25
|
+
opts.on('--relate-failure-issue FILES', String, 'Relate test failures to failure issues from RSpec JSON files') do |files|
|
26
|
+
report_options[:relate_failure_issue] = true
|
27
|
+
report_options[:input_files] = files if files
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on('--max-diff-ratio DIFF_RATO', Float, 'Max stacktrace diff ratio for QA failure issues detection. Used by with --relate-failure-issue') do |value|
|
31
|
+
report_options[:max_diff_ratio] = value
|
32
|
+
end
|
33
|
+
|
34
|
+
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 and --relate-failure-issue') do |value|
|
25
35
|
report_options[:project] = value
|
26
36
|
end
|
27
37
|
|
28
|
-
opts.on('-
|
38
|
+
opts.on('--generate-test-session FILES', String, 'Generate test session report') do |files|
|
39
|
+
report_options[:generate_test_session] = true
|
40
|
+
report_options[:input_files] = files if files
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on('-t', '--token ACCESS_TOKEN', String, 'A valid access token. Required by --report-in-issues and --relate-failure-issue') do |value|
|
29
44
|
report_options[:token] = value
|
30
45
|
end
|
31
46
|
|
@@ -45,6 +60,10 @@ module Gitlab
|
|
45
60
|
report_options[:files] = files
|
46
61
|
end
|
47
62
|
|
63
|
+
opts.on('--dry-run', "Perform a dry-run (don't create or update issues)") do |files|
|
64
|
+
report_options[:dry_run] = true
|
65
|
+
end
|
66
|
+
|
48
67
|
opts.on_tail('-v', '--version', 'Show the version') do
|
49
68
|
require 'gitlab/qa/version'
|
50
69
|
puts "#{$PROGRAM_NAME} : #{VERSION}"
|
@@ -63,10 +82,18 @@ module Gitlab
|
|
63
82
|
if report_options.delete(:prepare_stage_reports)
|
64
83
|
Gitlab::QA::Report::PrepareStageReports.new(**report_options).invoke!
|
65
84
|
|
85
|
+
elsif report_options.delete(:relate_failure_issue)
|
86
|
+
report_options[:token] = Runtime::TokenFinder.find_token!(report_options[:token])
|
87
|
+
Gitlab::QA::Report::RelateFailureIssue.new(**report_options).invoke!
|
88
|
+
|
66
89
|
elsif report_options.delete(:report_in_issues)
|
67
90
|
report_options[:token] = Runtime::TokenFinder.find_token!(report_options[:token])
|
68
91
|
Gitlab::QA::Report::ResultsInIssues.new(**report_options).invoke!
|
69
92
|
|
93
|
+
elsif report_options.delete(:generate_test_session)
|
94
|
+
report_options[:token] = Runtime::TokenFinder.find_token!(report_options[:token])
|
95
|
+
Gitlab::QA::Report::GenerateTestSession.new(**report_options).invoke!
|
96
|
+
|
70
97
|
elsif slack_options.delete(:post_to_slack)
|
71
98
|
Gitlab::QA::Slack::PostToSlack.new(**slack_options).invoke!
|
72
99
|
|
@@ -79,6 +106,7 @@ module Gitlab
|
|
79
106
|
exit 1
|
80
107
|
end
|
81
108
|
end
|
109
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
82
110
|
# rubocop:enable Metrics/AbcSize
|
83
111
|
end
|
84
112
|
end
|
@@ -62,7 +62,7 @@ module Gitlab
|
|
62
62
|
'KNAPSACK_TEST_FILE_PATTERN' => :knapsack_test_file_pattern,
|
63
63
|
'KNAPSACK_TEST_DIR' => :knapsack_test_dir,
|
64
64
|
'CI' => :ci,
|
65
|
-
'
|
65
|
+
'CI_JOB_URL' => :ci_job_url,
|
66
66
|
'CI_RUNNER_ID' => :ci_runner_id,
|
67
67
|
'CI_SERVER_HOST' => :ci_server_host,
|
68
68
|
'CI_SERVER_PERSONAL_ACCESS_TOKEN' => :ci_server_personal_access_token,
|
@@ -86,8 +86,15 @@ module Gitlab
|
|
86
86
|
'DEPLOY_VERSION' => :deploy_version
|
87
87
|
}.freeze
|
88
88
|
|
89
|
-
ENV_VARIABLES.
|
90
|
-
|
89
|
+
ENV_VARIABLES.each do |env_name, method_name|
|
90
|
+
attr_writer(method_name)
|
91
|
+
|
92
|
+
define_method(method_name) do
|
93
|
+
ENV[env_name] ||
|
94
|
+
if instance_variable_defined?("@#{method_name}")
|
95
|
+
instance_variable_get("@#{method_name}")
|
96
|
+
end
|
97
|
+
end
|
91
98
|
end
|
92
99
|
|
93
100
|
def gitlab_username
|
@@ -114,42 +121,38 @@ module Gitlab
|
|
114
121
|
ENV['CI_JOB_TOKEN']
|
115
122
|
end
|
116
123
|
|
117
|
-
def ci_job_url
|
118
|
-
ENV['CI_JOB_URL']
|
119
|
-
end
|
120
|
-
|
121
124
|
def ci_pipeline_source
|
122
125
|
ENV['CI_PIPELINE_SOURCE']
|
123
126
|
end
|
124
127
|
|
125
|
-
def
|
126
|
-
ENV['
|
128
|
+
def ci_pipeline_url
|
129
|
+
ENV['CI_PIPELINE_URL']
|
127
130
|
end
|
128
131
|
|
129
|
-
def
|
130
|
-
ENV['
|
132
|
+
def ci_pipeline_id
|
133
|
+
ENV['CI_PIPELINE_ID']
|
131
134
|
end
|
132
135
|
|
133
|
-
def
|
134
|
-
|
135
|
-
end
|
136
|
-
|
137
|
-
def slack_qa_channel
|
138
|
-
ENV['SLACK_QA_CHANNEL']
|
136
|
+
def ci_project_name
|
137
|
+
ENV['CI_PROJECT_NAME']
|
139
138
|
end
|
140
139
|
|
141
|
-
def
|
142
|
-
|
140
|
+
def pipeline_from_project_name
|
141
|
+
if ci_project_name.to_s.start_with?('gitlab-qa')
|
142
|
+
if ENV['TOP_UPSTREAM_SOURCE_JOB'].to_s.start_with?('https://ops.gitlab.net')
|
143
|
+
'staging-orchestrated'
|
144
|
+
else
|
145
|
+
'master'
|
146
|
+
end
|
147
|
+
else
|
148
|
+
ci_project_name
|
149
|
+
end
|
143
150
|
end
|
144
151
|
|
145
152
|
def run_id
|
146
153
|
@run_id ||= "gitlab-qa-run-#{Time.now.strftime('%Y-%m-%d-%H-%M-%S')}-#{SecureRandom.hex(4)}"
|
147
154
|
end
|
148
155
|
|
149
|
-
def qa_access_token
|
150
|
-
ENV['GITLAB_QA_ACCESS_TOKEN']
|
151
|
-
end
|
152
|
-
|
153
156
|
def dev_access_token_variable
|
154
157
|
env_value_if_defined('GITLAB_QA_DEV_ACCESS_TOKEN')
|
155
158
|
end
|
@@ -162,6 +165,14 @@ module Gitlab
|
|
162
165
|
ENV['GITLAB_QA_CONTAINER_REGISTRY_ACCESS_TOKEN']
|
163
166
|
end
|
164
167
|
|
168
|
+
def qa_issue_url
|
169
|
+
ENV['GITLAB_QA_ISSUE_URL']
|
170
|
+
end
|
171
|
+
|
172
|
+
def deploy_environment
|
173
|
+
ENV['DEPLOY_ENVIRONMENT'] || pipeline_from_project_name
|
174
|
+
end
|
175
|
+
|
165
176
|
def host_artifacts_dir
|
166
177
|
@host_artifacts_dir ||= File.join(ENV['QA_ARTIFACTS_DIR'] || '/tmp/gitlab-qa', Runtime::Env.run_id)
|
167
178
|
end
|
@@ -229,10 +240,6 @@ module Gitlab
|
|
229
240
|
enabled?(ENV['QA_SKIP_PULL'], default: false)
|
230
241
|
end
|
231
242
|
|
232
|
-
def gitlab_qa_formless_login_token
|
233
|
-
env_value_if_defined('GITLAB_QA_FORMLESS_LOGIN_TOKEN')
|
234
|
-
end
|
235
|
-
|
236
243
|
private
|
237
244
|
|
238
245
|
def enabled?(value, default: true)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module QA
|
3
|
+
module Scenario
|
4
|
+
module Test
|
5
|
+
module Integration
|
6
|
+
class Actioncable < Scenario::Template
|
7
|
+
def perform(release, *rspec_args)
|
8
|
+
Component::Gitlab.perform do |gitlab|
|
9
|
+
gitlab.release = QA::Release.new(release)
|
10
|
+
gitlab.name = 'gitlab-actioncable'
|
11
|
+
gitlab.network = 'test'
|
12
|
+
gitlab.omnibus_config = <<~OMNIBUS
|
13
|
+
actioncable['enable'] = true;
|
14
|
+
OMNIBUS
|
15
|
+
|
16
|
+
gitlab.instance do
|
17
|
+
puts "Running actioncable specs!"
|
18
|
+
|
19
|
+
rspec_args << "--" unless rspec_args.include?('--')
|
20
|
+
rspec_args << %w[--tag actioncable]
|
21
|
+
|
22
|
+
Component::Specs.perform do |specs|
|
23
|
+
specs.suite = 'Test::Instance::All'
|
24
|
+
specs.release = gitlab.release
|
25
|
+
specs.network = gitlab.network
|
26
|
+
specs.args = [gitlab.address, *rspec_args]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -15,6 +15,8 @@ module Gitlab
|
|
15
15
|
@database = 'postgres'
|
16
16
|
@spec_suite = 'Test::Instance::All'
|
17
17
|
@network = 'test'
|
18
|
+
@env = {}
|
19
|
+
@tag = 'gitaly_cluster'
|
18
20
|
end
|
19
21
|
|
20
22
|
# rubocop:disable Metrics/AbcSize
|
@@ -51,14 +53,17 @@ module Gitlab
|
|
51
53
|
gitlab.instance do
|
52
54
|
puts "Running Gitaly Cluster specs!"
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
+
if @tag
|
57
|
+
rspec_args << "--" unless rspec_args.include?('--')
|
58
|
+
rspec_args << "--tag" << @tag
|
59
|
+
end
|
56
60
|
|
57
61
|
Component::Specs.perform do |specs|
|
58
62
|
specs.suite = spec_suite
|
59
63
|
specs.release = gitlab.release
|
60
64
|
specs.network = gitlab.network
|
61
65
|
specs.args = [gitlab.address, *rspec_args]
|
66
|
+
specs.env = @env
|
62
67
|
end
|
63
68
|
end
|
64
69
|
end
|
@@ -3,105 +3,62 @@ module Gitlab
|
|
3
3
|
module Scenario
|
4
4
|
module Test
|
5
5
|
module Integration
|
6
|
-
class Praefect <
|
7
|
-
|
8
|
-
def perform(release, *rspec_args)
|
9
|
-
Docker::Volumes.new.with_temporary_volumes do |volumes|
|
10
|
-
# Create the Praefect database before enabling Praefect
|
11
|
-
Component::Gitlab.perform do |gitlab|
|
12
|
-
gitlab.release = QA::Release.new(release)
|
13
|
-
gitlab.name = 'gitlab'
|
14
|
-
gitlab.network = 'test'
|
15
|
-
gitlab.volumes = volumes
|
16
|
-
gitlab.exec_commands = [
|
17
|
-
'gitlab-psql -d template1 -c "CREATE DATABASE praefect_production OWNER gitlab"',
|
18
|
-
'mkdir -p /var/opt/gitlab/git-data/repositories/praefect',
|
19
|
-
'chown -R git:root /var/opt/gitlab/git-data/repositories'
|
20
|
-
]
|
6
|
+
class Praefect < GitalyCluster
|
7
|
+
attr_reader :gitlab_name, :spec_suite
|
21
8
|
|
22
|
-
|
23
|
-
|
24
|
-
start
|
25
|
-
reconfigure
|
26
|
-
process_exec_commands
|
27
|
-
wait_until_ready
|
28
|
-
teardown!
|
29
|
-
end
|
30
|
-
end
|
9
|
+
def initialize
|
10
|
+
super
|
31
11
|
|
32
|
-
|
33
|
-
|
34
|
-
gitlab.release = QA::Release.new(release)
|
35
|
-
gitlab.name = 'gitlab'
|
36
|
-
gitlab.network = 'test'
|
37
|
-
gitlab.volumes = volumes
|
38
|
-
gitlab.omnibus_config = omnibus_config_with_praefect
|
39
|
-
|
40
|
-
gitlab.act do
|
41
|
-
prepare_gitlab_omnibus_config
|
42
|
-
start
|
43
|
-
reconfigure
|
44
|
-
wait_until_ready
|
45
|
-
|
46
|
-
puts "Running Praefect specs!"
|
47
|
-
|
48
|
-
Component::Specs.perform do |specs|
|
49
|
-
specs.suite = 'Test::Instance::All'
|
50
|
-
specs.release = gitlab.release
|
51
|
-
specs.network = gitlab.network
|
52
|
-
specs.args = [gitlab.address, *rspec_args]
|
53
|
-
specs.env = { QA_PRAEFECT_REPOSITORY_STORAGE: 'default' }
|
54
|
-
end
|
55
|
-
|
56
|
-
teardown
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
12
|
+
@tag = nil
|
13
|
+
@env = { QA_PRAEFECT_REPOSITORY_STORAGE: 'default' }
|
60
14
|
end
|
61
|
-
# rubocop:enable Metrics/AbcSize
|
62
|
-
|
63
|
-
private
|
64
15
|
|
65
|
-
def
|
16
|
+
def gitlab_omnibus_configuration
|
66
17
|
<<~OMNIBUS
|
67
|
-
|
18
|
+
external_url 'http://#{@gitlab_name}.#{@network}';
|
19
|
+
|
20
|
+
git_data_dirs({
|
21
|
+
'default' => {
|
22
|
+
'gitaly_address' => 'tcp://#{@praefect_node_name}.#{@network}:2305',
|
23
|
+
'gitaly_token' => 'PRAEFECT_EXTERNAL_TOKEN'
|
24
|
+
},
|
25
|
+
'gitaly' => {
|
26
|
+
'gitaly_address' => 'tcp://#{@gitlab_name}.#{@network}:8075',
|
27
|
+
'path' => '/var/opt/gitlab/git-data'
|
28
|
+
}
|
29
|
+
});
|
68
30
|
gitaly['listen_addr'] = '0.0.0.0:8075';
|
69
31
|
gitaly['auth_token'] = 'secret-token';
|
70
32
|
gitaly['storage'] = [
|
71
|
-
{
|
72
|
-
'name' => 'praefect-gitaly-0',
|
73
|
-
'path' => '/var/opt/gitlab/git-data/repositories/praefect'
|
74
|
-
},
|
75
33
|
{
|
76
34
|
'name' => 'gitaly',
|
77
|
-
'path' => '/var/opt/gitlab/git-data/repositories
|
35
|
+
'path' => '/var/opt/gitlab/git-data/repositories'
|
78
36
|
}
|
79
37
|
];
|
80
|
-
praefect['enable'] = true;
|
81
|
-
praefect['listen_addr'] = '0.0.0.0:2305';
|
82
|
-
praefect['auth_token'] = 'secret-token';
|
83
|
-
praefect['virtual_storages'] = {
|
84
|
-
'default' => {
|
85
|
-
'praefect-gitaly-0' => {
|
86
|
-
'address' => 'tcp://localhost:8075',
|
87
|
-
'token' => 'secret-token',
|
88
|
-
'primary' => true
|
89
|
-
}
|
90
|
-
}
|
91
|
-
};
|
92
|
-
praefect['database_host'] = '/var/opt/gitlab/postgresql';
|
93
|
-
praefect['database_user'] = 'gitlab';
|
94
|
-
praefect['database_dbname'] = 'praefect_production';
|
95
|
-
praefect['postgres_queue_enabled'] = true;
|
96
38
|
gitlab_rails['gitaly_token'] = 'secret-token';
|
97
|
-
|
98
|
-
|
99
|
-
|
39
|
+
gitlab_shell['secret_token'] = 'GITLAB_SHELL_SECRET_TOKEN';
|
40
|
+
prometheus['scrape_configs'] = [
|
41
|
+
{
|
42
|
+
'job_name' => 'praefect',
|
43
|
+
'static_configs' => [
|
44
|
+
'targets' => [
|
45
|
+
'#{@praefect_node_name}.#{@network}:9652'
|
46
|
+
]
|
47
|
+
]
|
100
48
|
},
|
101
|
-
|
102
|
-
'
|
49
|
+
{
|
50
|
+
'job_name' => 'praefect-gitaly',
|
51
|
+
'static_configs' => [
|
52
|
+
'targets' => [
|
53
|
+
'#{@primary_node_name}.#{@network}:9236',
|
54
|
+
'#{@secondary_node_name}.#{@network}:9236',
|
55
|
+
'#{@tertiary_node_name}.#{@network}:9236'
|
56
|
+
]
|
57
|
+
]
|
103
58
|
}
|
104
|
-
|
59
|
+
];
|
60
|
+
grafana['disable_login_form'] = false;
|
61
|
+
grafana['admin_password'] = 'GRAFANA_ADMIN_PASSWORD';
|
105
62
|
OMNIBUS
|
106
63
|
end
|
107
64
|
end
|
data/lib/gitlab/qa/version.rb
CHANGED