zendesk_apps_support 3.2.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/config/locales/en.yml +1 -0
- data/config/locales/translations/zendesk_apps_support.yml +6 -0
- data/lib/zendesk_apps_support.rb +2 -0
- data/lib/zendesk_apps_support/assets/src.js.erb +1 -1
- data/lib/zendesk_apps_support/finders.rb +6 -4
- data/lib/zendesk_apps_support/i18n.rb +5 -0
- data/lib/zendesk_apps_support/manifest.rb +55 -6
- data/lib/zendesk_apps_support/manifest/location_options.rb +34 -0
- data/lib/zendesk_apps_support/package.rb +21 -37
- data/lib/zendesk_apps_support/validations/manifest.rb +19 -41
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a9e45de07d4fc43d38abc3c8acc5181bc91e2186
|
4
|
+
data.tar.gz: 641719f94991cc135fa59d776cf1323dba3f93a1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8317dae950108e25ade2c756ab55687dfa72c01cc5d114470e3ed531c4b1be4ff17cd9fbce201568b0116b688daace243ea7147c3cb7a7dd561e6ae26e2e0cd3
|
7
|
+
data.tar.gz: 1bc68d32b49422d96f9d1f74572d7393f6a26def3140d558a4629426c1918687d94a49c847ec77171ce30179ac08c36dcdbaa7a4ed0d4a288f7f7e0a92d5c841
|
data/config/locales/en.yml
CHANGED
@@ -60,6 +60,7 @@ en:
|
|
60
60
|
invalid_location:
|
61
61
|
one: "%{invalid_locations} is an invalid location in %{host_name}."
|
62
62
|
other: "%{invalid_locations} are invalid locations in %{host_name}."
|
63
|
+
blank_location_uri: "%{location} location does not specify a URI."
|
63
64
|
invalid_location_uri: "%{uri} is either an invalid location URI, refers
|
64
65
|
to a missing asset, or does not use HTTPS."
|
65
66
|
duplicate_location:
|
@@ -144,6 +144,10 @@ parts:
|
|
144
144
|
key: "txt.apps.admin.error.app_build.invalid_location.other"
|
145
145
|
title: "App builder job: invalid locations"
|
146
146
|
value: "%{invalid_locations} are invalid locations in %{host_name}."
|
147
|
+
- translation:
|
148
|
+
key: "txt.apps.admin.error.app_build.blank_location_uri"
|
149
|
+
title: "App builder job: invalid URI for an iframe in the manifest"
|
150
|
+
value: "%{location} location does not specify a URI."
|
147
151
|
- translation:
|
148
152
|
key: "txt.apps.admin.error.app_build.invalid_location_uri"
|
149
153
|
title: "App builder job: invalid URI for an iframe in the manifest"
|
@@ -152,10 +156,12 @@ parts:
|
|
152
156
|
key: "txt.apps.admin.error.app_build.duplicate_location.one"
|
153
157
|
title: "App builder job: duplicate locations"
|
154
158
|
value: "%{duplicate_locations} is a duplicate location."
|
159
|
+
obsolete: "2016-12-31"
|
155
160
|
- translation:
|
156
161
|
key: "txt.apps.admin.error.app_build.duplicate_location.other"
|
157
162
|
title: "App builder job: duplicate locations"
|
158
163
|
value: "%{duplicate_locations} are duplicate locations."
|
164
|
+
obsolete: "2016-12-31"
|
159
165
|
- translation:
|
160
166
|
key: "txt.apps.admin.error.app_build.name_as_parameter_name"
|
161
167
|
title: "App builder job: error message when developer names a parameter 'name'"
|
data/lib/zendesk_apps_support.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module ZendeskAppsSupport
|
2
3
|
require 'zendesk_apps_support/engine'
|
3
4
|
|
@@ -29,6 +30,7 @@ module ZendeskAppsSupport
|
|
29
30
|
end
|
30
31
|
|
31
32
|
class Manifest
|
33
|
+
autoload :LocationOptions, 'zendesk_apps_support/manifest/location_options'
|
32
34
|
autoload :Parameter, 'zendesk_apps_support/manifest/parameter'
|
33
35
|
autoload :NoOverrideHash, 'zendesk_apps_support/manifest/no_override_hash'
|
34
36
|
end
|
@@ -15,7 +15,7 @@ with( ZendeskApps.AppScope.create() ) {
|
|
15
15
|
}
|
16
16
|
<% end %>
|
17
17
|
var app = ZendeskApps.defineApp(<%= iframe_only ? 'null' : 'source' %>)
|
18
|
-
.reopenClass(<%=
|
18
|
+
.reopenClass(<%= app_class_properties.to_json %>)
|
19
19
|
.reopen({
|
20
20
|
appName: <%= name.to_json %>,
|
21
21
|
appVersion: <%= version.to_json %>,
|
@@ -23,10 +23,12 @@ module ZendeskAppsSupport
|
|
23
23
|
private
|
24
24
|
|
25
25
|
def filter_by_arg(arg)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
lambda do |findable_record|
|
27
|
+
arg.all? do |attribute, value|
|
28
|
+
value = value.to_s if value.is_a? Symbol
|
29
|
+
findable_record.public_send(attribute) == value
|
30
|
+
end
|
31
|
+
end
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
@@ -26,7 +26,6 @@ module ZendeskAppsSupport
|
|
26
26
|
}.freeze
|
27
27
|
|
28
28
|
attr_reader(*RUBY_TO_JSON.keys)
|
29
|
-
attr_reader :locations
|
30
29
|
|
31
30
|
alias_method :requirements_only?, :requirements_only
|
32
31
|
alias_method :marketing_only?, :marketing_only
|
@@ -46,8 +45,42 @@ module ZendeskAppsSupport
|
|
46
45
|
no_template || []
|
47
46
|
end
|
48
47
|
|
49
|
-
def
|
50
|
-
|
48
|
+
def products
|
49
|
+
@products ||=
|
50
|
+
location_options.map { |lo| lo.location.product_code }
|
51
|
+
.uniq
|
52
|
+
.map { |code| Product.find_by(code: code) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def location_options
|
56
|
+
@location_options ||= locations.flat_map do |product_key, locations|
|
57
|
+
product = Product.find_by(name: product_key)
|
58
|
+
locations.map do |location_key, location_options|
|
59
|
+
location = product && Location.find_by(product_code: product.code, name: location_key)
|
60
|
+
options_with_defaults = {
|
61
|
+
'signed' => signed_urls?
|
62
|
+
}.merge(location_options)
|
63
|
+
Manifest::LocationOptions.new(location, options_with_defaults)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def app_class_properties
|
69
|
+
{
|
70
|
+
experiments: experiments,
|
71
|
+
location: locations,
|
72
|
+
noTemplate: no_template_locations,
|
73
|
+
singleInstall: single_install?,
|
74
|
+
signedUrls: signed_urls?
|
75
|
+
}.select { |_k, v| !v.nil? }
|
76
|
+
end
|
77
|
+
|
78
|
+
def unknown_locations(host)
|
79
|
+
if locations.key?(host)
|
80
|
+
locations[host].keys.uniq - Location::LOCATIONS_AVAILABLE.map(&:name)
|
81
|
+
else
|
82
|
+
[]
|
83
|
+
end
|
51
84
|
end
|
52
85
|
|
53
86
|
def unknown_hosts
|
@@ -87,8 +120,13 @@ module ZendeskAppsSupport
|
|
87
120
|
set_locations_and_hosts
|
88
121
|
end
|
89
122
|
|
123
|
+
LEGACY_LOCATION_OBJECT = { 'url' => LEGACY_URI_STUB }.freeze
|
124
|
+
private_constant :LEGACY_LOCATION_OBJECT
|
125
|
+
|
90
126
|
private
|
91
127
|
|
128
|
+
attr_reader :locations
|
129
|
+
|
92
130
|
def set_locations_and_hosts
|
93
131
|
@locations =
|
94
132
|
case original_locations
|
@@ -97,10 +135,11 @@ module ZendeskAppsSupport
|
|
97
135
|
replace_legacy_locations original_locations
|
98
136
|
when Array
|
99
137
|
@used_hosts = ['support']
|
100
|
-
|
138
|
+
new_locations = NoOverrideHash[original_locations.map { |location| [ location, LEGACY_LOCATION_OBJECT ] }]
|
139
|
+
{ 'support' => new_locations }
|
101
140
|
when String
|
102
141
|
@used_hosts = ['support']
|
103
|
-
{ 'support' => { original_locations =>
|
142
|
+
{ 'support' => { original_locations => LEGACY_LOCATION_OBJECT } }
|
104
143
|
# TODO: error out for numbers and Booleans
|
105
144
|
else # NilClass
|
106
145
|
@used_hosts = ['support']
|
@@ -114,7 +153,17 @@ module ZendeskAppsSupport
|
|
114
153
|
product_key = product.name.to_s
|
115
154
|
legacy_key = product.legacy_name.to_s
|
116
155
|
value_for_product = original_locations.fetch(product_key, original_locations[legacy_key])
|
117
|
-
value_for_product && new_locations_obj[product_key] = value_for_product
|
156
|
+
value_for_product && new_locations_obj[product_key] = replace_string_uris(value_for_product)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def replace_string_uris(product_locations)
|
162
|
+
product_locations.each_with_object({}) do |(k, v), new_locations|
|
163
|
+
if v.is_a? Hash
|
164
|
+
new_locations[k] = v
|
165
|
+
else
|
166
|
+
new_locations[k] = { 'url' => v }
|
118
167
|
end
|
119
168
|
end
|
120
169
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ZendeskAppsSupport
|
3
|
+
class Manifest
|
4
|
+
class LocationOptions
|
5
|
+
RUBY_TO_JSON = {
|
6
|
+
legacy: 'legacy',
|
7
|
+
auto_load: 'autoLoad',
|
8
|
+
auto_hide: 'autoHide',
|
9
|
+
signed: 'signed',
|
10
|
+
url: 'url'
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
attr_reader :location
|
14
|
+
attr_reader(*RUBY_TO_JSON.keys)
|
15
|
+
|
16
|
+
alias_method :signed?, :signed
|
17
|
+
alias_method :legacy?, :legacy
|
18
|
+
alias_method :auto_load?, :auto_load
|
19
|
+
alias_method :auto_hide?, :auto_hide
|
20
|
+
|
21
|
+
def initialize(location, options)
|
22
|
+
@location = location
|
23
|
+
|
24
|
+
RUBY_TO_JSON.each do |ruby, json|
|
25
|
+
instance_variable_set(:"@#{ruby}", options[json])
|
26
|
+
end
|
27
|
+
@legacy ||= @url == ZendeskAppsSupport::Manifest::LEGACY_URI_STUB
|
28
|
+
@auto_load = options.fetch('autoLoad', true)
|
29
|
+
@auto_hide ||= false
|
30
|
+
@signed ||= false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -15,7 +15,7 @@ module ZendeskAppsSupport
|
|
15
15
|
DEFAULT_SCSS = File.read(File.expand_path('../assets/default_styles.scss', __FILE__))
|
16
16
|
SRC_TEMPLATE = Erubis::Eruby.new(File.read(File.expand_path('../assets/src.js.erb', __FILE__)))
|
17
17
|
|
18
|
-
LOCATIONS_WITH_ICONS =
|
18
|
+
LOCATIONS_WITH_ICONS = %w(top_bar nav_bar system_top_bar).freeze
|
19
19
|
|
20
20
|
attr_reader :lib_root, :root, :warnings
|
21
21
|
|
@@ -119,19 +119,11 @@ module ZendeskAppsSupport
|
|
119
119
|
# if no_template is an array, we still need the templates
|
120
120
|
templates = manifest.no_template == true ? {} : compiled_templates(app_id, asset_url_prefix)
|
121
121
|
|
122
|
-
app_settings = {
|
123
|
-
experiments: manifest.experiments,
|
124
|
-
location: manifest.locations,
|
125
|
-
noTemplate: manifest.no_template_locations,
|
126
|
-
singleInstall: manifest.single_install?,
|
127
|
-
signedUrls: manifest.signed_urls?
|
128
|
-
}.select { |_k, v| !v.nil? }
|
129
|
-
|
130
122
|
SRC_TEMPLATE.result(
|
131
123
|
name: name,
|
132
124
|
version: manifest.version,
|
133
125
|
source: source,
|
134
|
-
|
126
|
+
app_class_properties: manifest.app_class_properties,
|
135
127
|
asset_url_prefix: asset_url_prefix,
|
136
128
|
location_icons: location_icons,
|
137
129
|
app_class_name: app_class_name,
|
@@ -184,11 +176,6 @@ module ZendeskAppsSupport
|
|
184
176
|
trans[manifest.default_locale]
|
185
177
|
end
|
186
178
|
|
187
|
-
def has_location?
|
188
|
-
manifest.location?
|
189
|
-
end
|
190
|
-
deprecate :has_location?, 'manifest.location?', 2016, 9
|
191
|
-
|
192
179
|
def has_file?(path)
|
193
180
|
File.file?(path_to(path))
|
194
181
|
end
|
@@ -203,11 +190,6 @@ module ZendeskAppsSupport
|
|
203
190
|
File.exist?(scss_file) ? File.read(scss_file) : ( File.exist?(css_file) ? File.read(css_file) : '' )
|
204
191
|
end
|
205
192
|
|
206
|
-
def locations
|
207
|
-
manifest.locations
|
208
|
-
end
|
209
|
-
deprecate :locations, 'manifest.locations', 2016, 9
|
210
|
-
|
211
193
|
def iframe_only?
|
212
194
|
manifest.iframe_only?
|
213
195
|
end
|
@@ -282,23 +264,25 @@ module ZendeskAppsSupport
|
|
282
264
|
end
|
283
265
|
|
284
266
|
def location_icons
|
285
|
-
{}.tap do |location_icons|
|
286
|
-
manifest.
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
}
|
299
|
-
|
300
|
-
{}
|
301
|
-
|
267
|
+
Hash.new { |h, k| h[k] = {} }.tap do |location_icons|
|
268
|
+
manifest.location_options.each do |location_options|
|
269
|
+
next unless location_options.location &&
|
270
|
+
LOCATIONS_WITH_ICONS.include?(location_options.location.name) &&
|
271
|
+
location_options.location.product == Product::SUPPORT
|
272
|
+
|
273
|
+
host = location_options.location.product.name
|
274
|
+
location = location_options.location.name
|
275
|
+
location_icons[host][location] = if (has_file?("assets/icon_#{location}.svg"))
|
276
|
+
cache_busting_param = "?#{Time.now.to_i}" unless @is_cached
|
277
|
+
{ 'svg' => "icon_#{location}.svg#{cache_busting_param}" }
|
278
|
+
elsif (has_file?("assets/icon_#{location}_inactive.png"))
|
279
|
+
{
|
280
|
+
'inactive' => "icon_#{location}_inactive.png",
|
281
|
+
'active' => has_file?("assets/icon_#{location}_active.png") ? "icon_#{location}_active.png" : "icon_#{location}_inactive.png",
|
282
|
+
'hover' => has_file?("assets/icon_#{location}_hover.png") ? "icon_#{location}_hover.png" : "icon_#{location}_inactive.png"
|
283
|
+
}
|
284
|
+
else
|
285
|
+
{}
|
302
286
|
end
|
303
287
|
end
|
304
288
|
end
|
@@ -34,7 +34,6 @@ module ZendeskAppsSupport
|
|
34
34
|
else
|
35
35
|
errors << missing_location_error(package)
|
36
36
|
errors << invalid_location_error(package)
|
37
|
-
errors << duplicate_location_error(manifest)
|
38
37
|
errors << missing_framework_version(manifest)
|
39
38
|
errors << location_framework_mismatch(manifest)
|
40
39
|
errors << invalid_version_error(manifest, package)
|
@@ -75,7 +74,7 @@ module ZendeskAppsSupport
|
|
75
74
|
end
|
76
75
|
|
77
76
|
def ban_location(manifest)
|
78
|
-
ValidationError.new(:no_location_required)
|
77
|
+
ValidationError.new(:no_location_required) unless manifest.location_options.empty?
|
79
78
|
end
|
80
79
|
|
81
80
|
def ban_framework_version(manifest)
|
@@ -139,31 +138,32 @@ module ZendeskAppsSupport
|
|
139
138
|
end
|
140
139
|
|
141
140
|
def missing_location_error(package)
|
142
|
-
missing_keys_validation_error(['location'])
|
141
|
+
missing_keys_validation_error(['location']) if package.manifest.location_options.empty?
|
143
142
|
end
|
144
143
|
|
145
144
|
def invalid_location_error(package)
|
146
145
|
errors = []
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
if (invalid_locations = locations.keys - locations_allowed).any?
|
153
|
-
errors << ValidationError.new(:invalid_location,
|
154
|
-
invalid_locations: invalid_locations.join(', '),
|
155
|
-
host_name: host,
|
156
|
-
count: invalid_locations.length)
|
146
|
+
package.manifest.location_options.each do |location_options|
|
147
|
+
if location_options.url && !location_options.url.empty?
|
148
|
+
errors << invalid_location_uri_error(package, location_options.url)
|
149
|
+
elsif location_options.auto_load?
|
150
|
+
errors << ValidationError.new(:blank_location_uri, location: location_options.location.name)
|
157
151
|
end
|
152
|
+
end
|
158
153
|
|
159
|
-
|
160
|
-
|
161
|
-
|
154
|
+
Product::PRODUCTS_AVAILABLE.each do |product|
|
155
|
+
invalid_locations = package.manifest.unknown_locations(product.name)
|
156
|
+
next if invalid_locations.empty?
|
157
|
+
errors << ValidationError.new(:invalid_location,
|
158
|
+
invalid_locations: invalid_locations.join(', '),
|
159
|
+
host_name: product.name,
|
160
|
+
count: invalid_locations.length)
|
162
161
|
end
|
163
162
|
|
164
163
|
package.manifest.unknown_hosts.each do |unknown_host|
|
165
164
|
errors << ValidationError.new(:invalid_host, host_name: unknown_host)
|
166
165
|
end
|
166
|
+
|
167
167
|
errors
|
168
168
|
end
|
169
169
|
|
@@ -186,15 +186,6 @@ module ZendeskAppsSupport
|
|
186
186
|
uri.path.start_with?('assets/') && package.has_file?(uri.path)
|
187
187
|
end
|
188
188
|
|
189
|
-
def duplicate_location_error(manifest)
|
190
|
-
locations = *manifest.locations
|
191
|
-
duplicate_locations = *locations.select { |location| locations.count(location) > 1 }.uniq
|
192
|
-
|
193
|
-
unless duplicate_locations.empty?
|
194
|
-
ValidationError.new(:duplicate_location, duplicate_locations: duplicate_locations.join(', '), count: duplicate_locations.length)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
189
|
def missing_framework_version(manifest)
|
199
190
|
missing_keys_validation_error([RUBY_TO_JSON[:framework_version]]) if manifest.framework_version.nil?
|
200
191
|
end
|
@@ -246,27 +237,14 @@ module ZendeskAppsSupport
|
|
246
237
|
end
|
247
238
|
|
248
239
|
def location_framework_mismatch(manifest)
|
249
|
-
|
250
|
-
stub = ZendeskAppsSupport::Manifest::LEGACY_URI_STUB
|
251
|
-
iframe_locations = locations_any?(locations) do |url|
|
252
|
-
url != stub
|
253
|
-
end
|
254
|
-
legacy_locations = (!iframe_locations && manifest.location?) || locations_any?(locations) do |url|
|
255
|
-
url == stub
|
256
|
-
end
|
240
|
+
legacy_locations, iframe_locations = manifest.location_options.partition(&:legacy?)
|
257
241
|
if manifest.iframe_only?
|
258
|
-
return ValidationError.new(:locations_must_be_urls)
|
259
|
-
elsif iframe_locations
|
242
|
+
return ValidationError.new(:locations_must_be_urls) unless legacy_locations.empty?
|
243
|
+
elsif !iframe_locations.empty?
|
260
244
|
return ValidationError.new(:locations_cant_be_urls)
|
261
245
|
end
|
262
246
|
end
|
263
247
|
|
264
|
-
def locations_any?(locations)
|
265
|
-
locations.values.any? do |location_hash|
|
266
|
-
location_hash.values.any? { |url| yield(url) }
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
248
|
# TODO: support the new location format in the no_template array and check the app actually runs in
|
271
249
|
# included locations
|
272
250
|
def no_template_format_error(manifest)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zendesk_apps_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James A. Rosen
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2016-12-
|
14
|
+
date: 2016-12-05 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: i18n
|
@@ -139,6 +139,20 @@ dependencies:
|
|
139
139
|
- - "~>"
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: 1.6.6
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: rubocop
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - "~>"
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: 0.46.0
|
149
|
+
type: :development
|
150
|
+
prerelease: false
|
151
|
+
version_requirements: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - "~>"
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: 0.46.0
|
142
156
|
description: Support to help you develop Zendesk Apps.
|
143
157
|
email:
|
144
158
|
- dev@zendesk.com
|
@@ -166,6 +180,7 @@ files:
|
|
166
180
|
- lib/zendesk_apps_support/installed.rb
|
167
181
|
- lib/zendesk_apps_support/location.rb
|
168
182
|
- lib/zendesk_apps_support/manifest.rb
|
183
|
+
- lib/zendesk_apps_support/manifest/location_options.rb
|
169
184
|
- lib/zendesk_apps_support/manifest/no_override_hash.rb
|
170
185
|
- lib/zendesk_apps_support/manifest/parameter.rb
|
171
186
|
- lib/zendesk_apps_support/package.rb
|
@@ -201,7 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
201
216
|
version: 1.3.6
|
202
217
|
requirements: []
|
203
218
|
rubyforge_project:
|
204
|
-
rubygems_version: 2.
|
219
|
+
rubygems_version: 2.6.8
|
205
220
|
signing_key:
|
206
221
|
specification_version: 4
|
207
222
|
summary: Support to help you develop Zendesk Apps.
|