bender-bot 0.5.6 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/lib/bender/bot.rb +54 -52
- data/lib/bender/helpers.rb +25 -35
- data/lib/bender/main.rb +90 -166
- data/lib/bender/metadata.rb +0 -1
- data/lib/bender/mjolnir.rb +0 -7
- metadata +2 -36
- data/lib/bender/web.rb +0 -36
- data/web/app/bender.js +0 -5
- data/web/app/style/bender.css +0 -0
- data/web/public/favicon.ico +0 -0
- data/web/views/app.erb +0 -1
- data/web/views/layout.erb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c7feb7ff451b53acb7ea0171573c05e0658a217
|
4
|
+
data.tar.gz: f337922a2e8310c05de4ad7ab7e44bb743a22a6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15069ef3e4408d5166023b7031bbbf7e810350687c77738fff83c3cbe8430717a1eb6f7f0095a0c8e47e29e7ae8b92a62059845e89b2d66dbe5416585c07e853
|
7
|
+
data.tar.gz: 6782aa69d9109eb06b92299f9246a552e80eef81f8cb5f80660ccb12c48fd6fac80d19d27116e362598d04e3af8509db59c48dcf877a7b17176a0a45d37dc3e6
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.0
|
data/lib/bender/bot.rb
CHANGED
@@ -15,11 +15,11 @@ Bot = Robut # alias
|
|
15
15
|
|
16
16
|
|
17
17
|
module Bot
|
18
|
-
def self.run!
|
19
|
-
hipchat = HipChat::Client.new(
|
18
|
+
def self.run! config, logger
|
19
|
+
hipchat = HipChat::Client.new(config[:hipchat_token])
|
20
20
|
BenderBot.class_variable_set :@@hipchat, hipchat
|
21
21
|
BenderBot.class_variable_set :@@rooms, hipchat.rooms
|
22
|
-
BenderBot.class_variable_set :@@
|
22
|
+
BenderBot.class_variable_set :@@config, config
|
23
23
|
BenderBot.class_variable_set :@@logger, logger
|
24
24
|
Bot::Plugin.plugins = [ BenderBot ]
|
25
25
|
conn = Bot::Connection.new
|
@@ -36,39 +36,41 @@ class BenderBot
|
|
36
36
|
|
37
37
|
JARO = FuzzyStringMatch::JaroWinkler.create :native
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
39
|
+
def self.set_commands
|
40
|
+
BenderBot.const_set :COMMANDS, {
|
41
|
+
help: {
|
42
|
+
desc: 'Display this help text',
|
43
|
+
},
|
44
|
+
list: {
|
45
|
+
cmd: '',
|
46
|
+
desc: 'List open incidents'
|
47
|
+
},
|
48
|
+
show: {
|
49
|
+
cmd: '',
|
50
|
+
fmt: 'INCIDENT_NUMBER',
|
51
|
+
desc: 'Display incident details'
|
52
|
+
},
|
53
|
+
resolve: {
|
54
|
+
fmt: 'INCIDENT_NUMBER',
|
55
|
+
desc: 'Resolve an incident',
|
56
|
+
},
|
57
|
+
close: {
|
58
|
+
fmt: 'INCIDENT_NUMBER',
|
59
|
+
desc: 'Close an incident',
|
60
|
+
},
|
61
|
+
open: {
|
62
|
+
fmt: "SEVERITY=#{SEVERITIES.keys.sort_by(&:to_i).join(',')} SUMMARY_TEXT",
|
63
|
+
desc: 'Open a new incident',
|
64
|
+
},
|
65
|
+
summary: {
|
66
|
+
desc: 'Summarize incidents from past 24 hours (open or closed)'
|
67
|
+
},
|
68
|
+
comment: {
|
69
|
+
fmt: 'INCIDENT_NUMBER COMMENT_TEXT',
|
70
|
+
desc: 'Add a comment to an incident'
|
71
|
+
}
|
70
72
|
}
|
71
|
-
|
73
|
+
end
|
72
74
|
|
73
75
|
|
74
76
|
|
@@ -104,7 +106,7 @@ class BenderBot
|
|
104
106
|
@this_room = @@rooms.select { |r| r.xmpp_jid == jid }.first
|
105
107
|
@@hipchat[@this_room.name].get_room # test
|
106
108
|
rescue
|
107
|
-
@@hipchat = HipChat::Client.new(@@
|
109
|
+
@@hipchat = HipChat::Client.new(@@config[:hipchat_token])
|
108
110
|
@@rooms = @@hipchat.rooms
|
109
111
|
@this_room = @@rooms.select { |r| r.xmpp_jid == jid }.first
|
110
112
|
end
|
@@ -252,7 +254,7 @@ class BenderBot
|
|
252
254
|
else
|
253
255
|
incident = select_incident $1
|
254
256
|
if incident
|
255
|
-
reply_html
|
257
|
+
reply_html(*resolve_incident(incident))
|
256
258
|
else
|
257
259
|
reply_html 'Sorry, no such incident!', :red
|
258
260
|
end
|
@@ -265,7 +267,7 @@ class BenderBot
|
|
265
267
|
else
|
266
268
|
incident = select_incident $1
|
267
269
|
if incident
|
268
|
-
reply_html
|
270
|
+
reply_html(*close_incident(incident))
|
269
271
|
else
|
270
272
|
reply_html 'Sorry, no such incident!', :red
|
271
273
|
end
|
@@ -279,8 +281,8 @@ class BenderBot
|
|
279
281
|
user = user_where name: sender
|
280
282
|
data = {
|
281
283
|
fields: {
|
282
|
-
project: { key:
|
283
|
-
issuetype: { name:
|
284
|
+
project: { key: config[:jira_project] },
|
285
|
+
issuetype: { name: config[:jira_type] },
|
284
286
|
reporter: { name: user[:nick] },
|
285
287
|
summary: $3,
|
286
288
|
SHOW_FIELDS.key('Severity') => {
|
@@ -289,7 +291,7 @@ class BenderBot
|
|
289
291
|
}
|
290
292
|
}
|
291
293
|
|
292
|
-
reply_html
|
294
|
+
reply_html(*file_incident(data))
|
293
295
|
end
|
294
296
|
|
295
297
|
|
@@ -302,7 +304,7 @@ class BenderBot
|
|
302
304
|
if !user
|
303
305
|
reply_html "Couldn't find the associated user in JIRA", :red
|
304
306
|
elsif incident
|
305
|
-
reply_html
|
307
|
+
reply_html(*comment_on_incident(incident, comment, user))
|
306
308
|
else
|
307
309
|
reply_html 'Sorry, no such incident!', :red
|
308
310
|
end
|
@@ -323,7 +325,7 @@ private
|
|
323
325
|
|
324
326
|
def log ; @@logger end
|
325
327
|
|
326
|
-
def
|
328
|
+
def config ; @@config end
|
327
329
|
|
328
330
|
def user_where fields, threshold=0.85
|
329
331
|
field, value = fields.to_a.shift
|
@@ -335,7 +337,7 @@ private
|
|
335
337
|
|
336
338
|
user = distance < threshold ? nil : suggested_user
|
337
339
|
|
338
|
-
log.
|
340
|
+
log.debug \
|
339
341
|
action: 'user_where',
|
340
342
|
fields: fields,
|
341
343
|
threshold: threshold,
|
@@ -359,11 +361,11 @@ private
|
|
359
361
|
|
360
362
|
def file_incident data
|
361
363
|
req_path = '/rest/api/2/issue'
|
362
|
-
uri = URI(
|
364
|
+
uri = URI(config[:jira_site] + req_path)
|
363
365
|
http = Net::HTTP.new uri.hostname, uri.port
|
364
366
|
|
365
367
|
req = Net::HTTP::Post.new uri
|
366
|
-
req.basic_auth
|
368
|
+
req.basic_auth config[:jira_user], config[:jira_pass]
|
367
369
|
req['Content-Type'] = 'application/json'
|
368
370
|
req['Accept'] = 'application/json'
|
369
371
|
req.body = data.to_json
|
@@ -397,11 +399,11 @@ private
|
|
397
399
|
req_path = '/rest/api/2/issue/%s/transitions?expand=transitions.fields' % [
|
398
400
|
incident['key']
|
399
401
|
]
|
400
|
-
uri = URI(
|
402
|
+
uri = URI(config[:jira_site] + req_path)
|
401
403
|
http = Net::HTTP.new uri.hostname, uri.port
|
402
404
|
|
403
405
|
req = Net::HTTP::Post.new uri
|
404
|
-
req.basic_auth
|
406
|
+
req.basic_auth config[:jira_user], config[:jira_pass]
|
405
407
|
req['Content-Type'] = 'application/json'
|
406
408
|
req['Accept'] = 'application/json'
|
407
409
|
|
@@ -439,11 +441,11 @@ private
|
|
439
441
|
req_path = '/rest/api/2/issue/%s/transitions?expand=transitions.fields' % [
|
440
442
|
incident['key']
|
441
443
|
]
|
442
|
-
uri = URI(
|
444
|
+
uri = URI(config[:jira_site] + req_path)
|
443
445
|
http = Net::HTTP.new uri.hostname, uri.port
|
444
446
|
|
445
447
|
req = Net::HTTP::Post.new uri
|
446
|
-
req.basic_auth
|
448
|
+
req.basic_auth config[:jira_user], config[:jira_pass]
|
447
449
|
req['Content-Type'] = 'application/json'
|
448
450
|
req['Accept'] = 'application/json'
|
449
451
|
|
@@ -470,11 +472,11 @@ private
|
|
470
472
|
|
471
473
|
def comment_on_incident incident, comment, user
|
472
474
|
req_path = '/rest/api/2/issue/%s/comment' % incident['key']
|
473
|
-
uri = URI(
|
475
|
+
uri = URI(config[:jira_site] + req_path)
|
474
476
|
http = Net::HTTP.new uri.hostname, uri.port
|
475
477
|
|
476
478
|
req = Net::HTTP::Post.new uri
|
477
|
-
req.basic_auth
|
479
|
+
req.basic_auth config[:jira_user], config[:jira_pass]
|
478
480
|
req['Content-Type'] = 'application/json'
|
479
481
|
req['Accept'] = 'application/json'
|
480
482
|
req.body = { body: '_[~%s]_ says: %s' % [ user[:nick], comment ] }.to_json
|
data/lib/bender/helpers.rb
CHANGED
@@ -1,37 +1,27 @@
|
|
1
1
|
module Helpers
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
'customfield_11251' => 'Impact Started',
|
24
|
-
'customfield_11252' => 'Impact Ended',
|
25
|
-
'customfield_11253' => 'Reported By',
|
26
|
-
'customfield_11254' => 'Services Affected',
|
27
|
-
'customfield_11255' => 'Cause',
|
28
|
-
'status' => 'Status',
|
29
|
-
'created' => 'Created',
|
30
|
-
'updated' => 'Updated'
|
2
|
+
DEFAULT_CONFIG = {
|
3
|
+
hipchat_token: nil,
|
4
|
+
hipchat_v2_token: nil,
|
5
|
+
primary_room_id: nil,
|
6
|
+
jid: nil,
|
7
|
+
password: nil,
|
8
|
+
nick: nil,
|
9
|
+
mention: nil,
|
10
|
+
rooms: nil,
|
11
|
+
database: nil,
|
12
|
+
jira_user: nil,
|
13
|
+
jira_pass: nil,
|
14
|
+
jira_site: nil,
|
15
|
+
jira_project: nil,
|
16
|
+
jira_group: nil,
|
17
|
+
jira_type: nil,
|
18
|
+
user_refresh: 300,
|
19
|
+
issue_refresh: 5,
|
20
|
+
group_refresh: 60,
|
21
|
+
room_base_name: nil,
|
22
|
+
order: false
|
31
23
|
}
|
32
24
|
|
33
|
-
SEVERITY_FIELD = SHOW_FIELDS.key('Severity')
|
34
|
-
|
35
25
|
QUOTES = [
|
36
26
|
'Bite my shiny metal ass!',
|
37
27
|
'This is the worst kind of discrimination there is: the kind against me!',
|
@@ -55,16 +45,16 @@ module Helpers
|
|
55
45
|
def refresh_incidents bot=self
|
56
46
|
req_path = '/rest/api/2/search'
|
57
47
|
req_params = QueryParams.encode \
|
58
|
-
jql: "project = #{
|
48
|
+
jql: "project = #{config[:jira_project]} ORDER BY created ASC, priority DESC",
|
59
49
|
fields: SHOW_FIELDS.keys.join(','),
|
60
50
|
startAt: 0,
|
61
51
|
maxResults: 1_000_000
|
62
52
|
|
63
|
-
uri = URI(
|
53
|
+
uri = URI(config[:jira_site] + req_path + '?' + req_params)
|
64
54
|
http = Net::HTTP.new uri.hostname, uri.port
|
65
55
|
|
66
56
|
req = Net::HTTP::Get.new uri
|
67
|
-
req.basic_auth
|
57
|
+
req.basic_auth config[:jira_user], config[:jira_pass]
|
68
58
|
req['Content-Type'] = 'application/json'
|
69
59
|
req['Accept'] = 'application/json'
|
70
60
|
|
@@ -129,7 +119,7 @@ module Helpers
|
|
129
119
|
|
130
120
|
|
131
121
|
def incident_url incident
|
132
|
-
|
122
|
+
config[:jira_site] + '/browse/' + incident['key']
|
133
123
|
end
|
134
124
|
|
135
125
|
def incident_link incident
|
data/lib/bender/main.rb
CHANGED
@@ -8,7 +8,6 @@ require 'queryparams'
|
|
8
8
|
require_relative 'metadata'
|
9
9
|
require_relative 'mjolnir'
|
10
10
|
require_relative 'helpers'
|
11
|
-
require_relative 'web'
|
12
11
|
require_relative 'bot'
|
13
12
|
|
14
13
|
Thread.abort_on_exception = true
|
@@ -31,130 +30,71 @@ module Bender
|
|
31
30
|
|
32
31
|
|
33
32
|
|
34
|
-
desc '
|
35
|
-
option :
|
36
|
-
type: :string,
|
37
|
-
aliases: %w[ -b ],
|
38
|
-
desc: 'Set Sinatra interface',
|
39
|
-
default: '0.0.0.0'
|
40
|
-
option :port, \
|
41
|
-
type: :numeric,
|
42
|
-
aliases: %w[ -o ],
|
43
|
-
desc: 'Set Sinatra port',
|
44
|
-
default: 4567
|
45
|
-
option :environment, \
|
46
|
-
type: :string,
|
47
|
-
aliases: %w[ -e ],
|
48
|
-
desc: 'Set Sinatra environment',
|
49
|
-
default: 'development'
|
50
|
-
option :hipchat_token, \
|
51
|
-
type: :string,
|
52
|
-
aliases: %w[ -t ],
|
53
|
-
desc: 'Set HipChat v1 API token',
|
54
|
-
required: true
|
55
|
-
option :hipchat_v2_token, \
|
33
|
+
desc 'start', 'Start Bender HipChat bot and Web server'
|
34
|
+
option :config, \
|
56
35
|
type: :string,
|
57
36
|
aliases: %w[ -c ],
|
58
|
-
desc: 'Set
|
59
|
-
required: true
|
60
|
-
option :primary_room_id, \
|
61
|
-
type: :string,
|
62
|
-
aliases: %w[ -i ],
|
63
|
-
desc: 'Set HipChat primary room ID',
|
64
|
-
required: true
|
65
|
-
option :jid, \
|
66
|
-
type: :string,
|
67
|
-
aliases: %w[ -j ],
|
68
|
-
desc: 'Set HipChat JID',
|
69
|
-
required: true
|
70
|
-
option :password, \
|
71
|
-
type: :string,
|
72
|
-
aliases: %w[ -p ],
|
73
|
-
desc: 'Set HipChat password',
|
74
|
-
required: true
|
75
|
-
option :nick, \
|
76
|
-
type: :string,
|
77
|
-
aliases: %w[ -n ],
|
78
|
-
desc: 'Set HipChat nick name',
|
79
|
-
required: true
|
80
|
-
option :mention, \
|
81
|
-
type: :string,
|
82
|
-
aliases: %w[ -m ],
|
83
|
-
desc: 'Set HipChat mention name',
|
84
|
-
required: true
|
85
|
-
option :rooms, \
|
86
|
-
type: :string,
|
87
|
-
aliases: %w[ -r ],
|
88
|
-
desc: 'Set HipChat rooms (comma-separated)',
|
89
|
-
required: true
|
90
|
-
option :database, \
|
91
|
-
type: :string,
|
92
|
-
aliases: %w[ -d ],
|
93
|
-
desc: 'Set path to application database',
|
94
|
-
required: true
|
95
|
-
option :jira_user, \
|
96
|
-
type: :string,
|
97
|
-
aliases: %w[ -U ],
|
98
|
-
desc: 'Set JIRA username',
|
99
|
-
required: true
|
100
|
-
option :jira_pass, \
|
101
|
-
type: :string,
|
102
|
-
aliases: %w[ -P ],
|
103
|
-
desc: 'Set JIRA password',
|
37
|
+
desc: 'Set path to config file',
|
104
38
|
required: true
|
105
|
-
option :jira_site, \
|
106
|
-
type: :string,
|
107
|
-
aliases: %w[ -S ],
|
108
|
-
desc: 'Set JIRA site',
|
109
|
-
required: true
|
110
|
-
option :jira_project, \
|
111
|
-
type: :string,
|
112
|
-
aliases: %w[ -J ],
|
113
|
-
desc: 'Set JIRA project',
|
114
|
-
required: true
|
115
|
-
option :jira_group, \
|
116
|
-
type: :string,
|
117
|
-
aliases: %w[ -G ],
|
118
|
-
desc: 'Set JIRA group for write mode',
|
119
|
-
required: true
|
120
|
-
option :jira_type, \
|
121
|
-
type: :string,
|
122
|
-
aliases: %w[ -T ],
|
123
|
-
desc: 'Set JIRA issue type',
|
124
|
-
required: true
|
125
|
-
option :user_refresh, \
|
126
|
-
type: :numeric,
|
127
|
-
aliases: %w[ -R ],
|
128
|
-
desc: 'Set JIRA user refresh rate',
|
129
|
-
default: 300
|
130
|
-
option :issue_refresh, \
|
131
|
-
type: :numeric,
|
132
|
-
aliases: %w[ -S ],
|
133
|
-
desc: 'Set JIRA issue refresh rate',
|
134
|
-
default: 5
|
135
|
-
option :group_refresh, \
|
136
|
-
type: :numeric,
|
137
|
-
aliases: %w[ -T ],
|
138
|
-
desc: 'Set JIRA group refresh rate',
|
139
|
-
default: 60
|
140
|
-
option :order, \
|
141
|
-
type: :boolean,
|
142
|
-
aliases: %w[ -O ],
|
143
|
-
desc: 'Reverse order of HipChat API loading (hack)',
|
144
|
-
default: false
|
145
|
-
option :room_base_name, \
|
146
|
-
type: :string,
|
147
|
-
aliases: %w[ -N ],
|
148
|
-
desc: 'Base name for the primary room',
|
149
|
-
default: 'Production Indicent'
|
150
39
|
include_common_options
|
151
40
|
def start
|
41
|
+
raw_config = JSON.parse File.read(options.config), symbolize_names: true
|
42
|
+
@config = DEFAULT_CONFIG.merge! raw_config
|
43
|
+
|
44
|
+
BenderBot.const_set :RESOLVED_TRANSITIONS, %w[ 51 ]
|
45
|
+
Bender.const_set :RESOLVED_TRANSITIONS, BenderBot::RESOLVED_TRANSITIONS
|
46
|
+
Helpers.const_set :RESOLVED_TRANSITIONS, BenderBot::RESOLVED_TRANSITIONS
|
47
|
+
|
48
|
+
BenderBot.const_set :RESOLVED_STATE, /resolve/i
|
49
|
+
Bender.const_set :RESOLVED_STATE, BenderBot::RESOLVED_STATE
|
50
|
+
Helpers.const_set :RESOLVED_STATE, BenderBot::RESOLVED_STATE
|
51
|
+
|
52
|
+
BenderBot.const_set :CLOSED_TRANSITIONS, %w[ 61 71 ]
|
53
|
+
Bender.const_set :CLOSED_TRANSITIONS, BenderBot::CLOSED_TRANSITIONS
|
54
|
+
Helpers.const_set :CLOSED_TRANSITIONS, BenderBot::CLOSED_TRANSITIONS
|
55
|
+
|
56
|
+
BenderBot.const_set :CLOSED_STATE, /close/i
|
57
|
+
Bender.const_set :CLOSED_STATE, BenderBot::CLOSED_STATE
|
58
|
+
Helpers.const_set :CLOSED_STATE, BenderBot::CLOSED_STATE
|
59
|
+
|
60
|
+
BenderBot.const_set :SEVERITIES, {
|
61
|
+
1 => '10480',
|
62
|
+
2 => '10481',
|
63
|
+
3 => '10482',
|
64
|
+
4 => '10483',
|
65
|
+
5 => '10484'
|
66
|
+
}
|
67
|
+
Bender.const_set :SEVERITIES, BenderBot::SEVERITIES
|
68
|
+
Helpers.const_set :SEVERITIES, BenderBot::SEVERITIES
|
69
|
+
|
70
|
+
BenderBot.const_set :SHOW_FIELDS, {
|
71
|
+
'summary' => 'Summary',
|
72
|
+
'description' => 'Description',
|
73
|
+
'customfield_11250' => 'Severity',
|
74
|
+
'customfield_11251' => 'Impact Started',
|
75
|
+
'customfield_11252' => 'Impact Ended',
|
76
|
+
'customfield_11253' => 'Reported By',
|
77
|
+
'customfield_11254' => 'Services Affected',
|
78
|
+
'customfield_11255' => 'Cause',
|
79
|
+
'status' => 'Status',
|
80
|
+
'created' => 'Created',
|
81
|
+
'updated' => 'Updated'
|
82
|
+
}
|
83
|
+
Bender.const_set :SHOW_FIELDS, BenderBot::SHOW_FIELDS
|
84
|
+
Helpers.const_set :SHOW_FIELDS, BenderBot::SHOW_FIELDS
|
85
|
+
|
86
|
+
BenderBot.const_set :SEVERITY_FIELD, SHOW_FIELDS.key('Severity')
|
87
|
+
Bender.const_set :SEVERITY_FIELD, BenderBot::SEVERITY_FIELD
|
88
|
+
Helpers.const_set :SEVERITY_FIELD, BenderBot::SEVERITY_FIELD
|
89
|
+
|
90
|
+
BenderBot.set_commands
|
91
|
+
|
152
92
|
bot = start_bot
|
153
93
|
ts = []
|
154
94
|
ts << periodically_refresh_group(bot)
|
155
95
|
ts << periodically_refresh_users(bot)
|
156
96
|
ts << periodically_refresh_incidents(bot)
|
157
|
-
|
97
|
+
|
158
98
|
ts.map(&:join)
|
159
99
|
end
|
160
100
|
|
@@ -162,21 +102,24 @@ module Bender
|
|
162
102
|
|
163
103
|
private
|
164
104
|
|
165
|
-
def
|
166
|
-
Bot::Connection.configure do |config|
|
167
|
-
config.jid = options.jid
|
168
|
-
config.password = options.password
|
169
|
-
config.nick = options.mention
|
170
|
-
config.mention_name = options.nick
|
171
|
-
config.rooms = options.rooms.split(',')
|
172
|
-
|
173
|
-
Bot::Storage::YamlStore.file = options.database
|
174
|
-
config.store = Bot::Storage::YamlStore
|
105
|
+
def config ; @config end
|
175
106
|
|
176
|
-
|
107
|
+
def start_bot
|
108
|
+
Bot::Connection.configure do |conn|
|
109
|
+
conn.jid = config[:jid]
|
110
|
+
conn.password = config[:password]
|
111
|
+
conn.nick = config[:mention]
|
112
|
+
conn.mention_name = config[:nick]
|
113
|
+
conn.rooms = config[:rooms].is_a?(Array) ? \
|
114
|
+
config[:rooms] : config[:rooms].split(',')
|
115
|
+
|
116
|
+
Bot::Storage::YamlStore.file = config[:database]
|
117
|
+
conn.store = Bot::Storage::YamlStore
|
118
|
+
|
119
|
+
conn.logger = log
|
177
120
|
end
|
178
121
|
|
179
|
-
Bot.run!
|
122
|
+
Bot.run! config, log
|
180
123
|
end
|
181
124
|
|
182
125
|
|
@@ -205,7 +148,7 @@ module Bender
|
|
205
148
|
|
206
149
|
@open = nil unless defined? @open
|
207
150
|
|
208
|
-
log.
|
151
|
+
log.debug \
|
209
152
|
primary_room_name: bot.store['primary_room_name'],
|
210
153
|
primary_room_topic: bot.store['primary_room_topic'],
|
211
154
|
new_room_name: new_room['name'],
|
@@ -216,7 +159,7 @@ module Bender
|
|
216
159
|
|
217
160
|
if open_incidents.empty?
|
218
161
|
if @open.nil? || @open > 0
|
219
|
-
new_room['name'] = '[NONE] %s' %
|
162
|
+
new_room['name'] = '[NONE] %s' % config[:room_base_name]
|
220
163
|
new_room['topic'] = 'Good news everyone! No high-severity incidents at the moment'
|
221
164
|
apply_room_name_and_topic new_room
|
222
165
|
end
|
@@ -230,7 +173,7 @@ module Bender
|
|
230
173
|
end
|
231
174
|
|
232
175
|
unless @open == open_incidents.size
|
233
|
-
new_room['name'] = '[IN PROGRESS] %s' %
|
176
|
+
new_room['name'] = '[IN PROGRESS] %s' % config[:room_base_name]
|
234
177
|
tha_news = open_incidents.size == 1 ? "There's a high-severity incident" : "There are #{open_incidents.size} high-severity incidents"
|
235
178
|
new_room['topic'] = "Terrible news everyone! #{tha_news}"
|
236
179
|
apply_room_name_and_topic new_room
|
@@ -247,10 +190,10 @@ module Bender
|
|
247
190
|
def apply_room_name_and_topic room
|
248
191
|
uri = URI room['links']['self']
|
249
192
|
|
250
|
-
|
193
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
251
194
|
req = Net::HTTP::Put.new uri
|
252
195
|
req['Content-Type'] = 'application/json'
|
253
|
-
req['Authorization'] = 'Bearer %s' %
|
196
|
+
req['Authorization'] = 'Bearer %s' % config[:hipchat_v2_token]
|
254
197
|
req.body = {
|
255
198
|
name: room['name'],
|
256
199
|
topic: room['topic'],
|
@@ -267,24 +210,24 @@ module Bender
|
|
267
210
|
|
268
211
|
def periodically_refresh_incidents bot
|
269
212
|
Thread.new do
|
270
|
-
if
|
213
|
+
if config[:order]
|
271
214
|
hipchat_v1 = HipChat::Client.new \
|
272
|
-
|
215
|
+
config[:hipchat_token], api_version: 'v1'
|
273
216
|
hipchat_v2 = HipChat::Client.new \
|
274
|
-
|
217
|
+
config[:hipchat_v2_token], api_version: 'v2'
|
275
218
|
else
|
276
219
|
hipchat_v2 = HipChat::Client.new \
|
277
|
-
|
220
|
+
config[:hipchat_v2_token], api_version: 'v2'
|
278
221
|
hipchat_v1 = HipChat::Client.new \
|
279
|
-
|
222
|
+
config[:hipchat_token], api_version: 'v1'
|
280
223
|
end
|
281
224
|
|
282
|
-
room_id =
|
225
|
+
room_id = config[:primary_room_id]
|
283
226
|
|
284
227
|
loop do
|
285
228
|
is = refresh_incidents bot
|
286
229
|
set_room_name_and_topic room_id, is, hipchat_v2, bot
|
287
|
-
sleep
|
230
|
+
sleep config[:issue_refresh]
|
288
231
|
end
|
289
232
|
end
|
290
233
|
end
|
@@ -293,15 +236,15 @@ module Bender
|
|
293
236
|
def periodically_refresh_users bot
|
294
237
|
req_path = '/rest/api/2/user/assignable/search'
|
295
238
|
req_params = QueryParams.encode \
|
296
|
-
project:
|
239
|
+
project: config[:jira_project],
|
297
240
|
startAt: 0,
|
298
241
|
maxResults: 1_000_000
|
299
242
|
|
300
|
-
uri = URI(
|
243
|
+
uri = URI(config[:jira_site] + req_path + '?' + req_params)
|
301
244
|
http = Net::HTTP.new uri.hostname, uri.port
|
302
245
|
|
303
246
|
req = Net::HTTP::Get.new uri
|
304
|
-
req.basic_auth
|
247
|
+
req.basic_auth config[:jira_user], config[:jira_pass]
|
305
248
|
req['Content-Type'] = 'application/json'
|
306
249
|
req['Accept'] = 'application/json'
|
307
250
|
|
@@ -329,7 +272,7 @@ module Bender
|
|
329
272
|
|
330
273
|
bot.store['users'] = users
|
331
274
|
|
332
|
-
sleep
|
275
|
+
sleep config[:user_refresh]
|
333
276
|
end
|
334
277
|
end
|
335
278
|
end
|
@@ -338,14 +281,14 @@ module Bender
|
|
338
281
|
def periodically_refresh_group bot
|
339
282
|
req_path = '/rest/api/2/group'
|
340
283
|
req_params = QueryParams.encode \
|
341
|
-
groupname:
|
284
|
+
groupname: config[:jira_group],
|
342
285
|
expand: 'users'
|
343
286
|
|
344
|
-
uri = URI(
|
287
|
+
uri = URI(config[:jira_site] + req_path + '?' + req_params)
|
345
288
|
http = Net::HTTP.new uri.hostname, uri.port
|
346
289
|
|
347
290
|
req = Net::HTTP::Get.new uri
|
348
|
-
req.basic_auth
|
291
|
+
req.basic_auth config[:jira_user], config[:jira_pass]
|
349
292
|
req['Content-Type'] = 'application/json'
|
350
293
|
req['Accept'] = 'application/json'
|
351
294
|
|
@@ -364,29 +307,10 @@ module Bender
|
|
364
307
|
|
365
308
|
user_names = data['users']['items'].map { |u| u['displayName'] }
|
366
309
|
bot.store['group'] = user_names
|
367
|
-
sleep
|
310
|
+
sleep config[:group_refresh]
|
368
311
|
end
|
369
312
|
end
|
370
313
|
end
|
371
314
|
|
372
|
-
|
373
|
-
def serve_web bot
|
374
|
-
Web.set :environment, options.environment
|
375
|
-
Web.set :port, options.port
|
376
|
-
Web.set :bind, options.bind
|
377
|
-
Web.set :store, options.database
|
378
|
-
|
379
|
-
if log.level >= ::Logger::DEBUG
|
380
|
-
Web.set :raise_errors, true
|
381
|
-
Web.set :dump_errors, true
|
382
|
-
Web.set :show_exceptions, true
|
383
|
-
Web.set :logging, ::Logger::DEBUG
|
384
|
-
end
|
385
|
-
|
386
|
-
Web.set :bot, bot
|
387
|
-
Web.run!
|
388
|
-
end
|
389
|
-
|
390
|
-
|
391
315
|
end
|
392
316
|
end
|
data/lib/bender/metadata.rb
CHANGED
data/lib/bender/mjolnir.rb
CHANGED
@@ -18,12 +18,6 @@ class Mjolnir < Thor
|
|
18
18
|
aliases: %w[ -V ],
|
19
19
|
desc: 'Enable DEBUG-level logging',
|
20
20
|
default: ENV['BENDER_DEBUG'] || false
|
21
|
-
},
|
22
|
-
trace: {
|
23
|
-
type: :boolean,
|
24
|
-
aliases: %w[ -VV ],
|
25
|
-
desc: 'Enable TRACE-level logging',
|
26
|
-
default: ENV['BENDER_TRACE'] || false
|
27
21
|
}
|
28
22
|
}
|
29
23
|
|
@@ -42,7 +36,6 @@ class Mjolnir < Thor
|
|
42
36
|
return @logger if defined? @logger
|
43
37
|
level = :info
|
44
38
|
level = :debug if options.debug?
|
45
|
-
level = :trace if options.trace?
|
46
39
|
device = options.log || $stderr
|
47
40
|
pretty = device.tty? rescue false
|
48
41
|
@logger = Slog.new \
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bender-bot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Clemmer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: sinatra
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '1.4'
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '1.4'
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: sclemmer-robut
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,20 +108,6 @@ dependencies:
|
|
122
108
|
- - '='
|
123
109
|
- !ruby/object:Gem::Version
|
124
110
|
version: 1.0.4
|
125
|
-
- !ruby/object:Gem::Dependency
|
126
|
-
name: thin
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
128
|
-
requirements:
|
129
|
-
- - '='
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
version: 1.6.3
|
132
|
-
type: :runtime
|
133
|
-
prerelease: false
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
135
|
-
requirements:
|
136
|
-
- - '='
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
version: 1.6.3
|
139
111
|
- !ruby/object:Gem::Dependency
|
140
112
|
name: json
|
141
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -181,12 +153,6 @@ files:
|
|
181
153
|
- lib/bender/main.rb
|
182
154
|
- lib/bender/metadata.rb
|
183
155
|
- lib/bender/mjolnir.rb
|
184
|
-
- lib/bender/web.rb
|
185
|
-
- web/app/bender.js
|
186
|
-
- web/app/style/bender.css
|
187
|
-
- web/public/favicon.ico
|
188
|
-
- web/views/app.erb
|
189
|
-
- web/views/layout.erb
|
190
156
|
homepage: https://github.com/sczizzo/bender
|
191
157
|
licenses:
|
192
158
|
- ISC
|
data/lib/bender/web.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'pathname'
|
2
|
-
require 'thread'
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
require 'sinatra/base'
|
6
|
-
|
7
|
-
require_relative 'metadata'
|
8
|
-
|
9
|
-
Thread.abort_on_exception = true
|
10
|
-
|
11
|
-
|
12
|
-
module Bender
|
13
|
-
class Web < Sinatra::Application
|
14
|
-
set :root, File.join(Bender::ROOT, 'web')
|
15
|
-
|
16
|
-
get '/v' do
|
17
|
-
content_type :text
|
18
|
-
VERSION
|
19
|
-
end
|
20
|
-
|
21
|
-
get '/' do
|
22
|
-
erb :app
|
23
|
-
end
|
24
|
-
|
25
|
-
get '/favicon.ico' do
|
26
|
-
send_file File.join(settings.root, 'favicon.ico'), \
|
27
|
-
disposition: 'inline'
|
28
|
-
end
|
29
|
-
|
30
|
-
get %r|/app/(.*)| do |fn|
|
31
|
-
send_file File.join(settings.root, 'app', fn), \
|
32
|
-
disposition: 'inline'
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
data/web/app/bender.js
DELETED
data/web/app/style/bender.css
DELETED
File without changes
|
data/web/public/favicon.ico
DELETED
Binary file
|
data/web/views/app.erb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
Heyo!
|
data/web/views/layout.erb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html lang="en">
|
3
|
-
<head>
|
4
|
-
<title>Bender</title>
|
5
|
-
<meta charset="utf-8" />
|
6
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
8
|
-
<meta name="description" content="Weave." />
|
9
|
-
<meta name="author" content="Sean Clemmer" />
|
10
|
-
<link rel="icon" href="/favicon.ico" />
|
11
|
-
<link href="//maxcdn.bootstrapcdn.com/bootswatch/3.3.4/superhero/bootstrap.min.css" rel="stylesheet" />
|
12
|
-
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet" />
|
13
|
-
<link href="/app/style/bender.css" rel="stylesheet" />
|
14
|
-
</head>
|
15
|
-
<body>
|
16
|
-
<%= yield %>
|
17
|
-
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
18
|
-
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
|
19
|
-
<script src="/app/bender.js"></script>
|
20
|
-
</body>
|
21
|
-
</html>
|