dri 0.1.3 → 0.2.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.
@@ -1,44 +1,51 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../../command'
4
-
5
- require 'tty-table'
4
+ require_relative '../../utils/table'
6
5
 
7
6
  module Dri
8
7
  module Commands
9
8
  class Fetch
10
9
  class Quarantines < Dri::Command
10
+ include Dri::Utils::Table
11
11
  using Refinements
12
12
 
13
- def initialize(options)
13
+ def initialize(options, search: '[QUARANTINE]')
14
14
  @options = options
15
+ @search = search
16
+
15
17
  @today_iso_format = Time.now.strftime('%Y-%m-%dT00:00:00Z')
16
18
  end
17
19
 
18
20
  def execute(input: $stdin, output: $stdout)
19
21
  verify_config_exists
20
-
21
22
  title = add_color('Example name', :bright_yellow)
22
23
  url = add_color('URL', :bright_yellow)
23
24
 
24
25
  headers = [title, url]
25
26
  mrs = []
26
27
 
27
- logger.info 'Fetching Quarantine MRs...'
28
+ logger.info "Fetching #{@search} MRs..."
28
29
 
29
30
  spinner.run do
30
- response = api_client.fetch_mrs(project_id: 'gitlab-org/gitlab', labels: 'QA,Quality', search: '[QUARANTINE]', in: :title, state: :opened)
31
+ response = api_client.fetch_mrs(
32
+ project_id: 'gitlab-org/gitlab',
33
+ labels: 'QA,Quality',
34
+ search: @search,
35
+ in: :title,
36
+ state: :opened
37
+ )
31
38
 
32
39
  mrs = response.each_with_object([]) do |mr, found_mrs|
33
- title = mr['title'][13..] # remove the "[QUARANTINE] " prefix
40
+ title = mr['title'][13..].truncate(60) # remove the "[QUARANTINE] " prefix
34
41
  url = mr['web_url']
35
42
 
36
43
  found_mrs << [title, url]
37
44
  end
38
45
  end
39
46
 
40
- puts TTY::Table.new(headers, mrs).render(:ascii, resize: true, alignments: %i[left center])
41
- output.puts "Found #{mrs.size} open Quarantine MRs"
47
+ print_table(headers, mrs, alignments: [:left, :left])
48
+ output.puts "Found #{mrs.size} open #{@search} MRs"
42
49
  end
43
50
  end
44
51
  end
@@ -8,13 +8,22 @@ module Dri
8
8
  module Commands
9
9
  class Fetch
10
10
  class Testcases < Dri::Command
11
-
12
11
  def initialize(options)
13
12
  @options = options
14
- @available_pipelines = %w(main canary master nightly production staging-canary staging-orchestrated staging-ref staging)
13
+ @available_pipelines = %w[
14
+ main
15
+ canary
16
+ master
17
+ nightly
18
+ production
19
+ staging-canary
20
+ staging-orchestrated
21
+ staging-ref
22
+ staging
23
+ ]
15
24
  end
16
25
 
