dri 0.7.0 → 0.8.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: e6ee21fc2a0243e0850f7bab281b0611021807a1a4559e89433741b1faed40f2
4
- data.tar.gz: 5b97afcdbc1e1e9307b084eab6e2afddbff94556cc102f2b174a0dedc3f51c33
3
+ metadata.gz: 3b4a86b6e658b2426bfce682d92f34f1441a9a1812f0cc805088b8c250991d4d
4
+ data.tar.gz: 3cf2b62c9aa5b1ef8de5cd51f8fdd927fa5335c9a1299b4947ab162b8afe2526
5
5
  SHA512:
6
- metadata.gz: f5b54fee2e4f0d99d0d013d0c9a211306eda149dabb6c0cedf05ec0c5a92274dd4038377fc270b6185782ba2dfdbe5c2be6028136c77a4e77dceb21989a82894
7
- data.tar.gz: c2d5056697c04ea976e00db46f183cd716091e3681687ad369c6dc3c11dab7ecd5592022460948a19ce779da7b114c2c90c4ba3c712a0bfe6256524cf6859934
6
+ metadata.gz: 4d79cdc2db7e1f959fee5b80988516677455a1d18e151a300923b2d19a58f0bb4fc4342db5e3785c34b5ef4475655b37cb10ad8850e488429ab12cfd8ad03fb8
7
+ data.tar.gz: 5120e934a2e8a45a51b4328bf5a1ae3af1a55b19e42023e538f65c958bfad0a8810f89844b7f2ef40608d0c7233d64f652ba9f101cff37f203a900d940084771
data/.gitlab-ci.yml CHANGED
@@ -15,12 +15,12 @@
15
15
  - vendor/bundle
16
16
  policy: pull
17
17
  rules:
18
- - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
18
+ - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
19
19
  - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
20
20
 
21
21
  include:
22
22
  - project: gitlab-org/quality/pipeline-common
23
- ref: 0.15.1
23
+ ref: 1.2.3
24
24
  file:
25
25
  - /ci/gem-release.yml
26
26
  - /ci/ref-update.gitlab-ci.yml
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dri (0.7.0)
4
+ dri (0.8.0)
5
5
  amatch (~> 0.4.1)
6
6
  gitlab (~> 4.18)
7
7
  httparty (~> 0.20.0)
data/README.md CHANGED
@@ -156,12 +156,13 @@ $ dri publish report --format=table # formats the report in a table (default)
156
156
  $ dri publish report --dry-run # the report is only generated locally
157
157
  $ dri publish report --actions # activate the actions prompt for each failure
158
158
  $ dri publish report --feature-flags # includes a summary of the feature flag changes on each environment
159
+ $ dri publish report --update # update the report note if has already been posted
159
160
  ```
160
161
 
161
162
  **Note:** These options above can be combined like:
162
163
 
163
164
  ```shell
