dri 0.4.0 → 0.5.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: 8718d907e41f0cfb472a255898ed513af0fe81ae4cfe782c7aa7d270cb0c2b9f
4
- data.tar.gz: 718f976b309b6eb0cab9f65b32e58de5876edd5507aafcc20a2f098068bb5929
3
+ metadata.gz: 879c4292254a2a17a0ebcd8e2c0a3f8bbc6e654a69c153ad66423c71eb750fc4
4
+ data.tar.gz: 51f8e1acec1894ce4a6ab264ef690cf063259f46512d743609bf2f5a6529132f
5
5
  SHA512:
6
- metadata.gz: 643631388b378a127bca182911c9dfb304a1134b568fb71c716976f637f31f2a8d5056c2e30f0f9e2a72e7528e9e7f58a0bda4c0cbc1066efab02c3159353777
7
- data.tar.gz: 46514571671417008fe79dadc26cee33b97ad642e61822e2a2097f4e83d774290d1389f3d7d5c6a8ddf7be7a1974d733b4f5cacef3e7c0084af16a37db30ee0d
6
+ metadata.gz: ad020b17eb8d05322800332e59b5d286dcb8712df055dab50be7f234df2864a5ba719f900d61b0ba25308a1ea130fa2b586b7f01215beec90eafb614cc8c6da1
7
+ data.tar.gz: c0ef20575dcc1f9fa3312df5970b79a8b6fa11b8401a1a80d30561c8a764c7bcd140d4e649c619fbce1be6b9f71c943fb51aa5a48c20b18c5f480af4a821bc07
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dri (0.3.1)
4
+ dri (0.4.0)
5
5
  gitlab (~> 4.18)
6
6
  httparty (~> 0.20.0)
7
7
  json (~> 2.6.1)
data/README.md CHANGED
@@ -145,6 +145,7 @@ $ dri publish report --format=list # formats the report in a list
145
145
  $ dri publish report --format=table # formats the report in a table (default)
146
146
  $ dri publish report --dry-run # the report is only generated locally
147
147
  $ dri publish report --actions # activate the actions prompt for each failure
148
+ $ dri publish report --feature-flags # includes a summary of the feature flag changes on each environment
148
149
  ```
149
150
 
150
151
  **Note:** These options above can be combined like:
data/lib/dri/command.rb CHANGED
@@ -26,8 +26,8 @@ module Dri
26
26
  config = TTY::Config.new
27
27
  config.filename = ".dri_profile"
28
28
  config.extname = ".yml"
29
- config.append_path Dir.pwd
30
29
  config.append_path Dir.home
30
+ config.append_path Dir.pwd
31
31
  config
32
32
  end
33
33
  end
@@ -2,34 +2,29 @@
2
2
 
3
3
  require_relative '../../command'
4
4
  require_relative '../../utils/table'
5
+ require_relative '../../utils/feature_flag_consts'
6
+ require_relative '../../feature_flag_report'
5
7
 
6
8
  module Dri
7
9
  module Commands
8
10
  class Fetch
9
11
  class FeatureFlags < Dri::Command
10
12
  include Dri::Utils::Table
11
-
12
- PRODUCTION = 'host::gitlab.com'
13
- STAGING = 'host::staging.gitlab.com'
14
- STAGING_REF = 'host::staging-ref.gitlab.com'
15
- PREPROD = 'host::pre.gitlab.com'
13
+ include Dri::Utils::FeatureFlagConsts
16
14
 
17
15
  def initialize(options)
18
16
  @options = options
19
17
  @today_iso_format = Time.now.strftime('%Y-%m-%dT00:00:00Z')
20
18
  end
21
19
 
22
- def execute(input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
20
+ def execute(input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
23
21
  verify_config_exists
24
22
 
25
23
  summary = add_color('Summary', :bright_yellow)
26
24
  changed_on = add_color('Changed(UTC)', :bright_yellow)
27
25
  url = add_color('URL', :bright_yellow)
28
26
 
29
- prod_feature_flags = []
30
- staging_feature_flags = []
31
- staging_ref_feature_flags = []
32
- preprod_feature_flags = []
27
+ report = Dri::FeatureFlagReport.new
33
28
 
34
29
  headers = [summary, changed_on, url]
35
30
 
@@ -37,42 +32,23 @@ module Dri
37
32
 
38
33
  spinner.run do
39
34
  response = api_client.fetch_feature_flag_logs(@today_iso_format)
35
+
40
36
  if response.empty?
41
37
  logger.info 'It\'s been quiet...no feature flag changes for today 👀'
42
38
  break
43
39
  end
44
40
 
45
41
  response.each do |feature_flag|
46
- summary = feature_flag.title
47
-
48
- substrings = ["set to \"true\"", "set to \"false\""]
49
- next unless substrings.any? { |substr| summary.include?(substr) }
50
-
51
- changed_on = feature_flag.description[/(?<=Changed on \(in UTC\): ).+?(?=\n)/].delete('`')
52
- url = feature_flag.web_url
53
-
54
- feature_flag_data = [summary, changed_on, url]
55
-
56
- labels = feature_flag.labels
57
- host_label = labels.select { |label| /^host::/.match(label) }.join('')
42
+ next unless TITLE_SUBSTRINGS.any? { |substr| feature_flag.title.include?(substr) }
58
43
 
