embulk-input-zendesk 0.2.6 → 0.2.7
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/CHANGELOG.md +4 -0
- data/embulk-input-zendesk.gemspec +1 -1
- data/lib/embulk/input/zendesk/client.rb +78 -76
- data/test/embulk/input/zendesk/test_client.rb +57 -0
- metadata +51 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d1102bce0d8a2464284659c4349277604022de6
|
4
|
+
data.tar.gz: 44688236a95097808b51dfaa2528c87ba3230f6f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ee108f8f523bbc57ef69d4f943d51fa2ad1c18db75e91d8433b5a01178bc1f037a45f43db4334f7e0ca3cb8ed350e9d89180f769340eef53e0668a4b86bd81b
|
7
|
+
data.tar.gz: f3ac93d20e468e462a622ece7c2287935c9011739064935aaeccd899b3629aebc91258ee6363d8b1ca111b918a7202484cd21c78b71f4aa412159accd56f62cc
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
## 0.2.7 - 2017-07-19
|
2
|
+
* [fixed] Ensure thread pool is shutdown [#38](https://github.com/treasure-data/embulk-input-zendesk/pull/38)
|
3
|
+
* [enhancement] Add retry for temporary error: missing required key from JSON response
|
4
|
+
|
1
5
|
## 0.2.6 - 2017-05-23
|
2
6
|
* [enhancement] Enable incremental loading for ticket_metrics
|
3
7
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
Gem::Specification.new do |spec|
|
3
3
|
spec.name = "embulk-input-zendesk"
|
4
|
-
spec.version = "0.2.
|
4
|
+
spec.version = "0.2.7"
|
5
5
|
spec.authors = ["uu59", "muga", "sakama"]
|
6
6
|
spec.summary = "Zendesk input plugin for Embulk"
|
7
7
|
spec.description = "Loads records from Zendesk."
|
@@ -31,7 +31,7 @@ module Embulk
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
def
|
34
|
+
def create_pool
|
35
35
|
Concurrent::ThreadPoolExecutor.new(
|
36
36
|
min_threads: 10,
|
37
37
|
max_threads: 100,
|
@@ -69,36 +69,25 @@ module Embulk
|
|
69
69
|
end
|
70
70
|
|
71
71
|
# they have both Incremental API and non-incremental API
|
72
|
-
|
72
|
+
# 170717: `ticket_events` can use standard endpoint format now, ie. `<target>.json`
|
73
|
+
%w(tickets ticket_events users organizations).each do |target|
|
73
74
|
define_method(target) do |partial = true, start_time = 0, &block|
|
74
75
|
# Always use incremental_export. There is some difference between incremental_export and export.
|
75
76
|
incremental_export("/api/v2/incremental/#{target}.json", target, start_time, [], partial, &block)
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
79
|
-
# they have incremental API only
|
80
|
-
%w(ticket_events).each do |target|
|
81
|
-
define_method(target) do |partial = true, start_time = 0, &block|
|
82
|
-
path = "/api/v2/incremental/#{target}"
|
83
|
-
incremental_export(path, target, start_time, [], partial, &block)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
80
|
# Ticket metrics will need to be export using both the non incremental and incremental on ticket
|
88
81
|
# We provide support by filter out ticket_metrics with created at smaller than start time
|
89
82
|
# while passing the incremental start time to the incremental ticket/ticket_metrics export
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
export(path, target, &block)
|
99
|
-
else
|
100
|
-
incremental_export(path, "metric_sets", start_time, [], partial,{include: "metric_sets"}, &block)
|
101
|
-
end
|
83
|
+
define_method('ticket_metrics') do |partial = true, start_time = 0, &block|
|
84
|
+
if partial
|
85
|
+
# If partial export then we need to use the old end point. Since new end point return both ticket and
|
86
|
+
# ticket metric with ticket come first so the current approach that cut off the response packet won't work
|
87
|
+
# Since partial is only use for preview and guess so this should be fine
|
88
|
+
export('/api/v2/ticket_metrics.json', 'ticket_metrics', &block)
|
89
|
+
else
|
90
|
+
incremental_export('/api/v2/incremental/tickets.json', 'metric_sets', start_time, [], partial, { include: 'metric_sets' }, &block)
|
102
91
|
end
|
103
92
|
end
|
104
93
|
|
@@ -139,24 +128,21 @@ module Embulk
|
|
139
128
|
|
140
129
|
first_fetched[key].uniq { |r| r['id'] }.each do |record|
|
141
130
|
block.call record
|
142
|
-
# known_ticket_ids: collect fetched ticket IDs, to exclude in next step
|
143
131
|
end
|
144
132
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
133
|
+
execute_thread_pool do |pool|
|
134
|
+
(2..last_page_num).each do |page|
|
135
|
+
pool.post do
|
136
|
+
response = request(path, per_page: per_page, page: page)
|
137
|
+
fetched_records = extract_records_from_response(response, key)
|
138
|
+
Embulk.logger.info "Fetched #{key} on page=#{page} >>> size: #{fetched_records.length}"
|
139
|
+
fetched_records.uniq { |r| r['id'] }.each do |record|
|
140
|
+
block.call record
|
141
|
+
end
|
153
142
|
end
|
154
143
|
end
|
155
144
|
end
|
156
145
|
|
157
|
-
pool.shutdown
|
158
|
-
pool.wait_for_termination
|
159
|
-
|
160
146
|
nil # this is necessary different with incremental_export
|
161
147
|
end
|
162
148
|
|
@@ -177,60 +163,55 @@ module Embulk
|
|
177
163
|
end
|
178
164
|
end
|
179
165
|
|
180
|
-
def incremental_export(path, key, start_time = 0, known_ids = [], partial = true,query = {}, &block)
|
166
|
+
def incremental_export(path, key, start_time = 0, known_ids = [], partial = true, query = {}, &block)
|
167
|
+
query.merge!(start_time: start_time)
|
181
168
|
if partial
|
182
|
-
records = request_partial(path, query
|
169
|
+
records = request_partial(path, query).first(5)
|
183
170
|
records.uniq{|r| r["id"]}.each do |record|
|
184
171
|
block.call record
|
185
172
|
end
|
186
173
|
return
|
187
174
|
end
|
188
175
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
176
|
+
execute_thread_pool do |pool|
|
177
|
+
loop do
|
178
|
+
start_fetching = Time.now
|
179
|
+
response = request(path, query)
|
180
|
+
actual_fetched = 0
|
194
181
|
data = JSON.parse(response.body)
|
195
|
-
|
196
|
-
raise
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
updated_at = Time.parse(record["updated_at"])
|
210
|
-
next if updated_at <= Time.at(start_time)
|
211
|
-
end
|
182
|
+
# no key found in response occasionally => retry
|
183
|
+
raise TempError, "No '#{key}' found in JSON response" unless data.key? key
|
184
|
+
data[key].each do |record|
|
185
|
+
# https://developer.zendesk.com/rest_api/docs/core/incremental_export#excluding-system-updates
|
186
|
+
# "generated_timestamp" will be updated when Zendesk internal changing
|
187
|
+
# "updated_at" will be updated when ticket data was changed
|
188
|
+
# start_time for query parameter will be processed on Zendesk with generated_timestamp,
|
189
|
+
# but it was calculated by record' updated_at time.
|
190
|
+
# So the doesn't changed record from previous import would be appear by Zendesk internal changes.
|
191
|
+
# We ignore record that has updated_at <= start_time
|
192
|
+
if start_time && record["generated_timestamp"] && record["updated_at"]
|
193
|
+
updated_at = Time.parse(record["updated_at"])
|
194
|
+
next if updated_at <= Time.at(start_time)
|
195
|
+
end
|
212
196
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
197
|
+
# de-duplicated records.
|
198
|
+
# https://developer.zendesk.com/rest_api/docs/core/incremental_export#usage-notes
|
199
|
+
# https://github.com/zendesk/zendesk_api_client_rb/issues/251
|
200
|
+
next if known_ids.include?(record["id"])
|
217
201
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
202
|
+
known_ids << record["id"]
|
203
|
+
pool.post { block.call record }
|
204
|
+
actual_fetched += 1
|
205
|
+
end
|
206
|
+
Embulk.logger.info "Fetched #{actual_fetched} records from start_time:#{start_time} (#{Time.at(start_time)}) within #{Time.now.to_i - start_fetching.to_i} seconds"
|
207
|
+
start_time = data["end_time"]
|
224
208
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
209
|
+
# NOTE: If count is less than 1000, then stop paginating.
|
210
|
+
# Otherwise, use the next_page URL to get the next page of results.
|
211
|
+
# https://developer.zendesk.com/rest_api/docs/core/incremental_export#pagination
|
212
|
+
break data if data["count"] < 1000
|
213
|
+
end
|
229
214
|
end
|
230
|
-
|
231
|
-
pool.shutdown
|
232
|
-
pool.wait_for_termination
|
233
|
-
last_data
|
234
215
|
end
|
235
216
|
|
236
217
|
def extract_records_from_response(response, key)
|
@@ -387,6 +368,27 @@ module Embulk
|
|
387
368
|
end
|
388
369
|
end
|
389
370
|
|
371
|
+
def execute_thread_pool(&block)
|
372
|
+
pool = create_pool
|
373
|
+
pr = PerfectRetry.new do |config|
|
374
|
+
config.limit = @config[:retry_limit]
|
375
|
+
config.logger = Embulk.logger
|
376
|
+
config.log_level = nil
|
377
|
+
config.rescues = [TempError]
|
378
|
+
config.sleep = lambda{|n| @config[:retry_initial_wait_sec]* (2 ** (n-1)) }
|
379
|
+
end
|
380
|
+
pr.with_retry { block.call(pool) }
|
381
|
+
rescue => e
|
382
|
+
raise Embulk::DataError.new(e)
|
383
|
+
ensure
|
384
|
+
Embulk.logger.info 'ThreadPool shutting down...'
|
385
|
+
pool.shutdown
|
386
|
+
pool.wait_for_termination
|
387
|
+
Embulk.logger.info "ThreadPool shutdown? #{pool.shutdown?}"
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
class TempError < StandardError
|
390
392
|
end
|
391
393
|
end
|
392
394
|
end
|
@@ -572,6 +572,63 @@ module Embulk
|
|
572
572
|
end
|
573
573
|
end
|
574
574
|
|
575
|
+
sub_test_case "ensure thread pool is shutdown with/without errors, retry for TempError" do
|
576
|
+
def client
|
577
|
+
@client ||= Client.new(login_url: login_url, auth_method: "oauth", access_token: access_token, retry_limit: 1, retry_initial_wait_sec: 0)
|
578
|
+
end
|
579
|
+
|
580
|
+
setup do
|
581
|
+
stub(Embulk).logger { Logger.new(File::NULL) }
|
582
|
+
@httpclient = client.httpclient
|
583
|
+
stub(client).httpclient { @httpclient }
|
584
|
+
@pool = Concurrent::ThreadPoolExecutor.new
|
585
|
+
stub(client).create_pool { @pool }
|
586
|
+
end
|
587
|
+
test "should shutdown pool - without error" do
|
588
|
+
@httpclient.test_loopback_http_response << [
|
589
|
+
"HTTP/1.1 200",
|
590
|
+
"Content-Type: application/json",
|
591
|
+
"",
|
592
|
+
{
|
593
|
+
ticket_fields: [{ id: 1 }],
|
594
|
+
count: 1
|
595
|
+
}.to_json
|
596
|
+
].join("\r\n")
|
597
|
+
handler = proc { }
|
598
|
+
client.ticket_fields(false, &handler)
|
599
|
+
assert_equal(true, @pool.shutdown?)
|
600
|
+
end
|
601
|
+
|
602
|
+
test "should shutdown pool - with TempError (retry)" do
|
603
|
+
response = [
|
604
|
+
"HTTP/1.1 200",
|
605
|
+
"Content-Type: application/json",
|
606
|
+
"",
|
607
|
+
{ }.to_json # no required key: `tickets`, raise TempError
|
608
|
+
].join("\r\n")
|
609
|
+
@httpclient.test_loopback_http_response << response
|
610
|
+
@httpclient.test_loopback_http_response << response # retry 1
|
611
|
+
assert_raise(TempError) do
|
612
|
+
client.tickets(false)
|
613
|
+
end
|
614
|
+
assert_equal(true, @pool.shutdown?)
|
615
|
+
end
|
616
|
+
|
617
|
+
test "should shutdown pool - with DataError (no retry)" do
|
618
|
+
response = [
|
619
|
+
"HTTP/1.1 400", # unhandled error, wrapped in DataError
|
620
|
+
"Content-Type: application/json",
|
621
|
+
"",
|
622
|
+
{ }.to_json
|
623
|
+
].join("\r\n")
|
624
|
+
@httpclient.test_loopback_http_response << response
|
625
|
+
assert_raise(DataError) do
|
626
|
+
client.tickets(false)
|
627
|
+
end
|
628
|
+
assert_equal(true, @pool.shutdown?)
|
629
|
+
end
|
630
|
+
end
|
631
|
+
|
575
632
|
def login_url
|
576
633
|
"http://example.com"
|
577
634
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: embulk-input-zendesk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- uu59
|
@@ -10,190 +10,190 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-
|
13
|
+
date: 2017-07-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
+
name: perfect_retry
|
17
|
+
version_requirements: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - "~>"
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.5'
|
16
22
|
requirement: !ruby/object:Gem::Requirement
|
17
23
|
requirements:
|
18
24
|
- - "~>"
|
19
25
|
- !ruby/object:Gem::Version
|
20
26
|
version: '0.5'
|
21
|
-
name: perfect_retry
|
22
27
|
prerelease: false
|
23
28
|
type: :runtime
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: httpclient
|
24
31
|
version_requirements: !ruby/object:Gem::Requirement
|
25
32
|
requirements:
|
26
|
-
- - "
|
33
|
+
- - ">="
|
27
34
|
- !ruby/object:Gem::Version
|
28
|
-
version: '0
|
29
|
-
- !ruby/object:Gem::Dependency
|
35
|
+
version: '0'
|
30
36
|
requirement: !ruby/object:Gem::Requirement
|
31
37
|
requirements:
|
32
38
|
- - ">="
|
33
39
|
- !ruby/object:Gem::Version
|
34
40
|
version: '0'
|
35
|
-
name: httpclient
|
36
41
|
prerelease: false
|
37
42
|
type: :runtime
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: concurrent-ruby
|
38
45
|
version_requirements: !ruby/object:Gem::Requirement
|
39
46
|
requirements:
|
40
47
|
- - ">="
|
41
48
|
- !ruby/object:Gem::Version
|
42
49
|
version: '0'
|
43
|
-
- !ruby/object:Gem::Dependency
|
44
50
|
requirement: !ruby/object:Gem::Requirement
|
45
51
|
requirements:
|
46
52
|
- - ">="
|
47
53
|
- !ruby/object:Gem::Version
|
48
54
|
version: '0'
|
49
|
-
name: concurrent-ruby
|
50
55
|
prerelease: false
|
51
56
|
type: :runtime
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: embulk
|
52
59
|
version_requirements: !ruby/object:Gem::Requirement
|
53
60
|
requirements:
|
54
|
-
- - "
|
61
|
+
- - "~>"
|
55
62
|
- !ruby/object:Gem::Version
|
56
|
-
version:
|
57
|
-
- !ruby/object:Gem::Dependency
|
63
|
+
version: 0.8.1
|
58
64
|
requirement: !ruby/object:Gem::Requirement
|
59
65
|
requirements:
|
60
66
|
- - "~>"
|
61
67
|
- !ruby/object:Gem::Version
|
62
68
|
version: 0.8.1
|
63
|
-
name: embulk
|
64
69
|
prerelease: false
|
65
70
|
type: :development
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: bundler
|
66
73
|
version_requirements: !ruby/object:Gem::Requirement
|
67
74
|
requirements:
|
68
75
|
- - "~>"
|
69
76
|
- !ruby/object:Gem::Version
|
70
|
-
version: 0
|
71
|
-
- !ruby/object:Gem::Dependency
|
77
|
+
version: '1.0'
|
72
78
|
requirement: !ruby/object:Gem::Requirement
|
73
79
|
requirements:
|
74
80
|
- - "~>"
|
75
81
|
- !ruby/object:Gem::Version
|
76
82
|
version: '1.0'
|
77
|
-
name: bundler
|
78
83
|
prerelease: false
|
79
84
|
type: :development
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: rake
|
80
87
|
version_requirements: !ruby/object:Gem::Requirement
|
81
88
|
requirements:
|
82
|
-
- - "
|
89
|
+
- - ">="
|
83
90
|
- !ruby/object:Gem::Version
|
84
|
-
version: '
|
85
|
-
- !ruby/object:Gem::Dependency
|
91
|
+
version: '10.0'
|
86
92
|
requirement: !ruby/object:Gem::Requirement
|
87
93
|
requirements:
|
88
94
|
- - ">="
|
89
95
|
- !ruby/object:Gem::Version
|
90
96
|
version: '10.0'
|
91
|
-
name: rake
|
92
97
|
prerelease: false
|
93
98
|
type: :development
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: pry
|
94
101
|
version_requirements: !ruby/object:Gem::Requirement
|
95
102
|
requirements:
|
96
103
|
- - ">="
|
97
104
|
- !ruby/object:Gem::Version
|
98
|
-
version: '
|
99
|
-
- !ruby/object:Gem::Dependency
|
105
|
+
version: '0'
|
100
106
|
requirement: !ruby/object:Gem::Requirement
|
101
107
|
requirements:
|
102
108
|
- - ">="
|
103
109
|
- !ruby/object:Gem::Version
|
104
110
|
version: '0'
|
105
|
-
name: pry
|
106
111
|
prerelease: false
|
107
112
|
type: :development
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: test-unit
|
108
115
|
version_requirements: !ruby/object:Gem::Requirement
|
109
116
|
requirements:
|
110
|
-
- - "
|
117
|
+
- - "~>"
|
111
118
|
- !ruby/object:Gem::Version
|
112
|
-
version:
|
113
|
-
- !ruby/object:Gem::Dependency
|
119
|
+
version: 3.1.5
|
114
120
|
requirement: !ruby/object:Gem::Requirement
|
115
121
|
requirements:
|
116
122
|
- - "~>"
|
117
123
|
- !ruby/object:Gem::Version
|
118
124
|
version: 3.1.5
|
119
|
-
name: test-unit
|
120
125
|
prerelease: false
|
121
126
|
type: :development
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: test-unit-rr
|
122
129
|
version_requirements: !ruby/object:Gem::Requirement
|
123
130
|
requirements:
|
124
|
-
- - "
|
131
|
+
- - ">="
|
125
132
|
- !ruby/object:Gem::Version
|
126
|
-
version:
|
127
|
-
- !ruby/object:Gem::Dependency
|
133
|
+
version: '0'
|
128
134
|
requirement: !ruby/object:Gem::Requirement
|
129
135
|
requirements:
|
130
136
|
- - ">="
|
131
137
|
- !ruby/object:Gem::Version
|
132
138
|
version: '0'
|
133
|
-
name: test-unit-rr
|
134
139
|
prerelease: false
|
135
140
|
type: :development
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
name: rr
|
136
143
|
version_requirements: !ruby/object:Gem::Requirement
|
137
144
|
requirements:
|
138
|
-
- - "
|
145
|
+
- - "~>"
|
139
146
|
- !ruby/object:Gem::Version
|
140
|
-
version:
|
141
|
-
- !ruby/object:Gem::Dependency
|
147
|
+
version: 1.1.2
|
142
148
|
requirement: !ruby/object:Gem::Requirement
|
143
149
|
requirements:
|
144
150
|
- - "~>"
|
145
151
|
- !ruby/object:Gem::Version
|
146
152
|
version: 1.1.2
|
147
|
-
name: rr
|
148
153
|
prerelease: false
|
149
154
|
type: :development
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
name: simplecov
|
150
157
|
version_requirements: !ruby/object:Gem::Requirement
|
151
158
|
requirements:
|
152
|
-
- - "
|
159
|
+
- - ">="
|
153
160
|
- !ruby/object:Gem::Version
|
154
|
-
version:
|
155
|
-
- !ruby/object:Gem::Dependency
|
161
|
+
version: '0'
|
156
162
|
requirement: !ruby/object:Gem::Requirement
|
157
163
|
requirements:
|
158
164
|
- - ">="
|
159
165
|
- !ruby/object:Gem::Version
|
160
166
|
version: '0'
|
161
|
-
name: simplecov
|
162
167
|
prerelease: false
|
163
168
|
type: :development
|
169
|
+
- !ruby/object:Gem::Dependency
|
170
|
+
name: gem_release_helper
|
164
171
|
version_requirements: !ruby/object:Gem::Requirement
|
165
172
|
requirements:
|
166
|
-
- - "
|
173
|
+
- - "~>"
|
167
174
|
- !ruby/object:Gem::Version
|
168
|
-
version: '0'
|
169
|
-
- !ruby/object:Gem::Dependency
|
175
|
+
version: '1.0'
|
170
176
|
requirement: !ruby/object:Gem::Requirement
|
171
177
|
requirements:
|
172
178
|
- - "~>"
|
173
179
|
- !ruby/object:Gem::Version
|
174
180
|
version: '1.0'
|
175
|
-
name: gem_release_helper
|
176
181
|
prerelease: false
|
177
182
|
type: :development
|
183
|
+
- !ruby/object:Gem::Dependency
|
184
|
+
name: codeclimate-test-reporter
|
178
185
|
version_requirements: !ruby/object:Gem::Requirement
|
179
186
|
requirements:
|
180
187
|
- - "~>"
|
181
188
|
- !ruby/object:Gem::Version
|
182
|
-
version: '
|
183
|
-
- !ruby/object:Gem::Dependency
|
189
|
+
version: '0.6'
|
184
190
|
requirement: !ruby/object:Gem::Requirement
|
185
191
|
requirements:
|
186
192
|
- - "~>"
|
187
193
|
- !ruby/object:Gem::Version
|
188
194
|
version: '0.6'
|
189
|
-
name: codeclimate-test-reporter
|
190
195
|
prerelease: false
|
191
196
|
type: :development
|
192
|
-
version_requirements: !ruby/object:Gem::Requirement
|
193
|
-
requirements:
|
194
|
-
- - "~>"
|
195
|
-
- !ruby/object:Gem::Version
|
196
|
-
version: '0.6'
|
197
197
|
description: Loads records from Zendesk.
|
198
198
|
email:
|
199
199
|
- k@uu59.org
|