gitlab-qa 10.0.0 → 10.1.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: 14c426ca85861845164d12c2bfe65ba51aeb3791d383920ce872b9066f7d50ca
4
- data.tar.gz: 33e80bd2dd23bc1949018fe46f70bb892fecf0a9789f0365e0ccef6c01334267
3
+ metadata.gz: d3d71c9b26ee6da1b637bd155fc3dca98e47f739435802737110b8c76273068f
4
+ data.tar.gz: 4ede3accf59fadf7ba32c05cb49e0ba53eb3e9c809aa4c0978edb650e04ae529
5
5
  SHA512:
6
- metadata.gz: 560b02f9b0a4321cb1b7be3c1e482f73a306b4c171bcc0bff4c6527fdd9fdabd68fb33ee042a4033cd047f3a23e8e5d84ae8017936ed6885cfd1de0c0c3eb646
7
- data.tar.gz: 149bfc867c9913c3af4865964e12ba21d96509eaf0d4c1feb2bcf8c19c3d7da1933a68fa790bb41724ae824f4090f818d4240d5562a532e1fd2461a50138d21c
6
+ metadata.gz: 70441f243143e6d241f91729d1f35ba1d1668438bbd61bfe534e616e501c989af6382606986fdf593043d2a70a7e7dd59c9d7af5ccf52f93245b29a32dcf2bb7
7
+ data.tar.gz: 00ecb2e2599f15295e57bfda8313b9312e780693ddc9015b344a21f25d7b0ece878789e9ee6772825617abe8ae7d262429082fe7884cc4c8e8f07ff99a5a6018
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- gitlab-qa (10.0.0)
4
+ gitlab-qa (10.1.0)
5
5
  activesupport (~> 6.1)
6
6
  gitlab (~> 4.18.0)
7
7
  http (~> 5.0)
@@ -23,8 +23,9 @@ module Gitlab
23
23
 
24
24
  MultipleIssuesFound = Class.new(StandardError)
25
25
 
26
- def initialize(max_diff_ratio: DEFAULT_MAX_DIFF_RATIO_FOR_DETECTION, **kwargs)
26
+ def initialize(system_logs: [], max_diff_ratio: DEFAULT_MAX_DIFF_RATIO_FOR_DETECTION, **kwargs)
27
27
  super
28
+ @system_logs = Dir.glob(system_logs)
28
29
  @max_diff_ratio = max_diff_ratio.to_f
29
30
  @issue_type = 'issue'
30
31
  @commented_issue_list = Set.new
@@ -217,7 +218,7 @@ module Gitlab
217
218
  stacktrace_match = stacktrace.match(regex)
218
219
 
219
220
  if stacktrace_match
