dri 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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...'
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Refinements
4
+ refine String do
5
+ # Truncate string to limit of _n_ characters
6
+ # @param [Integer] limit the limit of characters
7
+ # @return [String] the resulting string after truncation
8
+ def truncate(limit = 50)
9
+ return freeze if size <= limit
10
+
11
+ # limit - 3 for the ellipses
12
+ self[0...(limit - 3)] << '...'
13
+ end
14
+ end
15
+ end
data/lib/dri/report.rb CHANGED
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dri
2
- class Report
4
+ class Report # rubocop:disable Metrics/ClassLength
3
5
  attr_reader :header, :failures, :labels
4
6
 
5
7
  def initialize(config)
6
8
  @labels = ['Title', 'Issue', 'Pipelines', 'Stack Trace', 'Actions']
7
9
  @failures = []
8
10
  @date = Date.today
9
- @today = Date.today.strftime("%Y-%m-%d")
11
+ @today = Date.today.strftime("%Y-%m-%d")
10
12
  @weekday = Date.today.strftime("%A")
11
13
  @header = nil
12
14
 
@@ -19,20 +21,24 @@ module Dri
19
21
 
20
22
  def add_failure(failure, actions_opts = [])
21
23
  iid = failure["iid"]
22
- title = failure["title"]
24
+ title = format_title(failure["title"])
23
25
  link = failure["web_url"]
24
26
  labels = failure["labels"]
25
27
  created_at = failure["created_at"]
26
28
  assignees = failure["assignees"]
27
- award_emoji_url = failure["_links"]["award_emoji"]
28
29
  description = failure["description"]
29
30
 
30
31
  related_mrs = @api_client.fetch_related_mrs(issue_iid: iid)
31
32
  emoji = classify_failure_emoji(created_at)
32
33
  emojified_link = "#{emoji} #{link}"
