ruboty-redmine 0.1.7 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -52
- data/lib/ruboty/handlers/redmine.rb +145 -229
- data/lib/ruboty/redmine/client.rb +30 -0
- data/lib/ruboty/redmine/version.rb +1 -1
- data/ruboty-redmine.gemspec +2 -0
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d200e7bc660e4bcab752cb57f74289d882679bbd
|
4
|
+
data.tar.gz: 63326c9214311143f44365859121ed79ea245869
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ce30f6536f2e2d126180252b101371456cdd181ba65863f4ebfe4f26850fea54a7e4c54dc084b22a09fb4c1ca02b70453b2c00b632b8e355270a6c04a4bf0ab0
|
7
|
+
data.tar.gz: c4e8e22e7f4af6193391bcab9a0a011eed9e3d444583d2eef269028710f7d4f48a6df01f59fbc3a30a1c82be447aa91833b4713751f639797927694c4a277079
|
data/README.md
CHANGED
@@ -2,64 +2,27 @@
|
|
2
2
|
|
3
3
|
Redmine plugin for Ruboty
|
4
4
|
|
5
|
-
This plugin
|
5
|
+
**This plugin currently supports only Slack**
|
6
6
|
|
7
7
|
## Available commands
|
8
8
|
|
9
|
-
### create issue
|
10
|
-
|
11
|
-
```
|
12
|
-
> ruboty create issue "subject" "Mobile" project "Feature" tracker
|
13
|
-
```
|
14
|
-
|
15
|
-
### watch issues
|
16
|
-
|
17
|
-
```
|
18
|
-
> ruboty watch redmine issues in "Feature" tracker of "Mobile" project
|
19
|
-
```
|
20
|
-
|
21
|
-
You will get notifications:
|
22
|
-
|
23
9
|
```
|
24
|
-
|
25
|
-
|
26
|
-
|
10
|
+
# Creating an issue
|
11
|
+
ruboty create redmine YOURTRACKER issue in YOURPROJECT subject of your issue
|
12
|
+
# Automatic assign
|
13
|
+
ruboty assign YOURTRACKER issues in YOURPROJECT to @MENTION_NAME_OF_ASSIGNEE REDMINE_USER_ID_OF_ASSIGNEE and notify to #CHANNEL_TO_BE_NOTIFIED
|
14
|
+
# List assignees
|
15
|
+
ruboty list redmine assignees
|
16
|
+
# Remove assignee
|
17
|
+
ruboty remove redmine assignee ID_GOT_FROM_LIST_COMMAND
|
18
|
+
# Pause assigning temporalily
|
19
|
+
ruboty pause assigning redmine issues to @MENTION_NAME_OF_ASSIGNEE for 1w1d1h1m1s
|
20
|
+
# Unpause assigning
|
21
|
+
ruboty unpause assigning redmien issues to @MENTION_NAME_OF_ASSIGNEE
|
22
|
+
# List paused assignees
|
23
|
+
ruboty list paused assignees
|
27
24
|
```
|
28
25
|
|
29
|
-
You can list and stop watching issues:
|
30
|
-
|
31
|
-
```
|
32
|
-
> ruboty list watching redmine issues
|
33
|
-
#1 Feature tracker in Mobile project and assign to [] (your_chat_room)
|
34
|
-
> ruboty stop watching redmine issues 1
|
35
|
-
```
|
36
|
-
|
37
|
-
### watch and assign issues
|
38
|
-
|
39
|
-
First, associate Redmine user ID with your name in chat:
|
40
|
-
|
41
|
-
```
|
42
|
-
> ruboty redmine user #123 is @bob
|
43
|
-
> ruboty redmine user #456 is @alice
|
44
|
-
```
|
45
|
-
|
46
|
-
Register tracker:
|
47
|
-
|
48
|
-
```
|
49
|
-
> ruboty watch redmine issues in "Feature" tracker of "Mobile" project and assign to 123,456
|
50
|
-
```
|
51
|
-
|
52
|
-
You will get notifications and the issue is assigned automatically:
|
53
|
-
|
54
|
-
```
|
55
|
-
New Issue of Feature in Mobile project
|
56
|
-
-> Awesome search feature
|
57
|
-
-> Assigned to @bob
|
58
|
-
-> https://redmine.example.com/issues/123
|
59
|
-
```
|
60
|
-
|
61
|
-
The assignee will be elected by round-robin.
|
62
|
-
|
63
26
|
## Installation
|
64
27
|
|
65
28
|
Add this line to your application's Gemfile:
|
@@ -1,7 +1,9 @@
|
|
1
|
+
require 'slack-notifier'
|
2
|
+
|
1
3
|
module Ruboty
|
2
4
|
module Handlers
|
3
5
|
class Redmine < Base
|
4
|
-
NAMESPACE = '
|
6
|
+
NAMESPACE = 'redmine_v1'
|
5
7
|
|
6
8
|
env :REDMINE_URL, 'Redmine url (e.g. http://your-redmine)', optional: false
|
7
9
|
env :REDMINE_API_KEY, 'Redmine REST API key', optional: false
|
@@ -9,217 +11,223 @@ module Ruboty
|
|
9
11
|
env :REDMINE_BASIC_AUTH_PASSWORD, 'Basic Auth Password', optional: true
|
10
12
|
env :REDMINE_CHECK_INTERVAL, 'Interval to check new issues', optional: true
|
11
13
|
env :REDMINE_HTTP_PROXY, 'HTTP proxy', optional: true
|
14
|
+
env :SLACK_WEBHOOK_URL, 'Slack webhook URL', optional: false
|
12
15
|
|
13
16
|
on(
|
14
|
-
/create issue (?<
|
17
|
+
/create redmine (?<tracker>[^ ]+) issue in (?<project>[^ ]+) (?<subject>.+)/,
|
15
18
|
name: 'create_issue',
|
16
|
-
description: 'Create a new issue'
|
19
|
+
description: 'Create a new Redmine issue'
|
17
20
|
)
|
18
21
|
|
19
22
|
on(
|
20
|
-
/
|
21
|
-
name: '
|
22
|
-
description: '
|
23
|
+
/assign redmine (?<tracker>[^ ]+) issues in (?<project>[^ ]+) to (?<mention_name>[^ ]+) (?<redmine_user_id>\d+) and notify to (?<channel>[^ ]+)/,
|
24
|
+
name: 'assign_issues',
|
25
|
+
description: 'Assign Redmine issues when created'
|
23
26
|
)
|
24
27
|
|
25
28
|
on(
|
26
|
-
/list
|
27
|
-
name: '
|
28
|
-
description: 'List
|
29
|
+
/list redmine assignees/,
|
30
|
+
name: 'list_assignees',
|
31
|
+
description: 'List rules to assign Redmine issues',
|
29
32
|
)
|
30
33
|
|
31
34
|
on(
|
32
|
-
/
|
33
|
-
name: '
|
34
|
-
description: 'Stop
|
35
|
+
/remove redmine assignee (?<id>\d+)/,
|
36
|
+
name: 'remove_redmine_assignee',
|
37
|
+
description: 'Stop assigning Redmine issues'
|
35
38
|
)
|
36
39
|
|
37
40
|
on(
|
38
|
-
/redmine
|
39
|
-
name: '
|
40
|
-
description: '
|
41
|
+
/pause assigning redmine issues to (?<mention_name>[^ ]+) for (?<duration>[^ ]+)/,
|
42
|
+
name: 'pause_assigning',
|
43
|
+
description: 'Pause assigning Redmine issues',
|
41
44
|
)
|
42
45
|
|
43
46
|
on(
|
44
|
-
/redmine
|
45
|
-
name: '
|
46
|
-
description: '
|
47
|
+
/unpause assigning redmine issues to (?<mention_name>[^ ]+)/,
|
48
|
+
name: 'unpause_assigning',
|
49
|
+
description: 'Unpause assigning Redmine issues',
|
47
50
|
)
|
48
51
|
|
49
52
|
on(
|
50
|
-
/
|
51
|
-
name: '
|
52
|
-
description: '
|
53
|
-
)
|
54
|
-
|
55
|
-
on(
|
56
|
-
/redmine list absent users/,
|
57
|
-
name: 'list_absent_users',
|
58
|
-
description: 'List absent users',
|
53
|
+
/list paused assignees/,
|
54
|
+
name: 'list_paused_assignees',
|
55
|
+
description: 'List paused Redmine assignees',
|
59
56
|
)
|
60
57
|
|
61
58
|
def initialize(*args)
|
62
59
|
super
|
63
|
-
|
64
|
-
start_to_watch_issues
|
65
60
|
end
|
66
61
|
|
67
62
|
def create_issue(message)
|
68
63
|
from_name = message.original[:from_name]
|
69
64
|
|
70
|
-
words = parse_arg(message[:rest])
|
71
65
|
req = {}
|
72
|
-
req[:subject] = "#{
|
73
|
-
|
74
|
-
words.each_with_index do |word, i|
|
75
|
-
next if i == 0
|
76
|
-
|
77
|
-
arg = words[i - 1]
|
78
|
-
|
79
|
-
case word
|
80
|
-
when 'project'
|
81
|
-
project = redmine.find_project(arg)
|
82
|
-
|
83
|
-
unless project
|
84
|
-
message.reply("Project '#{arg}' is not found.")
|
85
|
-
return
|
86
|
-
end
|
87
|
-
|
88
|
-
req[:project] = project
|
89
|
-
when 'tracker'
|
90
|
-
tracker = redmine.find_tracker(arg)
|
66
|
+
req[:subject] = "#{message[:subject]} (from #{from_name})"
|
91
67
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
req[:tracker] = tracker
|
98
|
-
end
|
68
|
+
project = redmine.find_project(message[:project])
|
69
|
+
unless project
|
70
|
+
message.reply("Project '#{message[:project]}' is not found.")
|
71
|
+
return
|
99
72
|
end
|
73
|
+
req[:project] = project
|
100
74
|
|
101
|
-
|
102
|
-
|
75
|
+
tracker = redmine.find_tracker(message[:tracker])
|
76
|
+
unless tracker
|
77
|
+
message.reply("Tracker '#{message[:tracker]}' is not found.")
|
103
78
|
return
|
104
79
|
end
|
80
|
+
req[:tracker] = tracker
|
105
81
|
|
106
82
|
issue = redmine.create_issue(req)
|
83
|
+
Ruboty.logger.debug("Created new issue: #{issue.inspect}")
|
107
84
|
message.reply("Issue created: #{redmine.url_for_issue(issue)}")
|
108
|
-
end
|
109
85
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
86
|
+
rules = assignees.select do |r|
|
87
|
+
paused = active_paused_assignees.find do |a|
|
88
|
+
a[:mention_name] == r[:mention_name]
|
89
|
+
end
|
90
|
+
next false if paused
|
91
|
+
|
92
|
+
r[:project] == issue.project['name'] &&
|
93
|
+
r[:tracker] == issue.tracker['name']
|
115
94
|
end
|
95
|
+
rule = rules[issue.id % rules.size]
|
96
|
+
redmine.update_issue(issue, assigned_to_id: rule[:redmine_user_id])
|
116
97
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
98
|
+
notify_slack(rule[:notify_to], <<-EOTEXT)
|
99
|
+
New Issue of #{issue.tracker['name']} in #{issue.project['name']} project
|
100
|
+
-> #{issue.subject}
|
101
|
+
-> Assigned to @#{rule[:mention_name]}
|
102
|
+
-> #{redmine.url_for_issue(issue)}
|
103
|
+
EOTEXT
|
104
|
+
end
|
122
105
|
|
123
|
-
|
124
|
-
|
125
|
-
|
106
|
+
def assignees
|
107
|
+
robot.brain.data["#{NAMESPACE}_assigns"] ||= []
|
108
|
+
end
|
126
109
|
|
127
|
-
|
110
|
+
def paused_assignees
|
111
|
+
robot.brain.data["#{NAMESPACE}_paused_assignees"] ||= []
|
128
112
|
end
|
129
113
|
|
130
|
-
def
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
114
|
+
def active_paused_assignees
|
115
|
+
paused_assignees.select do |a|
|
116
|
+
Time.now < Time.at(a[:expire_at])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def assign_issues(message)
|
121
|
+
rule = {
|
122
|
+
tracker: message[:tracker],
|
123
|
+
project: message[:project],
|
124
|
+
mention_name: message[:mention_name].gsub(/\A@/, ''),
|
125
|
+
redmine_user_id: message[:redmine_user_id].gsub(/\A#/, '').to_i,
|
126
|
+
notify_to: message[:channel].gsub(/\A#/, ''),
|
127
|
+
}
|
128
|
+
|
129
|
+
assignees << rule
|
130
|
+
|
131
|
+
message.reply("Registered: #{rule}")
|
132
|
+
end
|
136
133
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
watch['from_name']
|
142
|
-
else
|
143
|
-
"unknown"
|
144
|
-
end
|
134
|
+
def list_assignees(message)
|
135
|
+
if assignees.empty?
|
136
|
+
message.reply("No rule is found")
|
137
|
+
end
|
145
138
|
|
146
|
-
|
139
|
+
reply = assignees.map do |rule|
|
140
|
+
"#{rule.object_id} #{rule}"
|
147
141
|
end.join("\n")
|
148
142
|
|
149
143
|
message.reply(reply)
|
150
144
|
end
|
151
145
|
|
152
|
-
def
|
146
|
+
def remove_redmine_assignee(message)
|
153
147
|
id = message[:id].to_i
|
154
|
-
|
155
|
-
|
148
|
+
rule = assignees.find {|r| r.object_id == id }
|
149
|
+
if rule
|
150
|
+
assignees.delete(rule)
|
151
|
+
message.reply("Rule #{id} is removed")
|
152
|
+
else
|
153
|
+
message.reply("The rule is not found")
|
156
154
|
end
|
157
|
-
|
158
|
-
message.reply("Stopped.")
|
159
155
|
end
|
160
156
|
|
161
|
-
def
|
162
|
-
|
157
|
+
def pause_assigning(message)
|
158
|
+
mention_name = message[:mention_name]
|
159
|
+
duration = message[:duration]
|
160
|
+
|
161
|
+
expire_at = Time.now + parse_duration_to_sec(duration)
|
163
162
|
|
164
|
-
|
163
|
+
pause = {
|
164
|
+
mention_name: mention_name.gsub(/\A@/, ''),
|
165
|
+
expire_at: expire_at.to_i
|
166
|
+
}
|
167
|
+
paused_assignees << pause
|
168
|
+
|
169
|
+
message.reply("Paused: #{pause}")
|
165
170
|
end
|
166
171
|
|
167
|
-
def
|
168
|
-
|
169
|
-
unless u
|
170
|
-
message.reply("#{message[:user]} is not found")
|
171
|
-
return
|
172
|
-
end
|
172
|
+
def unpause_assigning(message)
|
173
|
+
mention_name = message[:mention_name].gsub(/\A@/, '')
|
173
174
|
|
174
|
-
|
175
|
-
|
176
|
-
|
175
|
+
prev_size = paused_assignees.size
|
176
|
+
paused_assignees.reject! do |a|
|
177
|
+
a[:mention_name] == mention_name
|
177
178
|
end
|
178
179
|
|
179
|
-
|
180
|
-
|
180
|
+
if parsed_assignees.size == prev_size
|
181
|
+
message.reply("No paused assignee is found")
|
182
|
+
else
|
183
|
+
message.reply("Unpaused")
|
184
|
+
end
|
181
185
|
end
|
182
186
|
|
183
|
-
def
|
184
|
-
|
185
|
-
|
186
|
-
message.reply("#{message[:user]} is not found")
|
187
|
+
def list_paused_assignees(message)
|
188
|
+
if paused_assignees.empty?
|
189
|
+
message.reply("No paused assingee is found.")
|
187
190
|
return
|
188
191
|
end
|
189
192
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
end
|
193
|
+
reply = active_paused_assignees.map do |a|
|
194
|
+
"#{a[:mention_name]} (until #{Time.at(a[:expire_at])})"
|
195
|
+
end.join("\n")
|
194
196
|
|
195
|
-
|
196
|
-
message.reply("Start assigning issues to #{u}")
|
197
|
+
message.reply(reply)
|
197
198
|
end
|
198
199
|
|
199
|
-
def
|
200
|
-
|
200
|
+
def parse_duration_to_sec(d)
|
201
|
+
sum = 0
|
202
|
+
d.scan(/(\d+)([smhdw])/) do |n, u|
|
203
|
+
scale = case u
|
204
|
+
when 's'
|
205
|
+
1
|
206
|
+
when 'm'
|
207
|
+
60
|
208
|
+
when 'h'
|
209
|
+
60*60
|
210
|
+
when 'd'
|
211
|
+
24*60*60
|
212
|
+
when 'w'
|
213
|
+
7*24*60*60
|
214
|
+
end
|
215
|
+
sum += n.to_i + scale
|
216
|
+
end
|
217
|
+
sum
|
201
218
|
end
|
202
219
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
u = users.find do |u|
|
211
|
-
u['chat_name'] == username
|
212
|
-
end
|
213
|
-
|
214
|
-
u && u['redmine_id'].to_i
|
215
|
-
end
|
220
|
+
def notify_slack(channel, message)
|
221
|
+
slack_notifier.ping(
|
222
|
+
text: message,
|
223
|
+
channel: channel,
|
224
|
+
username: 'ruboty',
|
225
|
+
link_names: '1',
|
226
|
+
)
|
216
227
|
end
|
217
228
|
|
218
|
-
def
|
219
|
-
|
220
|
-
u['redmine_id'] == redmine_id.to_i
|
221
|
-
end
|
222
|
-
u && u['chat_name']
|
229
|
+
def slack_notifier
|
230
|
+
@slack_notifier ||= Slack::Notifier.new(ENV['SLACK_WEBHOOK_URL'])
|
223
231
|
end
|
224
232
|
|
225
233
|
def redmine
|
@@ -231,98 +239,6 @@ module Ruboty
|
|
231
239
|
http_proxy: ENV['REDMINE_HTTP_PROXY'],
|
232
240
|
)
|
233
241
|
end
|
234
|
-
|
235
|
-
def watches
|
236
|
-
robot.brain.data["#{NAMESPACE}_watches"] ||= []
|
237
|
-
end
|
238
|
-
|
239
|
-
def users
|
240
|
-
robot.brain.data["#{NAMESPACE}_users"] ||= []
|
241
|
-
end
|
242
|
-
|
243
|
-
def absent_users
|
244
|
-
robot.brain.data["#{NAMESPACE}_absent_users"] ||= []
|
245
|
-
end
|
246
|
-
|
247
|
-
def find_user_by_id(id)
|
248
|
-
users.find {|user| user['redmine_id'] == id }
|
249
|
-
end
|
250
|
-
|
251
|
-
def parse_arg(text)
|
252
|
-
text.scan(/("([^"]+)"|'([^']+)'|([^ ]+))/).map do |v|
|
253
|
-
v.shift
|
254
|
-
v.find {|itself| itself }
|
255
|
-
end
|
256
|
-
end
|
257
|
-
|
258
|
-
def start_to_watch_issues
|
259
|
-
thread = Thread.start do
|
260
|
-
last_issues_for_watch = {}
|
261
|
-
|
262
|
-
while true
|
263
|
-
sleep (ENV['REDMINE_CHECK_INTERVAL'] || 30).to_i
|
264
|
-
watches.each do |watch|
|
265
|
-
project = redmine.find_project(watch['project'])
|
266
|
-
tracker = redmine.find_tracker(watch['tracker'])
|
267
|
-
|
268
|
-
issues = redmine.issues(project: project, tracker: tracker, sort: 'id:desc')
|
269
|
-
if last_issues = last_issues_for_watch[watch]
|
270
|
-
new_issues = []
|
271
|
-
issues.each do |issue|
|
272
|
-
found = last_issues.find do |last_issue|
|
273
|
-
last_issue.id == issue.id
|
274
|
-
end
|
275
|
-
|
276
|
-
if found
|
277
|
-
break
|
278
|
-
else
|
279
|
-
new_issues << issue
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
new_issues.each do |new_issue|
|
284
|
-
assignees = watch['assignees']
|
285
|
-
assignee = nil
|
286
|
-
if !assignees.empty? && !new_issue.assigned_to
|
287
|
-
assignees -= absent_users
|
288
|
-
assignee = assignees[watch['assignee_index'] % assignees.size]
|
289
|
-
watch['assignee_index'] += 1
|
290
|
-
|
291
|
-
assignee = find_user_by_id(assignee)
|
292
|
-
end
|
293
|
-
|
294
|
-
if assignee
|
295
|
-
redmine.update_issue(new_issue, assigned_to_id: assignee['redmine_id'])
|
296
|
-
end
|
297
|
-
|
298
|
-
msg = <<-EOC
|
299
|
-
New Issue of #{tracker.name} in #{project.name} project
|
300
|
-
-> #{new_issue.subject}
|
301
|
-
EOC
|
302
|
-
|
303
|
-
if assignee
|
304
|
-
msg += <<-EOC
|
305
|
-
-> Assigned to @#{assignee['chat_name']}
|
306
|
-
EOC
|
307
|
-
end
|
308
|
-
|
309
|
-
msg += <<-EOC
|
310
|
-
-> #{redmine.url_for_issue(new_issue)}
|
311
|
-
EOC
|
312
|
-
|
313
|
-
Message.new(
|
314
|
-
watch.symbolize_keys.merge(robot: robot)
|
315
|
-
).reply(msg)
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
last_issues_for_watch[watch] = issues
|
320
|
-
end
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
thread.abort_on_exception = true
|
325
|
-
end
|
326
242
|
end
|
327
243
|
end
|
328
244
|
end
|
@@ -68,6 +68,36 @@ module Ruboty
|
|
68
68
|
OpenStruct.new(
|
69
69
|
JSON.parse(post('/issues.json', req).body)['issue']
|
70
70
|
)
|
71
|
+
# {
|
72
|
+
# "issue": {
|
73
|
+
# "id": 1,
|
74
|
+
# "project": {
|
75
|
+
# "id": 1,
|
76
|
+
# "name": "..."
|
77
|
+
# },
|
78
|
+
# "tracker": {
|
79
|
+
# "id": 1,
|
80
|
+
# "name": "..."
|
81
|
+
# },
|
82
|
+
# "status": {
|
83
|
+
# "id": 1,
|
84
|
+
# "name": "new"
|
85
|
+
# },
|
86
|
+
# "priority": {
|
87
|
+
# "id": 4,
|
88
|
+
# "name": "通常"
|
89
|
+
# },
|
90
|
+
# "author": {
|
91
|
+
# "id": 1,
|
92
|
+
# "name": "Arai Ryota"
|
93
|
+
# },
|
94
|
+
# "subject": "This is test",
|
95
|
+
# "start_date": "2017-02-01",
|
96
|
+
# "done_ratio": 0,
|
97
|
+
# "created_on": "2017-02-01T11:10:35Z",
|
98
|
+
# "updated_on": "2017-02-01T11:10:35Z"
|
99
|
+
# }
|
100
|
+
# }
|
71
101
|
end
|
72
102
|
|
73
103
|
def update_issue(issue, opts)
|
data/ruboty-redmine.gemspec
CHANGED
@@ -20,8 +20,10 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.add_dependency "ruboty"
|
21
21
|
spec.add_dependency "faraday"
|
22
22
|
spec.add_dependency "activesupport"
|
23
|
+
spec.add_dependency "slack-notifier"
|
23
24
|
|
24
25
|
spec.add_development_dependency "pry-byebug"
|
26
|
+
spec.add_development_dependency "ruboty-slack_rtm"
|
25
27
|
spec.add_development_dependency "bundler", "~> 1.7"
|
26
28
|
spec.add_development_dependency "rake", "~> 10.0"
|
27
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruboty-redmine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryota Arai
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruboty
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: slack-notifier
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: pry-byebug
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +80,20 @@ dependencies:
|
|
66
80
|
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: ruboty-slack_rtm
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: bundler
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|