dri 0.10.2 → 1.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 +4 -4
- data/.gitlab/changelog_config.yml +13 -0
- data/.gitlab/merge_request_templates/Default.md +27 -0
- data/.gitlab/merge_request_templates/Release.md +8 -23
- data/.gitlab-ci.yml +6 -4
- data/.rubocop.yml +9 -1
- data/.ruby-version +1 -1
- data/.tool-versions +1 -1
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile.lock +58 -32
- data/README.md +88 -113
- data/dri.gemspec +9 -4
- data/exe/dri +2 -1
- data/faq.yaml +7 -7
- data/lefthook.yml +24 -0
- data/lib/dri/api_client.rb +66 -25
- data/lib/dri/cli.rb +2 -11
- data/lib/dri/command.rb +21 -52
- data/lib/dri/commands/add/fast_quarantine.rb +72 -0
- data/lib/dri/commands/add.rb +45 -0
- data/lib/dri/commands/analyze/stack_traces.rb +1 -4
- data/lib/dri/commands/analyze.rb +0 -1
- data/lib/dri/commands/faq.rb +1 -2
- data/lib/dri/commands/fetch/failures.rb +102 -43
- data/lib/dri/commands/fetch/{featureflags.rb → feature_flags.rb} +1 -6
- data/lib/dri/commands/fetch/pipelines.rb +3 -7
- data/lib/dri/commands/fetch/runbooks.rb +1 -3
- data/lib/dri/commands/fetch/testcases.rb +1 -3
- data/lib/dri/commands/fetch/triaged.rb +2 -6
- data/lib/dri/commands/fetch.rb +0 -30
- data/lib/dri/commands/incidents.rb +2 -6
- data/lib/dri/commands/init.rb +1 -3
- data/lib/dri/commands/profile.rb +3 -5
- data/lib/dri/commands/publish/report.rb +24 -26
- data/lib/dri/commands/publish.rb +0 -1
- data/lib/dri/commands/rm/emoji.rb +1 -3
- data/lib/dri/commands/rm/profile.rb +1 -2
- data/lib/dri/commands/rm/reports.rb +1 -2
- data/lib/dri/commands/rm.rb +0 -3
- data/lib/dri/commands/view/fast_quarantine.rb +25 -0
- data/lib/dri/commands/view.rb +22 -0
- data/lib/dri/feature_flag_report.rb +1 -3
- data/lib/dri/refinements/gitlab.rb +22 -0
- data/lib/dri/refinements/string.rb +19 -0
- data/lib/dri/report.rb +13 -55
- data/lib/dri/support/configuration.rb +62 -0
- data/lib/dri/support/influxdb_tools.rb +37 -0
- data/lib/dri/utils/constants.rb +2 -1
- data/lib/dri/utils/helpers.rb +15 -0
- data/lib/dri/version.rb +1 -1
- data/lib/dri.rb +8 -1
- metadata +96 -16
- data/lib/dri/commands/fetch/quarantines.rb +0 -55
- data/lib/dri/gitlab/issues.rb +0 -19
- data/lib/dri/refinements/truncate.rb +0 -15
data/lib/dri/commands/fetch.rb
CHANGED
@@ -14,7 +14,6 @@ module Dri
|
|
14
14
|
if options[:help]
|
15
15
|
invoke :help, ['featureflags']
|
16
16
|
else
|
17
|
-
require_relative 'fetch/featureflags'
|
18
17
|
Dri::Commands::Fetch::FeatureFlags.new(options).execute
|
19
18
|
end
|
20
19
|
end
|
@@ -26,7 +25,6 @@ module Dri
|
|
26
25
|
if options[:help]
|
27
26
|
invoke :help, ['triaged']
|
28
27
|
else
|
29
|
-
require_relative 'fetch/triaged'
|
30
28
|
Dri::Commands::Fetch::Triaged.new(options).execute
|
31
29
|
end
|
32
30
|
end
|
@@ -40,7 +38,6 @@ module Dri
|
|
40
38
|
if options[:help]
|
41
39
|
invoke :help, ['testcases']
|
42
40
|
else
|
43
|
-
require_relative 'fetch/testcases'
|
44
41
|
Dri::Commands::Fetch::Testcases.new(options).execute
|
45
42
|
end
|
46
43
|
end
|
@@ -48,8 +45,6 @@ module Dri
|
|
48
45
|
desc 'failures', 'Display failures opened on a given period.'
|
49
46
|
method_option :help, aliases: '-h', type: :boolean,
|
50
47
|
desc: 'Display usage information'
|
51
|
-
method_option :urgent, type: :boolean,
|
52
|
-
desc: 'Shows failures that quickly escalated'
|
53
48
|
method_option :sort_by, type: :string,
|
54
49
|
desc: 'Shows failures in specified order'
|
55
50
|
method_option :start_date, type: :string,
|
@@ -63,33 +58,10 @@ module Dri
|
|
63
58
|
if options[:help]
|
64
59
|
invoke :help, ['failures']
|
65
60
|
else
|
66
|
-
require_relative 'fetch/failures'
|
67
61
|
Dri::Commands::Fetch::Failures.new(options).execute
|
68
62
|
end
|
69
63
|
end
|
70
64
|
|
71
|
-
desc 'quarantines', 'Display open quarantine MRs'
|
72
|
-
method_option :help, aliases: '-h', type: :boolean,
|
73
|
-
desc: 'Display usage information'
|
74
|
-
def quarantines(*)
|
75
|
-
if options[:help]
|
76
|
-
invoke :help, ['quarantines']
|
77
|
-
else
|
78
|
-
require_relative 'fetch/quarantines'
|
79
|
-
Dri::Commands::Fetch::Quarantines.new(options, search: '[QUARANTINE]').execute
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
desc 'dequarantines', 'Display open dequarantine MRs'
|
84
|
-
method_option :help, aliases: '-h', type: :boolean,
|
85
|
-
desc: 'Display usage information'
|
86
|
-
def dequarantines(*)
|
87
|
-
return invoke :help, %w[quarantines] if options[:help]
|
88
|
-
|
89
|
-
require_relative 'fetch/quarantines'
|
90
|
-
Dri::Commands::Fetch::Quarantines.new(options, search: '[DEQUARANTINE]').execute
|
91
|
-
end
|
92
|
-
|
93
65
|
desc 'pipelines', 'Display status of pipelines'
|
94
66
|
method_option :help, aliases: '-h', type: :boolean,
|
95
67
|
desc: 'Display pipelines usage information'
|
@@ -98,7 +70,6 @@ module Dri
|
|
98
70
|
def pipelines(*)
|
99
71
|
return invoke :help, %w[pipelines] if options[:help]
|
100
72
|
|
101
|
-
require_relative 'fetch/pipelines'
|
102
73
|
Dri::Commands::Fetch::Pipelines.new(options).execute
|
103
74
|
end
|
104
75
|
|
@@ -109,7 +80,6 @@ module Dri
|
|
109
80
|
def runbooks(*args)
|
110
81
|
return invoke :help, %w[runbooks] if options[:help]
|
111
82
|
|
112
|
-
require_relative 'fetch/runbooks'
|
113
83
|
Dri::Commands::Fetch::Runbooks.new(options).execute(folder: args.first)
|
114
84
|
end
|
115
85
|
end
|
@@ -1,21 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../command'
|
4
|
-
require_relative '../utils/table'
|
5
|
-
require_relative '../utils/constants'
|
6
|
-
|
7
3
|
module Dri
|
8
4
|
module Commands
|
9
5
|
class Incidents < Dri::Command
|
10
6
|
include Dri::Utils::Table
|
11
7
|
include Dri::Utils::Constants::Triage::Labels
|
12
|
-
using Refinements
|
8
|
+
using Refinements::String
|
13
9
|
|
14
10
|
def initialize(options)
|
15
11
|
@options = options
|
16
12
|
end
|
17
13
|
|
18
|
-
def execute(
|
14
|
+
def execute(_input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize
|
19
15
|
verify_config_exists
|
20
16
|
|
21
17
|
incident = add_color('Incident', :bright_yellow)
|
data/lib/dri/commands/init.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../command'
|
4
|
-
|
5
3
|
require "tty-font"
|
6
4
|
|
7
5
|
module Dri
|
@@ -14,7 +12,7 @@ module Dri
|
|
14
12
|
puts pastel.yellow(font.write("DRI"))
|
15
13
|
end
|
16
14
|
|
17
|
-
def execute(
|
15
|
+
def execute(_input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize
|
18
16
|
output.puts "🤖 Welcome to DRI 🤖\n"
|
19
17
|
|
20
18
|
logger.info "🔎 Scanning for existing configurations...\n"
|
data/lib/dri/commands/profile.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../command'
|
4
|
-
|
5
3
|
require 'tty-box'
|
6
4
|
|
7
5
|
module Dri
|
@@ -11,7 +9,7 @@ module Dri
|
|
11
9
|
@options = options
|
12
10
|
end
|
13
11
|
|
14
|
-
def execute(
|
12
|
+
def execute(_input: $stdin, output: $stdout)
|
15
13
|
if config.exist? && @options["edit"]
|
16
14
|
editor.open(config.source_file)
|
17
15
|
return
|
@@ -39,13 +37,13 @@ module Dri
|
|
39
37
|
|
40
38
|
def pretty_print_profile
|
41
39
|
<<~PROFILE
|
42
|
-
#{add_color('User:', :bright_cyan)} #{username}
|
40
|
+
#{add_color('User:', :bright_cyan)} #{username}#{' '}
|
43
41
|
#{add_color('Token:', :bright_cyan)} #{token}
|
44
42
|
#{add_color('OpsToken:', :bright_cyan)} #{ops_token}
|
45
43
|
#{add_color('Timezone:', :bright_cyan)} #{timezone}
|
46
44
|
#{add_color('Emoji:', :bright_cyan)} #{emoji}
|
47
45
|
#{add_color('Report Path:', :bright_cyan)} #{handover_report_path}
|
48
|
-
|
46
|
+
|
49
47
|
PROFILE
|
50
48
|
end
|
51
49
|
end
|
@@ -1,14 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../command'
|
4
|
-
require_relative '../../utils/markdown_lists'
|
5
|
-
require_relative '../../utils/constants'
|
6
|
-
require_relative '../../report'
|
7
|
-
require_relative '../../feature_flag_report'
|
8
|
-
|
9
3
|
require 'markdown-tables'
|
10
4
|
require 'fileutils'
|
11
5
|
require 'uri'
|
6
|
+
require 'date'
|
12
7
|
|
13
8
|
module Dri
|
14
9
|
module Commands
|
@@ -24,7 +19,7 @@ module Dri
|
|
24
19
|
@today_iso_format = Time.now.strftime('%Y-%m-%dT00:00:00Z')
|
25
20
|
end
|
26
21
|
|
27
|
-
def execute(
|
22
|
+
def execute(_input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
|
28
23
|
verify_config_exists
|
29
24
|
report = Dri::Report.new(config)
|
30
25
|
|
@@ -161,43 +156,34 @@ module Dri
|
|
161
156
|
logger.info 'Downloading the report... '
|
162
157
|
|
163
158
|
spinner.start
|
164
|
-
|
165
|
-
|
166
|
-
report_path = "#{handover_report_path.chomp('/')}/report-#{@date}-#{@time}.md"
|
167
|
-
|
168
|
-
File.open(report_path, 'a') do |out_file|
|
169
|
-
out_file.puts note
|
170
|
-
end
|
171
|
-
|
159
|
+
report_md = File.join(handover_report_path, "report-#{@date}-#{@time}.md")
|
160
|
+
File.write(report_md, note)
|
172
161
|
spinner.stop
|
173
162
|
|
174
163
|
output.puts "Done! ✅\n"
|
175
|
-
logger.success "Report is ready at: #{
|
164
|
+
logger.success "Report is ready at: #{report_md}"
|
176
165
|
exit 0
|
177
166
|
end
|
178
167
|
|
179
168
|
# sends note to the weekly triage report
|
180
169
|
issues = api_client.fetch_current_triage_issue
|
181
|
-
current_issue_iid = issues.
|
170
|
+
current_issue_iid = issues.iid
|
182
171
|
|
183
172
|
note_action = 'posted'
|
184
173
|
posted_note = nil
|
185
174
|
if @options[:update]
|
186
|
-
|
187
|
-
|
175
|
+
unless File.exist?(report_json_file)
|
176
|
+
return logger.warn("Update action requires initial publish to be executed first!")
|
177
|
+
end
|
178
|
+
|
179
|
+
report_json = JSON.parse(File.read(report_json_file))
|
188
180
|
posted_note = api_client.update_triage_report_note(
|
189
181
|
iid: current_issue_iid, note_id: report_json['id'], body: note
|
190
182
|
)
|
191
183
|
note_action = 'updated'
|
192
184
|
else
|
193
185
|
posted_note = api_client.post_triage_report_note(iid: current_issue_iid, body: note)
|
194
|
-
|
195
|
-
FileUtils.mkdir_p("#{Dir.pwd}/handover_reports/.tmp")
|
196
|
-
report_path = "handover_reports/.tmp/report-#{@date}.json"
|
197
|
-
|
198
|
-
File.open(report_path, 'w') do |out_file|
|
199
|
-
out_file.write(posted_note.to_h.to_json)
|
200
|
-
end
|
186
|
+
File.write(report_json_file, posted_note.to_h.to_json)
|
201
187
|
end
|
202
188
|
|
203
189
|
output.puts "Done! ✅\n"
|
@@ -208,6 +194,18 @@ module Dri
|
|
208
194
|
|
209
195
|
private
|
210
196
|
|
197
|
+
def report_json_file
|
198
|
+
@report_json ||= File.join(handover_tmp_dir, "report-#{@date}.json")
|
199
|
+
end
|
200
|
+
|
201
|
+
def handover_tmp_dir
|
202
|
+
@handover_tmp_dir ||= File.join(handover_report_path, ".tmp").tap { |dir| FileUtils.mkdir_p(dir) }
|
203
|
+
end
|
204
|
+
|
205
|
+
def handover_report_path
|
206
|
+
@handover_report_path ||= super.tap { |dir| FileUtils.mkdir_p(dir) }
|
207
|
+
end
|
208
|
+
|
211
209
|
def format_feature_flag_changes(env, changes, labels, format_type)
|
212
210
|
unless format_type == :table || format_type == :list
|
213
211
|
raise ArgumentError, 'format_type must be one of type :table or :list'
|
data/lib/dri/commands/publish.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../command'
|
4
|
-
|
5
3
|
module Dri
|
6
4
|
module Commands
|
7
5
|
class Rm
|
@@ -10,7 +8,7 @@ module Dri
|
|
10
8
|
@options = options
|
11
9
|
end
|
12
10
|
|
13
|
-
def execute(
|
11
|
+
def execute(_input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize
|
14
12
|
verify_config_exists
|
15
13
|
|
16
14
|
remove = prompt.yes? "Are you sure you want to remove all #{emoji} award emojis from issues?"
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../command'
|
4
3
|
require 'fileutils'
|
5
4
|
|
6
5
|
module Dri
|
@@ -11,7 +10,7 @@ module Dri
|
|
11
10
|
@options = options
|
12
11
|
end
|
13
12
|
|
14
|
-
def execute(
|
13
|
+
def execute(*)
|
15
14
|
verify_config_exists
|
16
15
|
|
17
16
|
remove = prompt.yes? "Are you sure you want to remove existing profile?"
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../../command'
|
4
3
|
require 'fileutils'
|
5
4
|
|
6
5
|
module Dri
|
@@ -11,7 +10,7 @@ module Dri
|
|
11
10
|
@options = options
|
12
11
|
end
|
13
12
|
|
14
|
-
def execute(
|
13
|
+
def execute(*)
|
15
14
|
FileUtils.rm_rf(handover_report_path) if prompt.yes?("Remove everything in #{handover_report_path}?")
|
16
15
|
end
|
17
16
|
end
|
data/lib/dri/commands/rm.rb
CHANGED
@@ -14,7 +14,6 @@ module Dri
|
|
14
14
|
if options[:help]
|
15
15
|
invoke :help, ['profile']
|
16
16
|
else
|
17
|
-
require_relative 'rm/profile'
|
18
17
|
Dri::Commands::Rm::Profile.new(options).execute
|
19
18
|
end
|
20
19
|
end
|
@@ -26,7 +25,6 @@ module Dri
|
|
26
25
|
if options[:help]
|
27
26
|
invoke :help, ['reports']
|
28
27
|
else
|
29
|
-
require_relative 'rm/reports'
|
30
28
|
Dri::Commands::Rm::Reports.new(options).execute
|
31
29
|
end
|
32
30
|
end
|
@@ -38,7 +36,6 @@ module Dri
|
|
38
36
|
if options[:help]
|
39
37
|
invoke :help, ['emoji']
|
40
38
|
else
|
41
|
-
require_relative 'rm/emoji'
|
42
39
|
Dri::Commands::Rm::Emoji.new(options).execute
|
43
40
|
end
|
44
41
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dri
|
4
|
+
module Commands
|
5
|
+
class View
|
6
|
+
class FastQuarantine < Dri::Command
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute(*)
|
12
|
+
verify_config_exists
|
13
|
+
|
14
|
+
logger.info "Fetching fast quarantined tests..."
|
15
|
+
|
16
|
+
file_content = api_client.get_fast_quarantine_tests
|
17
|
+
|
18
|
+
file_content.each_line do |line|
|
19
|
+
puts "• #{line}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
module Dri
|
6
|
+
module Commands
|
7
|
+
class View < Thor
|
8
|
+
namespace :view
|
9
|
+
|
10
|
+
desc 'fastquarantine', 'View fast-quarantine tests'
|
11
|
+
method_option :help, aliases: '-h', type: :boolean,
|
12
|
+
desc: 'Display usage information'
|
13
|
+
def fastquarantine(*)
|
14
|
+
if options[:help]
|
15
|
+
invoke :help, ['fastquarantine']
|
16
|
+
else
|
17
|
+
Dri::Commands::View::FastQuarantine.new(options).execute
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative './utils/constants'
|
4
|
-
|
5
3
|
module Dri
|
6
4
|
class FeatureFlagReport
|
7
5
|
include Dri::Utils::Constants::FeatureFlag::Labels
|
@@ -26,7 +24,7 @@ module Dri
|
|
26
24
|
feature_flag_data = [summary, changed_on, url]
|
27
25
|
|
28
26
|
labels = feature_flag.labels
|
29
|
-
host_label = labels.select { |label| /^host::/.match(label) }.join
|
27
|
+
host_label = labels.select { |label| /^host::/.match(label) }.join
|
30
28
|
|
31
29
|
case host_label
|
32
30
|
when PRODUCTION
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Gitlab gem refinement for related merge requests
|
4
|
+
# TODO: Add method upstream (https://github.com/NARKOZ/gitlab/pull/683)
|
5
|
+
module Dri
|
6
|
+
module Refinements
|
7
|
+
module Gitlab
|
8
|
+
refine ::Gitlab::Client::Issues do
|
9
|
+
# List related merge requests
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# Gitlab.related_issue_merge_requests(3, 42)
|
13
|
+
#
|
14
|
+
# @param [Integer, String] project The ID or name of a project.
|
15
|
+
# @param [Integer] id The ID of an issue.
|
16
|
+
def related_issue_merge_requests(project, id)
|
17
|
+
get("/projects/#{url_encode project}/issues/#{id}/related_merge_requests")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dri
|
4
|
+
module Refinements
|
5
|
+
module String
|
6
|
+
refine ::String do
|
7
|
+
# Truncate string to limit of _n_ characters
|
8
|
+
# @param [Integer] limit the limit of characters
|
9
|
+
# @return [String] the resulting string after truncation
|
10
|
+
def truncate(limit = 50)
|
11
|
+
return freeze if size <= limit
|
12
|
+
|
13
|
+
# limit - 3 for the ellipses
|
14
|
+
self[0...(limit - 3)] << '...'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/dri/report.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative './utils/constants'
|
4
|
-
|
5
3
|
module Dri
|
6
4
|
class Report # rubocop:disable Metrics/ClassLength
|
7
5
|
include Dri::Utils::Constants::Triage::Labels
|
8
|
-
using Refinements
|
6
|
+
using Refinements::String
|
9
7
|
|
10
8
|
attr_reader :header, :failures, :labels, :labels_incidents, :incidents
|
11
9
|
|
@@ -63,66 +61,17 @@ module Dri
|
|
63
61
|
|
64
62
|
failure_type = filter_failure_type_labels(labels)
|
65
63
|
assigned_status = assigned?(failure["assignees"])
|
66
|
-
pipelines =
|
67
|
-
|
68
|
-
linked_pipelines = link_pipelines(project_id, iid, pipelines, description)
|
64
|
+
pipelines = format_pipelines(labels)
|
69
65
|
|
70
66
|
actions_status = actions_status_template(failure_type, assigned_status, actions_opts)
|
71
67
|
actions_fixes = actions_fixes_template(related_mrs)
|
72
68
|
|
73
|
-
@failures << [title, emojified_link,
|
69
|
+
@failures << [title, emojified_link, pipelines, stack_trace, "#{actions_status}#{actions_fixes}"]
|
74
70
|
end
|
75
71
|
|
76
72
|
private
|
77
73
|
|
78
|
-
def
|
79
|
-
linked = []
|
80
|
-
label_pipeline_map = {
|
81
|
-
'gitlab.com' => '/quality/production',
|
82
|
-
'canary.gitlab.com' => '/quality/canary',
|
83
|
-
'canary.staging.gitlab.com' => '/quality/staging-canary',
|
84
|
-
'main' => '/gitlab-org/gitlab-qa-mirror',
|
85
|
-
'master' => '/gitlab-org/gitlab-qa-mirror',
|
86
|
-
'pre.gitlab.com' => '/quality/preprod',
|
87
|
-
'staging-ref' => '/quality/staging-ref',
|
88
|
-
'staging.gitlab.com' => '/quality/staging',
|
89
|
-
'release' => '/quality/release'
|
90
|
-
}
|
91
|
-
|
92
|
-
failure_notes = @api_client.fetch_failure_notes(project_id, iid)
|
93
|
-
|
94
|
-
return if pipelines.empty?
|
95
|
-
|
96
|
-
pipelines.each do |pipeline|
|
97
|
-
next unless label_pipeline_map.has_key?(pipeline)
|
98
|
-
|
99
|
-
pipeline_in_notes_found = false
|
100
|
-
pipeline_link = ''
|
101
|
-
pipeline_markdown = pipeline.gsub(/.gitlab.com/, '')
|
102
|
-
|
103
|
-
failure_notes.each do |note|
|
104
|
-
next unless note.body.include?(label_pipeline_map.fetch(pipeline))
|
105
|
-
|
106
|
-
pipeline_in_notes_found = true
|
107
|
-
pipeline_link = URI.extract(note.body, %w[https])
|
108
|
-
end
|
109
|
-
|
110
|
-
unless pipeline_in_notes_found
|
111
|
-
links_description = URI.extract(description, %w[https])
|
112
|
-
pipeline_link = links_description.select { |link| link.include? label_pipeline_map.fetch(pipeline) }
|
113
|
-
end
|
114
|
-
|
115
|
-
unless pipeline_link.empty?
|
116
|
-
pipeline_link_sanitized = pipeline_link.join.strip
|
117
|
-
pipeline_markdown = "[#{pipeline_markdown}](#{pipeline_link_sanitized})"
|
118
|
-
end
|
119
|
-
|
120
|
-
linked << pipeline_markdown
|
121
|
-
end
|
122
|
-
linked.join(', ')
|
123
|
-
end
|
124
|
-
|
125
|
-
def actions_status_template(failure_type, assigned_status, actions_opts) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity/MethodLength
|
74
|
+
def actions_status_template(failure_type, assigned_status, actions_opts) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity/
|
126
75
|
quarantined = ''
|
127
76
|
reproduced = ''
|
128
77
|
transient = ''
|
@@ -184,6 +133,15 @@ module Dri
|
|
184
133
|
pipelines
|
185
134
|
end
|
186
135
|
|
136
|
+
def format_pipelines(labels)
|
137
|
+
labels.filter_map do |label|
|
138
|
+
next unless label.include?(FOUND)
|
139
|
+
|
140
|
+
sanitized_label = label.gsub(FOUND, ' ').strip
|
141
|
+
sanitized_label.gsub(/.gitlab.com/, '')
|
142
|
+
end.join(', ')
|
143
|
+
end
|
144
|
+
|
187
145
|
def filter_failure_type_labels(labels)
|
188
146
|
labels.each do |label|
|
189
147
|
@type = label.gsub!(FAILURE, ' ').to_s if label.include? FAILURE
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tzinfo"
|
4
|
+
require "tty-config"
|
5
|
+
|
6
|
+
module Dri
|
7
|
+
module Support
|
8
|
+
class Configuration
|
9
|
+
include Utils::Helpers
|
10
|
+
|
11
|
+
TZ = {
|
12
|
+
"AMER" => "America/New_York",
|
13
|
+
"EMEA" => "Europe/London",
|
14
|
+
"APAC" => "Asia/Tokyo"
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@config = TTY::Config.new do |conf|
|
19
|
+
conf.filename = ".dri_profile"
|
20
|
+
conf.extname = ".yml"
|
21
|
+
conf.append_path Dir.home
|
22
|
+
conf.append_path Dir.pwd
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :config
|
27
|
+
|
28
|
+
def profile
|
29
|
+
@profile ||= config.read
|
30
|
+
end
|
31
|
+
|
32
|
+
def emoji
|
33
|
+
@emoji ||= profile["settings"]["emoji"]
|
34
|
+
end
|
35
|
+
|
36
|
+
def username
|
37
|
+
@username ||= profile["settings"]["user"]
|
38
|
+
end
|
39
|
+
|
40
|
+
def token
|
41
|
+
@token ||= profile["settings"]["token"]
|
42
|
+
end
|
43
|
+
|
44
|
+
def ops_token
|
45
|
+
@ops_token ||= profile["settings"]["ops_token"]
|
46
|
+
end
|
47
|
+
|
48
|
+
def handover_report_path
|
49
|
+
@handover_report_path ||= profile["settings"]["handover_report_path"] || File.join(Dir.home,
|
50
|
+
".handover_reports")
|
51
|
+
end
|
52
|
+
|
53
|
+
def timezone
|
54
|
+
@timezone ||= profile["settings"]["timezone"]
|
55
|
+
end
|
56
|
+
|
57
|
+
def tz
|
58
|
+
@tz ||= TZInfo::Timezone.get(profile["settings"]["tz"] || TZ[timezone])
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dri
|
4
|
+
module Support
|
5
|
+
# Common tools for use with influxdb metrics setup
|
6
|
+
#
|
7
|
+
module InfluxdbTools
|
8
|
+
# @return [String] bucket for storing metrics from main runs
|
9
|
+
INFLUX_MAIN_TEST_METRICS_BUCKET = "e2e-test-stats-main"
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
# Query client
|
14
|
+
#
|
15
|
+
# @return [QueryApi]
|
16
|
+
def query_api
|
17
|
+
return nil unless influx_client
|
18
|
+
|
19
|
+
@query_api ||= influx_client.create_query_api
|
20
|
+
end
|
21
|
+
|
22
|
+
# InfluxDb client
|
23
|
+
#
|
24
|
+
# @return [InfluxDB2::Client]
|
25
|
+
def influx_client
|
26
|
+
return nil unless ENV["QA_INFLUXDB_URL"] && ENV["QA_INFLUXDB_TOKEN"]
|
27
|
+
|
28
|
+
@influx_client ||= InfluxDB2::Client.new(
|
29
|
+
ENV.fetch("QA_INFLUXDB_URL", nil),
|
30
|
+
ENV.fetch("QA_INFLUXDB_TOKEN", nil),
|
31
|
+
bucket: INFLUX_MAIN_TEST_METRICS_BUCKET,
|
32
|
+
org: "gitlab-qa"
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/dri/utils/constants.rb
CHANGED
@@ -11,13 +11,14 @@ module Dri
|
|
11
11
|
FEATURE_FLAG_LOG_PROJECT_ID = 15208716
|
12
12
|
INFRA_TEAM_PROD_PROJECT_ID = 7444821
|
13
13
|
RUNBOOKS_PROJECT_ID = 41045213
|
14
|
+
FAST_QUARANTINE_PROJECT_ID = 45427186
|
14
15
|
end
|
15
16
|
|
16
17
|
module Triage
|
17
18
|
module Labels
|
18
19
|
FOUND = 'found:'
|
19
20
|
FAILURE = 'failure::'
|
20
|
-
FAILURE_NEW = "#{FAILURE}new"
|
21
|
+
FAILURE_NEW = "#{FAILURE}new".freeze
|
21
22
|
QA = "QA"
|
22
23
|
INCIDENT = 'Incident::'
|
23
24
|
SERVICE = 'Service::'
|