164
- $ dri publish report --format=list --dry-run --actions
165
+ $ dri publish report --format=list --dry-run --actions --update
165
166
  ```
166
167
 
167
168
  **Actions**
@@ -6,16 +6,16 @@ require "tty-config"
6
6
  require "cgi"
7
7
  require "gitlab"
8
8
 
9
+ require_relative './utils/constants'
10
+
9
11
  module Dri
10
12
  TokenNotProvidedError = Class.new(StandardError)
11
13
  class ApiClient # rubocop:disable Metrics/ClassLength
14
+ include Dri::Utils::Constants::ProjectIDs
15
+ include Dri::Utils::Constants::Triage::Labels
16
+
12
17
  API_URL = "https://gitlab.com/api/v4"
13
18
  OPS_API_URL = "https://ops.gitlab.net/api/v4"
14
- TESTCASES_PROJECT_ID = 11229385
15
- TRIAGE_PROJECT_ID = 15291320
16
- GITLAB_PROJECT_ID = 278964
17
- FEATURE_FLAG_LOG_PROJECT_ID = 15208716
18
- INFRA_TEAM_PROD_PROJECT_ID = 7444821
19
19
 
20
20
  def initialize(config, ops = false)
21
21
  @token = config.read.dig("settings", "token")
@@ -28,14 +28,31 @@ module Dri
28
28
  @ops_instance = ops
29
29
  end
30
30
 
31
- # Fetch triaged failures
31
+ # Fetch all triaged failures
32
32
  #
33
33
  # @param [String] emoji
34
34
  # @param [String] state
35
- # @return [Gitlab::ObjectifiedHash]
36
- def fetch_triaged_failures(emoji:, state:)
35
+ # @return [Array<Gitlab::ObjectifiedHash>]
36
+ def fetch_all_triaged_failures(emoji:, state:)
37
+ project_ids = [GITLAB_PROJECT_ID, CUSTOMERSDOT_PROJECT_ID]
38
+ failures = []
39
+
40
+ project_ids.each do |project_id|
41
+ failures += fetch_triaged_failures(project_id: project_id, emoji: emoji, state: state)
42
+ end
43
+
44
+ failures
45
+ end
46
+
47
+ # Fetch triaged failures for a given project
48
+ #
49
+ # @param [Integer] project_id
50
+ # @param [String] emoji
51
+ # @param [String] state
52
+ # @return [Array<Gitlab::ObjectifiedHash>]
53
+ def fetch_triaged_failures(project_id:, emoji:, state:)
37
54
  gitlab.issues(
38
- GITLAB_PROJECT_ID,
55
+ project_id,
39
56
  order_by: "updated_at",
40
57
  my_reaction_emoji: emoji,
41
58
  scope: "all",
@@ -61,7 +78,7 @@ module Dri
61
78
  # @param [Integer] issue_iid
62
79
  # @param [Integer] project_id
63
80
  # @return [Array<Gitlab::ObjectifiedHash>]
64
- def fetch_awarded_emojis(issue_iid, project_id: GITLAB_PROJECT_ID)
81
+ def fetch_awarded_emojis(issue_iid, project_id:)
65
82
  gitlab.award_emojis(project_id, issue_iid, "issue")
66
83
  end
67
84
 
@@ -76,14 +93,14 @@ module Dri
76
93
  labels: "#{pipeline}::failed",
77
94
  state: state,
78
95
  scope: "all",
79
- "not[labels]": "quarantine"
96
+ "not[labels]": QUARANTINE
80
97
  ).auto_paginate
81
98
  end
82
99
 
83
100
  # Fetch issues related to failing test cases
84
101
  #
85
102
  # @return [Array<Gitlab::ObjectifiedHash>]
86
- def fetch_test_failure_issues(labels: 'failure::new')
103
+ def fetch_test_failure_issues(labels: FAILURE_NEW)
87
104
  gitlab.issues(
88
105
  GITLAB_PROJECT_ID,
89
106
  labels: labels,
@@ -94,10 +111,11 @@ module Dri
94
111
 
95
112
  # Fetch related issue mrs
96
113
  #
114
+ # @param [Integer] project_id
97
115
  # @param [Integer] issue_iid
98
116
  # @return [Array<Gitlab::ObjectifiedHash>]
99
- def fetch_related_mrs(issue_iid)
100
- gitlab.related_issue_merge_requests(GITLAB_PROJECT_ID, issue_iid)
117
+ def fetch_related_mrs(project_id, issue_iid)
118
+ gitlab.related_issue_merge_requests(project_id, issue_iid)
101
119
  end
102
120
 
103
121
  # Fetch MRs
@@ -130,15 +148,42 @@ module Dri
130
148
  gitlab.create_issue_note(TRIAGE_PROJECT_ID, iid, body)
131
149
  end
132
150
 
133
- # Fetch new failures
151
+ # Update triage report note
152
+ #
153
+ # @param [Integer] iid
154
+ # @param [Integer] note_id
155
+ # @param [String] body
156
+ # @return [Gitlab::ObjectifiedHash]
157
+ def update_triage_report_note(iid:, note_id:, body:)
158
+ gitlab.edit_issue_note(TRIAGE_PROJECT_ID, iid, note_id, body)
159
+ end
160
+
161
+ # Fetch all new failures
162
+ #
163
+ # @param [String] date
164
+ # @param [String] state
165
+ # @return [Array<Gitlab::ObjectifiedHash>]
166
+ def fetch_all_new_failures(date:, state:)
167
+ project_ids = [GITLAB_PROJECT_ID, CUSTOMERSDOT_PROJECT_ID]
168
+ failures = []
169
+
170
+ project_ids.each do |project_id|
171
+ failures += fetch_new_failures(project_id: project_id, date: date, state: state)
172
+ end
173
+
174
+ failures
175
+ end
176
+
177
+ # Fetch new failures for a given project
134
178
  #
179
+ # @param [Integer] project_id
135
180
  # @param [String] date
136
181
  # @param [String] state
137
182
  # @return [Array<Gitlab::ObjectifiedHash>]
138
- def fetch_failures(date:, state:)
183
+ def fetch_new_failures(project_id:, date:, state:)
139
184
  gitlab.issues(
140
- GITLAB_PROJECT_ID,
141
- labels: "failure::new",
185
+ project_id,
186
+ labels: FAILURE_NEW,
142
187
  order_by: "updated_at",
143
188
  state: state,
144
189
  scope: "all",
@@ -149,10 +194,11 @@ module Dri
149
194
 
150
195
  # Fetch failure notes
151
196
  #
197
+ # @param [Integer] project_id
152
198
  # @param [Integer] issue_iid
153
199
  # @return [Array<Gitlab::ObjectifiedHash>]
154
- def fetch_failure_notes(issue_iid)
155
- gitlab.issue_notes(GITLAB_PROJECT_ID, issue_iid, per_page: 100).auto_paginate
200
+ def fetch_failure_notes(project_id, issue_iid)
201
+ gitlab.issue_notes(project_id, issue_iid, per_page: 100).auto_paginate
156
202
  end
157
203
 
158
204
  # Delete award emoji
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative '../../command'
4
4
  require_relative '../../utils/table'
5
+ require_relative '../../utils/constants'
5
6
  require 'amatch'
6
7
  require 'fileutils'
7
8
 
@@ -11,10 +12,11 @@ module Dri
11
12
  class StackTraces < Dri::Command
12
13
  include Amatch
13
14
  include Dri::Utils::Table
15
+ include Dri::Utils::Constants::Triage::Labels
14
16
 
15
17
  def initialize(options)
16
18
  @options = options
17
- @labels = options[:labels] || 'failure::new'
19
+ @labels = options[:labels] || FAILURE_NEW
18
20
  @similarity_score_threshold = options[:similarity_score_threshold] || 0.9
19
21
  end
20
22
 
@@ -29,7 +31,7 @@ module Dri
29
31
  logger.info "#{Time.now.utc} API response completed"
30
32
 
31
33
  if response.empty?
32
- logger.info 'There are no failure::new issues identified!'
34
+ logger.info "There are no #{FAILURE_NEW} issues identified!"
33
35
  exit 0
34
36
  end
35
37
 
@@ -2,12 +2,14 @@
2
2
 
3
3
  require_relative '../../command'
4
4
  require_relative '../../utils/table'
5
+ require_relative '../../utils/constants'
5
6
 
6
7
  module Dri
7
8
  module Commands
8
9
  class Fetch
9
10
  class Failures < Dri::Command
10
11
  include Dri::Utils::Table
12
+ include Dri::Utils::Constants::Triage::Labels
11
13
  using Refinements
12
14
 
13
15
  SORT_BY_OPTIONS = {
@@ -34,33 +36,34 @@ module Dri
34
36
  author = add_color('Author', :bright_yellow)
35
37
  url = add_color('URL', :bright_yellow)
36
38
 
37
- failures = []
39
+ sorted_failures = []
38
40
  labels = [title, triaged, environment, author, url]
39
41
  triaged_counter = 0
40
42
 
41
43
  logger.info "Fetching today's failures..."
42
44
 
43
45
  spinner.run do # rubocop:disable Metrics/BlockLength
44
- response = api_client.fetch_failures(date: @today_iso_format, state: 'opened')
46
+ failures = api_client.fetch_all_new_failures(date: @today_iso_format, state: 'opened')
45
47
 
46
- if response.empty?
48
+ if failures.empty?
47
49
  logger.info 'Life is great, there are no new failures today!'
48
50
  exit 0
49
51
  end
50
52
 
51
- response.each do |failure|
53
+ failures.each do |failure|
54
+ project_id = failure.project_id
52
55
  title = failure.title.truncate(60)
53
56
  author = failure.to_h.dig('author', 'username')
54
57
  url = failure.web_url
55
58
  triaged = add_color('x', :red)
56
- envs = failure.labels.select { |l| l.include?('found:') }.map do |l|
59
+ envs = failure.labels.select { |l| l.include?(FOUND) }.map do |l|
57
60
  env = l.split(':').last.gsub('.gitlab.com', '')
58
61
 
59
62
  env == 'gitlab.com' ? 'production' : env
60
63
  end
61
64
  urgent = urgent_environments.all? { |env| envs.include?(env) }
62
65
 
63
- emoji_awards = api_client.fetch_awarded_emojis(failure.iid).find do |e|
66
+ emoji_awards = api_client.fetch_awarded_emojis(failure.iid, project_id: project_id).find do |e|
64
67
  e.name == emoji && e.to_h.dig('user', 'username') == username
65
68
  end
66
69
 
@@ -70,26 +73,26 @@ module Dri
70
73
  end
71
74
 
72
75
  if @options[:urgent]
73
- failures << [title, triaged, envs.first, author, url] if urgent
76
+ sorted_failures << [title, triaged, envs.first, author, url] if urgent
74
77
  else
75
- failures << [title, triaged, envs.first, author, url]
78
+ sorted_failures << [title, triaged, envs.first, author, url]
76
79
  end
77
80
  end
78
81
 
79
- failures.sort_by! { |failure| failure[SORT_BY_OPTIONS[@options[:sort_by]&.to_sym || :environment]] }
82
+ sorted_failures.sort_by! { |failure| failure[SORT_BY_OPTIONS[@options[:sort_by]&.to_sym || :environment]] }
80
83
  end
81
84
 
82
85
  msg = if @options[:urgent]
83
86
  <<~MSG
84
- Found: #{failures.size} urgent failures, occurring in both canary.gitlab.com and canary.staging.gitlab.com.
87
+ Found: #{sorted_failures.size} urgent failures, occurring in both canary.gitlab.com and canary.staging.gitlab.com.
85
88
  MSG
86
89
  else
87
90
  <<~MSG
88
- Found: #{failures.size} failures, of these #{triaged_counter} have been triaged with a #{emoji}.
91
+ Found: #{sorted_failures.size} failures, of these #{triaged_counter} have been triaged with a #{emoji}.
89
92
  MSG
90
93
  end
91
94
 
92
- print_table(labels, failures, alignments: [:left, :center, :center, :left])
95
+ print_table(labels, sorted_failures, alignments: [:left, :center, :center, :left])
93
96
  output.puts(msg)
94
97
  end
95
98
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative '../../command'
4
4
  require_relative '../../utils/table'
5
- require_relative '../../utils/feature_flag_consts'
5
+ require_relative '../../utils/constants'
6
6
  require_relative '../../feature_flag_report'
7
7
 
8
8
  module Dri
@@ -10,7 +10,7 @@ module Dri
10
10
  class Fetch
11
11
  class FeatureFlags < Dri::Command
12
12
  include Dri::Utils::Table
13
- include Dri::Utils::FeatureFlagConsts
13
+ include Dri::Utils::Constants::FeatureFlag
14
14
 
15
15
  def initialize(options)
16
16
  @options = options
@@ -10,6 +10,7 @@ module Dri
10
10
  class Fetch
11
11
  class Pipelines < Dri::Command # rubocop:disable Metrics/ClassLength
12
12
  include Dri::Utils::Table
13
+ include Dri::Utils::Constants
13
14
  using Refinements
14
15
 
15
16
  NUM_OF_TESTS_LIVE_ENV = 1000
@@ -27,7 +28,7 @@ module Dri
27
28
  table_labels = define_table_labels
28
29
 
29
30
  spinner.run do
30
- Dri::Utils::Constants::PIPELINE_ENVIRONMENTS.each do |environment, details|
31
+ PIPELINE_ENVIRONMENTS.each do |environment, details|
31
32
  logger.info "Fetching last executed #{environment} pipeline"
32
33
  pipelines << fetch_pipeline(pipeline_name: environment.to_s, details: details)
33
34
  logger.info "Fetching complete for #{environment} ✓"
@@ -2,12 +2,14 @@
2
2
 
3
3
  require_relative '../../command'
4
4
  require_relative '../../utils/table'
5
+ require_relative '../../utils/constants'
5
6
 
6
7
  module Dri
7
8
  module Commands
8
9
  class Fetch
9
10
  class Quarantines < Dri::Command
10
11
  include Dri::Utils::Table
12
+ include Dri::Utils::Constants::Triage::Labels
11
13
  using Refinements
12
14
 
13
15
  def initialize(options, search: '[QUARANTINE]')
@@ -30,7 +32,7 @@ module Dri
30
32
  spinner.run do
31
33
  response = api_client.fetch_mrs(
32
34
  project_id: 'gitlab-org/gitlab',
33
- labels: 'QA,Quality',
35
+ labels: "#{QA},#{QUALITY}",
34
36
  search: @search,
35
37
  in: :title,
36
38
  state: :opened
@@ -2,12 +2,14 @@
2
2
 
3
3
  require_relative '../../command'
4
4
  require_relative '../../utils/table'
5
+ require_relative '../../utils/constants'
5
6
 
6
7
  module Dri
7
8
  module Commands
8
9
  class Fetch
9
10
  class Triaged < Dri::Command
10
11
  include Dri::Utils::Table
12
+ include Dri::Utils::Constants::Triage::Labels
11
13
  using Refinements
12
14
 
13
15
  def initialize(options)
@@ -27,21 +29,21 @@ module Dri
27
29
  logger.info "Fetching your triaged failures..."
28
30
  spinner.start
29
31
 
30
- response = api_client.fetch_triaged_failures(emoji: emoji, state: 'opened')
32
+ failures = api_client.fetch_all_triaged_failures(emoji: emoji, state: 'opened')
31
33
 
32
- if response.empty?
34
+ if failures.empty?
33
35
  logger.info "There are no failures triaged yet with #{add_color(emoji, :black, :on_white)}."
34
36
  exit 0
35
37
  end
36
38
 
37
- response.each do |triaged|
39
+ failures.each do |triaged|
38
40
  title = triaged["title"].truncate(70)
39
41
  url = triaged["web_url"]
40
42
  labels = triaged["labels"]
41
43
  type = ""
42
44
 
43
45
  labels.each do |label|
44
- type = label.gsub!('failure::', ' ').to_s if label.include? "failure::"
46
+ type = label.gsub!(FAILURE, ' ').to_s if label.include? FAILURE
45
47
  end
46
48
 
47
49
  failures_triaged << [title, url, type]
@@ -2,11 +2,13 @@
2
2
 
3
3
  require_relative '../command'
4
4
  require_relative '../utils/table'
5
+ require_relative '../utils/constants'
5
6
 
6
7
  module Dri
7
8
  module Commands
8
9
  class Incidents < Dri::Command
9
10
  include Dri::Utils::Table
11
+ include Dri::Utils::Constants::Triage::Labels
10
12
  using Refinements
11
13
 
12
14
  def initialize(options)
@@ -42,8 +44,8 @@ module Dri
42
44
  service = "N/A"
43
45
 
44
46
  labels.each do |label|
45
- status = label.gsub!('Incident::', ' ').to_s if label.include? "Incident::"
46
- service = label.gsub!('Service::', ' ').to_s if label.include? "Service::"
47
+ status = label.gsub!(INCIDENT, ' ').to_s if label.include? INCIDENT
48
+ service = label.gsub!(SERVICE, ' ').to_s if label.include? SERVICE
47
49
  end
48
50
 
49
51
  incidents << [title, service, status, url]
@@ -2,7 +2,7 @@
2
2
 
3
3
  require_relative '../../command'
4
4
  require_relative '../../utils/markdown_lists'
5
- require_relative '../../utils/feature_flag_consts'
5
+ require_relative '../../utils/constants'
6
6
  require_relative '../../report'
7
7
  require_relative '../../feature_flag_report'
8
8
 
@@ -14,7 +14,7 @@ module Dri
14
14
  module Commands
15
15
  class Publish
16
16
  class Report < Dri::Command # rubocop:disable Metrics/ClassLength
17
- include Dri::Utils::FeatureFlagConsts
17
+ include Dri::Utils::Constants::FeatureFlag
18
18
 
19
19
  def initialize(options)
20
20
  @options = options
@@ -32,13 +32,13 @@ module Dri
32
32
 
33
33
  spinner.start
34
34
 
35
- issues = api_client.fetch_triaged_failures(emoji: emoji, state: 'opened')
35
+ failures = api_client.fetch_all_triaged_failures(emoji: emoji, state: 'opened')
36
36
  incidents = api_client.fetch_triaged_incidents(emoji: emoji)
37
37
 
38
38
  spinner.stop
39
39
 
40
- if issues.empty? && incidents.empty?
41
- logger.warn "Found no issues nor incidents associated with \"#{emoji}\" emoji. Will exit. Bye 👋"
40
+ if failures.empty? && incidents.empty?
41
+ logger.warn "Found no failures nor incidents associated with \"#{emoji}\" emoji. Will exit. Bye 👋"
42
42
  exit 1
43
43
  end
44
44
 
@@ -58,18 +58,18 @@ module Dri
58
58
 
59
59
  spinner.start
60
60
 
61
- issues.each do |issue|
61
+ failures.each do |failure|
62
62
  actions = []
63
63
 
64
64
  if @options[:actions]
65
65
  actions = prompt.multi_select(
66
- "Please mark the actions on #{add_color(issue.title, :yellow)}: ",
66
+ "Please mark the actions on #{add_color(failure.title, :yellow)}: ",
67
67
  action_options,
68
68
  per_page: 9
69
69
  )
70
70
  end
71
71
 
72
- report.add_failure(issue, actions)
72
+ report.add_failure(failure, actions)
73
73
  end
74
74
 
75
75
  unless incidents.empty?
@@ -180,11 +180,29 @@ module Dri
180
180
  issues = api_client.fetch_current_triage_issue
181
181
  current_issue_iid = issues.first.iid
182
182
 
183
- api_client.post_triage_report_note(iid: current_issue_iid, body: note)
183
+ note_action = 'posted'
184
+ posted_note = nil
185
+ if @options[:update]
186
+ report_file = File.read("handover_reports/.tmp/report-#{@date}.json")
187
+ report_json = JSON.parse(report_file) if report_file
188
+ posted_note = api_client.update_triage_report_note(
189
+ iid: current_issue_iid, note_id: report_json['id'], body: note
190
+ )
191
+ note_action = 'updated'
192
+ else
193
+ 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
201
+ end
184
202
 
185
203
  output.puts "Done! ✅\n"
186
204
  logger.success(<<~MSG)
187
- Thanks @#{username}, your report was posted at https://gitlab.com/gitlab-org/quality/pipeline-triage/-/issues/#{current_issue_iid} 🎉
205
+ Thanks @#{username}, your report was #{note_action} at https://gitlab.com/gitlab-org/quality/pipeline-triage/-/issues/#{current_issue_iid}#note_#{posted_note.id} 🎉
188
206
  MSG
189
207
  end
190
208
 
@@ -16,6 +16,9 @@ module Dri
16
16
  desc: 'Updates actions on failures'
17
17
  method_option :feature_flags, type: :boolean,
18
18
  desc: 'Adds summary of feature flag changes'
19
+ method_option :update, aliases: '-u', type: :boolean,
20
+ desc: 'Updates an existing report'
21
+
19
22
  def report(*)
20
23
  if options[:help]
21
24
  invoke :help, ['report']
@@ -24,7 +24,7 @@ module Dri
24
24
 
25
25
  spinner.start
26
26
 
27
- failures_with_award_emoji = api_client.fetch_triaged_failures(emoji: emoji, state: 'opened')
27
+ failures_with_award_emoji = api_client.fetch_all_triaged_failures(emoji: emoji, state: 'opened')
28
28
  incidents_with_award_emoji = api_client.fetch_triaged_incidents(emoji: emoji)
29
29
 
30
30
  issues_with_award_emoji = failures_with_award_emoji + incidents_with_award_emoji
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative './utils/feature_flag_consts'
3
+ require_relative './utils/constants'
4
4
 
5
5
  module Dri
6
6
  class FeatureFlagReport
7
- include Dri::Utils::FeatureFlagConsts
7
+ include Dri::Utils::Constants::FeatureFlag::Labels
8
8
 
9
9
  attr_reader :header, :labels, :prod, :staging, :staging_ref, :preprod
10
10
 
data/lib/dri/report.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative './utils/constants'
4
+
3
5
  module Dri
4
6
  class Report # rubocop:disable Metrics/ClassLength
7
+ include Dri::Utils::Constants::Triage::Labels
5
8
  using Refinements
6
9
 
7
10
  attr_reader :header, :failures, :labels, :labels_incidents, :incidents
@@ -31,24 +34,23 @@ module Dri
31
34
  service = 'N/A'
32
35
 
33
36
  labels.each do |label|
34
- status = label.gsub!('Incident::', ' ').to_s if label.include? "Incident::"
35
- service = label.gsub!('Service::', ' ').to_s if label.include? "Service::"
37
+ status = label.gsub!(INCIDENT, ' ').to_s if label.include? INCIDENT
38
+ service = label.gsub!(SERVICE, ' ').to_s if label.include? SERVICE
36
39
  end
37
40
 
38
41
  @incidents << [title, service, status, url]
39
42
  end
40
43
 
41
44
  def add_failure(failure, actions_opts = [])
45
+ project_id = failure["project_id"]
42
46
  iid = failure["iid"]
43
47
  title = format_title(failure["title"])
44
48
  link = failure["web_url"]
45
49
  labels = failure["labels"]
46
- created_at = failure["created_at"]
47
- assignees = failure["assignees"]
48
50
  description = failure["description"]
49
51
 
50
- related_mrs = @api_client.fetch_related_mrs(iid)
51
- emoji = classify_failure_emoji(created_at)
52
+ related_mrs = @api_client.fetch_related_mrs(project_id, iid)
53
+ emoji = classify_failure_emoji(failure["created_at"])
52
54
  emojified_link = "#{emoji} #{link}"
53
55
 
54
56
  stack_blob = if description.empty?
@@ -60,10 +62,10 @@ module Dri
60
62
  stack_trace = ":link:[`#{stack_blob}...`](#{link}#stack-trace)"