59
- case host_label
60
- when PRODUCTION
61
- prod_feature_flags << feature_flag_data
62
- when STAGING
63
- staging_feature_flags << feature_flag_data
64
- when STAGING_REF
65
- staging_ref_feature_flags << feature_flag_data
66
- when PREPROD
67
- preprod_feature_flags << feature_flag_data
68
- end
44
+ report.add_change(feature_flag)
69
45
  end
70
46
  end
71
47
 
72
- print_results('Production', headers, prod_feature_flags, output) unless prod_feature_flags.empty?
73
- print_results('Staging', headers, staging_feature_flags, output) unless staging_feature_flags.empty?
74
- print_results('Staging Ref', headers, staging_ref_feature_flags, output) unless staging_ref_feature_flags.empty? # rubocop:disable Layout/LineLength
75
- print_results('Preprod', headers, preprod_feature_flags, output) unless preprod_feature_flags.empty?
48
+ print_results('Production', headers, report.prod, output) unless report.prod.empty?
49
+ print_results('Staging', headers, report.staging, output) unless report.staging.empty?
50
+ print_results('Staging Ref', headers, report.staging_ref, output) unless report.staging_ref.empty?
51
+ print_results('Preprod', headers, report.preprod, output) unless report.preprod.empty?
76
52
  end
77
53
 
78
54
  private
@@ -2,21 +2,26 @@
2
2
 
3
3
  require_relative '../../command'
4
4
  require_relative '../../utils/markdown_lists'
5
- require_relative "../../report"
5
+ require_relative '../../utils/feature_flag_consts'
6
+ require_relative '../../report'
7
+ require_relative '../../feature_flag_report'
6
8
 
7
9
  require 'markdown-tables'
8
10
  require 'fileutils'
9
- require "uri"
11
+ require 'uri'
10
12
 
11
13
  module Dri
12
14
  module Commands
13
15
  class Publish
14
- class Report < Dri::Command
16
+ class Report < Dri::Command # rubocop:disable Metrics/ClassLength
17
+ include Dri::Utils::FeatureFlagConsts
18
+
15
19
  def initialize(options)
16
20
  @options = options
17
21
 
18
22
  @date = Date.today
19
23
  @time = Time.now.to_i
24
+ @today_iso_format = Time.now.strftime('%Y-%m-%dT00:00:00Z')
20
25
  end
21
26
 
22
27
  def execute(input: $stdin, output: $stdout) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/MethodLength
@@ -26,7 +31,9 @@ module Dri
26
31
  logger.info "Fetching triaged failures with award emoji #{emoji}..."
27
32
 
28
33
  spinner.start
