gitlab_support_readiness 1.0.11 → 1.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) 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/jobs.rb +189 -0
  13. data/lib/support_readiness/gitlab/markdown.rb +37 -0
  14. data/lib/support_readiness/gitlab/merge_requests.rb +127 -0
  15. data/lib/support_readiness/gitlab/namespaces.rb +22 -0
  16. data/lib/support_readiness/gitlab/pipelines.rb +191 -0
  17. data/lib/support_readiness/gitlab/projects.rb +85 -1
  18. data/lib/support_readiness/gitlab/repositories.rb +174 -0
  19. data/lib/support_readiness/gitlab/users.rb +24 -0
  20. data/lib/support_readiness/gitlab.rb +4 -0
  21. data/lib/support_readiness/google_calendar/client.rb +59 -0
  22. data/lib/support_readiness/google_calendar/configuration.rb +39 -0
  23. data/lib/support_readiness/google_calendar/events.rb +169 -0
  24. data/lib/support_readiness/google_calendar.rb +14 -0
  25. data/lib/support_readiness/mailgun/bounces.rb +103 -0
  26. data/lib/support_readiness/mailgun/client.rb +65 -0
  27. data/lib/support_readiness/mailgun/configuration.rb +46 -0
  28. data/lib/support_readiness/mailgun/emails.rb +95 -0
  29. data/lib/support_readiness/mailgun.rb +15 -0
  30. data/lib/support_readiness/pagerduty/escalation_policies.rb +1 -1
  31. data/lib/support_readiness/pagerduty/schedules.rb +27 -3
  32. data/lib/support_readiness/pagerduty/services.rb +1 -1
  33. data/lib/support_readiness/pagerduty/users.rb +197 -0
  34. data/lib/support_readiness/pagerduty.rb +1 -0
  35. data/lib/support_readiness/repos/articles.rb +335 -0
  36. data/lib/support_readiness/repos/automations.rb +247 -0
  37. data/lib/support_readiness/repos/groups.rb +188 -0
  38. data/lib/support_readiness/repos/macros.rb +224 -0
  39. data/lib/support_readiness/repos/organization_fields.rb +193 -0
  40. data/lib/support_readiness/repos/sla_policies.rb +192 -0
  41. data/lib/support_readiness/repos/ticket_fields.rb +200 -0
  42. data/lib/support_readiness/repos/ticket_forms.rb +200 -0
  43. data/lib/support_readiness/repos/triggers.rb +255 -0
  44. data/lib/support_readiness/repos/user_fields.rb +201 -0
  45. data/lib/support_readiness/repos/views.rb +362 -0
  46. data/lib/support_readiness/repos.rb +22 -0
  47. data/lib/support_readiness/salesforce/accounts.rb +109 -0
  48. data/lib/support_readiness/salesforce/cases.rb +109 -0
  49. data/lib/support_readiness/salesforce/client.rb +64 -0
  50. data/lib/support_readiness/salesforce/configuration.rb +49 -0
  51. data/lib/support_readiness/salesforce/queries.rb +62 -0
  52. data/lib/support_readiness/salesforce.rb +16 -0
  53. data/lib/support_readiness/slack/client.rb +63 -0
  54. data/lib/support_readiness/slack/configuration.rb +43 -0
  55. data/lib/support_readiness/slack/messages.rb +37 -0
  56. data/lib/support_readiness/slack.rb +14 -0
  57. data/lib/support_readiness/zendesk/app_job_statuses.rb +140 -0
  58. data/lib/support_readiness/zendesk/apps.rb +209 -0
  59. data/lib/support_readiness/zendesk/automations.rb +1 -2
  60. data/lib/support_readiness/zendesk/macros.rb +1 -3
  61. data/lib/support_readiness/zendesk/organization_fields.rb +1 -1
  62. data/lib/support_readiness/zendesk/theme_job_statuses.rb +136 -0
  63. data/lib/support_readiness/zendesk/themes.rb +303 -0
  64. data/lib/support_readiness/zendesk/ticket_field_options.rb +110 -0
  65. data/lib/support_readiness/zendesk/ticket_fields.rb +85 -16
  66. data/lib/support_readiness/zendesk/ticket_forms.rb +65 -2
  67. data/lib/support_readiness/zendesk/tickets.rb +77 -0
  68. data/lib/support_readiness/zendesk/triggers.rb +1 -2
  69. data/lib/support_readiness/zendesk/user_field_options.rb +110 -0
  70. data/lib/support_readiness/zendesk/user_fields.rb +257 -0
  71. data/lib/support_readiness/zendesk/views.rb +49 -2
  72. data/lib/support_readiness/zendesk.rb +7 -0
  73. data/lib/support_readiness.rb +16 -0
  74. metadata +122 -2