61
63
 
62
64
  failure_type = filter_failure_type_labels(labels)
63
- assigned_status = assigned?(assignees)
65
+ assigned_status = assigned?(failure["assignees"])
64
66
  pipelines = filter_pipeline_labels(labels)
65
67
 
66
- linked_pipelines = link_pipelines(iid, pipelines, description)
68
+ linked_pipelines = link_pipelines(project_id, iid, pipelines, description)
67
69
 
68
70
  actions_status = actions_status_template(failure_type, assigned_status, actions_opts)
69
71
  actions_fixes = actions_fixes_template(related_mrs)
@@ -73,7 +75,7 @@ module Dri
73
75
 
74
76
  private
75
77
 
76
- def link_pipelines(iid, pipelines, description) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
78
+ def link_pipelines(project_id, iid, pipelines, description) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
77
79
  linked = []
78
80
  label_pipeline_map = {
79
81
  'gitlab.com' => '/quality/production',
@@ -88,7 +90,7 @@ module Dri
88
90
  'release' => '/quality/release'
89
91
  }
90
92
 
91
- failure_notes = @api_client.fetch_failure_notes(iid)
93
+ failure_notes = @api_client.fetch_failure_notes(project_id, iid)
92
94
 
93
95
  return if pipelines.empty?
94
96
 
