gitlab_support_readiness 1.0.11 → 1.0.12

Sign up to get free protection for your applications and to get access to all the features.
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,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Defines the module Readiness.
4
+ module Readiness
5
+ # Defines the module Pagerduty
6
+ module Pagerduty
7
+ ##
8
+ # Defines the class Users within the module {Readiness::Pagerduty}.
9
+ #
10
+ # @author Jason Colyer
11
+ # @since 1.0.12
12
+ class Users < Readiness::Client
13
+ attr_accessor :avatar_url, :color, :contact_methods, :description, :email, :html_url, :id, :invitation_sent, :job_title, :license, :name, :notification_rules, :role, :self, :summary, :teams, :time_zone, :type
14
+
15
+ ##
16
+ # Creates a new {Readiness::Pagerduty::Users} instance
17
+ #
18
+ # @author Jason Colyer
19
+ # @since 1.0.12
20
+ # @param object [Object] An instance of {Readiness::Pagerduty::Users}
21
+ # @example
22
+ # require 'support_readiness'
23
+ # Readiness::Pagerduty::Users.new
24
+ def initialize(object = {})
25
+ @avatar_url = object['avatar_url']
26
+ @color = object['color']
27
+ @contact_methods = object['contact_methods']
28
+ @description = object['description']
29
+ @email = object['email']
30
+ @html_url = object['html_url']
31
+ @id = object['id']
32
+ @invitation_sent = object['invitation_sent']
33
+ @job_title = object['job_title']
34
+ @license = object['license']
35
+ @name = object['name']
36
+ @notification_rules = object['notification_rules']
37
+ @role = object['role']
38
+ @self = object['self']
39
+ @summary = object['summary']
40
+ @teams = object['teams']
41
+ @time_zone = object['time_zone']
42
+ @type = object['type']
43
+ end
44
+
45
+ ##
46
+ # Lists users within Pagerduty
47
+ #
48
+ # @author Jason Colyer
49
+ # @since 1.0.12
50
+ # @param client [Object] An instance of {Readiness::Pagerduty::Client}
51
+ # @return [Array]
52
+ # @see https://developer.pagerduty.com/api-reference/c96e889522dd6-list-users Pagerduty API > Users > List users
53
+ # @example
54
+ # require 'support_readiness'
55
+ # config = Readiness::Pagerduty::Configuration.new
56
+ # config.token = 'abc123'
57
+ # client = Readiness::Pagerduty::Client.new(config)
58
+ # users = Readiness::Pagerduty::Users.list(client)
59
+ # pp users.count
60
+ # # => 436
61
+ def self.list(client)
62
+ array = []
63
+ offset = 0
64
+ loop do
65
+ response = client.connection.get "users?limit=100&offset=#{offset}"
66
+ body = Oj.load(response.body)
67
+ array += body['users'].map { |u| Users.new(u) }
68
+ break unless body['more']
69
+
70
+ offset += 100
71
+ end
72
+ array.uniq
73
+ end
74
+
75
+ ##
76
+ # Shows info of a Pagerduty user. This will not exit on error (except for Auth errors)
77
+ #
78
+ # @author Jason Colyer
79
+ # @since 1.0.12
80
+ # @param client [Object] An instance of {Readiness::Pagerduty::Client}
81
+ # @see https://developer.pagerduty.com/api-reference/2395ca1feb25e-get-a-user Pagerduty API > Users > Get a user
82
+ # @param uid [String] The user ID to look for
83
+ # @return [Hash]
84
+ # @example
85
+ # require 'support_readiness'
86
+ # config = Readiness::Pagerduty::Configuration.new
87
+ # config.token = 'abc123'
88
+ # client = Readiness::Pagerduty::Client.new(config)
89
+ # user = Readiness::Pagerduty::Users.find(client, 'ABC123')
90
+ # pp user.name
91
+ # # => "Alice Example"
92
+ def self.find(client, uid)
93
+ response = client.connection.get("users/#{uid}")
94
+ handle_request_error(0, 'Pagerduty', response.status, { action: 'get', id: uid }) unless response.status == 200
95
+ return Users.new(Oj.load(response.body)['user']) if response.status == 200
96
+
97
+ Oj.load(response.body)
98
+ end
99
+
100
+ ##
101
+ # Shows info of a Pagerduty user. This will exit on error
102
+ #
103
+ # @author Jason Colyer
104
+ # @since 1.0.12
105
+ # @param client [Object] An instance of {Readiness::Pagerduty::Client}
106
+ # @param uid [String] The user ID to look for
107
+ # @return [Object] An instance of {Readiness::Pagerduty::Users}
108
+ # @see https://developer.pagerduty.com/api-reference/2395ca1feb25e-get-a-user Pagerduty API > Users > Get a user
109
+ # @example
110
+ # require 'support_readiness'
111
+ # config = Readiness::Pagerduty::Configuration.new
112
+ # config.token = 'abc123'
113
+ # client = Readiness::Pagerduty::Client.new(config)
114
+ # user = Readiness::Pagerduty::Users.find!(client, 'ABC123')
115
+ # pp user.name
116
+ # # => "Alice Example"
117
+ def self.find!(client, uid)
118
+ response = client.connection.get("users/#{uid}")
119
+ handle_request_error(1, 'Pagerduty', response.status, { action: 'Find user', id: uid }) unless response.status == 200
120
+ Users.new(Oj.load(response.body)['user'])
121
+ end
122
+
123
+ ##
124
+ # Shows info of a Pagerduty user using their email to find them. This will not exit on error (except Auth errors)
125
+ #
126
+ # @author Jason Colyer
127
+ # @since 1.0.12
128
+ # @param client [Object] An instance of {Readiness::Pagerduty::Client}
129
+ # @param email [String] The email to look for
130
+ # @return [Object] An instance of {Readiness::Pagerduty::Users}
131
+ # @example
132
+ # require 'support_readiness'
133
+ # config = Readiness::Pagerduty::Configuration.new
134
+ # config.token = 'abc123'
135
+ # client = Readiness::Pagerduty::Client.new(config)
136
+ # user = Readiness::Pagerduty::Users.find_by_email(client, 'alice@example.com')
137
+ # pp user.name
138
+ # # => "Alice Example"
139
+ def self.find_by_email(client, email)
140
+ list(client).detect { |u| u.email == email }
141
+ end
142
+
143
+ ##
144
+ # Shows info of a Pagerduty user using their email to find them. This will exit on error
145
+ #
146
+ # @author Jason Colyer
147
+ # @since 1.0.12
148
+ # @param client [Object] An instance of {Readiness::Pagerduty::Client}
149
+ # @param email [String] The email to look for
150
+ # @return [Object] An instance of {Readiness::Pagerduty::Users}
151
+ # @example
152
+ # require 'support_readiness'
153
+ # config = Readiness::Pagerduty::Configuration.new
154
+ # config.token = 'abc123'
155
+ # client = Readiness::Pagerduty::Client.new(config)
156
+ # user = Readiness::Pagerduty::Users.find_by_email!(client, 'alice@example.com')
157
+ # pp user.name
158
+ # # => "Alice Example"
159
+ def self.find_by_email!(client, email)
160
+ response = list(client).detect { |u| u.email == email }
161
+ handle_request_error(1, 'Pagerduty', 404, { action: 'Find user by email', id: email }) if response.nil?
162
+
163
+ response
164
+ end
165
+
166
+ ##
167
+ # Creates a user within Pagerduty. This will exit on error
168
+ #
169
+ # @author Jason Colyer
170
+ # @since 1.0.12
171
+ # @param client [Object] An instance of {Readiness::Pagerduty::Client}
172
+ # @param user [Object] An instance of {Readiness::Pagerduty::Users}
173
+ # @return [Object] An instance of {Readiness::Pagerduty::Users}
174
+ # @see https://developer.pagerduty.com/api-reference/4cb4fd0f5444a-create-a-user Pagerduty API > Users > Create a user
175
+ # @example
176
+ # require 'support_readiness'
177
+ # config = Readiness::Pagerduty::Configuration.new
178
+ # config.token = 'abc123'
179
+ # client = Readiness::Pagerduty::Client.new(config)
180
+ # user = Readiness::Pagerduty::Users.new
181
+ # user.name = 'Alice Example'
182
+ # user.email = 'alice@example.com'
183
+ # user.license = {
184
+ # id: 'P1C3FWI',
185
+ # type: 'license_reference'
186
+ # }
187
+ # create = Readiness::Pagerduty::Users.create!(client, user)
188
+ # pp create.id
189
+ # # => "ABC123"
190
+ def self.create!(client, user)
191
+ response = client.connection.post 'users', to_clean_json_with_key(user, 'user')
192
+ handle_request_error(1, 'Pagerduty', response.status, { action: 'Create user', id: user.email }) unless response.status == 201
193
+ Users.new(Oj.load(response.body)['user'])
194
+ end
195
+ end
196
+ end
197
+ end
@@ -12,5 +12,6 @@ module Readiness
12
12
  require "#{__dir__}/pagerduty/escalation_policies"
13
13
  require "#{__dir__}/pagerduty/schedules"
14
14
  require "#{__dir__}/pagerduty/services"
15
+ require "#{__dir__}/pagerduty/users"
15
16
  end
16
17
  end
@@ -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