dri 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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