ticket_abstractor_client 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +74 -11
- data/lib/ticket_abstractor_client/base/attachment.rb +16 -4
- data/lib/ticket_abstractor_client/base/client.rb +3 -1
- data/lib/ticket_abstractor_client/base/comment.rb +10 -2
- data/lib/ticket_abstractor_client/base/ticket.rb +10 -9
- data/lib/ticket_abstractor_client/base/{fields_filter.rb → tickets_filter.rb} +4 -6
- data/lib/ticket_abstractor_client/client_helper.rb +1 -0
- data/lib/ticket_abstractor_client/configuration.rb +12 -12
- data/lib/ticket_abstractor_client/jira/ticket.rb +9 -9
- data/lib/ticket_abstractor_client/service_now/client.rb +23 -7
- data/lib/ticket_abstractor_client/service_now/comment.rb +2 -2
- data/lib/ticket_abstractor_client/service_now/params_builder.rb +6 -5
- data/lib/ticket_abstractor_client/service_now/ticket.rb +25 -16
- data/lib/ticket_abstractor_client/version.rb +1 -1
- metadata +9 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 115d09ad3d18ed05d7d9bd31cd6bcf5f96f87a13
|
4
|
+
data.tar.gz: 4b9f066a917ec904c2ec00989cabf11c0b1d109d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 252d6de493963f80a6608c5288866a0e1490ba35e3582bc24d355992ffce225be53e34a4538a01251c120ce51e1e92a32ce2d4fe15bc2f2f793ffda54c5ba5e3
|
7
|
+
data.tar.gz: 948ace98118b77dd78f67aced69c995ddfa777a585c867fdad70c77af20b9fa2c8e7df56990cbddd537658e9506a56ab22662a567420509fe5cdf9a6e79f70f3
|
data/README.md
CHANGED
@@ -42,7 +42,7 @@ Since version 2.0.0, you operate with ticket as **PORO**.
|
|
42
42
|
|
43
43
|
**Base configuration options:**
|
44
44
|
|
45
|
-
TicketAbstractorClient.
|
45
|
+
TicketAbstractorClient.configure do |config|
|
46
46
|
config.ticket_abstractor_url = 'http://localhost:4567'
|
47
47
|
config.security_token = 'security_token_1'
|
48
48
|
end
|
@@ -75,7 +75,7 @@ this parameter defaults to false.
|
|
75
75
|
* `SNOW_DISPLAY_VALUE_ALL` returns both actual and display values.
|
76
76
|
|
77
77
|
|
78
|
-
|
78
|
+
config.snow_display_value = TicketAbstractorClient::Configuration::SNOW_DISPLAY_VALUE_ALL
|
79
79
|
|
80
80
|
[[table of contents](#content)]
|
81
81
|
|
@@ -165,6 +165,33 @@ Update ticket's status:
|
|
165
165
|
ticket.status = 'IN_PROGRESS'
|
166
166
|
ticket.sync!
|
167
167
|
|
168
|
+
Add comment:
|
169
|
+
|
170
|
+
include TicketAbstractorClient
|
171
|
+
...
|
172
|
+
|
173
|
+
ticket = Jira::Ticket.new(ticket_id: 'ISSUE-111', endpoint: 'tp')
|
174
|
+
ticket.add_comment(body: 'New comment body')
|
175
|
+
ticket.sync!
|
176
|
+
|
177
|
+
# or
|
178
|
+
|
179
|
+
Jira::Comment.new(ticket_id: 'ISSUE-111', endpoint: 'tp', body: 'New comment body').sync!
|
180
|
+
|
181
|
+
Add attachment:
|
182
|
+
|
183
|
+
include TicketAbstractorClient
|
184
|
+
...
|
185
|
+
|
186
|
+
ticket = Jira::Ticket.new(ticket_id: 'ISSUE-111', endpoint: 'tp')
|
187
|
+
ticket.add_attachment(file_attachment: '/path/to/file')
|
188
|
+
ticket.sync!
|
189
|
+
|
190
|
+
# or
|
191
|
+
|
192
|
+
Jira::Attachment.new(ticket_id: 'ISSUE-111', endpoint: 'tp', file_attachment: '/path/to/file').sync!
|
193
|
+
|
194
|
+
|
168
195
|
### <a name="snow"></a>ServiceNow
|
169
196
|
|
170
197
|
Get ticket by id:
|
@@ -178,7 +205,7 @@ Get ticket by id:
|
|
178
205
|
|
179
206
|
Get tickets by query:
|
180
207
|
|
181
|
-
ticket_opts = {
|
208
|
+
ticket_opts = { sysparm_query: 'numberIN(INC001,INC002,INC010)', endpoint: :test, project: 'incident' }
|
182
209
|
TicketAbstractorClient::ServiceNow::Ticket.fetch_tickets_by_query(ticket_opts)
|
183
210
|
|
184
211
|
Get ticket's comments:
|
@@ -244,11 +271,47 @@ Update ticket:
|
|
244
271
|
|
245
272
|
Update ticket's status:
|
246
273
|
|
247
|
-
ticket_opts = { ticket_id: 'INC011', endpoint: '
|
274
|
+
ticket_opts = { ticket_id: 'INC011', endpoint: 'test', project: :incident }
|
248
275
|
ticket = TicketAbstractorClient::ServiceNow::Ticket.new(ticket_opts)
|
249
276
|
ticket.status = 'IN_PROGRESS'
|
250
277
|
ticket.sync!
|
251
278
|
|
279
|
+
Add comment:
|
280
|
+
|
281
|
+
include TicketAbstractorClient
|
282
|
+
...
|
283
|
+
|
284
|
+
ticket = ServiceNow::Ticket.new(ticket_id: 'INC011', endpoint: 'test', project: :incident)
|
285
|
+
ticket.add_comment(body: 'New comment body')
|
286
|
+
ticket.sync!
|
287
|
+
|
288
|
+
# or
|
289
|
+
|
290
|
+
ServiceNow::Comment.new(
|
291
|
+
ticket_id: 'INC011',
|
292
|
+
endpoint: 'test',
|
293
|
+
project: :incident,
|
294
|
+
body: 'New comment body'
|
295
|
+
).sync!
|
296
|
+
|
297
|
+
Add attachment:
|
298
|
+
|
299
|
+
include TicketAbstractorClient
|
300
|
+
...
|
301
|
+
|
302
|
+
ticket = ServiceNow::Ticket.new(ticket_id: 'INC011', endpoint: 'test', project: :incident)
|
303
|
+
ticket.add_attachment(file_attachment: '/path/to/file')
|
304
|
+
ticket.sync!
|
305
|
+
|
306
|
+
# or
|
307
|
+
|
308
|
+
ServiceNow::Attachment.new(
|
309
|
+
ticket_id: 'INC011',
|
310
|
+
endpoint: 'test',
|
311
|
+
project: :incident,
|
312
|
+
file_attachment: '/path/to/file'
|
313
|
+
).sync!
|
314
|
+
|
252
315
|
|
253
316
|
[[table of contents](#content)]
|
254
317
|
|
@@ -258,18 +321,18 @@ Update ticket's status:
|
|
258
321
|
|
259
322
|
There is a situation when you need to convert some values, like datetimes, or skip any other values and so on,
|
260
323
|
before you start working with fetched ticket.
|
261
|
-
All you have to do is create a class that is inherited from `TicketAbstractorClient::Base::
|
262
|
-
and implement a `
|
324
|
+
All you have to do is create a class that is inherited from `TicketAbstractorClient::Base::TicketsFilter`
|
325
|
+
and implement a `filter_ticket` method, after that configure the gem to use your class.
|
263
326
|
|
264
327
|
**ServiceNow example:**
|
265
328
|
|
266
|
-
class MyServiceNowTicketsFilter < TicketAbstractorClient::Base::
|
267
|
-
def initialize(
|
268
|
-
super(
|
329
|
+
class MyServiceNowTicketsFilter < TicketAbstractorClient::Base::TicketsFilter
|
330
|
+
def initialize(raw_ticket)
|
331
|
+
super(raw_ticket)
|
269
332
|
end
|
270
333
|
|
271
|
-
def
|
272
|
-
|
334
|
+
def filter_ticket
|
335
|
+
@ticket.fields.each_with_object([]) |raw_field, filtered_fields|
|
273
336
|
# do some filtering here
|
274
337
|
end
|
275
338
|
end
|
@@ -3,6 +3,9 @@ module TicketAbstractorClient
|
|
3
3
|
class Attachment
|
4
4
|
attr_reader :file_path, :data_hash, :external_created_at
|
5
5
|
|
6
|
+
# Carrierwave uses the same regexp
|
7
|
+
SANITIZE_REGEXP = /[^[:word:]\.\-\+]/
|
8
|
+
|
6
9
|
class << self
|
7
10
|
def fetch
|
8
11
|
method_not_implemented __method__
|
@@ -23,16 +26,17 @@ module TicketAbstractorClient
|
|
23
26
|
end
|
24
27
|
|
25
28
|
def set_original_name(filepath, original_name)
|
29
|
+
sanitized_name = original_name.gsub(SANITIZE_REGEXP, "_")
|
26
30
|
tmp_basename = File.basename(filepath)
|
27
31
|
tmp_path = filepath.gsub(tmp_basename, '')
|
28
|
-
FileUtils.mv
|
29
|
-
File.join(tmp_path,
|
32
|
+
FileUtils.mv(filepath, File.join(tmp_path, sanitized_name))
|
33
|
+
File.join(tmp_path, sanitized_name)
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
33
37
|
def initialize(opts)
|
34
38
|
@file_path = opts[:file_path]
|
35
|
-
@external_created_at = opts[:external_created_at]
|
39
|
+
@external_created_at = opts[:external_created_at]
|
36
40
|
@data_hash = opts[:data_hash]
|
37
41
|
set_data_hash! if @data_hash.blank?
|
38
42
|
end
|
@@ -44,9 +48,17 @@ module TicketAbstractorClient
|
|
44
48
|
def set_data_hash!
|
45
49
|
return if self.file_path.blank?
|
46
50
|
file = File.new(self.file_path, 'rb')
|
47
|
-
@data_hash = Digest::
|
51
|
+
@data_hash = Digest::SHA512.hexdigest(file.read)
|
48
52
|
file.close
|
49
53
|
end
|
54
|
+
|
55
|
+
def to_hash
|
56
|
+
{ file_path: @file_path, external_created_at: @external_created_at, data_hash: @data_hash }
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_json
|
60
|
+
self.to_hash.to_json
|
61
|
+
end
|
50
62
|
end
|
51
63
|
end
|
52
64
|
end
|
@@ -47,7 +47,9 @@ module TicketAbstractorClient
|
|
47
47
|
rescue Errno::ECONNREFUSED => exception
|
48
48
|
raise Errors::UnexpectedError, exception.message
|
49
49
|
rescue RestClient::Exception => exception
|
50
|
-
|
50
|
+
response_body = exception.response.body rescue exception.message
|
51
|
+
error_message = JSON.parse(response_body)['error'] rescue response_body
|
52
|
+
raise Errors::UnexpectedError, error_message
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
@@ -11,20 +11,28 @@ module TicketAbstractorClient
|
|
11
11
|
opts = opts.with_indifferent_access
|
12
12
|
@author = opts[:author]
|
13
13
|
@body = opts.fetch(:body, nil) || raise(Errors::CommentArgumentError, 'Body is not given')
|
14
|
-
@external_created_at = opts[:external_created_at]
|
14
|
+
@external_created_at = opts[:external_created_at]
|
15
15
|
@data_hash = opts[:data_hash]
|
16
16
|
set_data_hash! if @data_hash.blank?
|
17
17
|
end
|
18
18
|
|
19
19
|
def set_data_hash!
|
20
20
|
content = "#{@external_created_at}:#{@author}:#{@body}"
|
21
|
-
@data_hash = Digest::
|
21
|
+
@data_hash = Digest::SHA512.hexdigest(content)
|
22
22
|
end
|
23
23
|
|
24
24
|
def sync!
|
25
25
|
self.class.method_not_implemented __method__
|
26
26
|
end
|
27
27
|
|
28
|
+
def to_hash
|
29
|
+
{ author: @author, body: @body, external_created_at: @external_created_at, data_hash: @data_hash }
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_json
|
33
|
+
self.to_hash.to_json
|
34
|
+
end
|
35
|
+
|
28
36
|
protected
|
29
37
|
|
30
38
|
def self.method_not_implemented(method_name)
|
@@ -1,9 +1,8 @@
|
|
1
1
|
module TicketAbstractorClient
|
2
2
|
module Base
|
3
3
|
class Ticket
|
4
|
-
|
5
|
-
|
6
|
-
attr_accessor :ticket_id, :endpoint, :project
|
4
|
+
attr_reader :attachments, :comments, :changes, :status
|
5
|
+
attr_accessor :ticket_id, :endpoint, :project, :fields
|
7
6
|
|
8
7
|
def initialize(opts = {})
|
9
8
|
opts = opts.with_indifferent_access
|
@@ -11,6 +10,8 @@ module TicketAbstractorClient
|
|
11
10
|
@fields = opts.fetch(:fields, {}).with_indifferent_access
|
12
11
|
@endpoint = opts[:endpoint] || raise(Errors::TicketArgumentError, 'Endpoint is not given')
|
13
12
|
@project = opts[:project]
|
13
|
+
@attachments ||= []
|
14
|
+
@comments ||= []
|
14
15
|
initialize_changes!
|
15
16
|
mark_changes!
|
16
17
|
end
|
@@ -43,12 +44,12 @@ module TicketAbstractorClient
|
|
43
44
|
|
44
45
|
def to_hash
|
45
46
|
{
|
46
|
-
ticket_id:
|
47
|
-
status:
|
48
|
-
|
49
|
-
fields:
|
50
|
-
comments:
|
51
|
-
attachments:
|
47
|
+
ticket_id: self.ticket_id,
|
48
|
+
status: self.status,
|
49
|
+
updated_at: self.updated_at,
|
50
|
+
fields: self.fields,
|
51
|
+
comments: self.comments.map(&:to_hash),
|
52
|
+
attachments: self.attachments.map(&:to_hash)
|
52
53
|
}
|
53
54
|
end
|
54
55
|
|
@@ -1,13 +1,11 @@
|
|
1
1
|
module TicketAbstractorClient
|
2
2
|
module Base
|
3
|
-
class
|
4
|
-
|
5
|
-
|
6
|
-
def initialize(raw_fields)
|
7
|
-
@raw_fields = raw_fields
|
3
|
+
class TicketsFilter
|
4
|
+
def initialize(raw_ticket)
|
5
|
+
@ticket = raw_ticket
|
8
6
|
end
|
9
7
|
|
10
|
-
def
|
8
|
+
def filter_ticket
|
11
9
|
raise Errors::NotImplementedError, "#{self}##{__method__} is not implemented"
|
12
10
|
end
|
13
11
|
end
|
@@ -15,14 +15,14 @@ module TicketAbstractorClient
|
|
15
15
|
|
16
16
|
DEFAULT_SSL_OPTIONS = { verify_ssl: true }.freeze
|
17
17
|
|
18
|
-
def
|
19
|
-
@
|
18
|
+
def jira_tickets_filter_class
|
19
|
+
@jira_tickets_filter_class.presence
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
raise_configuration_error(
|
22
|
+
def jira_tickets_filter_class=(filter_class)
|
23
|
+
raise_configuration_error(filter_class) unless filter_class < Base::TicketsFilter
|
24
24
|
|
25
|
-
@
|
25
|
+
@jira_tickets_filter_class = filter_class
|
26
26
|
end
|
27
27
|
|
28
28
|
def jira_fields_meta
|
@@ -37,14 +37,14 @@ module TicketAbstractorClient
|
|
37
37
|
@snow_display_value ||= DEFAULT_SNOW_DISPLAY_VALUE
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
41
|
-
@
|
40
|
+
def snow_tickets_filter_class
|
41
|
+
@snow_tickets_filter_class.presence
|
42
42
|
end
|
43
43
|
|
44
|
-
def
|
45
|
-
raise_configuration_error(
|
44
|
+
def snow_tickets_filter_class=(filter_class)
|
45
|
+
raise_configuration_error(filter_class) unless filter_class < Base::TicketsFilter
|
46
46
|
|
47
|
-
@
|
47
|
+
@snow_tickets_filter_class = filter_class
|
48
48
|
end
|
49
49
|
|
50
50
|
def ssl_options
|
@@ -53,8 +53,8 @@ module TicketAbstractorClient
|
|
53
53
|
|
54
54
|
private
|
55
55
|
|
56
|
-
def raise_configuration_error(
|
57
|
-
message = "Filter class '#{
|
56
|
+
def raise_configuration_error(filter_class)
|
57
|
+
message = "Filter class '#{filter_class.to_s}' isn't a subclass of Base::TicketsFilter"
|
58
58
|
raise Base::Errors::ConfigurationError, message
|
59
59
|
end
|
60
60
|
end
|
@@ -88,20 +88,20 @@ module TicketAbstractorClient
|
|
88
88
|
raw_tickets = raw_tickets['issues'] if raw_tickets.key?('issues')
|
89
89
|
|
90
90
|
Array.wrap(raw_tickets).map do |raw_ticket|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
91
|
+
ticket = new(ticket_id: raw_ticket['key'], endpoint: endpoint, fields: raw_ticket['fields'])
|
92
|
+
filtered_ticket = filter_ticket(ticket)
|
93
|
+
filtered_ticket.reset_changes!
|
94
|
+
filtered_ticket
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
-
def self.
|
99
|
-
fields.extract!('attachment', 'comment')
|
100
|
-
|
98
|
+
def self.filter_ticket(raw_ticket)
|
99
|
+
raw_ticket.fields.extract!('attachment', 'comment')
|
100
|
+
tickets_filter_class = TicketAbstractorClient.configuration.jira_tickets_filter_class
|
101
101
|
|
102
|
-
return
|
102
|
+
return raw_ticket if tickets_filter_class.blank?
|
103
103
|
|
104
|
-
|
104
|
+
tickets_filter_class.new(raw_ticket).filter_ticket
|
105
105
|
end
|
106
106
|
|
107
107
|
def create_ticket
|
@@ -19,19 +19,30 @@ module TicketAbstractorClient
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def get_comments(opts)
|
22
|
-
opts[:
|
23
|
-
opts[:
|
22
|
+
opts[:table_name] = opts[:project]
|
23
|
+
opts[:sys_id] = get_ticket_sys_id(opts)
|
24
|
+
opts[:display_value] = TicketAbstractorClient.configuration.snow_display_value if opts[:display_value].nil?
|
24
25
|
get(__method__, opts)
|
25
26
|
end
|
26
27
|
|
28
|
+
def endpoints
|
29
|
+
get(__method__)
|
30
|
+
end
|
31
|
+
|
27
32
|
def get_ticket_by_id(opts)
|
28
|
-
opts[:
|
29
|
-
opts[:
|
33
|
+
opts[:table_name] = opts[:project]
|
34
|
+
opts[:sys_id] = get_ticket_sys_id(opts)
|
35
|
+
opts[:display_value] = TicketAbstractorClient.configuration.snow_display_value if opts[:display_value].nil?
|
30
36
|
get(__method__, opts)
|
31
37
|
end
|
32
38
|
|
33
39
|
def get_tickets_by_query(opts)
|
34
|
-
opts[:
|
40
|
+
opts[:table_name] = opts[:project]
|
41
|
+
opts[:display_value] = TicketAbstractorClient.configuration.snow_display_value if opts[:display_value].nil?
|
42
|
+
get(__method__, opts)
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_users(opts)
|
35
46
|
get(__method__, opts)
|
36
47
|
end
|
37
48
|
|
@@ -50,11 +61,12 @@ module TicketAbstractorClient
|
|
50
61
|
end
|
51
62
|
|
52
63
|
def update_ticket(ticket)
|
53
|
-
ticket.
|
64
|
+
ticket.sys_id = get_ticket_sys_id(ticket_id: ticket.ticket_id, table_name: ticket.project)
|
54
65
|
post(__method__, build_ticket_params(ticket))
|
55
66
|
end
|
56
67
|
|
57
68
|
def update_ticket_status(ticket)
|
69
|
+
ticket.sys_id = get_ticket_sys_id(ticket_id: ticket.ticket.id, table_name: ticket.project)
|
58
70
|
post(:update_ticket, build_status_params(ticket))
|
59
71
|
end
|
60
72
|
|
@@ -63,7 +75,11 @@ module TicketAbstractorClient
|
|
63
75
|
def get_ticket_sys_id(opts)
|
64
76
|
return opts[:ticket_id] if opts[:ticket_id].length == SYS_ID_LENGTH
|
65
77
|
|
66
|
-
get(__method__, opts)
|
78
|
+
response = get(__method__, opts)
|
79
|
+
|
80
|
+
raise(Errors::NotFoundError, 'Ticket not found or incorrect ID given') if response.blank?
|
81
|
+
|
82
|
+
response[0]['sys_id']
|
67
83
|
end
|
68
84
|
|
69
85
|
def get(path, args = {}, params = {})
|
@@ -4,10 +4,10 @@ module TicketAbstractorClient
|
|
4
4
|
attr_accessor :ticket_id, :endpoint, :project
|
5
5
|
|
6
6
|
def self.fetch(ticket_id, endpoint, project)
|
7
|
-
response = Client.new(endpoint).get_comments(ticket_id: ticket_id,
|
7
|
+
response = Client.new(endpoint).get_comments(ticket_id: ticket_id, project: project)
|
8
8
|
response.map do |raw_comment|
|
9
9
|
new({
|
10
|
-
author: raw_comment['
|
10
|
+
author: raw_comment['sys_created_by'],
|
11
11
|
body: raw_comment['value'],
|
12
12
|
external_created_at: raw_comment['sys_created_on'],
|
13
13
|
ticket_id: ticket_id,
|
@@ -3,11 +3,12 @@ module TicketAbstractorClient
|
|
3
3
|
module ParamsBuilder
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
|
-
def
|
6
|
+
def build_all_tickets_params(opts)
|
7
|
+
opts[:table_name] = opts[:project]
|
7
8
|
opts[:sysparm_query] = build_sysparm_query(opts)
|
8
9
|
opts[:sysparm_fields] = Array.wrap(opts.delete(:fields))
|
9
10
|
opts.except!(:service_desk, :states)
|
10
|
-
opts[:display_value]
|
11
|
+
opts[:display_value] = TicketAbstractorClient.configuration.snow_display_value if opts[:display_value].nil?
|
11
12
|
opts
|
12
13
|
end
|
13
14
|
|
@@ -27,19 +28,19 @@ module TicketAbstractorClient
|
|
27
28
|
def build_comment_params(comment)
|
28
29
|
{
|
29
30
|
comment_params: { comments: comment.body },
|
30
|
-
|
31
|
+
sys_id: comment.ticket_id,
|
31
32
|
table_name: comment.project,
|
32
33
|
display_value: TicketAbstractorClient.configuration.snow_display_value
|
33
34
|
}
|
34
35
|
end
|
35
36
|
|
36
37
|
def build_status_params(ticket)
|
37
|
-
{ ticket_params: { state: ticket.status },
|
38
|
+
{ ticket_params: { state: ticket.status }, sys_id: ticket.sys_id, table_name: ticket.project }
|
38
39
|
end
|
39
40
|
|
40
41
|
def build_ticket_params(ticket)
|
41
42
|
opts = { ticket_params: ticket.fields, table_name: ticket.project }
|
42
|
-
opts.merge!(
|
43
|
+
opts.merge!(sys_id: ticket.sys_id) if ticket.sys_id.present?
|
43
44
|
opts
|
44
45
|
end
|
45
46
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module TicketAbstractorClient
|
2
2
|
module ServiceNow
|
3
3
|
class Ticket < Base::Ticket
|
4
|
+
attr_accessor :sys_id
|
4
5
|
|
5
6
|
def self.fetch_by_id(opts)
|
6
7
|
fetch(:by_id, opts).first
|
@@ -17,17 +18,18 @@ module TicketAbstractorClient
|
|
17
18
|
def initialize(opts = {})
|
18
19
|
super(opts)
|
19
20
|
@project = opts[:project] || raise(Errors::TicketArgumentError, 'Project is not given')
|
20
|
-
@
|
21
|
+
@sys_id = @fields['sys_id']
|
22
|
+
@status = @fields['state']
|
21
23
|
end
|
22
24
|
|
23
25
|
def add_attachment(attachment)
|
24
|
-
@attachments << Attachment.new(attachment.merge
|
26
|
+
@attachments << Attachment.new(attachment.merge(ticket_id: @ticket_id, endpoint: @endpoint, project: @project))
|
25
27
|
@changes[:new_attachments] += 1
|
26
28
|
self
|
27
29
|
end
|
28
30
|
|
29
31
|
def add_comment(comment)
|
30
|
-
@comments << Comment.new(comment.merge
|
32
|
+
@comments << Comment.new(comment.merge(ticket_id: @ticket_id, endpoint: @endpoint, project: @project))
|
31
33
|
@changes[:new_comments] += 1
|
32
34
|
self
|
33
35
|
end
|
@@ -37,7 +39,7 @@ module TicketAbstractorClient
|
|
37
39
|
|
38
40
|
return [] if @ticket_id.blank? && @attachments.blank?
|
39
41
|
|
40
|
-
@attachments = Attachment.fetch(@ticket_id, @endpoint)
|
42
|
+
@attachments = Attachment.fetch(@ticket_id, @endpoint, @project)
|
41
43
|
end
|
42
44
|
|
43
45
|
def comments
|
@@ -45,11 +47,15 @@ module TicketAbstractorClient
|
|
45
47
|
|
46
48
|
return [] if @ticket_id.blank? && @comments.blank?
|
47
49
|
|
48
|
-
@comments = Comment.fetch(@ticket_id, @endpoint)
|
50
|
+
@comments = Comment.fetch(@ticket_id, @endpoint, @project)
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_hash
|
54
|
+
{ sys_id: @sys_id }.merge(super())
|
49
55
|
end
|
50
56
|
|
51
57
|
def sync!
|
52
|
-
raise
|
58
|
+
raise(Errors::TicketArgumentError, 'No changes to apply') unless self.any_changes?
|
53
59
|
return create_ticket if @changes[:create]
|
54
60
|
update_ticket if @changes[:update]
|
55
61
|
update_status if @changes[:new_status]
|
@@ -74,27 +80,30 @@ module TicketAbstractorClient
|
|
74
80
|
method_map = { all: :get_all_tickets, by_id: :get_ticket_by_id, by_query: :get_tickets_by_query }
|
75
81
|
client_response = Client.new(endpoint).public_send(method_map.fetch(selektor.to_sym), opts)
|
76
82
|
|
77
|
-
Array.wrap(client_response).map do |
|
78
|
-
|
79
|
-
ticket = new(ticket_id:
|
80
|
-
ticket
|
81
|
-
|
83
|
+
Array.wrap(client_response).map do |ticket_hash|
|
84
|
+
ticket_id = opts[:ticket_id] || ticket_hash['number']
|
85
|
+
ticket = new(ticket_id: ticket_id, fields: ticket_hash, endpoint: endpoint, project: opts[:project])
|
86
|
+
filtered_ticket = filter_ticket(ticket)
|
87
|
+
filtered_ticket.reset_changes!
|
88
|
+
filtered_ticket
|
82
89
|
end
|
83
90
|
end
|
84
91
|
|
85
|
-
def self.
|
86
|
-
|
92
|
+
def self.filter_ticket(raw_ticket)
|
93
|
+
tickets_filter_class = TicketAbstractorClient.configuration.snow_tickets_filter_class
|
87
94
|
|
88
|
-
return
|
95
|
+
return raw_ticket if tickets_filter_class.blank?
|
89
96
|
|
90
|
-
|
97
|
+
tickets_filter_class.new(raw_ticket).filter_ticket
|
91
98
|
end
|
92
99
|
|
93
100
|
def create_ticket
|
94
101
|
response = Client.new(@endpoint).create_ticket(self)
|
95
|
-
ticket = Ticket.fetch_by_id(ticket_id: response['number'],
|
102
|
+
ticket = Ticket.fetch_by_id(ticket_id: response['number'], project: @project, endpoint: @endpoint)
|
103
|
+
@sys_id = ticket.sys_id
|
96
104
|
@fields = ticket.fields
|
97
105
|
@status = ticket.status
|
106
|
+
@ticket_id = ticket.ticket_id
|
98
107
|
reset_changes!
|
99
108
|
end
|
100
109
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ticket_abstractor_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roman Samoilov
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-
|
12
|
+
date: 2017-03-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -43,42 +43,42 @@ dependencies:
|
|
43
43
|
name: rest-client
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - "
|
46
|
+
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: 2.0.0
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- - "
|
53
|
+
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: 2.0.0
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: activesupport
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
|
-
- - "
|
60
|
+
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: 4.2.7
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- - "
|
67
|
+
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: 4.2.7
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: mime-types
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- - "
|
74
|
+
- - ">="
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: 1.25.1
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- - "
|
81
|
+
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: 1.25.1
|
84
84
|
description: Get access to Jira and Brouha ticketing systems through the single service
|
@@ -95,9 +95,9 @@ files:
|
|
95
95
|
- lib/ticket_abstractor_client/base/client.rb
|
96
96
|
- lib/ticket_abstractor_client/base/comment.rb
|
97
97
|
- lib/ticket_abstractor_client/base/errors.rb
|
98
|
-
- lib/ticket_abstractor_client/base/fields_filter.rb
|
99
98
|
- lib/ticket_abstractor_client/base/response_handler.rb
|
100
99
|
- lib/ticket_abstractor_client/base/ticket.rb
|
100
|
+
- lib/ticket_abstractor_client/base/tickets_filter.rb
|
101
101
|
- lib/ticket_abstractor_client/client_helper.rb
|
102
102
|
- lib/ticket_abstractor_client/configuration.rb
|
103
103
|
- lib/ticket_abstractor_client/jira/attachment.rb
|