@@ -0,0 +1,188 @@
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 Groups within the module {Readiness::Repos}.
9
+ #
10
+ # @author Jason Colyer
11
+ # @since 1.0.12
12
+ class Groups < Readiness::Client
13
+ ##
14
+ # Compares the repo automation files to the Zendesk instance groups
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::Groups.compare(client, 'groups/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::Groups.compare(client, 'groups/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::Groups.list(zendesk_client)
57
+ from_repo.each do |repo|
58
+ zd = from_zendesk.detect { |z| z.name == repo.name }
59
+ if zd.nil?
60
+ diffs[:creates].push(repo)
61
+ else
62
+ comparable = zd.dup
63
+ comparable.id = nil
64
+ diffs[:updates].push(update_object(repo, zd)) if to_clean_json(repo) != to_clean_json(comparable)
65
+ detailed_diff(repo, comparable) if verbose && to_clean_json(repo) != to_clean_json(comparable)
66
+ end
67
+ end
68
+ report_diffs(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
+ # @param diffs [Hash] The returned value of {compare}
78
+ def self.report_diffs(diffs)
79
+ puts 'Compare report:'
80
+ puts "- Creates: #{diffs[:creates].count}"
81
+ puts "- Updates: #{diffs[:updates].count}"
82
+ end
83
+
84
+ ##
85
+ # Outputs a comparison report
86
+ #
87
+ # @author Jason Colyer
88
+ # @since 1.0.12
89
+ # @param repo [Object] An instance of {Readiness::Zendesk::Groups}
90
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::Groups}
91
+ def self.detailed_diff(repo, zendesk)
92
+ puts "Detailed diff of #{repo.title}"
93
+ repo.instance_variables.each do |v|
94
+ next if v == :@id
95
+
96
+ if repo.instance_variable_get(v) != zendesk.instance_variable_get(v)
97
+ puts "- #{v} Repo:"
98
+ pp repo.instance_variable_get(v)
99
+ puts " #{v} Zendesk:"
100
+ pp zendesk.instance_variable_get(v)
101
+ end
102
+ end
103
+ end
104
+
105
+ ##
106
+ # Creates an instance of {Readiness::Zendesk::Groups} to use for updates
107
+ #
108
+ # @author Jason Colyer
109
+ # @since 1.0.12
110
+ # @param repo [Object] An instance of {Readiness::Zendesk::Groups}
111
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::Groups}
112
+ # @return [Object]
113
+ def self.update_object(repo, zendesk)
114
+ object = repo
115
+ object.id = zendesk.id
116
+ object
117
+ end
118
+
119
+ ##
120
+ # Parses repo group files
121
+ #
122
+ # @author Jason Colyer
123
+ # @since 1.0.12
124
+ # @param location [String] The location (relative or absolute) of the repo's data folder
125
+ # @return [Array]
126
+ # @example
127
+ # require 'support_readiness'
128
+ # repo = Readiness::Repos::Groups.gather('groups/data')
129
+ # pp repo.count
130
+ # # => 35
131
+ def self.gather(location = 'data')
132
+ @errors = []
133
+ @location = location
134
+ array = []
135
+ Dir["#{@location}/*.yaml"].each do |f|
136
+ object = YAML.safe_load_file(f)
137
+ validity_check(f, object)
138
+ object['id'] = nil
139
+ array.push(Zendesk::Groups.new(object))
140
+ end
141
+ repo_check(array)
142
+ report_errors unless @errors.count.zero?
143
+ array
144
+ end
145
+
146
+ ##
147
+ # Outputs an error report and exits with a status code of 1
148
+ #
149
+ # @author Jason Colyer
150
+ # @since 1.0.12
151
+ def self.report_errors
152
+ puts 'The following errors were found in the repo files:'
153
+ @errors.each do |e|
154
+ puts "- #{e}"
155
+ end
156
+ puts 'Rectify the errors and retry. We cannot proceed with those errors occurring.'
157
+ exit 1
158
+ end
159
+
160
+ ##
161
+ # Performs basic checks on a repo file
162
+ #
163
+ # @author Jason Colyer
164
+ # @since 1.0.12
165
+ # @param file [String] The path to the repo file
166
+ # @param object [Hash] The Hash derived from parsing a YAML file
167
+ def self.validity_check(file, object)
168
+ @errors.push("Missing name: #{file}") if object['name'].nil?
169
+ @errors.push("Deleted group file: #{file}") if object['deleted']
170
+ end
171
+
172
+ ##
173
+ # Performs basic checks on the repo
174
+ #
175
+ # @author Jason Colyer
176
+ # @since 1.0.12
177
+ # @param objects [Array] The Array of Hashes derived from parsing the repo files
178
+ def self.repo_check(objects)
179
+ duplicate_names = objects.group_by { |o| o.name }.select { |k, v| v.size > 1 }.map(&:first)
180
+ unless duplicate_names.count.zero?
181
+ duplicate_names.each do |d|
182
+ @errors.push("The name '#{d}' is used in multiple files")
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,224 @@
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 Macros within the module {Readiness::Repos}.
9
+ #
10
+ # @author Jason Colyer
11
+ # @since 1.0.12
12
+ class Macros < Readiness::Client
13
+ ##
14
+ # Compares the repo automation files to the Zendesk instance macros
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::Macros.compare(client, 'macros/data', false)
30
+ # pp diffs[:updates.count]
31
+ # # => 5
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::Macros.compare(client, 'macros/data', true)
40
+ # # => Detailed diff of Status::Close::Close solved tickets after 7 days
41
+ # # => - @default Repo:
42
+ # # => false
43
+ # # => @default Zendesk:
44
+ # # => true
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::Macros.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.dup
63
+ comparable.id = nil
64
+ diffs[:updates].push(update_object(repo, zd)) if to_clean_json(repo) != to_clean_json(comparable)
65
+ detailed_diff(repo, comparable) if verbose && to_clean_json(repo) != to_clean_json(comparable)
66
+ end
67
+ end
68
+ report_diffs(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
+ # @param diffs [Hash] The returned value of {compare}
78
+ def self.report_diffs(diffs)
79
+ puts 'Compare report:'
80
+ puts "- Creates: #{diffs[:creates].count}"
81
+ puts "- Updates: #{diffs[:updates].count}"
82
+ end
83
+
84
+ ##
85
+ # Outputs a comparison report
86
+ #
87
+ # @author Jason Colyer
88
+ # @since 1.0.12
89
+ # @param repo [Object] An instance of {Readiness::Zendesk::Macros}
90
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::Macros}
91
+ def self.detailed_diff(repo, zendesk)
92
+ puts "Detailed diff of #{repo.title}"
93
+ repo.instance_variables.each do |v|
94
+ next if v == :@id
95
+
96
+ if repo.instance_variable_get(v) != zendesk.instance_variable_get(v)
97
+ puts "- #{v} Repo:"
98
+ pp repo.instance_variable_get(v)
99
+ puts " #{v} Zendesk:"
100
+ pp zendesk.instance_variable_get(v)
101
+ end
102
+ end
103
+ end
104
+
105
+ ##
106
+ # Creates an instance of {Readiness::Zendesk::Macros} to use for updates
107
+ #
108
+ # @author Jason Colyer
109
+ # @since 1.0.12
110
+ # @param repo [Object] An instance of {Readiness::Zendesk::Macros}
111
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::Macros}
112
+ # @return [Object]
113
+ def self.update_object(repo, zendesk)
114
+ object = repo
115
+ object.id = zendesk.id
116
+ object
117
+ end
118
+
119
+ ##
120
+ # Parses repo macro files
121
+ #
122
+ # @author Jason Colyer
123
+ # @since 1.0.12
124
+ # @param location [String] The location (relative or absolute) of the repo's data folder
125
+ # @return [Array]
126
+ # @example
127
+ # require 'support_readiness'
128
+ # repo = Readiness::Repos::Macros.gather('macros/data')
129
+ # pp repo.count
130
+ # # => 35
131
+ def self.gather(location = 'data')
132
+ @errors = []
133
+ @location = location
134
+ array = []
135
+ Dir["#{@location}/**/*.yaml"].each do |f|
136
+ object = YAML.safe_load_file(f)
137
+ object = convert_managed_content(object) if object['contains_managed_content']
138
+ validity_check(f, object)
139
+ object['id'] = nil
140
+ array.push(Zendesk::Macros.new(object))
141
+ end
142
+ repo_check(array)
143
+ report_errors unless @errors.count.zero?
144
+ array
145
+ end
146
+
147
+ ##
148
+ # Outputs an error report and exits with a status code of 1
149
+ #
150
+ # @author Jason Colyer
151
+ # @since 1.0.12
152
+ def self.report_errors
153
+ puts 'The following errors were found in the repo files:'
154
+ @errors.each do |e|
155
+ puts "- #{e}"
156
+ end
157
+ puts 'Rectify the errors and retry. We cannot proceed with those errors occurring.'
158
+ exit 1
159
+ end
160
+
161
+ ##
162
+ # Performs basic checks on a repo file
163
+ #
164
+ # @author Jason Colyer
165
+ # @since 1.0.12
166
+ # @param file [String] The path to the repo file
167
+ # @param object [Hash] The Hash derived from parsing a YAML file
168
+ def self.validity_check(file, object)
169
+ folder = file.split("#{@location}/").last.split('/').first
170
+ @errors.push("Missing title: #{file}") if object['title'].nil?
171
+ @errors.push("Inactive macro in active folder: #{file}") if folder == 'active' && !object['active']
172
+ @errors.push("Active macro in inactive folder: #{file}") if folder == 'inactive' && object['active']
173
+ end
174
+
175
+ ##
176
+ # Performs basic checks on the repo
177
+ #
178
+ # @author Jason Colyer
179
+ # @since 1.0.12
180
+ # @param objects [Array] The Array of Hashes derived from parsing the repo files
181
+ def self.repo_check(objects)
182
+ duplicate_names = objects.group_by { |o| o.title }.select { |k, v| v.size > 1 }.map(&:first)
183
+ unless duplicate_names.count.zero?
184
+ duplicate_names.each do |d|
185
+ @errors.push("The title '#{d}' is used in multiple files")
186
+ end
187
+ end
188
+ end
189
+
190
+ ##
191
+ # Performs conversions for a repo file if using managed content
192
+ #
193
+ # @author Jason Colyer
194
+ # @since 1.0.12
195
+ # @param object [Hash] The Hash derived from parsing a YAML file
196
+ def self.convert_managed_content(object)
197
+ path = "#{@location}/managed_content/#{object['active'] ? '' : 'in'}active/#{object['title'].gsub('::', '/')}.md"
198
+ handle_request_error(1, 'Repos', 404, { action: 'Get managed content', id: object['title'] }) unless File.exist?(path)
199
+ object['actions'].each_with_index do |action, index|
200
+ if action['value'].is_a?(String)
201
+ if action['value'] =~ /MANAGED_CONTENT/
202
+ if action['value'] == 'MANAGED_CONTENT'
203
+ object['actions'][index]['value'] = action['value'].gsub('MANAGED_CONTENT', File.read(path).chomp)
204
+ else
205
+ object['actions'][index]['value'] = action['value'].gsub('MANAGED_CONTENT', File.read(path).chomp.gsub("\n", '\\n'))
206
+ end
207
+ end
208
+ elsif action['value'].is_a?(Array)
209
+ action['value'].each_with_index do |value, sub_index|
210
+ if value =~ /MANAGED_CONTENT/
211
+ if value == 'MANAGED_CONTENT'
212
+ object['actions'][index]['value'][sub_index] = value.gsub('MANAGED_CONTENT', File.read(path).chomp)
213
+ else
214
+ object['actions'][index]['value'][sub_index] = value.gsub('MANAGED_CONTENT', File.read(path).chomp.gsub("\n", '\\n'))
215
+ end
216
+ end
217
+ end
218
+ end
219
+ end
220
+ object
221
+ end
222
+ end
223
+ end
224
+ end
@@ -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