ferris-bueller 0.0.3 → 0.1.1
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/VERSION +1 -1
- data/lib/ferris-bueller/constants.rb +13 -1
- data/lib/ferris-bueller/helpers.rb +50 -15
- data/lib/ferris-bueller/jira_api.rb +22 -10
- data/lib/ferris-bueller/main.rb +5 -2
- data/lib/ferris-bueller/metadata.rb +9 -9
- data/lib/ferris-bueller/replies.rb +116 -52
- data/lib/ferris-bueller/slack_api.rb +3 -3
- data/lib/ferris-bueller/web.rb +3 -2
- data/lib/ferris-bueller/web_helpers.rb +7 -3
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f388396864494d4cdd8a39e1855e9e9ad00429cc
|
4
|
+
data.tar.gz: f255231cafc28d0003c9bf199ee02dec7c3ada56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 912d96dbb25ca30dcf194268416ce60196a7109eb1fb2cb82a3a821bc5eee05a90ddd2f034288398af6f219b21fb4ded7efdd9c51860e6db296f4e60c637df33
|
7
|
+
data.tar.gz: f672c22d2ab7578a697c4659f1dc0e9dcece80f160bad36f0e07be81d970e033445b5cc4be3da291eeffc0c7a2d860b74122bfa795f160f26733c35f5223d0b6
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.1
|
@@ -33,5 +33,17 @@ module FerrisBueller
|
|
33
33
|
}
|
34
34
|
|
35
35
|
SEVERITY_FIELD = SHOW_FIELDS.key('Severity')
|
36
|
+
|
37
|
+
HELP_TEXT = <<-END.gsub(/^ +/,'')
|
38
|
+
/inc help - print this message
|
39
|
+
/inc resolve <inc> - resolve incident number <inc>
|
40
|
+
/inc close <inc> - close incident number <inc>
|
41
|
+
/inc whoami - test to see if bueller can tell who you are
|
42
|
+
/inc list - list incidents
|
43
|
+
/inc summary - summary of incidents
|
44
|
+
/inc show <inc> - show incident info for incident <inc>
|
45
|
+
/inc comment <inc> <comment> - comment on incident <inc> with comment <comment>
|
46
|
+
/inc open <severity> <summary> - open incident with severity of 1(high)-5(low) <severity>
|
47
|
+
END
|
36
48
|
end
|
37
|
-
end
|
49
|
+
end
|
@@ -18,7 +18,7 @@ module FerrisBueller
|
|
18
18
|
def store ; @store end
|
19
19
|
|
20
20
|
|
21
|
-
def start_your_day_off
|
21
|
+
def start_your_day_off queue
|
22
22
|
Web.set :environment, options.environment
|
23
23
|
Web.set :port, options.port
|
24
24
|
Web.set :bind, options.bind
|
@@ -33,8 +33,10 @@ module FerrisBueller
|
|
33
33
|
logger: log
|
34
34
|
)
|
35
35
|
Web.set :jira_project, options.jira_project
|
36
|
+
Web.set :jira_url, options.jira_url
|
36
37
|
Web.set :jira_type, options.jira_type
|
37
38
|
Web.set :refresh_rate, options.incident_refresh
|
39
|
+
Web.set :post_queue, queue
|
38
40
|
|
39
41
|
if log.level >= ::Logger::DEBUG
|
40
42
|
Web.set :raise_errors, true
|
@@ -48,6 +50,26 @@ module FerrisBueller
|
|
48
50
|
Web.run!
|
49
51
|
end
|
50
52
|
|
53
|
+
def go_handle_postbacks queue
|
54
|
+
Thread.new do
|
55
|
+
loop do
|
56
|
+
post_lambda = queue.pop
|
57
|
+
response, uri_string = post_lambda.call
|
58
|
+
uri = URI uri_string
|
59
|
+
log.debug \
|
60
|
+
event: 'sending Slack response',
|
61
|
+
path: uri_string,
|
62
|
+
data: response
|
63
|
+
Net::HTTP.start(uri.hostname, uri.port, :use_ssl => uri.scheme == 'https') do |http|
|
64
|
+
req = Net::HTTP::Post.new uri
|
65
|
+
req['Content-Type'] = 'application/json'
|
66
|
+
req['Accept'] = 'application/json'
|
67
|
+
req.body = JSON.generate response
|
68
|
+
http.request req
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
51
73
|
|
52
74
|
def go_refresh_jira_users
|
53
75
|
Thread.new do
|
@@ -100,9 +122,8 @@ module FerrisBueller
|
|
100
122
|
log.error \
|
101
123
|
error: 'could not refresh users',
|
102
124
|
event: 'exception',
|
103
|
-
exception: e.inspect,
|
104
125
|
class: e.class,
|
105
|
-
message: e.message,
|
126
|
+
message: e.message.inspect,
|
106
127
|
backtrace: e.backtrace,
|
107
128
|
remediation: 'pausing breifly before retrying'
|
108
129
|
sleep RETRY_DELAY
|
@@ -111,20 +132,36 @@ module FerrisBueller
|
|
111
132
|
|
112
133
|
|
113
134
|
def refresh_jira_members
|
114
|
-
|
115
|
-
|
116
|
-
|
135
|
+
req_path = 'rest/api/2/group/member'
|
136
|
+
is_last, values, start = false, [], 0
|
137
|
+
until is_last
|
138
|
+
req_params = QueryParams.encode \
|
139
|
+
groupname: options.jira_group,
|
140
|
+
startAt: start
|
141
|
+
|
142
|
+
uri = URI(options.jira_url + req_path + '?' + req_params)
|
143
|
+
http = Net::HTTP.new uri.hostname, uri.port
|
144
|
+
|
145
|
+
req = Net::HTTP::Get.new uri
|
146
|
+
req.basic_auth options.jira_user, options.jira_pass
|
147
|
+
req['Content-Type'] = 'application/json'
|
148
|
+
req['Accept'] = 'application/json'
|
149
|
+
|
150
|
+
resp = http.request req
|
151
|
+
data = JSON.parse resp.body
|
152
|
+
values += data['values']
|
153
|
+
is_last = data['isLast']
|
154
|
+
start += data['maxResults']
|
155
|
+
end
|
117
156
|
|
118
|
-
user_names =
|
157
|
+
user_names = values.map { |u| u['name'] }
|
119
158
|
store[:jira_members] = user_names
|
120
|
-
|
121
159
|
rescue StandardError => e
|
122
160
|
log.error \
|
123
161
|
error: 'could not refresh members',
|
124
162
|
event: 'exception',
|
125
|
-
exception: e.inspect,
|
126
163
|
class: e.class,
|
127
|
-
message: e.message,
|
164
|
+
message: e.message.inspect,
|
128
165
|
backtrace: e.backtrace,
|
129
166
|
remediation: 'pausing breifly before retrying'
|
130
167
|
sleep RETRY_DELAY
|
@@ -142,14 +179,12 @@ module FerrisBueller
|
|
142
179
|
store[:jira_incidents] = data[:issues].map do |i|
|
143
180
|
i[:num] = i[:key].split('-', 2).last ; i
|
144
181
|
end
|
145
|
-
|
146
182
|
rescue StandardError => e
|
147
183
|
log.error \
|
148
184
|
error: 'could not refresh incidents',
|
149
185
|
event: 'exception',
|
150
|
-
exception: e.inspect,
|
151
186
|
class: e.class,
|
152
|
-
message: e.message,
|
187
|
+
message: e.message.inspect,
|
153
188
|
backtrace: e.backtrace,
|
154
189
|
remediation: 'pausing breifly before retrying'
|
155
190
|
sleep RETRY_DELAY
|
@@ -159,7 +194,7 @@ module FerrisBueller
|
|
159
194
|
|
160
195
|
def jira_request path, params
|
161
196
|
api_url = File.join options.jira_url, 'rest/api/latest', path
|
162
|
-
log.
|
197
|
+
log.debug \
|
163
198
|
event: 'jira request',
|
164
199
|
path: path,
|
165
200
|
params: params,
|
@@ -183,4 +218,4 @@ module FerrisBueller
|
|
183
218
|
end
|
184
219
|
|
185
220
|
end
|
186
|
-
end
|
221
|
+
end
|
@@ -14,7 +14,7 @@ module FerrisBueller
|
|
14
14
|
@api_url = options.fetch :api_url
|
15
15
|
@base_path = options.fetch :base_path, '/rest/api/2'
|
16
16
|
@logger = options.fetch :logger, Slog.new
|
17
|
-
log.
|
17
|
+
log.debug event: 'Jira API client initialized'
|
18
18
|
end
|
19
19
|
|
20
20
|
def send path, data={}
|
@@ -26,20 +26,32 @@ module FerrisBueller
|
|
26
26
|
req['Content-Type'] = 'application/json'
|
27
27
|
req['Accept'] = 'application/json'
|
28
28
|
req.body = JSON.generate data
|
29
|
-
log.
|
29
|
+
log.debug \
|
30
30
|
event: 'sending Jira API request',
|
31
31
|
path: path,
|
32
32
|
data: data
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
33
|
+
raw_res = http.request(req).body
|
34
|
+
begin
|
35
|
+
return nil unless raw_res
|
36
|
+
res = JSON.parse raw_res, symbolize_names: true
|
37
|
+
log.debug \
|
38
|
+
event: 'Jira API request returned',
|
39
|
+
path: path,
|
40
|
+
data: data,
|
41
|
+
response: res
|
42
|
+
res
|
43
|
+
rescue => e
|
44
|
+
log.error \
|
45
|
+
event: 'exception parsing jira response',
|
46
|
+
response: raw_res.inspect,
|
47
|
+
exception: e.class,
|
48
|
+
message: e.message.inspect,
|
49
|
+
backtrace: e.backtrace
|
50
|
+
raise e
|
51
|
+
end
|
40
52
|
end
|
41
53
|
|
42
54
|
private
|
43
55
|
def log ; @logger end
|
44
56
|
end
|
45
|
-
end
|
57
|
+
end
|
data/lib/ferris-bueller/main.rb
CHANGED
@@ -112,8 +112,11 @@ module FerrisBueller
|
|
112
112
|
go_refresh_jira_users
|
113
113
|
go_refresh_jira_members
|
114
114
|
go_refresh_jira_incidents
|
115
|
-
|
115
|
+
|
116
|
+
queue = Queue.new
|
117
|
+
go_handle_postbacks queue
|
118
|
+
start_your_day_off queue
|
116
119
|
end
|
117
120
|
|
118
121
|
end
|
119
|
-
end
|
122
|
+
end
|
@@ -29,15 +29,15 @@ module FerrisBueller
|
|
29
29
|
# Every project deserves its own ASCII art
|
30
30
|
ART = <<-'EOART' % VERSION
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
32
|
+
/$$$$$$$ /$$ /$$
|
33
|
+
| $$__ $$ | $$| $$
|
34
|
+
| $$ \ $$ /$$ /$$ /$$$$$$ | $$| $$ /$$$$$$ /$$$$$$
|
35
|
+
| $$$$$$$ | $$ | $$ /$$__ $$| $$| $$ /$$__ $$ /$$__ $$
|
36
|
+
| $$__ $$| $$ | $$| $$$$$$$$| $$| $$| $$$$$$$$| $$ \__/
|
37
|
+
| $$ \ $$| $$ | $$| $$_____/| $$| $$| $$_____/| $$
|
38
|
+
| $$$$$$$/| $$$$$$/| $$$$$$$| $$| $$| $$$$$$$| $$
|
39
|
+
|_______/ \______/ \_______/|__/|__/ \_______/|__/
|
40
40
|
|
41
41
|
|
42
42
|
EOART
|
43
|
-
end
|
43
|
+
end
|
@@ -13,13 +13,11 @@ module FerrisBueller
|
|
13
13
|
attachments: [
|
14
14
|
{
|
15
15
|
title: 'Slack User',
|
16
|
-
# pretext: 'User found via Slack APIs',
|
17
16
|
text: "```#{JSON.pretty_generate(u[:slack])}```",
|
18
17
|
mrkdwn_in: %w[ text pretext ]
|
19
18
|
},
|
20
19
|
{
|
21
20
|
title: 'Jira User',
|
22
|
-
# pretext: 'User found via Jira APIs',
|
23
21
|
text: "```#{JSON.pretty_generate(u[:jira])}```",
|
24
22
|
mrkdwn_in: %w[ text pretext ]
|
25
23
|
}
|
@@ -34,7 +32,7 @@ module FerrisBueller
|
|
34
32
|
|
35
33
|
|
36
34
|
def reply_help params
|
37
|
-
{ text:
|
35
|
+
{ text: HELP_TEXT }
|
38
36
|
end
|
39
37
|
|
40
38
|
|
@@ -49,7 +47,7 @@ module FerrisBueller
|
|
49
47
|
return { text: 'No open incidents at the moment' } if incidents.empty?
|
50
48
|
|
51
49
|
attachments = incidents.map do |i|
|
52
|
-
attach_incident(
|
50
|
+
attach_incident(i)
|
53
51
|
end
|
54
52
|
{
|
55
53
|
text: 'Found %d open incidents' % attachments.size,
|
@@ -60,13 +58,22 @@ module FerrisBueller
|
|
60
58
|
|
61
59
|
def reply_summary params
|
62
60
|
incidents = recent_incidents
|
63
|
-
return { text: 'Could not list incidents' } if incidents.nil?
|
64
|
-
return { text: 'No recent incidents' } if incidents.empty?
|
61
|
+
return { response_type: 'in_channel', text: 'Could not list incidents' } if incidents.nil?
|
62
|
+
return { response_type: 'in_channel', text: 'No recent incidents' } if incidents.empty?
|
65
63
|
|
66
|
-
|
64
|
+
incidents = incidents.sort { |i| i[:id].to_i }.reverse
|
65
|
+
|
66
|
+
partitioned_incidents = []
|
67
|
+
severities = incidents.map { |i| i[:fields][:customfield_11250][:value] }.sort.uniq
|
68
|
+
severities.each do |severity|
|
69
|
+
partitioned_incidents += incidents.select { |i| i[:fields][:customfield_11250][:value] == severity }
|
70
|
+
end
|
71
|
+
|
72
|
+
attachments = partitioned_incidents.map do |i|
|
67
73
|
attach_incident i
|
68
74
|
end
|
69
75
|
{
|
76
|
+
response_type: 'in_channel',
|
70
77
|
text: 'Found %d recent incidents' % attachments.size,
|
71
78
|
attachments: attachments
|
72
79
|
}
|
@@ -78,76 +85,94 @@ module FerrisBueller
|
|
78
85
|
return { text: 'Could not list incidents' } unless incident
|
79
86
|
|
80
87
|
{
|
88
|
+
text: 'Incident info',
|
81
89
|
attachments: [
|
82
|
-
attach_incident(incident)
|
90
|
+
attach_incident(incident, true)
|
83
91
|
]
|
84
92
|
}
|
85
93
|
end
|
86
94
|
|
87
95
|
|
88
96
|
def reply_resolve inc_num, params
|
89
|
-
return {
|
97
|
+
return { response_type: 'in_channel' }, lambda do
|
98
|
+
return { response_type: 'in_channel', text: "You're not allowed to do that" }, params[:response_url] unless allowed? params
|
90
99
|
|
91
|
-
|
92
|
-
|
100
|
+
incident = select_incident inc_num
|
101
|
+
return { response_type: 'in_channel', text: 'Could not list incidents' }, params[:response_url] unless incident
|
93
102
|
|
94
|
-
|
95
|
-
|
96
|
-
|
103
|
+
resolution = resolve_incident incident
|
104
|
+
return { response_type: 'in_channel', text: 'Could not resolve incident' }, params[:response_url] if resolution.nil?
|
105
|
+
return { response_type: 'in_channel', text: 'Already resolved' } if resolution == false
|
97
106
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
107
|
+
return {
|
108
|
+
response_type: 'in_channel',
|
109
|
+
text: 'Resolved incident',
|
110
|
+
attachments: [
|
111
|
+
attach_incident(incident)
|
112
|
+
]
|
113
|
+
}, params[:response_url]
|
114
|
+
end
|
104
115
|
end
|
105
116
|
|
106
117
|
|
107
118
|
def reply_close inc_num, params
|
108
|
-
return {
|
119
|
+
return { response_type: 'in_channel' }, lambda do
|
120
|
+
return { response_type: 'in_channel', text: "You're not allowed to do that" }, params[:response_url] unless allowed? params
|
109
121
|
|
110
|
-
|
111
|
-
|
122
|
+
incident = select_incident inc_num
|
123
|
+
return { response_type: 'in_channel', text: 'Could not list incidents' }, params[:response_url] unless incident
|
112
124
|
|
113
|
-
|
114
|
-
|
125
|
+
resolution = close_incident incident
|
126
|
+
return { response_type: 'in_channel', text: 'Could not close incident' }, params[:response_url] unless resolution
|
115
127
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
128
|
+
return {
|
129
|
+
response_type: 'in_channel',
|
130
|
+
text: 'Closed incident',
|
131
|
+
attachments: [
|
132
|
+
attach_incident(incident)
|
133
|
+
]
|
134
|
+
}, params[:response_url]
|
135
|
+
end
|
122
136
|
end
|
123
137
|
|
124
138
|
|
125
139
|
def reply_open sev_num, summary, params
|
126
|
-
return {
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
140
|
+
return { response_type: 'in_channel' }, lambda do
|
141
|
+
return { response_type: 'in_channel', text: "You're not allowed to do that" }, params[:response_url] unless allowed? params
|
142
|
+
|
143
|
+
new_incident = construct_incident sev_num, summary, params
|
144
|
+
incident = open_incident new_incident, summary
|
145
|
+
return { response_type: 'in_channel', text: 'Could not open incident' }, params[:response_url] unless incident
|
146
|
+
|
147
|
+
incident = new_incident.merge incident
|
148
|
+
log.debug \
|
149
|
+
event: 'created incident',
|
150
|
+
incident: incident
|
151
|
+
return {
|
152
|
+
response_type: 'in_channel',
|
153
|
+
text: 'Opened incident',
|
154
|
+
attachments: [
|
155
|
+
{
|
156
|
+
title: incident[:key],
|
157
|
+
title_link: File.join(settings.jira_url, 'browse', incident[:key]),
|
158
|
+
text: incident[:fields][:summary]
|
159
|
+
}
|
160
|
+
]
|
161
|
+
}, params[:response_url]
|
162
|
+
end
|
139
163
|
end
|
140
164
|
|
141
165
|
|
142
166
|
def reply_comment inc_num, message, params
|
143
167
|
incident = select_incident inc_num
|
144
|
-
return { text: 'Could not list incidents' } unless incident
|
168
|
+
return { response_type: 'in_channel', text: 'Could not list incidents' } unless incident
|
145
169
|
|
146
170
|
comment = construct_comment message, params
|
147
171
|
annotation = comment_on_incident incident, comment
|
148
|
-
return { text: 'Could not comment on incident' } unless annotation
|
172
|
+
return { response_type: 'in_channel', text: 'Could not comment on incident' } unless annotation
|
149
173
|
|
150
174
|
{
|
175
|
+
response_type: 'in_channel',
|
151
176
|
text: 'Commented on incident',
|
152
177
|
attachments: [
|
153
178
|
attach_incident(incident)
|
@@ -159,10 +184,49 @@ module FerrisBueller
|
|
159
184
|
|
160
185
|
private
|
161
186
|
|
162
|
-
def attach_incident i
|
187
|
+
def attach_incident i, detailed=false
|
188
|
+
severity_colors = {
|
189
|
+
'1' => '#e60000',
|
190
|
+
'2' => '#e60000',
|
191
|
+
'3' => '#ff6600',
|
192
|
+
'4' => '#ffff00',
|
193
|
+
'5' => '#ccff33'
|
194
|
+
}
|
195
|
+
severity = i[:fields][:customfield_11250][:value] rescue 'Unknown'
|
196
|
+
severity_color = severity_colors[severity[3]] rescue '#cccccc'
|
197
|
+
|
198
|
+
additional_fields = if detailed
|
199
|
+
[
|
200
|
+
{
|
201
|
+
title: 'Description',
|
202
|
+
value: i[:fields][:description]
|
203
|
+
}
|
204
|
+
]
|
205
|
+
end
|
206
|
+
|
163
207
|
{
|
164
208
|
title: i[:key],
|
165
|
-
|
209
|
+
title_link: File.join(settings.jira_url, 'browse', i[:key]),
|
210
|
+
text: "*#{severity}*\n_#{i[:fields][:summary]}_",
|
211
|
+
fields: [
|
212
|
+
{
|
213
|
+
title: 'Created',
|
214
|
+
value: (DateTime.parse(i[:fields][:created]).iso8601 rescue nil),
|
215
|
+
short: true
|
216
|
+
},
|
217
|
+
{
|
218
|
+
title: 'Status',
|
219
|
+
value: (i[:fields][:status][:name] rescue nil),
|
220
|
+
short: true
|
221
|
+
},
|
222
|
+
{
|
223
|
+
title: 'Updated',
|
224
|
+
value: (DateTime.parse(i[:fields][:updated]).iso8601 rescue nil),
|
225
|
+
short: true
|
226
|
+
},
|
227
|
+
*additional_fields
|
228
|
+
].reject { |f| f[:value].nil? || f[:value].empty? || f[:value] == 'Unknown' },
|
229
|
+
color: severity_color,
|
166
230
|
mrkdwn_in: %w[ text pretext ]
|
167
231
|
}
|
168
232
|
end
|
@@ -172,7 +236,7 @@ module FerrisBueller
|
|
172
236
|
status = normalize_value i[:fields][:status]
|
173
237
|
return false if status =~ RESOLVED_STATE
|
174
238
|
|
175
|
-
log.
|
239
|
+
log.debug \
|
176
240
|
event: 'resolving incident',
|
177
241
|
incident: i
|
178
242
|
|
@@ -201,7 +265,7 @@ module FerrisBueller
|
|
201
265
|
status = normalize_value i[:fields][:status]
|
202
266
|
return false if status =~ CLOSED_STATE
|
203
267
|
|
204
|
-
log.
|
268
|
+
log.debug \
|
205
269
|
event: 'closing incident',
|
206
270
|
incident: i
|
207
271
|
|
@@ -329,12 +393,12 @@ module FerrisBueller
|
|
329
393
|
24 * 60 * 60 # seconds/day
|
330
394
|
end
|
331
395
|
|
396
|
+
|
332
397
|
def allowed? params
|
333
398
|
u = user_lookup params
|
334
399
|
u && store[:jira_members] \
|
335
400
|
&& store[:jira_members].include?(u[:jira][:nick])
|
336
401
|
end
|
337
402
|
|
338
|
-
|
339
403
|
end
|
340
|
-
end
|
404
|
+
end
|
@@ -12,13 +12,13 @@ module FerrisBueller
|
|
12
12
|
@token = options.fetch :token
|
13
13
|
@logger = options.fetch :logger, Slog.new
|
14
14
|
@api_url = options.fetch :api_url, 'https://slack.com/api'
|
15
|
-
log.
|
15
|
+
log.debug event: 'Slack API client initialized'
|
16
16
|
end
|
17
17
|
|
18
18
|
def send method, options={}
|
19
19
|
uri = URI File.join(@api_url, method)
|
20
20
|
options = { token: @token }.merge(options)
|
21
|
-
log.
|
21
|
+
log.debug event: 'sending api request', method: method, options: options
|
22
22
|
res = Net::HTTP.post_form uri, options
|
23
23
|
log.debug event: 'sent api request', method: method, options: options, response: res
|
24
24
|
JSON.parse res.body, symbolize_names: true
|
@@ -27,4 +27,4 @@ module FerrisBueller
|
|
27
27
|
private
|
28
28
|
def log ; @logger end
|
29
29
|
end
|
30
|
-
end
|
30
|
+
end
|
data/lib/ferris-bueller/web.rb
CHANGED
@@ -42,7 +42,8 @@ module FerrisBueller
|
|
42
42
|
halt 403
|
43
43
|
else
|
44
44
|
content_type :json
|
45
|
-
reply = respond(params)
|
45
|
+
reply, post = respond(params)
|
46
|
+
settings.post_queue << post if post
|
46
47
|
JSON.generate reply if reply
|
47
48
|
end
|
48
49
|
end
|
@@ -81,4 +82,4 @@ module FerrisBueller
|
|
81
82
|
end
|
82
83
|
|
83
84
|
end
|
84
|
-
end
|
85
|
+
end
|
@@ -24,12 +24,16 @@ module FerrisBueller
|
|
24
24
|
email: data[:user][:email]
|
25
25
|
}
|
26
26
|
|
27
|
+
log.info \
|
28
|
+
event: 'matching user',
|
29
|
+
slack_user: slack_user
|
30
|
+
|
27
31
|
jira_matches = store[:jira_users].values.map do |jira_user|
|
28
32
|
distances = [ :name, :nick ].map do |k|
|
29
33
|
compare slack_user[k], jira_user[k]
|
30
34
|
end.compact
|
31
35
|
mean_distance = 1.0 * distances.inject(:+) / distances.size
|
32
|
-
if mean_distance > threshold
|
36
|
+
if mean_distance > threshold or distances.max > 0.99
|
33
37
|
{ user: jira_user, distance: mean_distance}
|
34
38
|
end
|
35
39
|
end.compact
|
@@ -56,7 +60,7 @@ module FerrisBueller
|
|
56
60
|
event: 'exception',
|
57
61
|
exception: e.inspect,
|
58
62
|
class: e.class,
|
59
|
-
message: e.message,
|
63
|
+
message: e.message.inspect,
|
60
64
|
backtrace: e.backtrace
|
61
65
|
return nil
|
62
66
|
end
|
@@ -71,4 +75,4 @@ module FerrisBueller
|
|
71
75
|
end
|
72
76
|
|
73
77
|
end
|
74
|
-
end
|
78
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ferris-bueller
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.1
|
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-
|
11
|
+
date: 2016-06-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: slog
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: thor
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|