34
+
29
35
  issues = api_client.fetch_triaged_failures(emoji: emoji, state: 'opened')
36
+
30
37
  spinner.stop
31
38
 
32
39
  if issues.empty?
@@ -34,27 +41,28 @@ module Dri
34
41
  exit 1
35
42
  end
36
43
 
37
- logger.info "Assembling the report... "
44
+ logger.info 'Assembling the failures report... '
38
45
  # sets each failure on the table
39
46
  action_options = [
40
- "pinged SET",
41
- "reproduced",
42
- "transient",
43
- "quarantined",
44
- "active investigation",
45
- "blocking pipelines",
46
- "awaiting for a fix to merge",
47
- "notified the team",
48
- "due to feature flag"
47
+ 'pinged SET',
48
+ 'reproduced',
49
+ 'transient',
50
+ 'quarantined',
51
+ 'active investigation',
52
+ 'blocking pipelines',
53
+ 'awaiting for a fix to merge',
54
+ 'notified the team',
55
+ 'due to feature flag'
49
56
  ]
50
57
 
51
58
  spinner.start
59
+
52
60
  issues.each do |issue|
53
61
  actions = []
54
62
 
55
63
  if @options[:actions]
56
64
  actions = prompt.multi_select(
57
- "Please mark the actions on #{add_color(issue['title'], :yellow)}: ",
65
+ "Please mark the actions on #{add_color(issue.title, :yellow)}: ",
58
66
  action_options,
59
67
  per_page: 9
60
68
  )
@@ -77,14 +85,59 @@ module Dri
77
85
  end
78
86
  end
79
87
 
88
+ spinner.stop
89
+
90
+ if @options[:feature_flags]
91
+ logger.info 'Fetching today\'s feature flag changes...'
92
+
93
+ feature_flag_report = Dri::FeatureFlagReport.new
94
+
95
+ spinner.start
96
+
97
+ feature_flags = api_client.fetch_feature_flag_logs(@today_iso_format)
98
+
99
+ feature_flags.each do |feature_flag|
100
+ next unless TITLE_SUBSTRINGS.any? { |substr| feature_flag.title.include?(substr) }
101
+
102
+ feature_flag_report.add_change(feature_flag)
103
+ end
104
+
105
+ spinner.stop
106
+
107
+ logger.info 'Assembling the feature flags report...'
108
+
109
+ spinner.start
110
+
111
+ feature_flag_note = "\n\n## Feature Flag Changes"
112
+ feature_flag_changes = ''
113
+
114
+ format_type = @options[:format] == 'list' ? :list : :table
115
+
116
+ feature_flag_report.get_all_flag_changes.each do |env, changes|
117
+ next if changes.empty?
118
+
119
+ feature_flag_changes += format_feature_flag_changes(
120
+ env, changes, feature_flag_report.labels, format_type
121
+ )
122
+ end
123
+
124
+ feature_flag_note += if feature_flag_changes.empty?
125
+ "\n\nNo changes found today"
126
+ else
127
+ "\n\n<details><summary>Click to expand</summary>#{feature_flag_changes}</details>"
128
+ end
129
+
130
+ spinner.stop
131
+ end
132
+
80
133
  report.set_header(timezone, username)
81
134
  note = "#{report.header}\n\n#{format_style}"
82
135
 
83
- spinner.stop
136
+ note += feature_flag_note if @options[:feature_flags]
84
137
 
85
138
  # creates an .md file with the report locally in /handover_reports
86
139
  if @options[:dry_run]
87
- logger.info "Downloading the report... "
140
+ logger.info 'Downloading the report... '
88
141
 
89
142
  spinner.start
90
143
 
@@ -104,7 +157,7 @@ module Dri
104
157
 
105
158
  # sends note to the weekly triage report
106
159
  issues = api_client.fetch_current_triage_issue
107
- current_issue_iid = issues[0]["iid"]
160
+ current_issue_iid = issues.first.iid
108
161
 
109
162
  api_client.post_triage_report_note(iid: current_issue_iid, body: note)
