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.
- checksums.yaml +4 -4
- data/lib/support_readiness/calendly/client.rb +64 -0
- data/lib/support_readiness/calendly/configuration.rb +45 -0
- data/lib/support_readiness/calendly/organization_memberships.rb +67 -0
- data/lib/support_readiness/calendly/organizations.rb +123 -0
- data/lib/support_readiness/calendly/users.rb +105 -0
- data/lib/support_readiness/calendly.rb +16 -0
- data/lib/support_readiness/client.rb +88 -1
- data/lib/support_readiness/dates.rb +90 -0
- data/lib/support_readiness/gitlab/configuration.rb +0 -1
- data/lib/support_readiness/gitlab/groups.rb +35 -0
- data/lib/support_readiness/gitlab/markdown.rb +37 -0
- data/lib/support_readiness/gitlab/merge_requests.rb +127 -0
- data/lib/support_readiness/gitlab/namespaces.rb +22 -0
- data/lib/support_readiness/gitlab/projects.rb +36 -1
- data/lib/support_readiness/gitlab/repositories.rb +174 -0
- data/lib/support_readiness/gitlab/users.rb +24 -0
- data/lib/support_readiness/gitlab.rb +2 -0
- data/lib/support_readiness/google_calendar/client.rb +59 -0
- data/lib/support_readiness/google_calendar/configuration.rb +39 -0
- data/lib/support_readiness/google_calendar/events.rb +169 -0
- data/lib/support_readiness/google_calendar.rb +14 -0
- data/lib/support_readiness/mailgun/bounces.rb +103 -0
- data/lib/support_readiness/mailgun/client.rb +65 -0
- data/lib/support_readiness/mailgun/configuration.rb +46 -0
- data/lib/support_readiness/mailgun/emails.rb +95 -0
- data/lib/support_readiness/mailgun.rb +15 -0
- data/lib/support_readiness/pagerduty/escalation_policies.rb +1 -1
- data/lib/support_readiness/pagerduty/schedules.rb +27 -3
- data/lib/support_readiness/pagerduty/services.rb +1 -1
- data/lib/support_readiness/pagerduty/users.rb +197 -0
- data/lib/support_readiness/pagerduty.rb +1 -0
- data/lib/support_readiness/repos/articles.rb +335 -0
- data/lib/support_readiness/repos/automations.rb +247 -0
- data/lib/support_readiness/repos/groups.rb +188 -0
- data/lib/support_readiness/repos/macros.rb +224 -0
- data/lib/support_readiness/repos/organization_fields.rb +193 -0
- data/lib/support_readiness/repos/sla_policies.rb +192 -0
- data/lib/support_readiness/repos/ticket_fields.rb +200 -0
- data/lib/support_readiness/repos/ticket_forms.rb +200 -0
- data/lib/support_readiness/repos/triggers.rb +255 -0
- data/lib/support_readiness/repos/user_fields.rb +201 -0
- data/lib/support_readiness/repos/views.rb +362 -0
- data/lib/support_readiness/repos.rb +22 -0
- data/lib/support_readiness/salesforce/accounts.rb +109 -0
- data/lib/support_readiness/salesforce/cases.rb +109 -0
- data/lib/support_readiness/salesforce/client.rb +64 -0
- data/lib/support_readiness/salesforce/configuration.rb +49 -0
- data/lib/support_readiness/salesforce/queries.rb +62 -0
- data/lib/support_readiness/salesforce.rb +16 -0
- data/lib/support_readiness/slack/client.rb +63 -0
- data/lib/support_readiness/slack/configuration.rb +43 -0
- data/lib/support_readiness/slack/messages.rb +37 -0
- data/lib/support_readiness/slack.rb +14 -0
- data/lib/support_readiness/zendesk/app_job_statuses.rb +140 -0
- data/lib/support_readiness/zendesk/apps.rb +209 -0
- data/lib/support_readiness/zendesk/automations.rb +1 -2
- data/lib/support_readiness/zendesk/macros.rb +1 -3
- data/lib/support_readiness/zendesk/organization_fields.rb +1 -1
- data/lib/support_readiness/zendesk/theme_job_statuses.rb +136 -0
- data/lib/support_readiness/zendesk/themes.rb +303 -0
- data/lib/support_readiness/zendesk/ticket_field_options.rb +110 -0
- data/lib/support_readiness/zendesk/ticket_fields.rb +85 -16
- data/lib/support_readiness/zendesk/ticket_forms.rb +65 -2
- data/lib/support_readiness/zendesk/tickets.rb +77 -0
- data/lib/support_readiness/zendesk/triggers.rb +1 -2
- data/lib/support_readiness/zendesk/user_field_options.rb +110 -0
- data/lib/support_readiness/zendesk/user_fields.rb +257 -0
- data/lib/support_readiness/zendesk/views.rb +49 -2
- data/lib/support_readiness/zendesk.rb +7 -0
- data/lib/support_readiness.rb +16 -0
- metadata +120 -2
@@ -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 TicketForms within the module {Readiness::Repos}.
|
9
|
+
#
|
10
|
+
# @author Jason Colyer
|
11
|
+
# @since 1.0.12
|
12
|
+
class TicketForms < Readiness::Client
|
13
|
+
##
|
14
|
+
# Compares the repo ticket forms files to the Zendesk instance ticket forms
|
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::TicketForms.compare(client, 'tickets/forms-and-fields/data/forms', 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::TicketForms.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 = zd.dup
|
63
|
+
comparable_repo = repo.dup
|
64
|
+
comparable_zd.id = nil
|
65
|
+
comparable_zd.agent_conditions.sort_by! { |a| [a['parent_field_id'], a['value']] }
|
66
|
+
comparable_zd.agent_conditions.map { |a| a['child_fields'].sort_by! { |c| c['id'] }}
|
67
|
+
comparable_zd.end_user_conditions.sort_by! { |a| [a['parent_field_id'], a['value']] }
|
68
|
+
comparable_zd.end_user_conditions.map { |a| a['child_fields'].sort_by! { |c| c['id'] }}
|
69
|
+
comparable_repo.agent_conditions.sort_by! { |a| [a['parent_field_id'], a['value']] }
|
70
|
+
comparable_repo.agent_conditions.map { |a| a['child_fields'].sort_by! { |c| c['id'] }}
|
71
|
+
comparable_repo.end_user_conditions.sort_by! { |a| [a['parent_field_id'], a['value']] }
|
72
|
+
comparable_repo.end_user_conditions.map { |a| a['child_fields'].sort_by! { |c| c['id'] }}
|
73
|
+
diffs[:updates].push(update_object(repo, zd)) if to_clean_json(comparable_repo) != to_clean_json(comparable_zd)
|
74
|
+
detailed_diff(comparable_repo, comparable_zd) if verbose && to_clean_json(comparable_repo) != to_clean_json(comparable_zd)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
report_diffs(diffs) if verbose
|
78
|
+
diffs
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Outputs a comparison report
|
83
|
+
#
|
84
|
+
# @author Jason Colyer
|
85
|
+
# @since 1.0.12
|
86
|
+
# @param diffs [Hash] The returned value of {compare}
|
87
|
+
def self.report_diffs(diffs)
|
88
|
+
puts 'Compare report:'
|
89
|
+
puts "- Creates: #{diffs[:creates].count}"
|
90
|
+
puts "- Updates: #{diffs[:updates].count}"
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# Outputs a comparison report
|
95
|
+
#
|
96
|
+
# @author Jason Colyer
|
97
|
+
# @since 1.0.12
|
98
|
+
# @param repo [Object] An instance of {Readiness::Zendesk::TicketForms}
|
99
|
+
# @param zendesk [Object] An instance of {Readiness::Zendesk::TicketForms}
|
100
|
+
def self.detailed_diff(repo, zendesk)
|
101
|
+
puts "Detailed diff of #{repo.name}"
|
102
|
+
repo.instance_variables.each do |v|
|
103
|
+
next if v == :@id
|
104
|
+
|
105
|
+
if repo.instance_variable_get(v) != zendesk.instance_variable_get(v)
|
106
|
+
puts "- #{v} Repo:"
|
107
|
+
pp repo.instance_variable_get(v)
|
108
|
+
puts " #{v} Zendesk:"
|
109
|
+
pp zendesk.instance_variable_get(v)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# Creates an instance of {Readiness::Zendesk::TicketForms} to use for updates
|
116
|
+
#
|
117
|
+
# @author Jason Colyer
|
118
|
+
# @since 1.0.12
|
119
|
+
# @param repo [Object] An instance of {Readiness::Zendesk::TicketForms}
|
120
|
+
# @param zendesk [Object] An instance of {Readiness::Zendesk::TicketForms}
|
121
|
+
# @return [Object]
|
122
|
+
def self.update_object(repo, zendesk)
|
123
|
+
object = repo
|
124
|
+
object.id = zendesk.id
|
125
|
+
object
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Parses repo ticket form files
|
130
|
+
#
|
131
|
+
# @author Jason Colyer
|
132
|
+
# @since 1.0.12
|
133
|
+
# @param location [String] The location (relative or absolute) of the repo's data folder
|
134
|
+
# @return [Array]
|
135
|
+
# @example
|
136
|
+
# require 'support_readiness'
|
137
|
+
# repo = Readiness::Repos::TicketForms.gather('groups/data')
|
138
|
+
# pp repo.count
|
139
|
+
# # => 35
|
140
|
+
def self.gather(location = 'data')
|
141
|
+
@errors = []
|
142
|
+
@location = location
|
143
|
+
array = []
|
144
|
+
Dir["#{@location}/**/*.yaml"].each do |f|
|
145
|
+
object = YAML.safe_load_file(f)
|
146
|
+
validity_check(f, object)
|
147
|
+
object['id'] = nil
|
148
|
+
array.push(Zendesk::TicketForms.new(object))
|
149
|
+
end
|
150
|
+
repo_check(array)
|
151
|
+
report_errors unless @errors.count.zero?
|
152
|
+
array
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# Outputs an error report and exits with a status code of 1
|
157
|
+
#
|
158
|
+
# @author Jason Colyer
|
159
|
+
# @since 1.0.12
|
160
|
+
def self.report_errors
|
161
|
+
puts 'The following errors were found in the repo files:'
|
162
|
+
@errors.each do |e|
|
163
|
+
puts "- #{e}"
|
164
|
+
end
|
165
|
+
puts 'Rectify the errors and retry. We cannot proceed with those errors occurring.'
|
166
|
+
exit 1
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# Performs basic checks on a repo file
|
171
|
+
#
|
172
|
+
# @author Jason Colyer
|
173
|
+
# @since 1.0.12
|
174
|
+
# @param file [String] The path to the repo file
|
175
|
+
# @param object [Hash] The Hash derived from parsing a YAML file
|
176
|
+
def self.validity_check(file, object)
|
177
|
+
folder = file.split("#{@location}/").last.split('/').first
|
178
|
+
@errors.push("Missing name: #{file}") if object['name'].nil?
|
179
|
+
@errors.push("Missing position: #{file}") if object['position'].nil?
|
180
|
+
@errors.push("Inactive form in active folder: #{file}") if folder == 'active' && !object['active']
|
181
|
+
@errors.push("Active form 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.name }.select { |k, v| v.size > 1 }.map(&:first)
|
192
|
+
unless duplicate_names.count.zero?
|
193
|
+
duplicate_names.each do |d|
|
194
|
+
@errors.push("The name '#{d}' is used in multiple files")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,255 @@
|
|
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 Triggers within the module {Readiness::Repos}.
|
9
|
+
#
|
10
|
+
# @author Jason Colyer
|
11
|
+
# @since 1.0.12
|
12
|
+
class Triggers < Readiness::Client
|
13
|
+
##
|
14
|
+
# Compares the repo trigger files to the Zendesk instance triggers
|
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::Triggers.compare(client, 'triggers/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::Triggers.compare(client, 'triggers/data', true)
|
40
|
+
# # => Detailed diff of Cleanup followup tickets
|
41
|
+
# # => - @position Repo:
|
42
|
+
# # => 13
|
43
|
+
# # => @position Zendesk:
|
44
|
+
# # => 12
|
45
|
+
# # => Detailed diff of New Billing ticket created via Webform
|
46
|
+
# # => - @position Repo:
|
47
|
+
# # => 11
|
48
|
+
# # => @position Zendesk:
|
49
|
+
# # => 10
|
50
|
+
# # => Compare report:
|
51
|
+
# # => - Creates: 0
|
52
|
+
# # => - Updates: 2
|
53
|
+
# pp diffs[:updates.count]
|
54
|
+
# # => 2
|
55
|
+
def self.compare(zendesk_client, location = 'data', verbose = false)
|
56
|
+
diffs = {
|
57
|
+
updates: [],
|
58
|
+
creates: []
|
59
|
+
}
|
60
|
+
from_repo = gather(location)
|
61
|
+
from_zendesk = Zendesk::Triggers.list(zendesk_client)
|
62
|
+
from_repo.each do |repo|
|
63
|
+
zd = from_zendesk.detect { |z| z.title == repo.title }
|
64
|
+
if zd.nil?
|
65
|
+
diffs[:creates].push(repo)
|
66
|
+
else
|
67
|
+
comparable = zd.dup
|
68
|
+
comparable.id = nil
|
69
|
+
diffs[:updates].push(update_object(repo, zd)) if to_clean_json(repo) != to_clean_json(comparable)
|
70
|
+
detailed_diff(repo, comparable) if verbose && to_clean_json(repo) != to_clean_json(comparable)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
report_diffs(diffs) if verbose
|
74
|
+
diffs
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Outputs a comparison report
|
79
|
+
#
|
80
|
+
# @author Jason Colyer
|
81
|
+
# @since 1.0.12
|
82
|
+
# @param diffs [Hash] The returned value of {compare}
|
83
|
+
def self.report_diffs(diffs)
|
84
|
+
puts 'Compare report:'
|
85
|
+
puts "- Creates: #{diffs[:creates].count}"
|
86
|
+
puts "- Updates: #{diffs[:updates].count}"
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Outputs a comparison report
|
91
|
+
#
|
92
|
+
# @author Jason Colyer
|
93
|
+
# @since 1.0.12
|
94
|
+
# @param repo [Object] An instance of {Readiness::Zendesk::Triggers}
|
95
|
+
# @param zendesk [Object] An instance of {Readiness::Zendesk::Triggers}
|
96
|
+
def self.detailed_diff(repo, zendesk)
|
97
|
+
puts "Detailed diff of #{repo.title}"
|
98
|
+
repo.instance_variables.each do |v|
|
99
|
+
next if v == :@id
|
100
|
+
|
101
|
+
if repo.instance_variable_get(v) != zendesk.instance_variable_get(v)
|
102
|
+
puts "- #{v} Repo:"
|
103
|
+
pp repo.instance_variable_get(v)
|
104
|
+
puts " #{v} Zendesk:"
|
105
|
+
pp zendesk.instance_variable_get(v)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# Creates an instance of {Readiness::Zendesk::Triggers} to use for updates
|
112
|
+
#
|
113
|
+
# @author Jason Colyer
|
114
|
+
# @since 1.0.12
|
115
|
+
# @param repo [Object] An instance of {Readiness::Zendesk::Triggers}
|
116
|
+
# @param zendesk [Object] An instance of {Readiness::Zendesk::Triggers}
|
117
|
+
# @return [Object]
|
118
|
+
def self.update_object(repo, zendesk)
|
119
|
+
object = repo
|
120
|
+
object.id = zendesk.id
|
121
|
+
object
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Parses repo trigger files
|
126
|
+
#
|
127
|
+
# @author Jason Colyer
|
128
|
+
# @since 1.0.12
|
129
|
+
# @param location [String] The location (relative or absolute) of the repo's data folder
|
130
|
+
# @return [Array]
|
131
|
+
# @example
|
132
|
+
# require 'support_readiness'
|
133
|
+
# repo = Readiness::Repos::Triggers.gather('triggers/data')
|
134
|
+
# pp repo.count
|
135
|
+
# # => 35
|
136
|
+
def self.gather(location = 'data')
|
137
|
+
@errors = []
|
138
|
+
@location = location
|
139
|
+
array = []
|
140
|
+
Dir["#{@location}/**/*.yaml"].each do |f|
|
141
|
+
object = YAML.safe_load_file(f)
|
142
|
+
object = convert_managed_content(object, f) if object['contains_managed_content']
|
143
|
+
object['default'] = false
|
144
|
+
#object = convert_managed_webhook(object, f) if object['contains_managed_webhook']
|
145
|
+
validity_check(f, object)
|
146
|
+
object['id'] = nil
|
147
|
+
array.push(Zendesk::Triggers.new(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 position: #{file}") if object['position'].nil?
|
178
|
+
@errors.push("Missing title: #{file}") if object['title'].nil?
|
179
|
+
@errors.push("Inactive trigger in active folder: #{file}") if folder == 'active' && !object['active']
|
180
|
+
@errors.push("Active trigger in inactive folder: #{file}") if folder == 'inactive' && object['active']
|
181
|
+
end
|
182
|
+
|
183
|
+
##
|
184
|
+
# Performs basic checks on the repo
|
185
|
+
#
|
186
|
+
# @author Jason Colyer
|
187
|
+
# @since 1.0.12
|
188
|
+
# @param objects [Array] The Array of Hashes derived from parsing the repo files
|
189
|
+
def self.repo_check(objects)
|
190
|
+
duplicate_names = objects.group_by { |o| o.title }.select { |k, v| v.size > 1 }.map(&:first)
|
191
|
+
unless duplicate_names.count.zero?
|
192
|
+
duplicate_names.each do |d|
|
193
|
+
@errors.push("The title '#{d}' is used in multiple files")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# Performs conversions for a repo file if using managed content
|
200
|
+
#
|
201
|
+
# @author Jason Colyer
|
202
|
+
# @since 1.0.12
|
203
|
+
# @param object [Hash] The Hash derived from parsing a YAML file
|
204
|
+
def self.convert_managed_content(object, file)
|
205
|
+
category = file.split("#{@location}/#{object['active'] ? '' : 'in' }active/").last.split('/').first
|
206
|
+
path = "#{@location}/managed_content/#{category}/#{object['title']}.md"
|
207
|
+
handle_request_error(1, 'Repos', 404, { action: 'Get managed content', id: object['title'] }) unless File.exist?(path)
|
208
|
+
object['actions'].each_with_index do |action, index|
|
209
|
+
if action['value'].is_a?(String)
|
210
|
+
if action['value'] =~ /MANAGED_CONTENT/
|
211
|
+
if action['value'] == 'MANAGED_CONTENT'
|
212
|
+
object['actions'][index]['value'] = action['value'].gsub('MANAGED_CONTENT', File.read(path).chomp)
|
213
|
+
else
|
214
|
+
object['actions'][index]['value'] = action['value'].gsub('MANAGED_CONTENT', File.read(path).chomp.gsub("\n", '\\n'))
|
215
|
+
end
|
216
|
+
end
|
217
|
+
elsif action['value'].is_a?(Array)
|
218
|
+
action['value'].each_with_index do |value, sub_index|
|
219
|
+
if value =~ /MANAGED_CONTENT/
|
220
|
+
if value == 'MANAGED_CONTENT'
|
221
|
+
object['actions'][index]['value'][sub_index] = value.gsub('MANAGED_CONTENT', File.read(path).chomp)
|
222
|
+
else
|
223
|
+
object['actions'][index]['value'][sub_index] = value.gsub('MANAGED_CONTENT', File.read(path).chomp.gsub("\n", '\\n'))
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
object
|
230
|
+
end
|
231
|
+
|
232
|
+
##
|
233
|
+
# Performs conversions for a repo file if using managed webhooks
|
234
|
+
#
|
235
|
+
# @author Jason Colyer
|
236
|
+
# @since 1.0.12
|
237
|
+
# @param object [Hash] The Hash derived from parsing a YAML file
|
238
|
+
def self.convert_managed_webhook(object, file)
|
239
|
+
category = file.split("#{@location}/#{object['active'] ? '' : 'in' }active/").last.split('/').first
|
240
|
+
path = "#{@location}/managed_content/#{category}/#{object['title']}.webhook"
|
241
|
+
handle_request_error(1, 'Repos', 404, { action: 'Get managed webhook', id: object['title'] }) unless File.exist?(path)
|
242
|
+
object['actions'].each_with_index do |action, index|
|
243
|
+
next unless action['value'].is_a?(Array)
|
244
|
+
|
245
|
+
action['value'].each_with_index do |value, sub_index|
|
246
|
+
next unless value == 'MANAGED_WEBHOOK'
|
247
|
+
|
248
|
+
object['actions'][index]['value'][sub_index] = JSON.parse(File.read(path))
|
249
|
+
end
|
250
|
+
end
|
251
|
+
object
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
@@ -0,0 +1,201 @@
|
|
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 UserFields within the module {Readiness::Repos}.
|
9
|
+
#
|
10
|
+
# @author Jason Colyer
|
11
|
+
# @since 1.0.12
|
12
|
+
class UserFields < Readiness::Client
|
13
|
+
##
|
14
|
+
# Compares the repo user fields files to the Zendesk instance user 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::UserFields.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
|
+
pp @from_zendesk
|
35
|
+
pp repo
|
36
|
+
@diffs[:field_creates].push(repo)
|
37
|
+
unless repo.custom_field_options.nil?
|
38
|
+
repo.custom_field_options.each do |o|
|
39
|
+
@diffs[:option_updates].push({ "#{repo.title}" => o })
|
40
|
+
end
|
41
|
+
end
|
42
|
+
else
|
43
|
+
comparable_zd = zd.dup
|
44
|
+
comparable_repo = repo.dup
|
45
|
+
comparable_zd.id = nil
|
46
|
+
comparable_zd.custom_field_options = nil
|
47
|
+
comparable_repo.custom_field_options = nil
|
48
|
+
@diffs[:field_updates].push(update_object(repo, zd)) if to_clean_json(comparable_zd) != to_clean_json(comparable_repo)
|
49
|
+
detailed_diff(comparable_repo, comparable_zd) if verbose && to_clean_json(comparable_repo) != to_clean_json(comparable_zd)
|
50
|
+
next if repo.custom_field_options.nil?
|
51
|
+
|
52
|
+
zd_options = @from_zendesk.detect { |z| z.title == repo.title }.custom_field_options
|
53
|
+
repo.custom_field_options.map! { |o| Zendesk::UserFieldOptions.new(o) } unless repo.custom_field_options.first.is_a? Object
|
54
|
+
repo.custom_field_options.each do |repo_option|
|
55
|
+
repo_option.position = repo.custom_field_options.index(repo_option) if repo_option.position.nil?
|
56
|
+
zd_option = zd_options.detect { |zd_o| zd_o.name == repo_option.name }
|
57
|
+
if zd_option.nil? || to_clean_json(zd_option) != to_clean_json(repo_option)
|
58
|
+
@diffs[:option_updates].push({ "#{repo.title}" => repo_option })
|
59
|
+
end
|
60
|
+
end
|
61
|
+
zd_options.each do |zd_option|
|
62
|
+
repo_option = repo.custom_field_options.detect { |rp_o| rp_o.name == zd_option.name }
|
63
|
+
if repo_option.nil?
|
64
|
+
@diffs[:option_deletes].push({ "#{repo.title}" => zd_option })
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
report_diffs if verbose
|
70
|
+
@diffs
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Outputs a comparison report
|
75
|
+
#
|
76
|
+
# @author Jason Colyer
|
77
|
+
# @since 1.0.12
|
78
|
+
def self.report_diffs
|
79
|
+
puts 'Compare report:'
|
80
|
+
puts "- Field Creates: #{@diffs[:field_creates].count}"
|
81
|
+
puts "- Field Updates: #{@diffs[:field_updates].count}"
|
82
|
+
puts "- Option Updates: #{@diffs[:option_updates].count}"
|
83
|
+
puts "- Option Deletes: #{@diffs[:option_deletes].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::UserFields}
|
92
|
+
# @param zendesk [Object] An instance of {Readiness::Zendesk::UserFields}
|
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::UserFields} to use for updates
|
109
|
+
#
|
110
|
+
# @author Jason Colyer
|
111
|
+
# @since 1.0.12
|
112
|
+
# @param repo [Object] An instance of {Readiness::Zendesk::UserFields}
|
113
|
+
# @param zendesk [Object] An instance of {Readiness::Zendesk::UserFields}
|
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 user field files
|
123
|
+
#
|
124
|
+
# @author Jason Colyer
|
125
|
+
# @since 1.0.12
|
126
|
+
# @param client [Object] An instance of {Readiness::Zendesk::Client}
|
127
|
+
# @param location [String] The location (relative or absolute) of the repo's data folder
|
128
|
+
# @return [Array]
|
129
|
+
# @example
|
130
|
+
# require 'support_readiness'
|
131
|
+
# config = Readiness::Zendesk::Configuration.new
|
132
|
+
# config.username = 'alice@example.com'
|
133
|
+
# config.token = 'test123abc'
|
134
|
+
# config.url = 'https://example.zendesk.com/api/v2'
|
135
|
+
# client = Readiness::Zendesk::Client.new(config)
|
136
|
+
# repo = Readiness::Repos::UserFields.gather(client, 'users/fields/data')
|
137
|
+
# pp repo.count
|
138
|
+
# # => 170
|
139
|
+
def self.gather(client, location = 'data')
|
140
|
+
@errors = []
|
141
|
+
@location = location
|
142
|
+
array = []
|
143
|
+
Dir["#{@location}/**/*.yaml"].each do |f|
|
144
|
+
object = YAML.safe_load_file(f)
|
145
|
+
validity_check(f, object)
|
146
|
+
object['id'] = nil
|
147
|
+
object['title_in_portal'] = (object['visible_in_portal'] ? object['title_in_portal'] : object['title'])
|
148
|
+
array.push(Zendesk::UserFields.new(client, object))
|
149
|
+
end
|
150
|
+
repo_check(array)
|
151
|
+
report_errors unless @errors.count.zero?
|
152
|
+
array
|
153
|
+
end
|
154
|
+
|
155
|
+
##
|
156
|
+
# Outputs an error report and exits with a status code of 1
|
157
|
+
#
|
158
|
+
# @author Jason Colyer
|
159
|
+
# @since 1.0.12
|
160
|
+
def self.report_errors
|
161
|
+
puts 'The following errors were found in the repo files:'
|
162
|
+
@errors.each do |e|
|
163
|
+
puts "- #{e}"
|
164
|
+
end
|
165
|
+
puts 'Rectify the errors and retry. We cannot proceed with those errors occurring.'
|
166
|
+
exit 1
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# Performs basic checks on a repo file
|
171
|
+
#
|
172
|
+
# @author Jason Colyer
|
173
|
+
# @since 1.0.12
|
174
|
+
# @param file [String] The path to the repo file
|
175
|
+
# @param object [Hash] The Hash derived from parsing a YAML file
|
176
|
+
def self.validity_check(file, object)
|
177
|
+
folder = file.split("#{@location}/").last.split('/').first
|
178
|
+
@errors.push("Missing type: #{file}") if object['type'].nil?
|
179
|
+
@errors.push("Missing title: #{file}") if object['title'].nil?
|
180
|
+
@errors.push("Missing position: #{file}") if object['position'].nil?
|
181
|
+
@errors.push("Inactive user field in active folder: #{file}") if folder == 'active' && !object['active']
|
182
|
+
@errors.push("Active user field in inactive folder: #{file}") if folder == 'inactive' && object['active']
|
183
|
+
end
|
184
|
+
|
185
|
+
##
|
186
|
+
# Performs basic checks on the repo
|
187
|
+
#
|
188
|
+
# @author Jason Colyer
|
189
|
+
# @since 1.0.12
|
190
|
+
# @param objects [Array] The Array of Hashes derived from parsing the repo files
|
191
|
+
def self.repo_check(objects)
|
192
|
+
duplicate_names = objects.group_by { |o| o.title }.select { |k, v| v.size > 1 }.map(&:first)
|
193
|
+
unless duplicate_names.count.zero?
|
194
|
+
duplicate_names.each do |d|
|
195
|
+
@errors.push("The title '#{d}' is used in multiple files")
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|