gitlab_support_readiness 1.0.11 → 1.0.13

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 (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,335 @@
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 Articles within the module {Readiness::Repos}.
9
+ #
10
+ # @author Jason Colyer
11
+ # @since 1.0.12
12
+ class Articles < Readiness::Client
13
+ def self.compare(zd_client, gl_client, instance, location = 'data', verbose = false)
14
+ diffs = {
15
+ updates: [],
16
+ creates: []
17
+ }
18
+ from_repo = gather(gl_client, instance, location)
19
+ from_zendesk = Zendesk::Articles.list(zd_client)
20
+ from_repo.each do |repo|
21
+ zd = from_zendesk.detect { |z| z.title == repo.title }
22
+ if zd.nil?
23
+ diffs[:creates].push(repo)
24
+ else
25
+ comparable = zd.dup
26
+ comparable.id = nil
27
+ diffs[:updates].push(update_object(repo, zd)) if to_clean_json(repo) != to_clean_json(comparable)
28
+ detailed_diff(repo, comparable) if verbose && to_clean_json(repo) != to_clean_json(comparable)
29
+ end
30
+ end
31
+ report_diffs(diffs) if verbose
32
+ diffs
33
+ end
34
+
35
+ ##
36
+ # Outputs a comparison report
37
+ #
38
+ # @author Jason Colyer
39
+ # @since 1.0.12
40
+ # @param diffs [Hash] The returned value of {compare}
41
+ def self.report_diffs(diffs)
42
+ puts 'Compare report:'
43
+ puts "- Creates: #{diffs[:creates].count}"
44
+ puts "- Updates: #{diffs[:updates].count}"
45
+ end
46
+
47
+ ##
48
+ # Outputs a comparison report
49
+ #
50
+ # @author Jason Colyer
51
+ # @since 1.0.12
52
+ # @param repo [Object] An instance of {Readiness::Zendesk::Automations}
53
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::Automations}
54
+ def self.detailed_diff(repo, zendesk)
55
+ puts "Detailed diff of #{repo.title}"
56
+ repo.instance_variables.each do |v|
57
+ next if v == :@id
58
+
59
+ if repo.instance_variable_get(v) != zendesk.instance_variable_get(v)
60
+ if v == :@body
61
+ puts "- #{v} Repo and #{v} Zendesk differ"
62
+ else
63
+ puts "- #{v} Repo:"
64
+ pp repo.instance_variable_get(v)
65
+ puts " #{v} Zendesk:"
66
+ pp zendesk.instance_variable_get(v)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ ##
73
+ # Creates an instance of {Readiness::Zendesk::Automations} to use for updates
74
+ #
75
+ # @author Jason Colyer
76
+ # @since 1.0.12
77
+ # @param repo [Object] An instance of {Readiness::Zendesk::Automations}
78
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::Automations}
79
+ # @return [Object]
80
+ def self.update_object(repo, zendesk)
81
+ object = repo
82
+ object.id = zendesk.id
83
+ object
84
+ end
85
+
86
+ ##
87
+ # Parses repo article files
88
+ #
89
+ # @author Jason Colyer
90
+ # @since 1.0.12
91
+ # @param gl_client [Object] An instance of {Readiness::GitLab::Client}
92
+ # @param instance [String] The Zendesk instance being worked with. Accepted values are:
93
+ # - Global
94
+ # - Global Sandbox
95
+ # - US Government
96
+ # - US Government Sandbox
97
+ # @param location [String] The location (relative or absolute) of the repo's data folder
98
+ # @return [Array]
99
+ # @example
100
+ # require 'support_readiness'
101
+ # gl_config = Readiness::GitLab::Configuration.new
102
+ # gl_config.token = ENV.fetch('GL_TOKEN')
103
+ # gl_client = Readiness::GitLab::Client.new(gl_config)
104
+ # repo = Readiness::Repos::Articles.gather(gl_client, 'Global', 'automations/data')
105
+ # pp repo.count
106
+ # # => 15
107
+ def self.gather(gl_client, instance = 'Global', location = 'data')
108
+ @errors = []
109
+ @gl_client = gl_client
110
+ @instance = instance
111
+ @location = location
112
+ array = []
113
+ Dir["#{@location}/articles/**/*.yaml"].each do |f|
114
+ object = YAML.safe_load_file(f)
115
+ object['body'] = full_conversion(object)
116
+ validity_check(f, object)
117
+ object['id'] = nil
118
+ array.push(Zendesk::Articles.new(object))
119
+ end
120
+ repo_check(array)
121
+ report_errors unless @errors.count.zero?
122
+ array
123
+ end
124
+
125
+ ##
126
+ # Outputs an error report and exits with a status code of 1
127
+ #
128
+ # @author Jason Colyer
129
+ # @since 1.0.12
130
+ def self.report_errors
131
+ puts 'The following errors were found in the repo files:'
132
+ @errors.each do |e|
133
+ puts "- #{e}"
134
+ end
135
+ puts 'Rectify the errors and retry. We cannot proceed with those errors occurring.'
136
+ exit 1
137
+ end
138
+
139
+ ##
140
+ # Performs basic checks on the repo
141
+ #
142
+ # @author Jason Colyer
143
+ # @since 1.0.12
144
+ # @param objects [Array] The Array of Hashes derived from parsing the repo files
145
+ def self.repo_check(objects)
146
+ duplicate_names = objects.group_by { |o| o.title }.select { |k, v| v.size > 1 }.map(&:first)
147
+ unless duplicate_names.count.zero?
148
+ duplicate_names.each do |d|
149
+ @errors.push("The title '#{d}' is used in multiple files")
150
+ end
151
+ end
152
+ end
153
+
154
+ ##
155
+ # Performs a full conversion on the article's body
156
+ #
157
+ # @author Jason Colyer
158
+ # @since 1.0.12
159
+ # @param object [Hash]
160
+ # @return [String]
161
+ def self.full_conversion(object)
162
+ html = markdown_to_html(object)
163
+ @doc = Nokogiri::HTML.fragment(html)
164
+ rearrange_anchors
165
+ replace_modifiers
166
+ @doc.to_html
167
+ end
168
+
169
+ ##
170
+ # Converts the manasged content file's markdown to html
171
+ #
172
+ # @author Jason Colyer
173
+ # @since 1.0.12
174
+ # @param object [Hash]
175
+ # @return [String]
176
+ def self.markdown_to_html(object)
177
+ markdown = File.readlines("#{@location}/managed_content/pages/#{object['content_path']}")
178
+ body = replace_internal_links(markdown, object)
179
+ html = Readiness::GitLab::Markdown.convert(@gl_client, body, true, 'gitlab-com/support/support-pages' )
180
+ data_object_dom(object) + html
181
+ end
182
+
183
+ ##
184
+ # Returns the data_object_dom String
185
+ #
186
+ # @author Jason Colyer
187
+ # @since 1.0.12
188
+ # @param object [Hash]
189
+ # @return [String]
190
+ def self.data_object_dom(object)
191
+ <<~STRING
192
+ <p id="data_object_dom" style="display: none;" data-path="pages/#{object['content_path']}">&nbsp;</p>
193
+ STRING
194
+ end
195
+
196
+ ##
197
+ # Replaces internal links with their external values
198
+ #
199
+ # @author Jason Colyer
200
+ # @since 1.0.12
201
+ # @param object [Hash]
202
+ # @return [String]
203
+ def self.replace_internal_links(lines, object)
204
+ lines.each_with_index do |line, index|
205
+ line.scan(/{{LINK:\ ([^}]+)}}/).each do |matches|
206
+ matches.each do |m|
207
+ parts = m.split('#')
208
+ anchor = determine_anchor(parts)
209
+ lines[index] = line.gsub("{{LINK: #{m}}}", support_url("#{find_file(parts.first)['id']}#{anchor}", object))
210
+ end
211
+ end
212
+ end
213
+ lines.join
214
+ end
215
+
216
+ ##
217
+ # Locates the correct YAML content
218
+ #
219
+ # @author Jason Colyer
220
+ # @since 1.0.12
221
+ # @param path [String]
222
+ # @return [Hash]
223
+ def self.find_file(path)
224
+ raw_yaml.detect { |y| y['content_path'] =~ /#{path}/ }
225
+ end
226
+
227
+ ##
228
+ # Determiens the correct anchor for a String
229
+ #
230
+ # @author Jason Colyer
231
+ # @since 1.0.12
232
+ # @param parts [Array]
233
+ # @return [String]
234
+ def self.determine_anchor(parts)
235
+ return '' if parts.count == 1
236
+
237
+ "##{parts.last}"
238
+ end
239
+
240
+ ##
241
+ # Placeholder functiont to set the global variable @raw_yaml
242
+ #
243
+ # @author Jason Colyer
244
+ # @since 1.0.12
245
+ # @return [Array]
246
+ def self.raw_yaml
247
+ @raw_yaml ||= determine_raw_yaml
248
+ end
249
+
250
+ ##
251
+ # Function to set the default value for the @raw_yaml global variable
252
+ #
253
+ # @author Jason Colyer
254
+ # @since 1.0.12
255
+ # @return [Array]
256
+ def self.determine_raw_yaml
257
+ array = []
258
+ Dir["#{@location}/articles/**/*.yaml"].each do |f|
259
+ array.push(YAML.safe_load_file(f))
260
+ end
261
+ array
262
+ end
263
+
264
+ ##
265
+ # Returns the external URL for a link
266
+ #
267
+ # @author Jason Colyer
268
+ # @since 1.0.12
269
+ # @param endpoint [String]
270
+ # @param yaml [Hash]
271
+ # @return [String]
272
+ def self.support_url(endpoint, yaml)
273
+ return "##{endpoint.split('#').last}" if endpoint.split('#').first.to_i == yaml['id'].to_i
274
+ return "https://support.gitlab.com/hc/en-us/articles/#{endpoint}" if @instance == 'Global'
275
+ return "https://gitlab1707170878.zendesk.com/hc/en-us/articles/#{endpoint}" if @instance == 'Global Sandbox'
276
+ return "https://federal-support.gitlab.com/hc/en-us/articles/#{endpoint}" if @instance == 'US Government'
277
+ return "https://gitlabfederalsupport1585318082.zendesk.com/hc/en-us/articles/#{endpoint}" if @instance == 'US Government Sandbox'
278
+
279
+ handle_request_error(1, 'Zendesk', 404, { action: 'Find ZD instance', id: @instance })
280
+ end
281
+
282
+ ##
283
+ # Rearranges anchors into the correct format
284
+ #
285
+ # @author Jason Colyer
286
+ # @since 1.0.12
287
+ def self.rearrange_anchors
288
+ %w[h1 h2 h3 h4 h5 h6].each do |h|
289
+ headers = @doc.css(h)
290
+ next if headers.count.zero?
291
+
292
+ headers.each do |header|
293
+ anchor = header.children.at_css '.anchor'
294
+ anchor['name'] = anchor['href'].gsub('#', '')
295
+ text = header.children.last
296
+ text.add_next_sibling(anchor)
297
+ end
298
+ end
299
+ end
300
+
301
+ ##
302
+ # Replaces internal modifiers with their external values
303
+ #
304
+ # @author Jason Colyer
305
+ # @since 1.0.12
306
+ def self.replace_modifiers
307
+ @doc.children.each do |children|
308
+ next unless children.to_s =~ /{{([^}]+)}}/
309
+
310
+ children.each do |child|
311
+ current = child.parent.get_attribute('class').to_s.split
312
+ current.push(child.to_s[/{{([^}]+)}}/, 1])
313
+ child.parent.set_attribute('class', current.join(' '))
314
+ child.content = child.to_s.gsub(/{{([^}]+)}}/, '')
315
+ end
316
+ end
317
+ end
318
+
319
+ ##
320
+ # Performs basic checks on a repo file
321
+ #
322
+ # @author Jason Colyer
323
+ # @since 1.0.12
324
+ # @param file [String] The path to the repo file
325
+ # @param object [Hash] The Hash derived from parsing a YAML file
326
+ def self.validity_check(file, object)
327
+ folder = file.split("#{@location}/").last.split('/').first
328
+ @errors.push("Missing position: #{file}") if object['position'].nil?
329
+ @errors.push("Missing title: #{file}") if object['title'].nil?
330
+ @errors.push("Inactive article in active folder: #{file}") if folder == 'active' && object['draft']
331
+ @errors.push("Active article in inactive folder: #{file}") if folder == 'inactive' && !object['draft']
332
+ end
333
+ end
334
+ end
335
+ end
@@ -0,0 +1,247 @@
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 Automations within the module {Readiness::Repos}.
9
+ #
10
+ # @author Jason Colyer
11
+ # @since 1.0.12
12
+ class Automations < Readiness::Client
13
+ ##
14
+ # Compares the repo automation files to the Zendesk instance automations
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::Automations.compare(client, 'automations/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::Automations.compare(client, 'automations/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::Automations.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::Automations}
90
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::Automations}
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::Automations} to use for updates
107
+ #
108
+ # @author Jason Colyer
109
+ # @since 1.0.12
110
+ # @param repo [Object] An instance of {Readiness::Zendesk::Automations}
111
+ # @param zendesk [Object] An instance of {Readiness::Zendesk::Automations}
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 automation 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::Automations.gather('automations/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
+ object = convert_managed_webhook(object) if object['contains_managed_webhook']
139
+ validity_check(f, object)
140
+ object['id'] = nil
141
+ array.push(Zendesk::Automations.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 position: #{file}") if object['position'].nil?
172
+ @errors.push("Missing title: #{file}") if object['title'].nil?
173
+ @errors.push("Inactive automation in active folder: #{file}") if folder == 'active' && !object['active']
174
+ @errors.push("Active automation 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 title '#{d}' is used in multiple files")
188
+ end
189
+ end
190
+ end
191
+
192
+ ##
193
+ # Performs conversions for a repo file if using managed content
194
+ #
195
+ # @author Jason Colyer
196
+ # @since 1.0.12
197
+ # @param object [Hash] The Hash derived from parsing a YAML file
198
+ def self.convert_managed_content(object)
199
+ path = "#{@location}/managed_content/#{object['title']}.md"
200
+ handle_request_error(1, 'Repos', 404, { action: 'Get managed content', id: object['title'] }) unless File.exist?(path)
201
+ object['actions'].each_with_index do |action, index|
202
+ if action['value'].is_a?(String)
203
+ if action['value'] =~ /MANAGED_CONTENT/
204
+ if action['value'] == 'MANAGED_CONTENT'
205
+ object['actions'][index]['value'] = action['value'].gsub('MANAGED_CONTENT', File.read(path).chomp)
206
+ else
207
+ object['actions'][index]['value'] = action['value'].gsub('MANAGED_CONTENT', File.read(path).chomp.gsub("\n", '\\n'))
208
+ end
209
+ end
210
+ elsif action['value'].is_a?(Array)
211
+ action['value'].each_with_index do |value, sub_index|
212
+ if value =~ /MANAGED_CONTENT/
213
+ if value == 'MANAGED_CONTENT'
214
+ object['actions'][index]['value'][sub_index] = value.gsub('MANAGED_CONTENT', File.read(path).chomp)
215
+ else
216
+ object['actions'][index]['value'][sub_index] = value.gsub('MANAGED_CONTENT', File.read(path).chomp.gsub("\n", '\\n'))
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
222
+ object
223
+ end
224
+
225
+ ##
226
+ # Performs conversions for a repo file if using managed webhooks
227
+ #
228
+ # @author Jason Colyer
229
+ # @since 1.0.12
230
+ # @param object [Hash] The Hash derived from parsing a YAML file
231
+ def self.convert_managed_webhook(object)
232
+ path = "#{@location}/managed_content/#{object['title']}.webhook"
233
+ handle_request_error(1, 'Repos', 404, { action: 'Get managed webhook', id: object['title'] }) unless File.exist?(path)
234
+ object['actions'].each_with_index do |action, index|
235
+ next unless action['value'].is_a?(Array)
236
+
237
+ action['value'].each_with_index do |value, sub_index|
238
+ next unless value == 'MANAGED_WEBHOOK'
239
+
240
+ object['actions'][index]['value'][sub_index] = JSON.parse(File.read(path))
241
+ end
242
+ end
243
+ object
244
+ end
245
+ end
246
+ end
247
+ end