gitlab_support_readiness 1.0.11 → 1.0.12

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/lib/support_readiness/calendly/client.rb +64 -0
  3. data/lib/support_readiness/calendly/configuration.rb +45 -0
  4. data/lib/support_readiness/calendly/organization_memberships.rb +67 -0
  5. data/lib/support_readiness/calendly/organizations.rb +123 -0
  6. data/lib/support_readiness/calendly/users.rb +105 -0
  7. data/lib/support_readiness/calendly.rb +16 -0
  8. data/lib/support_readiness/client.rb +88 -1
  9. data/lib/support_readiness/dates.rb +90 -0
  10. data/lib/support_readiness/gitlab/configuration.rb +0 -1
  11. data/lib/support_readiness/gitlab/groups.rb +35 -0
  12. data/lib/support_readiness/gitlab/markdown.rb +37 -0
  13. data/lib/support_readiness/gitlab/merge_requests.rb +127 -0
  14. data/lib/support_readiness/gitlab/namespaces.rb +22 -0
  15. data/lib/support_readiness/gitlab/projects.rb +36 -1
  16. data/lib/support_readiness/gitlab/repositories.rb +174 -0
  17. data/lib/support_readiness/gitlab/users.rb +24 -0
  18. data/lib/support_readiness/gitlab.rb +2 -0
  19. data/lib/support_readiness/google_calendar/client.rb +59 -0
  20. data/lib/support_readiness/google_calendar/configuration.rb +39 -0
  21. data/lib/support_readiness/google_calendar/events.rb +169 -0
  22. data/lib/support_readiness/google_calendar.rb +14 -0
  23. data/lib/support_readiness/mailgun/bounces.rb +103 -0
  24. data/lib/support_readiness/mailgun/client.rb +65 -0
  25. data/lib/support_readiness/mailgun/configuration.rb +46 -0
  26. data/lib/support_readiness/mailgun/emails.rb +95 -0
  27. data/lib/support_readiness/mailgun.rb +15 -0
  28. data/lib/support_readiness/pagerduty/escalation_policies.rb +1 -1
  29. data/lib/support_readiness/pagerduty/schedules.rb +27 -3
  30. data/lib/support_readiness/pagerduty/services.rb +1 -1
  31. data/lib/support_readiness/pagerduty/users.rb +197 -0
  32. data/lib/support_readiness/pagerduty.rb +1 -0
  33. data/lib/support_readiness/repos/articles.rb +335 -0
  34. data/lib/support_readiness/repos/automations.rb +247 -0
  35. data/lib/support_readiness/repos/groups.rb +188 -0
  36. data/lib/support_readiness/repos/macros.rb +224 -0
  37. data/lib/support_readiness/repos/organization_fields.rb +193 -0
  38. data/lib/support_readiness/repos/sla_policies.rb +192 -0
  39. data/lib/support_readiness/repos/ticket_fields.rb +200 -0
  40. data/lib/support_readiness/repos/ticket_forms.rb +200 -0
  41. data/lib/support_readiness/repos/triggers.rb +255 -0
  42. data/lib/support_readiness/repos/user_fields.rb +201 -0
  43. data/lib/support_readiness/repos/views.rb +362 -0
  44. data/lib/support_readiness/repos.rb +22 -0
  45. data/lib/support_readiness/salesforce/accounts.rb +109 -0
  46. data/lib/support_readiness/salesforce/cases.rb +109 -0
  47. data/lib/support_readiness/salesforce/client.rb +64 -0
  48. data/lib/support_readiness/salesforce/configuration.rb +49 -0
  49. data/lib/support_readiness/salesforce/queries.rb +62 -0
  50. data/lib/support_readiness/salesforce.rb +16 -0
  51. data/lib/support_readiness/slack/client.rb +63 -0
  52. data/lib/support_readiness/slack/configuration.rb +43 -0
  53. data/lib/support_readiness/slack/messages.rb +37 -0
  54. data/lib/support_readiness/slack.rb +14 -0
  55. data/lib/support_readiness/zendesk/app_job_statuses.rb +140 -0
  56. data/lib/support_readiness/zendesk/apps.rb +209 -0
  57. data/lib/support_readiness/zendesk/automations.rb +1 -2
  58. data/lib/support_readiness/zendesk/macros.rb +1 -3
  59. data/lib/support_readiness/zendesk/organization_fields.rb +1 -1
  60. data/lib/support_readiness/zendesk/theme_job_statuses.rb +136 -0
  61. data/lib/support_readiness/zendesk/themes.rb +303 -0
  62. data/lib/support_readiness/zendesk/ticket_field_options.rb +110 -0
  63. data/lib/support_readiness/zendesk/ticket_fields.rb +85 -16
  64. data/lib/support_readiness/zendesk/ticket_forms.rb +65 -2
  65. data/lib/support_readiness/zendesk/tickets.rb +77 -0
  66. data/lib/support_readiness/zendesk/triggers.rb +1 -2
  67. data/lib/support_readiness/zendesk/user_field_options.rb +110 -0
  68. data/lib/support_readiness/zendesk/user_fields.rb +257 -0
  69. data/lib/support_readiness/zendesk/views.rb +49 -2
  70. data/lib/support_readiness/zendesk.rb +7 -0
  71. data/lib/support_readiness.rb +16 -0
  72. metadata +120 -2
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Defines the module Readiness.
4
+ module Readiness
5
+ # Defines the module Repos
6
+ module Repos
7
+ ##
8
+ # Defines the class OrganizationFields within the module {Readiness::Repos}.
9
+ #
10
+ # @author Jason Colyer
11
+ # @since 1.0.12
12
+ class OrganizationFields < Readiness::Client
13
+ ##
14
+ # Compares the repo automation files to the Zendesk instance organization fields
15
+ #
16
+ # @author Jason Colyer
17
+ # @since 1.0.12
18
+ # @param zendesk_client [Object] An instance of {Readiness::Zendesk::Client}
19
+ # @param location [String] The location (relative or absolute) of the repo's data folder
20
+ # @param verbose [Boolean] Whether you want a detailed report or not
21
+ # @return [Hash]
22
+ # @example
23
+ # require 'support_readiness'
24
+ # config = Readiness::Zendesk::Configuration.new
25
+ # config.username = 'alice@example.com'
26
+ # config.token = 'test123abc'
27
+ # config.url = 'https://example.zendesk.com/api/v2'
28
+ # client = Readiness::Zendesk::Client.new(config)
29
+ # diffs = Readiness::Repos::OrganizationFields.compare(client, 'organizations/fields/data', false)
30
+ # pp diffs[:updates.count]
31
+ # # => 1
32
+ # @example
33
+ # require 'support_readiness'
34
+ # config = Readiness::Zendesk::Configuration.new
35
+ # config.username = 'alice@example.com'
36
+ # config.token = 'test123abc'
37
+ # config.url = 'https://example.zendesk.com/api/v2'
38
+ # client = Readiness::Zendesk::Client.new(config)
39
+ # diffs = Readiness::Repos::OrganizationFields.compare(client, 'organizations/fields/data', true)
40
+ # # => Detailed diff of Support Ops
41
+ # # => - @description Repo:
42
+ # # => "For GitLab Support Operations"
43
+ # # => @description Zendesk:
44
+ # # => "For GitLab Support Ops"
45
+ # # => Compare report:
46
+ # # => - Creates: 0
47
+ # # => - Updates: 1
48
+ # pp diffs[:updates.count]
49
+ # # => 1
50
+ def self.compare(zendesk_client, location = 'data', verbose = false)
51
+ diffs = {
52
+ updates: [],
53
+ creates: []
54
+ }
55
+ from_repo = gather(location)
56
+ from_zendesk = Zendesk::OrganizationFields.list(zendesk_client)
57
+ from_repo.each do |repo|
58
+ zd = from_zendesk.detect { |z| z.title == repo.title }
59
+ if zd.nil?
60
+ diffs[:creates].push(repo)
61
+ else
62
+ comparable_zd = zd.dup
63
+ comparable_repo = repo.dup
64
+ comparable_zd.id = nil
65
+ comparable_zd.custom_field_options.map { |a| a.delete('raw_name') } unless comparable_zd.custom_field_options.nil?
66
+ diffs[:updates].push(update_object(repo, zd)) if to_clean_json(comparable_repo) != to_clean_json(comparable_zd)
67
+ detailed_diff(comparable_repo, comparable_zd) if verbose && to_clean_json(comparable_repo) != to_clean_json(comparable_zd)
68
+ end
69
+ end
70
+ report_diffs(diffs) if verbose
71
+ diffs
72
+ end
73
+
74
+ ##
75
+ # Outputs a comparison report
76
+ #
77
+ # @author Jason Colyer
78
+ # @since 1.0.12
79
+ # @param diffs [Hash] The returned value of {compare}
80
+ def self.report_diffs(diffs)
81
+ puts 'Compare report:'
82
+ puts "- Creates: #{diffs[:creates].count}"
83
+ puts "- Updates: #{diffs[:updates].count}"
84
+ end
85
+
86
+ ##
87
+ # Outputs a comparison report
88
+ #
89
+ # @author Jason Colyer
90
+ # @since 1.0.12
91
+ # @param repo [Object] An instance of {Readiness::Zendesk::OrganizationFields}
92
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::OrganizationFields}
93
+ def self.detailed_diff(repo, zendesk)
94
+ puts "Detailed diff of #{repo.title}"
95
+ repo.instance_variables.each do |v|
96
+ next if v == :@id
97
+
98
+ if repo.instance_variable_get(v) != zendesk.instance_variable_get(v)
99
+ puts "- #{v} Repo:"
100
+ pp repo.instance_variable_get(v)
101
+ puts " #{v} Zendesk:"
102
+ pp zendesk.instance_variable_get(v)
103
+ end
104
+ end
105
+ end
106
+
107
+ ##
108
+ # Creates an instance of {Readiness::Zendesk::OrganizationFields} to use for updates
109
+ #
110
+ # @author Jason Colyer
111
+ # @since 1.0.12
112
+ # @param repo [Object] An instance of {Readiness::Zendesk::OrganizationFields}
113
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::OrganizationFields}
114
+ # @return [Object]
115
+ def self.update_object(repo, zendesk)
116
+ object = repo
117
+ object.id = zendesk.id
118
+ object
119
+ end
120
+
121
+ ##
122
+ # Parses repo group files
123
+ #
124
+ # @author Jason Colyer
125
+ # @since 1.0.12
126
+ # @param location [String] The location (relative or absolute) of the repo's data folder
127
+ # @return [Array]
128
+ # @example
129
+ # require 'support_readiness'
130
+ # repo = Readiness::Repos::OrganizationFields.gather('organizations/fields/data')
131
+ # pp repo.count
132
+ # # => 35
133
+ def self.gather(location = 'data')
134
+ @errors = []
135
+ @location = location
136
+ array = []
137
+ Dir["#{@location}/**/*.yaml"].each do |f|
138
+ object = YAML.safe_load_file(f)
139
+ validity_check(f, object)
140
+ object['id'] = nil
141
+ array.push(Zendesk::OrganizationFields.new(object))
142
+ end
143
+ repo_check(array)
144
+ report_errors unless @errors.count.zero?
145
+ array
146
+ end
147
+
148
+ ##
149
+ # Outputs an error report and exits with a status code of 1
150
+ #
151
+ # @author Jason Colyer
152
+ # @since 1.0.12
153
+ def self.report_errors
154
+ puts 'The following errors were found in the repo files:'
155
+ @errors.each do |e|
156
+ puts "- #{e}"
157
+ end
158
+ puts 'Rectify the errors and retry. We cannot proceed with those errors occurring.'
159
+ exit 1
160
+ end
161
+
162
+ ##
163
+ # Performs basic checks on a repo file
164
+ #
165
+ # @author Jason Colyer
166
+ # @since 1.0.12
167
+ # @param file [String] The path to the repo file
168
+ # @param object [Hash] The Hash derived from parsing a YAML file
169
+ def self.validity_check(file, object)
170
+ folder = file.split("#{@location}/").last.split('/').first
171
+ @errors.push("Missing title: #{file}") if object['title'].nil?
172
+ @errors.push("Missing position: #{file}") if object['position'].nil?
173
+ @errors.push("Inactive organization field in active folder: #{file}") if folder == 'active' && !object['active']
174
+ @errors.push("Active organization field in inactive folder: #{file}") if folder == 'inactive' && object['active']
175
+ end
176
+
177
+ ##
178
+ # Performs basic checks on the repo
179
+ #
180
+ # @author Jason Colyer
181
+ # @since 1.0.12
182
+ # @param objects [Array] The Array of Hashes derived from parsing the repo files
183
+ def self.repo_check(objects)
184
+ duplicate_names = objects.group_by { |o| o.title }.select { |k, v| v.size > 1 }.map(&:first)
185
+ unless duplicate_names.count.zero?
186
+ duplicate_names.each do |d|
187
+ @errors.push("The name '#{d}' is used in multiple files")
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,192 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Defines the module Readiness.
4
+ module Readiness
5
+ # Defines the module Repos
6
+ module Repos
7
+ ##
8
+ # Defines the class SLAs within the module {Readiness::Repos}.
9
+ #
10
+ # @author Jason Colyer
11
+ # @since 1.0.12
12
+ class SLAs < Readiness::Client
13
+ ##
14
+ # Compares the repo automation files to the Zendesk instance SLA policies
15
+ #
16
+ # @author Jason Colyer
17
+ # @since 1.0.12
18
+ # @param zendesk_client [Object] An instance of {Readiness::Zendesk::Client}
19
+ # @param location [String] The location (relative or absolute) of the repo's data folder
20
+ # @param verbose [Boolean] Whether you want a detailed report or not
21
+ # @return [Hash]
22
+ # @example
23
+ # require 'support_readiness'
24
+ # config = Readiness::Zendesk::Configuration.new
25
+ # config.username = 'alice@example.com'
26
+ # config.token = 'test123abc'
27
+ # config.url = 'https://example.zendesk.com/api/v2'
28
+ # client = Readiness::Zendesk::Client.new(config)
29
+ # diffs = Readiness::Repos::SLAs.compare(client, 'sla-polcies/data', false)
30
+ # pp diffs[:updates.count]
31
+ # # => 1
32
+ # @example
33
+ # require 'support_readiness'
34
+ # config = Readiness::Zendesk::Configuration.new
35
+ # config.username = 'alice@example.com'
36
+ # config.token = 'test123abc'
37
+ # config.url = 'https://example.zendesk.com/api/v2'
38
+ # client = Readiness::Zendesk::Client.new(config)
39
+ # diffs = Readiness::Repos::SLAs.compare(client, 'sla-polcies/data', true)
40
+ # # => Detailed diff of Support Ops
41
+ # # => - @description Repo:
42
+ # # => "For GitLab Support Operations"
43
+ # # => @description Zendesk:
44
+ # # => "For GitLab Support Ops"
45
+ # # => Compare report:
46
+ # # => - Creates: 0
47
+ # # => - Updates: 1
48
+ # pp diffs[:updates.count]
49
+ # # => 1
50
+ def self.compare(zendesk_client, location = 'data', verbose = false)
51
+ diffs = {
52
+ updates: [],
53
+ creates: []
54
+ }
55
+ from_repo = gather(location)
56
+ from_zendesk = Zendesk::SLAs.list(zendesk_client)
57
+ from_repo.each do |repo|
58
+ zd = from_zendesk.detect { |z| z.title == repo.title }
59
+ if zd.nil?
60
+ diffs[:creates].push(repo)
61
+ else
62
+ comparable_zd = zd.dup
63
+ comparable_repo = repo.dup
64
+ comparable_zd.id = nil
65
+ comparable_zd.policy_metrics.map { |a| a.delete('target_in_seconds') }
66
+ comparable_zd.policy_metrics.sort_by! { |a| [a['priority'], a['metric']] }
67
+ comparable_repo.policy_metrics.sort_by! { |a| [a['priority'], a['metric']] }
68
+ diffs[:updates].push(update_object(repo, zd)) if to_clean_json(comparable_repo) != to_clean_json(comparable_zd)
69
+ detailed_diff(repo, comparable) if verbose && to_clean_json(comparable_repo) != to_clean_json(comparable_zd)
70
+ end
71
+ end
72
+ report_diffs(diffs) if verbose
73
+ diffs
74
+ end
75
+
76
+ ##
77
+ # Outputs a comparison report
78
+ #
79
+ # @author Jason Colyer
80
+ # @since 1.0.12
81
+ # @param diffs [Hash] The returned value of {compare}
82
+ def self.report_diffs(diffs)
83
+ puts 'Compare report:'
84
+ puts "- Creates: #{diffs[:creates].count}"
85
+ puts "- Updates: #{diffs[:updates].count}"
86
+ end
87
+
88
+ ##
89
+ # Outputs a comparison report
90
+ #
91
+ # @author Jason Colyer
92
+ # @since 1.0.12
93
+ # @param repo [Object] An instance of {Readiness::Zendesk::SLAs}
94
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::SLAs}
95
+ def self.detailed_diff(repo, zendesk)
96
+ puts "Detailed diff of #{repo.title}"
97
+ repo.instance_variables.each do |v|
98
+ next if v == :@id
99
+
100
+ if repo.instance_variable_get(v) != zendesk.instance_variable_get(v)
101
+ puts "- #{v} Repo:"
102
+ pp repo.instance_variable_get(v)
103
+ puts " #{v} Zendesk:"
104
+ pp zendesk.instance_variable_get(v)
105
+ end
106
+ end
107
+ end
108
+
109
+ ##
110
+ # Creates an instance of {Readiness::Zendesk::Groups} to use for updates
111
+ #
112
+ # @author Jason Colyer
113
+ # @since 1.0.12
114
+ # @param repo [Object] An instance of {Readiness::Zendesk::Groups}
115
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::Groups}
116
+ # @return [Object]
117
+ def self.update_object(repo, zendesk)
118
+ object = repo
119
+ object.id = zendesk.id
120
+ object
121
+ end
122
+
123
+ ##
124
+ # Parses repo group files
125
+ #
126
+ # @author Jason Colyer
127
+ # @since 1.0.12
128
+ # @param location [String] The location (relative or absolute) of the repo's data folder
129
+ # @return [Array]
130
+ # @example
131
+ # require 'support_readiness'
132
+ # repo = Readiness::Repos::Groups.gather('groups/data')
133
+ # pp repo.count
134
+ # # => 35
135
+ def self.gather(location = 'data')
136
+ @errors = []
137
+ @location = location
138
+ array = []
139
+ Dir["#{@location}/*.yaml"].each do |f|
140
+ object = YAML.safe_load_file(f)
141
+ validity_check(f, object)
142
+ object['id'] = nil
143
+ array.push(Zendesk::SLAs.new(object))
144
+ end
145
+ repo_check(array)
146
+ report_errors unless @errors.count.zero?
147
+ array
148
+ end
149
+
150
+ ##
151
+ # Outputs an error report and exits with a status code of 1
152
+ #
153
+ # @author Jason Colyer
154
+ # @since 1.0.12
155
+ def self.report_errors
156
+ puts 'The following errors were found in the repo files:'
157
+ @errors.each do |e|
158
+ puts "- #{e}"
159
+ end
160
+ puts 'Rectify the errors and retry. We cannot proceed with those errors occurring.'
161
+ exit 1
162
+ end
163
+
164
+ ##
165
+ # Performs basic checks on a repo file
166
+ #
167
+ # @author Jason Colyer
168
+ # @since 1.0.12
169
+ # @param file [String] The path to the repo file
170
+ # @param object [Hash] The Hash derived from parsing a YAML file
171
+ def self.validity_check(file, object)
172
+ @errors.push("Missing title: #{file}") if object['title'].nil?
173
+ @errors.push("Missing position: #{file}") if object['position'].nil?
174
+ end
175
+
176
+ ##
177
+ # Performs basic checks on the repo
178
+ #
179
+ # @author Jason Colyer
180
+ # @since 1.0.12
181
+ # @param objects [Array] The Array of Hashes derived from parsing the repo files
182
+ def self.repo_check(objects)
183
+ duplicate_names = objects.group_by { |o| o.title }.select { |k, v| v.size > 1 }.map(&:first)
184
+ unless duplicate_names.count.zero?
185
+ duplicate_names.each do |d|
186
+ @errors.push("The name '#{d}' is used in multiple files")
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,200 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Defines the module Readiness.
4
+ module Readiness
5
+ # Defines the module Repos
6
+ module Repos
7
+ ##
8
+ # Defines the class TicketFields within the module {Readiness::Repos}.
9
+ #
10
+ # @author Jason Colyer
11
+ # @since 1.0.12
12
+ class TicketFields < Readiness::Client
13
+ ##
14
+ # Compares the repo ticket fields files to the Zendesk instance ticket fields
15
+ #
16
+ # @author Jason Colyer
17
+ # @since 1.0.12
18
+ # @param zendesk_client [Object] An instance of {Readiness::Zendesk::Client}
19
+ # @param location [String] The location (relative or absolute) of the repo's data folder
20
+ # @param verbose [Boolean] Whether you want a detailed report or not
21
+ # @return [Hash]
22
+ def self.compare(zendesk_client, location = 'data', verbose = false)
23
+ @from_repo = gather(zendesk_client, location)
24
+ @from_zendesk = Zendesk::TicketFields.list(zendesk_client)
25
+ @diffs = {
26
+ field_updates: [],
27
+ field_creates: [],
28
+ option_updates: [],
29
+ option_deletes: []
30
+ }
31
+ @from_repo.each do |repo|
32
+ zd = @from_zendesk.detect { |z| z.title == repo.title }
33
+ if zd.nil?
34
+ @diffs[:field_creates].push(repo)
35
+ unless repo.custom_field_options.nil?
36
+ repo.custom_field_options.each do |o|
37
+ @diffs[:option_updates].push({ "#{repo.title}" => o })
38
+ end
39
+ end
40
+ break
41
+ else
42
+ comparable_zd = zd.dup
43
+ comparable_repo = repo.dup
44
+ comparable_zd.id = nil
45
+ comparable_zd.custom_field_options = nil
46
+ comparable_repo.custom_field_options = nil
47
+ @diffs[:field_updates].push(update_object(repo, zd)) if to_clean_json(comparable_zd) != to_clean_json(comparable_repo)
48
+ detailed_diff(comparable_repo, comparable_zd) if verbose && to_clean_json(comparable_repo) != to_clean_json(comparable_zd)
49
+ next if repo.custom_field_options.nil?
50
+
51
+ zd_options = @from_zendesk.detect { |z| z.title == repo.title }.custom_field_options
52
+ repo.custom_field_options.map! { |o| Zendesk::TicketFieldOptions.new(o) } unless repo.custom_field_options.first.is_a? Object
53
+ repo.custom_field_options.each do |repo_option|
54
+ repo_option.position = repo.custom_field_options.index(repo_option) if repo_option.position.nil?
55
+ zd_option = zd_options.detect { |zd_o| zd_o.name == repo_option.name }
56
+ if zd_option.nil? || to_clean_json(zd_option) != to_clean_json(repo_option)
57
+ @diffs[:option_updates].push({ "#{repo.title}" => repo_option })
58
+ end
59
+ end
60
+ zd_options.each do |zd_option|
61
+ repo_option = repo.custom_field_options.detect { |rp_o| rp_o.name == zd_option.name }
62
+ if repo_option.nil?
63
+ @diffs[:option_deletes].push({ "#{repo.title}" => zd_option })
64
+ end
65
+ end
66
+ end
67
+ end
68
+ report_diffs if verbose
69
+ @diffs
70
+ end
71
+
72
+ ##
73
+ # Outputs a comparison report
74
+ #
75
+ # @author Jason Colyer
76
+ # @since 1.0.12
77
+ def self.report_diffs
78
+ puts 'Compare report:'
79
+ puts "- Field Creates: #{@diffs[:field_creates].count}"
80
+ puts "- Field Updates: #{@diffs[:field_updates].count}"
81
+ puts "- Option Updates: #{@diffs[:option_updates].count}"
82
+ puts "- Option Deletes: #{@diffs[:option_deletes].count}"
83
+ end
84
+
85
+ ##
86
+ # Outputs a comparison report
87
+ #
88
+ # @author Jason Colyer
89
+ # @since 1.0.12
90
+ # @param repo [Object] An instance of {Readiness::Zendesk::TicketFields}
91
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::TicketFields}
92
+ def self.detailed_diff(repo, zendesk)
93
+ puts "Detailed diff of #{repo.title}"
94
+ repo.instance_variables.each do |v|
95
+ next if v == :@id
96
+
97
+ if repo.instance_variable_get(v) != zendesk.instance_variable_get(v)
98
+ puts "- #{v} Repo:"
99
+ pp repo.instance_variable_get(v)
100
+ puts " #{v} Zendesk:"
101
+ pp zendesk.instance_variable_get(v)
102
+ end
103
+ end
104
+ end
105
+
106
+ ##
107
+ # Creates an instance of {Readiness::Zendesk::TicketFields} to use for updates
108
+ #
109
+ # @author Jason Colyer
110
+ # @since 1.0.12
111
+ # @param repo [Object] An instance of {Readiness::Zendesk::TicketFields}
112
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::TicketFields}
113
+ # @return [Object]
114
+ def self.update_object(repo, zendesk)
115
+ object = repo
116
+ object.id = zendesk.id
117
+ object
118
+ end
119
+
120
+ ##
121
+ # Parses repo ticket field files
122
+ #
123
+ # @author Jason Colyer
124
+ # @since 1.0.12
125
+ # @param client [Object] An instance of {Readiness::Zendesk::Client}
126
+ # @param location [String] The location (relative or absolute) of the repo's data folder
127
+ # @return [Array]
128
+ # @example
129
+ # require 'support_readiness'
130
+ # config = Readiness::Zendesk::Configuration.new
131
+ # config.username = 'alice@example.com'
132
+ # config.token = 'test123abc'
133
+ # config.url = 'https://example.zendesk.com/api/v2'
134
+ # client = Readiness::Zendesk::Client.new(config)
135
+ # repo = Readiness::Repos::TicketFields.gather(client, 'tickets/forms-and-fields/data/fields')
136
+ # pp repo.count
137
+ # # => 170
138
+ def self.gather(client, location = 'data')
139
+ @errors = []
140
+ @location = location
141
+ array = []
142
+ Dir["#{@location}/**/*.yaml"].each do |f|
143
+ object = YAML.safe_load_file(f)
144
+ validity_check(f, object)
145
+ object['id'] = nil
146
+ object['title_in_portal'] = (object['visible_in_portal'] ? object['title_in_portal'] : object['title'])
147
+ array.push(Zendesk::TicketFields.new(client, object))
148
+ end
149
+ repo_check(array)
150
+ report_errors unless @errors.count.zero?
151
+ array
152
+ end
153
+
154
+ ##
155
+ # Outputs an error report and exits with a status code of 1
156
+ #
157
+ # @author Jason Colyer
158
+ # @since 1.0.12
159
+ def self.report_errors
160
+ puts 'The following errors were found in the repo files:'
161
+ @errors.each do |e|
162
+ puts "- #{e}"
163
+ end
164
+ puts 'Rectify the errors and retry. We cannot proceed with those errors occurring.'
165
+ exit 1
166
+ end
167
+
168
+ ##
169
+ # Performs basic checks on a repo file
170
+ #
171
+ # @author Jason Colyer
172
+ # @since 1.0.12
173
+ # @param file [String] The path to the repo file
174
+ # @param object [Hash] The Hash derived from parsing a YAML file
175
+ def self.validity_check(file, object)
176
+ folder = file.split("#{@location}/").last.split('/').first
177
+ @errors.push("Missing type: #{file}") if object['type'].nil?
178
+ @errors.push("Missing title: #{file}") if object['title'].nil?
179
+ @errors.push("Missing position: #{file}") if object['position'].nil?
180
+ @errors.push("Inactive ticket field in active folder: #{file}") if folder == 'active' && !object['active']
181
+ @errors.push("Active ticket field in inactive folder: #{file}") if folder == 'inactive' && object['active']
182
+ end
183
+
184
+ ##
185
+ # Performs basic checks on the repo
186
+ #
187
+ # @author Jason Colyer
188
+ # @since 1.0.12
189
+ # @param objects [Array] The Array of Hashes derived from parsing the repo files
190
+ def self.repo_check(objects)
191
+ duplicate_names = objects.group_by { |o| o.title }.select { |k, v| v.size > 1 }.map(&:first)
192
+ unless duplicate_names.count.zero?
193
+ duplicate_names.each do |d|
194
+ @errors.push("The title '#{d}' is used in multiple files")
195
+ end
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end