@@ -173,10 +175,10 @@ module Dri
173
175
  pipelines = []
174
176
 
175
177
  labels.each do |label|
176
- matchers = { 'found:' => ' ' }
178
+ matchers = { FOUND => ' ' }
177
179
 
178
- if label.include? "found:"
179
- pipeline = label.gsub(/found:/) { |match| matchers[match] }
180
+ if label.include? FOUND
181
+ pipeline = label.gsub(/#{FOUND}/o) { |match| matchers[match] }
180
182
  pipelines << pipeline.strip
181
183
  end
182
184
  end
@@ -185,7 +187,7 @@ module Dri
185
187
 
186
188
  def filter_failure_type_labels(labels)
187
189
  labels.each do |label|
188
- @type = label.gsub!('failure::', ' ').to_s if label.include? "failure::"
190
+ @type = label.gsub!(FAILURE, ' ').to_s if label.include? FAILURE
189
191
  end
190
192
  @type
191
193
  end
@@ -3,6 +3,39 @@
3
3
  module Dri
4
4
  module Utils
5
5
  module Constants
6
+ module ProjectIDs
7
+ TESTCASES_PROJECT_ID = 11229385
8
+ TRIAGE_PROJECT_ID = 15291320
9
+ GITLAB_PROJECT_ID = 278964
10
+ CUSTOMERSDOT_PROJECT_ID = 2670515
11
+ FEATURE_FLAG_LOG_PROJECT_ID = 15208716
12
+ INFRA_TEAM_PROD_PROJECT_ID = 7444821
13
+ end
14
+
15
+ module Triage
16
+ module Labels
17
+ FOUND = 'found:'
18
+ FAILURE = 'failure::'
19
+ FAILURE_NEW = "#{FAILURE}new"
20
+ INCIDENT = 'Incident::'
21
+ SERVICE = 'Service::'
22
+ QA = 'QA'
23
+ QUALITY = 'Quality'
24
+ QUARANTINE = 'quarantine'
25
+ end
26
+ end
27
+
28
+ module FeatureFlag
29
+ module Labels
30
+ PRODUCTION = 'host::gitlab.com'
31
+ STAGING = 'host::staging.gitlab.com'
32
+ STAGING_REF = 'host::staging-ref.gitlab.com'
33
+ PREPROD = 'host::pre.gitlab.com'
34
+ end
35
+
36
+ TITLE_SUBSTRINGS = ["set to \"true\"", "set to \"false\""].freeze
37
+ end
38
+
6
39
  PIPELINE_ENVIRONMENTS =
7
40
  {
8
41
  production: {
data/lib/dri/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dri
4
- VERSION = "0.7.0"
4
+ VERSION = "0.8.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dri
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.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: 2022-09-12 00:00:00.000000000 Z
11
+ date: 2022-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: amatch
@@ -355,7 +355,6 @@ files:
355
355
  - lib/dri/refinements/truncate.rb
356
356
  - lib/dri/report.rb
357
357
  - lib/dri/utils/constants.rb
358
- - lib/dri/utils/feature_flag_consts.rb
359
358
  - lib/dri/utils/markdown_lists.rb
360
359
  - lib/dri/utils/table.rb
361
360
  - lib/dri/version.rb
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Dri
4
- module Utils
5
- module FeatureFlagConsts
6
- PRODUCTION = 'host::gitlab.com'
7
- STAGING = 'host::staging.gitlab.com'
8
- STAGING_REF = 'host::staging-ref.gitlab.com'
9
- PREPROD = 'host::pre.gitlab.com'
10
- TITLE_SUBSTRINGS = ["set to \"true\"", "set to \"false\""].freeze
11
- end
12
- end
13
- end