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.
@@ -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
- report['status'] == 'pending'
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
@@ -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('-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|
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('-t', '--token ACCESS_TOKEN', String, 'A valid access token. Used by --report-in-issues') do |value|
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
- 'CI_JOB_ID' => :ci_job_id,
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.each_value do |accessor|
90
- send(:attr_accessor, accessor) # rubocop:disable GitlabSecurity/PublicSend
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 ci_project_name
126
- ENV['CI_PROJECT_NAME']
128
+ def ci_pipeline_url
129
+ ENV['CI_PIPELINE_URL']
127
130
  end
128
131
 
129
- def ci_slack_webhook_url
130
- ENV['CI_SLACK_WEBHOOK_URL']
132
+ def ci_pipeline_id
133
+ ENV['CI_PIPELINE_ID']
131
134
  end
132
135
 
133
- def pipeline_from_project_name
134
- ci_project_name.to_s.start_with?('gitlab-qa') ? 'master' : ci_project_name
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 slack_icon_emoji
142
- ENV['SLACK_ICON_EMOJI']
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
- rspec_args << "--" unless rspec_args.include?('--')
55
- rspec_args << %w[--tag gitaly_cluster]
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 < Scenario::Template
7
- # rubocop:disable Metrics/AbcSize
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
- gitlab.act do
23
- prepare
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
- # Restart GitLab with Praefect enabled and then run the tests
33
- Component::Gitlab.perform do |gitlab|
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 omnibus_config_with_praefect
16
+ def gitlab_omnibus_configuration
66
17
  <<~OMNIBUS
67
- gitaly['enable'] = true;
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/gitaly'
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
- git_data_dirs({
98
- 'default' => {
99
- 'gitaly_address' => 'tcp://localhost:2305'
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
- 'gitaly' => {
102
- 'path' => '/var/opt/gitlab/git-data/repositories/gitaly'
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
@@ -1,5 +1,5 @@
1
1
  module Gitlab
2
2
  module QA
3
- VERSION = '6.4.0'.freeze
3
+ VERSION = '6.8.0'.freeze
4
4
  end
5
5
  end