33
-
34
- stack_blob = description.empty? ? "No stack trace found" : description.split("### Stack trace").last.gsub(/\n|`|!|\[|\]/, '').squeeze(" ")[0...250]
35
- stack_trace = ":link:[`#{stack_blob}...`](#{link + '#stack-trace'})"
34
+
35
+ stack_blob = if description.empty?
36
+ "No stack trace found"
37
+ else
38
+ description.split("### Stack trace").last.gsub(/\n|`|!|\[|\]/, '').squeeze(" ")[0...250]
39
+ end
40
+
41
+ stack_trace = ":link:[`#{stack_blob}...`](#{link}#stack-trace)"
36
42
 
37
43
  failure_type = filter_failure_type_labels(labels)
38
44
  assigned_status = assigned?(assignees)
@@ -40,21 +46,20 @@ module Dri
40
46
 
41
47
  linked_pipelines = link_pipelines(iid, pipelines, description)
42
48
 
43
- actions = ""
44
- actions.concat actions_status_template(failure_type, assigned_status, actions_opts)
45
- actions.concat actions_fixes_template(related_mrs)
49
+ actions_status = actions_status_template(failure_type, assigned_status, actions_opts)
50
+ actions_fixes = actions_fixes_template(related_mrs)
46
51
 
47
- @failures << [title, emojified_link, linked_pipelines, stack_trace, actions]
52
+ @failures << [title, emojified_link, linked_pipelines, stack_trace, "#{actions_status}#{actions_fixes}"]
48
53
  end
49
54
 
50
55
  private
51
56
 
52
- def link_pipelines(iid, pipelines, description)
57
+ def link_pipelines(iid, pipelines, description) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
53
58
  linked = []
54
59
  label_pipeline_map = {
55
60
  'gitlab.com' => '/quality/production',
56
61
  'canary.gitlab.com' => '/quality/canary',
57
- # 'canary.staging.gitlab.com' => '',
62
+ # 'canary.staging.gitlab.com' => '',
58
63
  'main' => '/gitlab-org/gitlab-qa-mirror',
59
64
  'master' => '/gitlab-org/gitlab-qa-mirror',
60
65
  'nightly' => '/quality/nightly',
@@ -66,34 +71,33 @@ module Dri
66
71
 
67
72
  failure_notes = @api_client.fetch_failure_notes(issue_iid: iid)
68
73
 
69
- return if pipelines.empty?
70
-
74
+ return if pipelines.empty?
75
+
71
76
  pipelines.each do |pipeline|
72
- next if !label_pipeline_map.has_key? pipeline
77
+ next unless label_pipeline_map.has_key?(pipeline)
73
78
 
74
79
  pipeline_in_notes_found = false
75
80
  pipeline_link = ''
76
- pipeline_link_sanitized = ''
77
- pipeline_markdown = ''
81
+ pipeline_markdown = pipeline.gsub(/.gitlab.com/, '')
78
82
 
79
83
  failure_notes.each do |note|
80
- if note["body"].include? label_pipeline_map.fetch(pipeline)
81
- pipeline_in_notes_found = true
82
- pipeline_link = URI.extract(note["body"], %w(https))
83
- break
84
- end
84
+ next unless note["body"].include?(label_pipeline_map.fetch(pipeline))
85
+
86
+ pipeline_in_notes_found = true
87
+ pipeline_link = URI.extract(note["body"], %w[https])
85
88
  end
86
-
89
+
87
90
  unless pipeline_in_notes_found
88
- links_description = URI.extract(description, %w(https))
89
- pipeline_link = links_description.select { |link| link.include? label_pipeline_map.fetch(pipeline) }
91
+ links_description = URI.extract(description, %w[https])
92
+ pipeline_link = links_description.select { |link| link.include? label_pipeline_map.fetch(pipeline) }
90
93
  end
91
94
 
92
- if !pipeline_link.empty?
95
+ unless pipeline_link.empty?
93
96
  pipeline_link_sanitized = pipeline_link.join.strip.chop
94
- pipeline_markdown = "[#{pipeline.gsub(/.gitlab.com/, '')}](#{pipeline_link_sanitized})"
95
- linked << pipeline_markdown
97
+ pipeline_markdown = "[#{pipeline_markdown}](#{pipeline_link_sanitized})"
96
98
  end
99
+
100
+ linked << pipeline_markdown
97
101
  end
98
102
  linked.join(', ')
99
103
  end
@@ -109,7 +113,7 @@ module Dri
109
113
  reproduced = '<li>[x] reproduced</li>' if actions_opts.include? 'reproduced'
110
114
  transient = '<li>[x] transient</li>' if actions_opts.include? 'transient'
111
115
 
112
- action_status = "<i>Status:</i><ul>"
116
+ action_status = ["<i>Status:</i><ul>"]
113
117
  action_status << "<li>#{failure_type}</li>"
114
118
  action_status << "</li><li>#{assigned_status}</li>"
115
119
  action_status << notified_set
@@ -117,28 +121,27 @@ module Dri
117
121
  action_status << reproduced
118
122
  action_status << transient
119
123
 
120
- action_status
124
+ action_status.join
121
125
  end
122
126
 
123
127
  def actions_fixes_template(related_mrs)
124
- actions_fixes_template = '<ul><i>Potential fixes:</i><br>'
125
- related_mrs.each do |mr|
126
- actions_fixes_template.concat "<li>[#{mr["title"]}](#{mr["web_url"]})</li>"
128
+ mrs = related_mrs.each_with_object(['<i>Potential fixes:</i><br>']) do |mr, fixes|
129
+ fixes << "<li>[#{mr['title']}](#{mr['web_url']})</li>"
127
130
  end
128
- actions_fixes_template.concat '</ul>'
129
- actions_fixes_template
131
+
132
+ "<ul>#{mrs.join}</ul>"
130
133
  end
131
134
 
132
135
  def assigned?(assignees)
133
- assignees.empty? ? 'Assigned :x:' : 'Assigned :white_check_mark:'
136
+ assignees.empty? ? 'Assigned :x:' : 'Assigned :white_check_mark:'
134
137
  end
135
138
 
136
139
  def filter_pipeline_labels(labels)
137
140
  pipelines = []
138
141
 
139
142
  labels.each do |label|
140
- matchers = { 'found:' => ' '}
141
-
143
+ matchers = { 'found:' => ' ' }
144
+
142
145
  if label.include? "found:"
143
146
  pipeline = label.gsub(/found:/) { |match| matchers[match] }
144
147
  pipelines << pipeline.strip
@@ -161,8 +164,20 @@ module Dri
161
164
  if created_at.include? @today
162
165
  new_failure_emoji
163
166
  else
164
- known_failure_emoji
167
+ known_failure_emoji
165
168
  end
166
169
  end
170
+
171
+ # Turns something like:
172
+ # Failure in browser_ui/3_create/merge_request/create_merge_request_spec.rb | Create a merge request
173
+ # into
174
+ # Failure&nbsp;in&nbsp;`browser_ui/3_create/merge_request/create_merge_request_spec.rb` | Create a merge request
175
+ def format_title(title)
176
+ path, desc = title.split('|')
177
+ path = "Failure in `#{path.strip}`" if path.delete_prefix!('Failure in ')
178
+ path = path.strip.gsub(' ', '&nbsp;') if desc
179
+
180
+ "#{path} | #{desc}"
181
+ end
167
182
  end
168
- end
183
+ end
@@ -1,20 +1,18 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Dri
3
4
  module Utils
4
5
  class MarkdownLists
5
6
  def self.make_list(labels, items)
6
- @list = ""
7
-
8
- @list.concat "<ul>"
9
- items.each do |item|
7
+ list = items.each_with_object([]) do |item, arr|
10
8
  item.zip(labels).each do |element, label|
11
- @list.concat "<li><b>#{label}</b>:<br> #{element}</li>"
9
+ arr << "<li><b>#{label}</b>:<br> #{element}</li>"
12
10
  end
13
- @list.concat "<hr>"
11
+ arr << "<hr>"
14
12
  end
15
- @list.concat "</ul>"
13
+
14
+ "<ul>#{list.join}</ul>"
16
15
  end
17
- @list
18
16
  end
19
17
  end
20
- end
18
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tty-table'
4
+
5
+ module Dri
6
+ module Utils
7
+ module Table
8
+ def print_table(headers, rows, alignments: [])
9
+ if alignments.empty?
10
+ (1..headers.size).each do
11
+ alignments.push(:center)
12
+ end
13
+ end
14
+
15
+ table = TTY::Table.new(headers, rows)
16
+ puts table.render(:ascii, resize: true, multiline: true, alignments: alignments)
17
+ end
18
+ end
19
+ end
20
+ end
data/lib/dri/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Dri
2
- VERSION = "0.1.1"
4
+ VERSION = "0.2.0"
3
5
  end
data/lib/dri.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "dri/version"
2
4
 
3
5
  module Dri
metadata CHANGED
@@ -1,85 +1,85 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dri
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab Quality
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-16 00:00:00.000000000 Z
11
+ date: 2022-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: tty-config
14
+ name: httparty
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.4.0
19
+ version: 0.20.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.4.0
26
+ version: 0.20.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: tty-font
28
+ name: json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.5'
33
+ version: 2.6.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.5'
40
+ version: 2.6.1
41
41
  - !ruby/object:Gem::Dependency
42
- name: tty-prompt
42
+ name: markdown-tables
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 0.23.1
47
+ version: 1.1.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 0.23.1
54
+ version: 1.1.1
55
55
  - !ruby/object:Gem::Dependency
56
- name: tty-spinner
56
+ name: pastel
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.9'
61
+ version: 0.8.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.9'
68
+ version: 0.8.0
69
69
  - !ruby/object:Gem::Dependency
70
- name: tty-table
70
+ name: thor
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 0.12.0
75
+ version: 1.0.1
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 0.12.0
82
+ version: 1.0.1
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: tty-box
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -95,19 +95,19 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.7.0
97
97
  - !ruby/object:Gem::Dependency
98
- name: tty-logger
98
+ name: tty-config
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 0.6.0
103
+ version: 0.4.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 0.6.0
110
+ version: 0.4.0
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: tty-editor
113
113
  requirement: !ruby/object:Gem::Requirement
@@ -123,75 +123,89 @@ dependencies:
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0.6'
125
125
  - !ruby/object:Gem::Dependency
126
- name: pastel
126
+ name: tty-font
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 0.8.0
131
+ version: '0.5'
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 0.8.0
138
+ version: '0.5'
139
139
  - !ruby/object:Gem::Dependency
140
- name: thor
140
+ name: tty-logger
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 1.0.1
145
+ version: 0.6.0
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 1.0.1
152
+ version: 0.6.0
153
153
  - !ruby/object:Gem::Dependency
154
- name: markdown-tables
154
+ name: tty-prompt
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: 1.1.1
159
+ version: 0.23.1
160
160
  type: :runtime
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: 1.1.1
166
+ version: 0.23.1
167
167
  - !ruby/object:Gem::Dependency
168
- name: json
168
+ name: tty-spinner
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
171
  - - "~>"
172
172
  - !ruby/object:Gem::Version
173
- version: 2.6.1
173
+ version: '0.9'
174
174
  type: :runtime
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
178
  - - "~>"
179
179
  - !ruby/object:Gem::Version
180
- version: 2.6.1
180
+ version: '0.9'
181
181
  - !ruby/object:Gem::Dependency
182
- name: httparty
182
+ name: tty-table
183
183
  requirement: !ruby/object:Gem::Requirement
184
184
  requirements:
185
185
  - - "~>"
186
186
  - !ruby/object:Gem::Version
187
- version: 0.20.0
187
+ version: 0.12.0
188
188
  type: :runtime
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
- version: 0.20.0
194
+ version: 0.12.0
195
+ - !ruby/object:Gem::Dependency
196
+ name: gitlab-styles
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: 7.0.0
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: 7.0.0
195
209
  - !ruby/object:Gem::Dependency
196
210
  name: rake
197
211
  requirement: !ruby/object:Gem::Requirement
@@ -221,34 +235,34 @@ dependencies:
221
235
  - !ruby/object:Gem::Version
222
236
  version: 3.10.0
223
237
  - !ruby/object:Gem::Dependency
224
- name: webmock
238
+ name: timecop
225
239
  requirement: !ruby/object:Gem::Requirement
226
240
  requirements:
227
241
  - - "~>"
228
242
  - !ruby/object:Gem::Version
229
- version: '3.5'
243
+ version: 0.9.1
230
244
  type: :development
231
245
  prerelease: false
232
246
  version_requirements: !ruby/object:Gem::Requirement
233
247
  requirements:
234
248
  - - "~>"
235
249
  - !ruby/object:Gem::Version
236
- version: '3.5'
250
+ version: 0.9.1
237
251
  - !ruby/object:Gem::Dependency
238
- name: timecop
252
+ name: webmock
239
253
  requirement: !ruby/object:Gem::Requirement
240
254
  requirements:
241
255
  - - "~>"
242
256
  - !ruby/object:Gem::Version
243
- version: 0.9.1
257
+ version: '3.5'
244
258
  type: :development
245
259
  prerelease: false
246
260
  version_requirements: !ruby/object:Gem::Requirement
247
261
  requirements:
248
262
  - - "~>"
249
263
  - !ruby/object:Gem::Version
250
- version: 0.9.1
251
- description:
264
+ version: '3.5'
265
+ description:
252
266
  email:
253
267
  - quality+dri@gitlab.com
254
268
  executables:
@@ -260,6 +274,9 @@ files:
260
274
  - ".gitignore"
261
275
  - ".gitlab-ci.yml"
262
276
  - ".rspec"
277
+ - ".rubocop.yml"
278
+ - ".ruby-version"
279
+ - ".tool-versions"
263
280
  - Gemfile
264
281
  - Gemfile.lock
265
282
  - LICENSE.txt
@@ -275,6 +292,8 @@ files:
275
292
  - lib/dri/command.rb
276
293
  - lib/dri/commands/fetch.rb
277
294
  - lib/dri/commands/fetch/failures.rb
295
+ - lib/dri/commands/fetch/featureflags.rb
296
+ - lib/dri/commands/fetch/quarantines.rb
278
297
  - lib/dri/commands/fetch/testcases.rb
279
298
  - lib/dri/commands/fetch/triaged.rb
280
299
  - lib/dri/commands/init.rb
@@ -285,14 +304,16 @@ files:
285
304
  - lib/dri/commands/rm/emoji.rb
286
305
  - lib/dri/commands/rm/profile.rb
287
306
  - lib/dri/commands/rm/reports.rb
307
+ - lib/dri/refinements/truncate.rb
288
308
  - lib/dri/report.rb
289
309
  - lib/dri/utils/markdown_lists.rb
310
+ - lib/dri/utils/table.rb
290
311
  - lib/dri/version.rb
291
312
  homepage: https://gitlab.com/gitlab-org/quality/dri
292
313
  licenses:
293
314
  - MIT
294
315
  metadata: {}
295
- post_install_message:
316
+ post_install_message:
296
317
  rdoc_options: []
297
318
  require_paths:
298
319
  - lib
@@ -300,7 +321,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
300
321
  requirements:
301
322
  - - ">="
302
323
  - !ruby/object:Gem::Version
303
- version: 2.5.0
324
+ version: 2.7.0
304
325
  required_rubygems_version: !ruby/object:Gem::Requirement
305
326
  requirements:
306
327
  - - ">="
@@ -308,7 +329,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
308
329
  version: '0'
309
330
  requirements: []
310
331
  rubygems_version: 3.1.6
311
- signing_key:
332
+ signing_key:
312
333
  specification_version: 4
313
334
  summary: CLI app to help triage GitLab QA pipelines
314
335
  test_files: []