220
- stacktrace_match[:stacktrace].gsub(/^\s*#.*$/, '').gsub(/^[[:space:]]+/, '').strip
221
+ stacktrace_match[:stacktrace].split('First happened in')[0].gsub(/^\s*#.*$/, '').gsub(/^[[:space:]]+/, '').strip
221
222
  else
222
223
  puts " => [DEBUG] Stacktrace doesn't match the expected regex (#{regex}):\n----------------\n#{stacktrace}\n----------------\n"
223
224
  end
@@ -252,10 +253,27 @@ module Gitlab
252
253
  "```\n#{full_stacktrace(test)}\n```",
253
254
  "First happened in #{test.ci_job_url}.",
254
255
  "Related test case: #{test.testcase}.",
255
- screenshot_section(test)
256
+ screenshot_section(test),
257
+ system_log_errors_section(test)
256
258
  ].join("\n\n")
257
259
  end
258
260
 
261
+ def system_log_errors_section(test)
262
+ correlation_id = test.failures.first['correlation_id']
263
+ section = ''
264
+
265
+ if @system_logs.any? && !correlation_id.nil?
266
+ section = SystemLogs::SystemLogsFormatter.new(
267
+ @system_logs,
268
+ correlation_id
269
+ ).system_logs_summary_markdown
270
+ end
271
+
272
+ puts " => No system logs or correlation id provided, skipping this section in issue description" if section.empty?
273
+
274
+ section
275
+ end
276
+
259
277
  def new_issue_labels(test)
260
278
  up_to_date_labels(test: test, new_labels: NEW_ISSUE_LABELS)
261
279
  end
@@ -128,7 +128,8 @@ module Gitlab
128
128
  {
129
129
  'message' => "#{exception['class']}: #{exception['message']}",
130
130
  'message_lines' => exception['message_lines'],
131
- 'stacktrace' => "#{format_message_lines(exception['message_lines'])}\n#{exception['backtrace'].slice(0..spec_file_first_index).join("\n")}"
131
+ 'stacktrace' => "#{format_message_lines(exception['message_lines'])}\n#{exception['backtrace'].slice(0..spec_file_first_index).join("\n")}",
132
+ 'correlation_id' => exception['correlation_id']
132
133
  }
133
134
  end
134
135
  end
@@ -7,6 +7,7 @@ module Gitlab
7
7
  class Reporter
8
8
  # rubocop:disable Metrics/AbcSize
9
9
  # rubocop:disable Metrics/PerceivedComplexity
10
+ # rubocop:disable Metrics/CyclomaticComplexity
10
11
  def self.invoke(args)
11
12
  report_options = {}
12
13
  slack_options = {}
@@ -65,6 +66,12 @@ module Gitlab
65
66
  slack_options[:message] = slack_options[:message] + "\n\n" + Gitlab::QA::Report::SummaryTable.create(input_files: files)
66
67
  end
67
68
 
69
+ opts.on('--include-system-log-errors FILES', String, 'Include errors from system logs in failure issues. To be used with --relate-failure-issue') do |files|
70
+ raise 'This option should be used with --relate-failure-issue.' unless report_options[:relate_failure_issue]
71
+
72
+ report_options[:system_logs] = files if files
73
+ end
74
+
68
75
  opts.on('--update-screenshot-path FILES', "Update the path to screenshots to container's host") do |files|
69
76
  report_options[:update_screenshot_path] = true
70
77
  report_options[:files] = files
@@ -116,6 +123,7 @@ module Gitlab
116
123
  exit 1
117
124
  end
118
125
  end
126
+ # rubocop:enable Metrics/CyclomaticComplexity
119
127
  # rubocop:enable Metrics/PerceivedComplexity
120
128
  # rubocop:enable Metrics/AbcSize
121
129
  end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Gitlab
6
+ module QA
7
+ module SystemLogs
8
+ module Finders
9
+ class JsonLogFinder
10
+ def initialize(base_path, file_path)
11
+ @base_path = base_path
12
+ @file_path = file_path
13
+ end
14
+
15
+ def find(correlation_id)
16
+ log_file_path = "#{@base_path}/#{@file_path}"
17
+ logs = []
18
+
19
+ if File.exist?(log_file_path) && !correlation_id.nil?
20
+ File.foreach(log_file_path) do |line|
21
+ begin
22
+ json_line = JSON.parse(line, symbolize_names: true)
23
+ rescue JSON::ParserError
24
+ Runtime::Logger.debug("JsonLogFinder#find attempted to parse invalid JSON: #{line}")
25
+
26
+ next
27
+ end
28
+
29
+ if (json_line[:correlation_id])&.casecmp?(correlation_id)
30
+ normalized_line = normalize_keys(json_line)
31
+ logs << new_log(normalized_line)
32
+ end
33
+ end
34
+ end
35
+
36
+ logs
37
+ end
38
+
39
+ def new_log(data)
40
+ raise 'abstract method new_log must be defined!'
41
+ end
42
+
43
+ private
44
+
45
+ def normalize_keys(json_line)
46
+ normalized_hash = {}
47
+
48
+ json_line.each_key do |old_key|
49
+ key_string = old_key.to_s
50
+
51
+ if key_string.include?('.')
52
+ normalized_key = key_string.tr('.', '_').to_sym
53
+ normalized_hash[normalized_key] = json_line[old_key]
54
+ else
55
+ normalized_hash[old_key] = json_line[old_key]
56
+ end
57
+ end
58
+
59
+ normalized_hash
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module SystemLogs
6
+ module Finders
7
+ module Rails
8
+ class ApiLogFinder < JsonLogFinder
9
+ def initialize(base_path, file_path = 'gitlab-rails/api_json.log')
10
+ super(base_path, file_path)
11
+ end
12
+
13
+ def new_log(data)
14
+ LogTypes::Rails::ApiLog.new(data)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module SystemLogs
6
+ module Finders
7
+ module Rails
8
+ class ApplicationLogFinder < JsonLogFinder
9
+ def initialize(base_path, file_path = 'gitlab-rails/application_json.log')
10
+ super(base_path, file_path)
11
+ end
12
+
13
+ def new_log(data)
14
+ LogTypes::Rails::ApplicationLog.new(data)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module SystemLogs
6
+ module Finders
7
+ module Rails
8
+ class ExceptionLogFinder < JsonLogFinder
9
+ def initialize(base_path, file_path = 'gitlab-rails/exceptions_json.log')
10
+ super(base_path, file_path)
11
+ end
12
+
13
+ def new_log(data)
14
+ LogTypes::Rails::ExceptionLog.new(data)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module SystemLogs
6
+ module Finders
7
+ module Rails
8
+ class GraphqlLogFinder < JsonLogFinder
9
+ def initialize(base_path, file_path = 'gitlab-rails/graphql_json.log')
10
+ super(base_path, file_path)
11
+ end
12
+
13
+ def new_log(data)
14
+ LogTypes::Rails::GraphqlLog.new(data)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module SystemLogs
6
+ module LogTypes
7
+ class Log
8
+ def initialize(name, data)
9
+ @name = name
10
+ @data = data
11
+ end
12
+
13
+ attr_reader :name, :data
14
+
15
+ def summary_fields
16
+ [
17
+ :severity,
18
+ :correlation_id,
19
+ :time,
20
+ :message
21
+ ]
22
+ end
23
+
24
+ def summary
25
+ summary = {}
26
+
27
+ summary_fields.each do |field|
28
+ value = data[field]
29
+ summary[field] = value unless value.nil?
30
+ end
31
+
32
+ summary
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module SystemLogs
6
+ module LogTypes
7
+ module Rails
8
+ class ApiLog < Log
9
+ include SharedFields::Exception
10
+ include SharedFields::Meta
11
+
12
+ def initialize(data)
13
+ super('Rails API', data)
14
+ end
15
+
16
+ def summary_fields
17
+ super.concat(
18
+ [
19
+ :method,
20
+ :path,
21
+ :status,
22
+ :params,
23
+ :api_error
24
+ ],
25
+ exception_fields,
26
+ meta_fields
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module SystemLogs
6
+ module LogTypes
7
+ module Rails
8
+ class ApplicationLog < Log
9
+ include SharedFields::Exception
10
+ include SharedFields::Meta
11
+
12
+ def initialize(data)
13
+ super('Rails Application', data)
14
+ end
15
+
16
+ def summary_fields
17
+ super.concat(
18
+ exception_fields,
19
+ meta_fields
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module SystemLogs
6
+ module LogTypes
7
+ module Rails
8
+ class ExceptionLog < Log
9
+ include SharedFields::Exception
10
+
11
+ def initialize(data)
12
+ super('Rails Exceptions', data)
13
+ end
14
+
15
+ def summary_fields
16
+ super.concat(exception_fields)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module SystemLogs
6
+ module LogTypes
7
+ module Rails
8
+ class GraphqlLog < Log
9
+ include SharedFields::Meta
10
+
11
+ def initialize(data)
12
+ super('Rails GraphQL', data)
13
+ end
14
+
15
+ def summary_fields
16
+ super.concat(
17
+ [
18
+ :operation_name,
19
+ :query_string,
20
+ :variables
21
+ ],
22
+ meta_fields
23
+ )
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module SystemLogs
6
+ module SharedFields
7
+ module Meta
8
+ def meta_fields
9
+ [
10
+ :meta_user,
11
+ :meta_project,
12
+ :meta_caller_id
13
+ ]
14
+ end
15
+ end
16
+
17
+ module Exception
18
+ def exception_fields
19
+ [
20
+ :exception_class,
21
+ :exception_message,
22
+ :exception_backtrace
23
+ ]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module SystemLogs
6
+ class SystemLogsFormatter
7
+ NUM_OF_LOG_SECTIONS = 4
8
+
9
+ def initialize(base_paths, correlation_id)
10
+ @base_paths = base_paths
11
+ @correlation_id = correlation_id
12
+ end
13
+
14
+ def system_logs_summary_markdown
15
+ log_sections = Array.new(NUM_OF_LOG_SECTIONS) { [] }
16
+
17
+ @base_paths.each do |base_path|
18
+ all_logs = [
19
+ Finders::Rails::ApiLogFinder.new(base_path).find(@correlation_id),
20
+ Finders::Rails::ExceptionLogFinder.new(base_path).find(@correlation_id),
21
+ Finders::Rails::ApplicationLogFinder.new(base_path).find(@correlation_id),
22
+ Finders::Rails::GraphqlLogFinder.new(base_path).find(@correlation_id)
23
+ ]
24
+
25
+ create_log_summary_sections!(all_logs, log_sections)
26
+ end
27
+
28
+ log_sections.prepend('### System Logs') unless log_sections.all?(&:empty?)
29
+ log_sections.join("\n").rstrip
30
+ end
31
+
32
+ private
33
+
34
+ def create_log_summary_sections!(all_logs, sections)
35
+ sections.zip(all_logs) do |section, logs|
36
+ unless logs.empty?
37
+ section_title = "\n#### #{logs.first.name}"
38
+ section.append(section_title) unless section.include?(section_title)
39
+ section.append(create_log_summaries(logs))
40
+ end
41
+ end
42
+ end
43
+
44
+ def create_log_summaries(logs)
45
+ section = []
46
+
47
+ logs.each do |log|
48
+ log_summary = <<~MARKDOWN.chomp
49
+ <details><summary>Click to expand</summary>
50
+
51
+ ```json
52
+ #{JSON.pretty_generate(log.summary)}
53
+ ```
54
+ </details>
55
+ MARKDOWN
56
+
57
+ section.append(log_summary)
58
+ end
59
+
60
+ section.join("\n\n")
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module QA
5
- VERSION = '10.0.0'
5
+ VERSION = '10.1.0'
6
6
  end
7
7
  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: 10.0.0
4
+ version: 10.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab Quality
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-04-07 00:00:00.000000000 Z
11
+ date: 2023-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -485,6 +485,18 @@ files:
485
485
  - lib/gitlab/qa/support/invalid_response_error.rb
486
486
  - lib/gitlab/qa/support/shell_command.rb
487
487
  - lib/gitlab/qa/support/shellout.rb
488
+ - lib/gitlab/qa/system_logs/finders/json_log_finder.rb
489
+ - lib/gitlab/qa/system_logs/finders/rails/api_log_finder.rb
490
+ - lib/gitlab/qa/system_logs/finders/rails/application_log_finder.rb
491
+ - lib/gitlab/qa/system_logs/finders/rails/exception_log_finder.rb
492
+ - lib/gitlab/qa/system_logs/finders/rails/graphql_log_finder.rb
493
+ - lib/gitlab/qa/system_logs/log_types/log.rb
494
+ - lib/gitlab/qa/system_logs/log_types/rails/api_log.rb
495
+ - lib/gitlab/qa/system_logs/log_types/rails/application_log.rb
496
+ - lib/gitlab/qa/system_logs/log_types/rails/exception_log.rb
497
+ - lib/gitlab/qa/system_logs/log_types/rails/graphql_log.rb
498
+ - lib/gitlab/qa/system_logs/shared_fields.rb
499
+ - lib/gitlab/qa/system_logs/system_logs_formatter.rb
488
500
  - lib/gitlab/qa/test_logger.rb
489
501
  - lib/gitlab/qa/version.rb
490
502
  - scripts/build-package-and-test-env