17
- def execute(input: $stdin, output: $stdout)
26
+ def execute(input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize
18
27
  verify_config_exists
19
28
 
20
29
  if @options[:filter_pipelines]
@@ -31,22 +40,20 @@ module Dri
31
40
 
32
41
  pipelines = @options[:filter_pipelines] ? filtered_pipelines : @available_pipelines
33
42
 
34
- if pipelines.empty?
35
- logger.error "No pipelines selected to continue to fetch testcases."
36
- end
43
+ logger.error "No pipelines selected to continue to fetch testcases." if pipelines.empty?
37
44
 
38
45
  pipelines.each do |pipeline|
39
46
  logger.info "Fetching failing testcases in #{pipeline}\n"
40
47
  response = api_client.fetch_failing_testcases(pipeline, state: 'opened')
41
-
48
+
42
49
  output.puts "♦♦♦♦♦ #{add_color(pipeline, :black, :on_white)}♦♦♦♦♦\n\n"
43
50
 
44
51
  response.each do |pipeline|
45
- output.puts "#{title_label} #{pipeline["title"]}\n#{url_label} #{pipeline["web_url"]}"
52
+ output.puts "#{title_label} #{pipeline['title']}\n#{url_label} #{pipeline['web_url']}"
46
53
  output.puts "#{divider}\n"
47
- end
54
+ end
48
55
  end
49
-
56
+
50
57
  spinner.stop
51
58
  end
52
59
  end
@@ -1,22 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../command'
2
- require 'tty-table'
4
+ require_relative '../../utils/table'
3
5
 
4
6
  module Dri
5
7
  module Commands
6
8
  class Fetch
7
9
  class Triaged < Dri::Command
10
+ include Dri::Utils::Table
11
+ using Refinements
12
+
8
13
  def initialize(options)
9
14
  @options = options
10
15
  end
11
16
 
12
- def execute(input: $stdin, output: $stdout)
17
+ def execute(input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize
13
18
  verify_config_exists
14
19
 
15
20
  title = add_color('Title', :magenta)
16
21
  url = add_color('URL', :magenta)
17
22
  type_label = add_color('Type', :magenta)
18
23
 
19
- table_labels = [ title, url, type_label ]
24
+ table_labels = [title, url, type_label]
20
25
  failures_triaged = []
21
26
 
22
27
  logger.info "Fetching your triaged failures..."
@@ -39,15 +44,12 @@ module Dri
39
44
  type = label.gsub!('failure::', ' ').to_s if label.include? "failure::"
40
45
  end
41
46
 
42
- labels = triaged["labels"]
43
-
44
47
  failures_triaged << [title, url, type]
45
48
  end
46
49
 
47
50
  spinner.stop
48
51
 
49
- table = TTY::Table.new(table_labels,failures_triaged)
50
- puts table.render(:ascii, resize: true, alignments: [:center, :center, :center])
52
+ print_table(table_labels, failures_triaged)
51
53
  end
52
54
  end
53
55
  end
@@ -7,6 +7,18 @@ module Dri
7
7
  class Fetch < Thor
8
8
  namespace :fetch
9
9
 
10
+ desc 'featureflags', 'Display feature flag changes for today'
11
+ method_option :help, aliases: '-h', type: :boolean,
12
+ desc: 'Display usage information'
13
+ def featureflags(*)
14
+ if options[:help]
15
+ invoke :help, ['featureflags']
16
+ else
17
+ require_relative 'fetch/featureflags'
18
+ Dri::Commands::Fetch::FeatureFlags.new(options).execute
19
+ end
20
+ end
21
+
10
22
  desc 'triaged', 'Command description...'
11
23
  method_option :help, aliases: '-h', type: :boolean,
12
24
  desc: 'Display usage information'
@@ -23,7 +35,7 @@ module Dri
23
35
  method_option :help, aliases: '-h', type: :boolean,
24
36
  desc: 'Display usage information'
25
37
  method_option :filter_pipelines, type: :boolean,
26
- desc: 'Filter by pipeline'
38
+ desc: 'Filter by pipeline'
27
39
  def testcases(*)
28
40
  if options[:help]
29
41
  invoke :help, ['testcases']
@@ -37,7 +49,7 @@ module Dri
37
49
  method_option :help, aliases: '-h', type: :boolean,
38
50
  desc: 'Display usage information'
39
51
  method_option :urgent, type: :boolean,
40
- desc: 'Shows failures that quickly escalated'
52
+ desc: 'Shows failures that quickly escalated'
41
53
  def failures(*)
42
54
  if options[:help]
43
55
  invoke :help, ['failures']
@@ -49,15 +61,25 @@ module Dri
49
61
 
50
62
  desc 'quarantines', 'Display open quarantine MRs'
51
63
  method_option :help, aliases: '-h', type: :boolean,
52
- desc: 'Display usage information'
64
+ desc: 'Display usage information'
53
65
  def quarantines(*)
54
66
  if options[:help]
55
67
  invoke :help, ['quarantines']
56
68
  else
57
69
  require_relative 'fetch/quarantines'
58
- Dri::Commands::Fetch::Quarantines.new(options).execute
70
+ Dri::Commands::Fetch::Quarantines.new(options, search: '[QUARANTINE]').execute
59
71
  end
60
72
  end
73
+
74
+ desc 'dequarantines', 'Display open dequarantine MRs'
75
+ method_option :help, aliases: '-h', type: :boolean,
76
+ desc: 'Display usage information'
77
+ def dequarantines(*)
78
+ return invoke :help, %w[quarantines] if options[:help]
79
+
80
+ require_relative 'fetch/quarantines'
81
+ Dri::Commands::Fetch::Quarantines.new(options, search: '[DEQUARANTINE]').execute
82
+ end
61
83
  end
62
84
  end
63
85
  end
@@ -10,11 +10,11 @@ module Dri
10
10
  def initialize(options)
11
11
  @options = options
12
12
 
13
- font = TTY::Font.new(:doom)
13
+ font = TTY::Font.new(:doom)
14
14
  puts pastel.yellow(font.write("DRI"))
15
15
  end
16
16
 
17
- def execute(input: $stdin, output: $stdout)
17
+ def execute(input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize
18
18
  output.puts "🤖 Welcome to DRI 🤖\n"
19
19
 
20
20
  logger.info "🔎 Scanning for existing configurations...\n"
@@ -22,14 +22,16 @@ module Dri
22
22
  if config.exist?
23
23
  overwrite = prompt.yes?("There is already a configuration initialized. Would you like to overwrite it?")
24
24
  unless overwrite
25
- output.puts "Using existing configuration. To view configuration in use try #{add_color('dri profile', :yellow)}."
25
+ output.puts(
26
+ "Using existing configuration. To view configuration in use try #{add_color('dri profile', :yellow)}."
27
+ )
26
28
  exit 0
27
29
  end
28
30
  end
29
31
 
30
32
  @username = prompt.ask("What is your GitLab username?")
31
33
  @token = prompt.mask("Please provide your GitLab personal access token:")
32
- @timezone = prompt.select("Choose your current timezone?", %w(EMEA AMER APAC))
34
+ @timezone = prompt.select("Choose your current timezone?", %w[EMEA AMER APAC])
33
35
  @emoji = prompt.ask("Have a triage emoji?")
34
36
 
35
37
  if (@emoji || @token || @username).nil?
@@ -43,7 +45,7 @@ module Dri
43
45
  config.set(:settings, :emoji, value: @emoji)
44
46
  config.write(force: true)
45
47
 
46
- logger.success "✅ We're ready to go 🚀"
48
+ logger.success "✅ We're ready to go 🚀"
47
49
  end
48
50
  end
49
51
  end
@@ -20,10 +20,15 @@ module Dri
20
20
  logger.info "🔎 Looking for profiles...\n"
21
21
 
22
22
  if config.exist?
23
- box = TTY::Box.frame(width: 30, height: 10, align: :center, padding: 1, title: {top_left: add_color('PROFILE:', :bright_cyan)}, border: :thick) do
24
- pretty_print_profile
25
- end
26
- print box
23
+ frame_args = {
24
+ width: 30,
25
+ height: 10,
26
+ align: :center,
27
+ padding: 1,
28
+ border: :thick,
29
+ title: { top_left: add_color('PROFILE:', :bright_cyan) }
30
+ }
31
+ output.print TTY::Box.frame(**frame_args) { pretty_print_profile.strip }
27
32
  output.puts "☝️ To modify this profile try passing #{add_color('dri profile --edit', :yellow)}.\n"
28
33
  else
29
34
  logger.error "Oops.. Profile not found. Try creating one using #{add_color('dri init', :yellow)}."
@@ -31,7 +36,11 @@ module Dri
31
36
  end
32
37
 
33
38
  def pretty_print_profile
34
- "#{add_color('User:', :bright_cyan)} #{username}\n #{add_color('Token:', :bright_cyan)} #{token}\n #{add_color('Timezone:', :bright_cyan)} #{timezone}\n #{add_color('Emoji:', :bright_cyan)} #{emoji}"
39
+ <<~PROFILE
40
+ #{add_color('User:', :bright_cyan)} #{username}\n #{add_color('Token:', :bright_cyan)} #{token}
41
+ #{add_color('Timezone:', :bright_cyan)} #{timezone}
42
+ #{add_color('Emoji:', :bright_cyan)} #{emoji}
43
+ PROFILE
35
44
  end
36
45
  end
37
46
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../command'
2
4
  require_relative '../../utils/markdown_lists'
3
5
  require_relative "../../report"
@@ -17,14 +19,14 @@ module Dri
17
19
  @time = Time.now.to_i
18
20
  end
19
21
 
20
- def execute(input: $stdin, output: $stdout)
22
+ def execute(input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
21
23
  verify_config_exists
22
24
  report = Dri::Report.new(config)
23
25
 
24
26
  logger.info "Fetching triaged failures with award emoji #{emoji}..."
25
27
 
26
28
  spinner.start
27
- issues = api_client.fetch_triaged_failures(emoji: emoji, state: 'opened')
29
+ issues = api_client.fetch_triaged_failures(emoji: emoji, state: 'opened')
28
30
  spinner.stop
29
31
 
30
32
  if issues.empty?
@@ -33,7 +35,7 @@ module Dri
33
35
  end
34
36
 
35
37
  logger.info "Assembling the report... "
36
- # sets each failure on the table
38
+ # sets each failure on the table
37
39
  action_options = ["pinged SET", "reproduced", "transient", "quarantined"]
38
40
 
39
41
  spinner.start
@@ -41,17 +43,27 @@ module Dri
41
43
  actions = []
42
44
 
43
45
  if @options[:actions]
44
- actions = prompt.multi_select("Please mark the actions on #{add_color(issue['title'], :yellow)}: ", action_options)
46
+ actions = prompt.multi_select(
47
+ "Please mark the actions on #{add_color(issue['title'], :yellow)}: ",
48
+ action_options
49
+ )
45
50
  end
51
+
46
52
  report.add_failure(issue, actions)
47
53
  end
48
54
 
49
55
  if @options[:format] == 'list'
50
56
  # generates markdown list with failures
51
57
  format_style = Utils::MarkdownLists.make_list(report.labels, report.failures) unless report.failures.empty?
52
- else
58
+ else
53
59
  # generates markdown table with rows as failures
54
- format_style = MarkdownTables.make_table(report.labels, report.failures, is_rows: true, align: %w[c l c l l]) unless report.failures.empty?
60
+ unless report.failures.empty?
61
+ format_style = MarkdownTables.make_table(
62
+ report.labels,
63
+ report.failures,
64
+ is_rows: true, align: %w[l l l l l]
65
+ )
66
+ end
55
67
  end
56
68
 
57
69
  report.set_header(timezone, username)
@@ -71,7 +83,7 @@ module Dri
71
83
  File.open(report_path, 'a') do |out_file|
72
84
  out_file.puts note
73
85
  end
74
-
86
+
75
87
  spinner.stop
76
88
 
77
89
  output.puts "Done! ✅\n"
@@ -82,10 +94,13 @@ module Dri
82
94
  # sends note to the weekly triage report
83
95
  issues = api_client.fetch_current_triage_issue
84
96
  current_issue_iid = issues[0]["iid"]
85
- response = api_client.post_triage_report_note(iid: current_issue_iid, body: note)
97
+
98
+ api_client.post_triage_report_note(iid: current_issue_iid, body: note)
86
99
 
87
100
  output.puts "Done! ✅\n"
88
- logger.success "Thanks @#{username}, your report was posted at https://gitlab.com/gitlab-org/quality/pipeline-triage/-/issues/#{current_issue_iid} 🎉"
101
+ logger.success(<<~MSG)
102
+ Thanks @#{username}, your report was posted at https://gitlab.com/gitlab-org/quality/pipeline-triage/-/issues/#{current_issue_iid} 🎉
103
+ MSG
89
104
  end
90
105
  end
91
106
  end
@@ -5,16 +5,15 @@ require 'thor'
5
5
  module Dri
6
6
  module Commands
7
7
  class Publish < Thor
8
-
9
8
  namespace :publish
10
9
 
11
10
  desc 'report', 'Generate a report'
12
11
  method_option :dry_run, type: :boolean,
13
- desc: 'Generates a report locally'
14
- method_option :format, aliases: '-f', type: :string, :default => "table",
15
- desc: 'Formats the report'
12
+ desc: 'Generates a report locally'
13
+ method_option :format, aliases: '-f', type: :string, default: "table",
14
+ desc: 'Formats the report'
16
15
  method_option :actions, type: :boolean,
17
- desc: 'Updates actions on failures'
16
+ desc: 'Updates actions on failures'
18
17
  def report(*)
19
18
  if options[:help]
20
19
  invoke :help, ['report']
@@ -10,9 +10,9 @@ module Dri
10
10
  @options = options
11
11
  end
12
12
 
13
- def execute(input: $stdin, output: $stdout)
13
+ def execute(input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize
14
14
  verify_config_exists
15
-
15
+
16
16
  remove = prompt.yes? "Are you sure you want to remove all #{emoji} award emojis from issues?"
17
17
 
18
18
  unless remove
@@ -29,7 +29,7 @@ module Dri
29
29
  spinner.stop
30
30
 
31
31
  issues_with_award_emoji.each do |issue|
32
- logger.info "Removing #{emoji} from #{issue["web_url"]}..."
32
+ logger.info "Removing #{emoji} from #{issue['web_url']}..."
33
33
 
34
34
  award_emoji_url = issue["_links"]["award_emoji"]
35
35
 
@@ -37,8 +37,8 @@ module Dri
37
37
 
38
38
  emoji_found = response.find { |e| e['name'] == emoji && e['user']['username'] == username }
39
39
 
40
- if !emoji_found.nil?
41
- url = "#{award_emoji_url}/#{emoji_found["id"]}"
40
+ unless emoji_found.nil?
41
+ url = "#{award_emoji_url}/#{emoji_found['id']}"
42
42
  api_client.delete_award_emoji(url)
43
43
  end
44
44
  end
@@ -13,7 +13,7 @@ module Dri
13
13
 
14
14
  def execute(input: $stdin, output: $stdout)
15
15
  verify_config_exists
16
-
16
+
17
17
  remove = prompt.yes? "Are you sure you want to remove existing profile?"
18
18
 
19
19
  unless remove
@@ -22,7 +22,7 @@ module Dri
22
22
  end
23
23
 
24
24
  logger.info "Removing profile..."
25
-
25
+
26
26
  FileUtils.rm("#{Dir.pwd}/.dri_profile.yml")
27
27
 
28
28
  logger.success "Done ✅"
@@ -5,7 +5,6 @@ require 'thor'
5
5
  module Dri
6
6
  module Commands
7
7
  class Rm < Thor
8
-
9
8
  namespace :rm
10
9
 
11
10
  desc 'profile', 'Command description...'
@@ -6,7 +6,7 @@ module Refinements
6
6
  # @param [Integer] limit the limit of characters
7
7
  # @return [String] the resulting string after truncation
8
8
  def truncate(limit = 50)
9
- return self.freeze if self.size <= limit
9
+ return freeze if size <= limit
10
10
 
11
11
  # limit - 3 for the ellipses
12
12
  self[0...(limit - 3)] << '...'