110
163
 
@@ -113,6 +166,27 @@ module Dri
113
166
  Thanks @#{username}, your report was posted at https://gitlab.com/gitlab-org/quality/pipeline-triage/-/issues/#{current_issue_iid} 🎉
114
167
  MSG
115
168
  end
169
+
170
+ private
171
+
172
+ def format_feature_flag_changes(env, changes, labels, format_type)
173
+ unless format_type == :table || format_type == :list
174
+ raise ArgumentError, 'format_type must be one of type :table or :list'
175
+ end
176
+
177
+ case format_type
178
+ when :list
179
+ formatted_changes = Utils::MarkdownLists.make_list(labels, changes)
180
+ when :table
181
+ formatted_changes = MarkdownTables.make_table(
182
+ labels,
183
+ changes,
184
+ is_rows: true, align: %w[l l l]
185
+ )
186
+ end
187
+
188
+ "\n\n### #{env.to_s.capitalize.tr('_', ' ')}\n\n#{formatted_changes}"
189
+ end
116
190
  end
117
191
  end
118
192
  end
@@ -14,6 +14,8 @@ module Dri
14
14
  desc: 'Formats the report'
15
15
  method_option :actions, type: :boolean,
16
16
  desc: 'Updates actions on failures'
17
+ method_option :feature_flags, type: :boolean,
18
+ desc: 'Adds summary of feature flag changes'
17
19
  def report(*)
18
20
  if options[:help]
19
21
  invoke :help, ['report']
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './utils/feature_flag_consts'
4
+
5
+ module Dri
6
+ class FeatureFlagReport
7
+ include Dri::Utils::FeatureFlagConsts
8
+
9
+ attr_reader :header, :labels, :prod, :staging, :staging_ref, :preprod
10
+
11
+ def initialize
12
+ @header = '## Feature Flag Changes'
13
+ @labels = %w[Summary Changed(UTC) URL]
14
+ @prod = []
15
+ @staging = []
16
+ @staging_ref = []
17
+ @preprod = []
18
+ end
19
+
20
+ def add_change(feature_flag)
21
+ summary = feature_flag.title
22
+
23
+ changed_on = feature_flag.description[/(?<=Changed on \(in UTC\): ).+?(?=\n)/].delete('`')
24
+ url = feature_flag.web_url
25
+
26
+ feature_flag_data = [summary, changed_on, url]
27
+
28
+ labels = feature_flag.labels
29
+ host_label = labels.select { |label| /^host::/.match(label) }.join('')
30
+
31
+ case host_label
32
+ when PRODUCTION
33
+ @prod << feature_flag_data
34
+ when STAGING
35
+ @staging << feature_flag_data
36
+ when STAGING_REF
37
+ @staging_ref << feature_flag_data
38
+ when PREPROD
39
+ @preprod << feature_flag_data
40
+ end
41
+ end
42
+
43
+ def get_all_flag_changes
44
+ { production: @prod, staging: @staging, staging_ref: @staging_ref, preprod: @preprod }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,13 @@
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
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.4.0"
4
+ VERSION = "0.5.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.4.0
4
+ version: 0.5.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-05-25 00:00:00.000000000 Z
11
+ date: 2022-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gitlab
@@ -333,10 +333,12 @@ files:
333
333
  - lib/dri/commands/rm/emoji.rb
334
334
  - lib/dri/commands/rm/profile.rb
335
335
  - lib/dri/commands/rm/reports.rb
336
+ - lib/dri/feature_flag_report.rb
336
337
  - lib/dri/gitlab/issues.rb
337
338
  - lib/dri/refinements/truncate.rb
338
339
  - lib/dri/report.rb
339
340
  - lib/dri/templates/incidents/.gitkeep
341
+ - lib/dri/utils/feature_flag_consts.rb
340
342
  - lib/dri/utils/markdown_lists.rb
341
343
  - lib/dri/utils/table.rb
342
344
  - lib/dri/version.rb