lita-jira 0.3.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 +7 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +17 -0
- data/.travis.yml +8 -0
- data/CONTRIBUTING.md +9 -0
- data/Gemfile +5 -0
- data/LICENSE +19 -0
- data/README.md +87 -0
- data/Rakefile +8 -0
- data/lib/lita/handlers/jira.rb +420 -0
- data/lib/lita-jira.rb +9 -0
- data/lita-jira.gemspec +26 -0
- data/locales/en.yml +41 -0
- data/spec/lita/handlers/jira_spec.rb +192 -0
- data/spec/spec_helper.rb +10 -0
- metadata +173 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ec792cf09935ca050ad43f9267251831c2c0e551
|
4
|
+
data.tar.gz: 2e5658bc5ed997068470279c7fb6eaf51acfb20a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cd93b6be7fe4d14ec6dc2d4f0862c63db299d9340bf64901ec58d1b2f03bd1fbf9073bbf1d27ed69865b2fbe1e273acce65d21890f12250333105fccea68343e
|
7
|
+
data.tar.gz: 3622a99a077d3c7784aa0cebfea90c5ff277eb5fa74baaa3e8ea28e40e50588630b219581cce1d16b6e747d4e08985acd70ebebc87bef362fa400fa0568d5c8b
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
Pull requests are awesome! Pull requests with tests are even more awesome!
|
2
|
+
|
3
|
+
## Quick steps
|
4
|
+
|
5
|
+
1. Fork the repo.
|
6
|
+
2. Run the tests: `bundle && rake`
|
7
|
+
3. Add a test for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, it needs a test!
|
8
|
+
4. Make the test pass.
|
9
|
+
5. Push to your fork and submit a pull request.
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2014 Eric Sigler
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# lita-jira
|
2
|
+
|
3
|
+
[](https://travis-ci.org/esigler/lita-jira)
|
4
|
+
[](https://tldrlegal.com/license/mit-license)
|
5
|
+
[](https://rubygems.org/gems/lita-jira)
|
6
|
+
[](https://coveralls.io/r/esigler/lita-jira)
|
7
|
+
[](https://codeclimate.com/github/esigler/lita-jira)
|
8
|
+
[](https://gemnasium.com/esigler/lita-jira)
|
9
|
+
|
10
|
+
JIRA (https://www.atlassian.com/software/jira) [handler](https://github.com/jimmycuadra/lita) for creating, updating issues.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add lita-jira to your Lita instance's Gemfile:
|
15
|
+
|
16
|
+
``` ruby
|
17
|
+
gem "lita-jira"
|
18
|
+
```
|
19
|
+
|
20
|
+
## Configuration
|
21
|
+
|
22
|
+
Add the following variables to your lita config file:
|
23
|
+
|
24
|
+
```
|
25
|
+
config.handlers.jira.username = 'your_jira_username'
|
26
|
+
config.handlers.jira.password = 'a_password'
|
27
|
+
config.handlers.jira.site = 'https://your.jira.instance.example.com/'
|
28
|
+
config.handlers.jira.context = '' # If your instance is in a /subdirectory, put that here
|
29
|
+
```
|
30
|
+
|
31
|
+
## Usage
|
32
|
+
|
33
|
+
### Shortcuts
|
34
|
+
|
35
|
+
```
|
36
|
+
todo <summary> - Creates an issue with your default priority and project settings, assigned to yourself
|
37
|
+
```
|
38
|
+
|
39
|
+
### Issues
|
40
|
+
|
41
|
+
```
|
42
|
+
jira issue assignee <issue ID> - Shows assignee of <issue ID>
|
43
|
+
jira issue assignee <issue ID> <email address> - Sets <email address> as the assignee
|
44
|
+
jira issue attachments <issue ID> - Shows all attachments for <issue ID>
|
45
|
+
jira issue attachments <issue ID> <URL> - Adds <URL> as an attachment on <issue ID>
|
46
|
+
jira issue comments <issue ID> - Shows all comments for <issue ID>
|
47
|
+
jira issue comments <issue ID> <text> - Adds <text> as a comment on <issue ID>
|
48
|
+
jira issue details <issue ID> - Shows all details for <issue ID>
|
49
|
+
jira issue issuetype <issue ID> - Shows the Issue Type of <issue ID>
|
50
|
+
jira issue issuetype <issue ID> <issuetype ID> - Sets the Issue Type of <issue ID> to <issuetype ID>
|
51
|
+
jira issue new <project ID> <args> - Creates a new issue in <project ID> with <args> (args is any name:"value" pair, such as summary:"Some text")
|
52
|
+
jira issue notify <issue ID> - Shows who is notified when <issue ID> is changed
|
53
|
+
jira issue notify <issue ID> <email address> - Adds <email address> to notification list for <issue ID>
|
54
|
+
jira issue priority <issue ID> - Shows priority of <issue ID>
|
55
|
+
jira issue priority <issue ID> <new priority> - Sets <new priority> of <issue ID>
|
56
|
+
jira issue summary <issue ID> - Shows summary of <issue ID>
|
57
|
+
jira issue summary <issue ID> <text> - Sets summary of <issue ID> to <text>
|
58
|
+
jira issue watchers <issue ID> - Shows watchers of <issue ID>
|
59
|
+
jira issue watchers <issue ID> <email address> - Adds <email address> to watchers list for <issue ID>
|
60
|
+
```
|
61
|
+
|
62
|
+
### Issue Types
|
63
|
+
|
64
|
+
```
|
65
|
+
jira issuetype list <project ID> - List all issuetypes for <project ID>
|
66
|
+
```
|
67
|
+
|
68
|
+
### Search
|
69
|
+
|
70
|
+
```
|
71
|
+
jira search "<text>" - Search for <text> across all of JIRA
|
72
|
+
jira search <project ID> "<text>" - Search for <text> within the scope of <project ID>
|
73
|
+
```
|
74
|
+
|
75
|
+
### Misc
|
76
|
+
|
77
|
+
```
|
78
|
+
jira identify <email address> - Associate your chat user with your email address
|
79
|
+
jira forget - Remove your chat user / email association
|
80
|
+
jira whoami - Show your chat user / email association
|
81
|
+
jira default project <project ID> - Set your default project ID to <project ID>
|
82
|
+
jira default priority <priority> - Set your default priority to <priority>
|
83
|
+
```
|
84
|
+
|
85
|
+
## License
|
86
|
+
|
87
|
+
[MIT](http://opensource.org/licenses/MIT)
|
data/Rakefile
ADDED
@@ -0,0 +1,420 @@
|
|
1
|
+
module Lita
|
2
|
+
module Handlers
|
3
|
+
class Jira < Handler
|
4
|
+
PROJECT_PATTERN = '[a-zA-Z0-9]{1,10}'
|
5
|
+
ISSUE_PATTERN = "#{PROJECT_PATTERN}-[0-9]{1,5}"
|
6
|
+
|
7
|
+
route(
|
8
|
+
/^todo\s(.*)$/,
|
9
|
+
:todo,
|
10
|
+
command: true,
|
11
|
+
help: {
|
12
|
+
t('help.todo.syntax') => t('help.todo.desc')
|
13
|
+
}
|
14
|
+
)
|
15
|
+
|
16
|
+
route(
|
17
|
+
/^jira\sissue\sassignee\s(#{ISSUE_PATTERN})$/,
|
18
|
+
:issue_assignee_list,
|
19
|
+
command: true,
|
20
|
+
help: {
|
21
|
+
t('help.issue.assignee_list.syntax') => t('help.issue.assignee_list.desc')
|
22
|
+
}
|
23
|
+
)
|
24
|
+
|
25
|
+
route(
|
26
|
+
/^jira\sissue\sassignee\s(#{ISSUE_PATTERN})\s(.+)$/,
|
27
|
+
:issue_assignee_set,
|
28
|
+
command: true,
|
29
|
+
help: {
|
30
|
+
t('help.issue.assignee_set.syntax') => t('help.issue.assignee_set.syntax')
|
31
|
+
}
|
32
|
+
)
|
33
|
+
|
34
|
+
route(
|
35
|
+
/^jira\sissue\sattachments\s(#{ISSUE_PATTERN})$/,
|
36
|
+
:issue_attachments_list,
|
37
|
+
command: true,
|
38
|
+
help: {
|
39
|
+
t('help.issue.attachments_list.syntax') => t('help.issue.attachments_list.desc')
|
40
|
+
}
|
41
|
+
)
|
42
|
+
|
43
|
+
route(
|
44
|
+
/^jira\sissue\sattachments\s(#{ISSUE_PATTERN})\s(.+)$/,
|
45
|
+
:issue_attachments_set,
|
46
|
+
command: true,
|
47
|
+
help: {
|
48
|
+
t('help.issue.attachments_set.syntax') => t('help.issue.attachments_set.desc')
|
49
|
+
}
|
50
|
+
)
|
51
|
+
|
52
|
+
route(
|
53
|
+
/^jira\sissue\scomments\s(#{ISSUE_PATTERN})$/,
|
54
|
+
:issue_comments_list,
|
55
|
+
command: true,
|
56
|
+
help: {
|
57
|
+
t('help.issue.comments_list.syntax') => t('help.issue.comments_list.desc')
|
58
|
+
}
|
59
|
+
)
|
60
|
+
|
61
|
+
route(
|
62
|
+
/^jira\sissue\scomments\s(#{ISSUE_PATTERN})\s(.+)$/,
|
63
|
+
:issue_comments_add,
|
64
|
+
command: true,
|
65
|
+
help: {
|
66
|
+
t('help.issue.comments_set.syntax') => t('help.issue.comments_set.desc')
|
67
|
+
}
|
68
|
+
)
|
69
|
+
|
70
|
+
route(
|
71
|
+
/^jira\sissue\sdetails\s(#{ISSUE_PATTERN})$/,
|
72
|
+
:issue_details,
|
73
|
+
command: true,
|
74
|
+
help: {
|
75
|
+
t('help.issue.details.syntax') => t('help.issue.details.desc')
|
76
|
+
}
|
77
|
+
)
|
78
|
+
|
79
|
+
route(
|
80
|
+
/^jira\sissue\sissuetype\s(#{ISSUE_PATTERN})$/,
|
81
|
+
:issue_issuetype_list,
|
82
|
+
command: true,
|
83
|
+
help: {
|
84
|
+
t('help.issue.issuetype_list.syntax') => t('help.issue.issuetype_list.desc')
|
85
|
+
}
|
86
|
+
)
|
87
|
+
|
88
|
+
route(
|
89
|
+
/^jira\sissue\sissuetype\s(#{ISSUE_PATTERN})\s(\d+)$/,
|
90
|
+
:issue_issuetype_set,
|
91
|
+
command: true,
|
92
|
+
help: {
|
93
|
+
t('help.issue.issuetype_set.syntax') => t('help.issue.issuetype_set.desc')
|
94
|
+
}
|
95
|
+
)
|
96
|
+
|
97
|
+
route(
|
98
|
+
/^jira\sissue\snew\s(#{PROJECT_PATTERN})\s(.+)$/,
|
99
|
+
:issue_new,
|
100
|
+
help: {
|
101
|
+
t('help.issue.new.syntax') => t('help.issue.new.desc')
|
102
|
+
}
|
103
|
+
)
|
104
|
+
|
105
|
+
route(
|
106
|
+
/^jira\sissue\snotify\s(#{ISSUE_PATTERN})$/,
|
107
|
+
:issue_notify_list,
|
108
|
+
help: {
|
109
|
+
t('help.issue.notify_list.syntax') => t('help.issue.notify_list.desc')
|
110
|
+
}
|
111
|
+
)
|
112
|
+
|
113
|
+
route(
|
114
|
+
/^jira\sissue\snotify\s(#{ISSUE_PATTERN})\s(.+)$/,
|
115
|
+
:issue_notify_set,
|
116
|
+
help: {
|
117
|
+
t('help.issue.notify_set.syntax') => t('help.issue.notify_set.desc')
|
118
|
+
}
|
119
|
+
)
|
120
|
+
|
121
|
+
route(
|
122
|
+
/^jira\sissue\spriority\s(#{ISSUE_PATTERN})$/,
|
123
|
+
:issue_priority_list,
|
124
|
+
help: {
|
125
|
+
t('help.issue.priority_list.syntax') => t('help.issue.priority_list.desc')
|
126
|
+
}
|
127
|
+
)
|
128
|
+
|
129
|
+
route(
|
130
|
+
/^jira\sissue\spriority\s(#{ISSUE_PATTERN})\s(\d+)$/,
|
131
|
+
:issue_priority_set,
|
132
|
+
help: {
|
133
|
+
t('help.issue.priority_set.syntax') => t('help.issue.priority_set.desc')
|
134
|
+
}
|
135
|
+
)
|
136
|
+
|
137
|
+
route(
|
138
|
+
/^jira\sissue\ssummary\s(#{ISSUE_PATTERN})$/,
|
139
|
+
:issue_summary_list,
|
140
|
+
help: {
|
141
|
+
t('help.issue.summary_list.syntax') => t('help.issue.summary_list.desc')
|
142
|
+
}
|
143
|
+
)
|
144
|
+
|
145
|
+
route(
|
146
|
+
/^jira\sissue\ssummary\s(#{ISSUE_PATTERN})\s(.+)$/,
|
147
|
+
:issue_summary_set,
|
148
|
+
help: {
|
149
|
+
t('help.issue.summary_set.syntax') => t('help.issue.summary_set.desc')
|
150
|
+
}
|
151
|
+
)
|
152
|
+
|
153
|
+
route(
|
154
|
+
/^jira\sissue\swatchers\s(#{ISSUE_PATTERN})$/,
|
155
|
+
:issue_watchers_list,
|
156
|
+
help: {
|
157
|
+
t('help.issue.watchers_list.syntax') => t('help.issue.watchers_list.desc')
|
158
|
+
}
|
159
|
+
)
|
160
|
+
|
161
|
+
route(
|
162
|
+
/^jira\sissue\swatchers\s(#{ISSUE_PATTERN})\s(.+)$/,
|
163
|
+
:issue_watchers_set,
|
164
|
+
help: {
|
165
|
+
t('help.issue.watchers_set.syntax') => t('help.issue.watchers_set.desc')
|
166
|
+
}
|
167
|
+
)
|
168
|
+
|
169
|
+
route(
|
170
|
+
/^jira\sissuetype\slist\s(#{PROJECT_PATTERN})$/,
|
171
|
+
:issuetype_list,
|
172
|
+
help: {
|
173
|
+
t('help.issuetype.list.syntax') => t('help.issuetype.list.desc')
|
174
|
+
}
|
175
|
+
)
|
176
|
+
|
177
|
+
route(
|
178
|
+
/^jira\ssearch\s(.+)$/,
|
179
|
+
:search_full,
|
180
|
+
help: {
|
181
|
+
t('help.search.full.syntax') => t('help.search.full.desc')
|
182
|
+
}
|
183
|
+
)
|
184
|
+
|
185
|
+
route(
|
186
|
+
/^jira\ssearch\s(#{PROJECT_PATTERN})\s(.+)$/,
|
187
|
+
:search_project,
|
188
|
+
help: {
|
189
|
+
t('help.search.project.syntax') => t('help.search.project.desc')
|
190
|
+
}
|
191
|
+
)
|
192
|
+
|
193
|
+
route(
|
194
|
+
/^jira\sidentify\s(.+)$/,
|
195
|
+
:identify,
|
196
|
+
help: {
|
197
|
+
t('help.identify.syntax') => t('help.identify.desc')
|
198
|
+
}
|
199
|
+
)
|
200
|
+
|
201
|
+
route(
|
202
|
+
/^jira\sforget$/,
|
203
|
+
:forget,
|
204
|
+
help: {
|
205
|
+
t('help.forget.syntax') => t('help.forget.desc')
|
206
|
+
}
|
207
|
+
)
|
208
|
+
|
209
|
+
route(
|
210
|
+
/^jira\swhoami$/,
|
211
|
+
:whoami,
|
212
|
+
help: {
|
213
|
+
t('help.whoami.syntax') => t('help.whoami.desc')
|
214
|
+
}
|
215
|
+
)
|
216
|
+
|
217
|
+
route(
|
218
|
+
/^jira\sdefault\sproject\s(#{PROJECT_PATTERN})$/,
|
219
|
+
:default_project,
|
220
|
+
help: {
|
221
|
+
t('help.default.project.syntax') => t('help.default.project.desc')
|
222
|
+
}
|
223
|
+
)
|
224
|
+
|
225
|
+
route(
|
226
|
+
/^jira\sdefault\spriority\s(\d+)$/,
|
227
|
+
:default_priority,
|
228
|
+
help: {
|
229
|
+
t('help.default.priority.syntax') => t('help.default.priority.desc')
|
230
|
+
}
|
231
|
+
)
|
232
|
+
|
233
|
+
route(
|
234
|
+
/^jira\s(#{ISSUE_PATTERN})$/,
|
235
|
+
:issue_summary,
|
236
|
+
command: true,
|
237
|
+
help: {
|
238
|
+
'jira <issue ID>' => 'Shows summary for <issue ID>'
|
239
|
+
}
|
240
|
+
)
|
241
|
+
|
242
|
+
route(
|
243
|
+
/^jira\s(#{ISSUE_PATTERN})\sdetails$/,
|
244
|
+
:issue_details,
|
245
|
+
command: true,
|
246
|
+
help: {
|
247
|
+
'jira <issue ID> details' => 'Shows detailed information for <issue ID>' }
|
248
|
+
)
|
249
|
+
|
250
|
+
def self.default_config(config)
|
251
|
+
config.username = nil
|
252
|
+
config.password = nil
|
253
|
+
config.site = nil
|
254
|
+
config.context = nil
|
255
|
+
end
|
256
|
+
|
257
|
+
def issue_summary(response)
|
258
|
+
key = response.matches[0][0]
|
259
|
+
issue = fetch_issue(key)
|
260
|
+
if issue
|
261
|
+
response.reply("#{key}: #{issue.summary}")
|
262
|
+
else
|
263
|
+
response.reply(t('error.request'))
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def issue_details(response)
|
268
|
+
key = response.matches[0][0]
|
269
|
+
issue = fetch_issue(key)
|
270
|
+
if issue
|
271
|
+
response.reply(format_issue(issue))
|
272
|
+
else
|
273
|
+
response.reply(t('error.request'))
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def todo(response)
|
278
|
+
response.reply(t('error.not_implemented'))
|
279
|
+
end
|
280
|
+
|
281
|
+
def issue_assignee_list(response)
|
282
|
+
response.reply(t('error.not_implemented'))
|
283
|
+
end
|
284
|
+
|
285
|
+
def issue_assignee_set(response)
|
286
|
+
response.reply(t('error.not_implemented'))
|
287
|
+
end
|
288
|
+
|
289
|
+
def issue_attachments_list(response)
|
290
|
+
response.reply(t('error.not_implemented'))
|
291
|
+
end
|
292
|
+
|
293
|
+
def issue_attachments_set(response)
|
294
|
+
response.reply(t('error.not_implemented'))
|
295
|
+
end
|
296
|
+
|
297
|
+
def issue_comments_list(response)
|
298
|
+
response.reply(t('error.not_implemented'))
|
299
|
+
end
|
300
|
+
|
301
|
+
def issue_comments_add(response)
|
302
|
+
response.reply(t('error.not_implemented'))
|
303
|
+
end
|
304
|
+
|
305
|
+
def issue_issuetype_list(response)
|
306
|
+
response.reply(t('error.not_implemented'))
|
307
|
+
end
|
308
|
+
|
309
|
+
def issue_issuetype_set(response)
|
310
|
+
response.reply(t('error.not_implemented'))
|
311
|
+
end
|
312
|
+
|
313
|
+
def issue_new(response)
|
314
|
+
response.reply(t('error.not_implemented'))
|
315
|
+
end
|
316
|
+
|
317
|
+
def issue_notify_list(response)
|
318
|
+
response.reply(t('error.not_implemented'))
|
319
|
+
end
|
320
|
+
|
321
|
+
def issue_notify_set(response)
|
322
|
+
response.reply(t('error.not_implemented'))
|
323
|
+
end
|
324
|
+
|
325
|
+
def issue_priority_list(response)
|
326
|
+
response.reply(t('error.not_implemented'))
|
327
|
+
end
|
328
|
+
|
329
|
+
def issue_priority_set(response)
|
330
|
+
response.reply(t('error.not_implemented'))
|
331
|
+
end
|
332
|
+
|
333
|
+
def issue_summary_list(response)
|
334
|
+
response.reply(t('error.not_implemented'))
|
335
|
+
end
|
336
|
+
|
337
|
+
def issue_summary_set(response)
|
338
|
+
response.reply(t('error.not_implemented'))
|
339
|
+
end
|
340
|
+
|
341
|
+
def issue_watchers_list(response)
|
342
|
+
response.reply(t('error.not_implemented'))
|
343
|
+
end
|
344
|
+
|
345
|
+
def issue_watchers_set(response)
|
346
|
+
response.reply(t('error.not_implemented'))
|
347
|
+
end
|
348
|
+
|
349
|
+
def issuetype_list(response)
|
350
|
+
response.reply(t('error.not_implemented'))
|
351
|
+
end
|
352
|
+
|
353
|
+
def search_full(response)
|
354
|
+
response.reply(t('error.not_implemented'))
|
355
|
+
end
|
356
|
+
|
357
|
+
def search_project(response)
|
358
|
+
response.reply(t('error.not_implemented'))
|
359
|
+
end
|
360
|
+
|
361
|
+
def identify(response)
|
362
|
+
response.reply(t('error.not_implemented'))
|
363
|
+
end
|
364
|
+
|
365
|
+
def forget(response)
|
366
|
+
response.reply(t('error.not_implemented'))
|
367
|
+
end
|
368
|
+
|
369
|
+
def whoami(response)
|
370
|
+
response.reply(t('error.not_implemented'))
|
371
|
+
end
|
372
|
+
|
373
|
+
def default_project(response)
|
374
|
+
response.reply(t('error.not_implemented'))
|
375
|
+
end
|
376
|
+
|
377
|
+
def default_priority(response)
|
378
|
+
response.reply(t('error.not_implemented'))
|
379
|
+
end
|
380
|
+
|
381
|
+
private
|
382
|
+
|
383
|
+
def j_client
|
384
|
+
if Lita.config.handlers.jira.username.nil? ||
|
385
|
+
Lita.config.handlers.jira.password.nil? ||
|
386
|
+
Lita.config.handlers.jira.site.nil? ||
|
387
|
+
Lita.config.handlers.jira.context.nil?
|
388
|
+
Lita.logger.error('Missing config for JIRA')
|
389
|
+
fail 'Missing config'
|
390
|
+
end
|
391
|
+
|
392
|
+
JIRA::Client.new(
|
393
|
+
username: Lita.config.handlers.jira.username,
|
394
|
+
password: Lita.config.handlers.jira.password,
|
395
|
+
site: Lita.config.handlers.jira.site,
|
396
|
+
context_path: Lita.config.handlers.jira.context,
|
397
|
+
auth_type: :basic
|
398
|
+
)
|
399
|
+
end
|
400
|
+
|
401
|
+
def fetch_issue(key)
|
402
|
+
j_client.Issue.find(key)
|
403
|
+
rescue JIRA::HTTPError
|
404
|
+
Lita.logger.error('JIRA HTTPError')
|
405
|
+
nil
|
406
|
+
end
|
407
|
+
|
408
|
+
def format_issue(issue)
|
409
|
+
t('issue.details',
|
410
|
+
key: issue.key,
|
411
|
+
summary: issue.summary,
|
412
|
+
assigned: issue.assignee.displayName,
|
413
|
+
priority: issue.priority.name,
|
414
|
+
status: issue.status.name)
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
Lita.register_handler(Jira)
|
419
|
+
end
|
420
|
+
end
|
data/lib/lita-jira.rb
ADDED
data/lita-jira.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
Gem::Specification.new do |spec|
|
2
|
+
spec.name = 'lita-jira'
|
3
|
+
spec.version = '0.3.1'
|
4
|
+
spec.authors = ['Eric Sigler']
|
5
|
+
spec.email = ['me@esigler.com']
|
6
|
+
spec.description = 'A Lita handler for interacting with a JIRA ticket tracker.'
|
7
|
+
spec.summary = 'A Lita handler for interacting with a JIRA ticket tracker.'
|
8
|
+
spec.homepage = 'https://github.com/esigler/lita-jira'
|
9
|
+
spec.license = 'MIT'
|
10
|
+
spec.metadata = { 'lita_plugin_type' => 'handler' }
|
11
|
+
|
12
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
13
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
14
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
15
|
+
spec.require_paths = ['lib']
|
16
|
+
|
17
|
+
spec.add_runtime_dependency 'lita', '>= 3.0'
|
18
|
+
spec.add_runtime_dependency 'jira-ruby', '>= 0.1.8'
|
19
|
+
|
20
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
21
|
+
spec.add_development_dependency 'rake'
|
22
|
+
spec.add_development_dependency 'rspec', '>= 3.0.0.beta2'
|
23
|
+
spec.add_development_dependency 'simplecov'
|
24
|
+
spec.add_development_dependency 'coveralls'
|
25
|
+
spec.add_development_dependency 'rubocop'
|
26
|
+
end
|
data/locales/en.yml
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
en:
|
2
|
+
lita:
|
3
|
+
handlers:
|
4
|
+
jira:
|
5
|
+
error:
|
6
|
+
not_implemented: Not implemented yet.
|
7
|
+
request: Error fetching JIRA issue
|
8
|
+
help:
|
9
|
+
todo:
|
10
|
+
syntax: todo <summary>
|
11
|
+
desc: Creates an issue with your default priority and project settings, assigned to yourself
|
12
|
+
issue:
|
13
|
+
assignee_list:
|
14
|
+
syntax: jira issue assignee <issue ID>
|
15
|
+
desc: Shows assignee of <issue ID>
|
16
|
+
assignee_set:
|
17
|
+
syntax: jira issue assignee <issue ID> <email address>
|
18
|
+
desc: Sets <email address> as the assignee
|
19
|
+
attachments_list:
|
20
|
+
syntax: jira issue attachments <issue ID>
|
21
|
+
desc: Shows all attachments for <issue ID>
|
22
|
+
attachments_set:
|
23
|
+
syntax: jira issue attachments <issue ID> <URL>
|
24
|
+
desc: Adds <URL> as an attachment on <issue ID>
|
25
|
+
comments_list:
|
26
|
+
syntax: jira issue comments <issue ID>
|
27
|
+
desc: Shows all comments for <issue ID>
|
28
|
+
comments_set:
|
29
|
+
syntax: jira issue comments <issue ID> <text>
|
30
|
+
desc: Adds <text> as a comment on <issue ID>
|
31
|
+
details:
|
32
|
+
syntax: jira issue details <issue ID>
|
33
|
+
desc: Shows all details for <issue ID>
|
34
|
+
issuetype_list:
|
35
|
+
syntax: jira issue issuetype <issue ID>
|
36
|
+
desc: Shows the Issue Type of <issue ID>
|
37
|
+
issuetype_set:
|
38
|
+
syntax: jira issue issuetype <issue ID> <issuetype ID>
|
39
|
+
desc: Sets the Issue Type of <issue ID> to <issuetype ID>
|
40
|
+
issue:
|
41
|
+
details: "%{key}: %{summary}, assigned to: %{assigned}, priority: %{priority}, status: %{status}"
|
@@ -0,0 +1,192 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lita::Handlers::Jira, lita_handler: true do
|
4
|
+
let(:open_issue) do
|
5
|
+
double(summary: 'Some summary text',
|
6
|
+
assignee: double(displayName: 'A Person'),
|
7
|
+
priority: double(name: 'P0'),
|
8
|
+
status: double(name: 'In Progress'),
|
9
|
+
key: 'XYZ-987')
|
10
|
+
end
|
11
|
+
|
12
|
+
def grab_issue_request(key, issue)
|
13
|
+
allow_any_instance_of(Lita::Handlers::Jira).to \
|
14
|
+
receive(:fetch_issue).with(key).and_return(issue)
|
15
|
+
end
|
16
|
+
|
17
|
+
it { routes_command('todo some text').to(:todo) }
|
18
|
+
it { routes_command('jira issue assignee ABC-123').to(:issue_assignee_list) }
|
19
|
+
it { routes_command('jira issue assignee ABC-123 foo@example.com').to(:issue_assignee_set) }
|
20
|
+
it { routes_command('jira issue attachments ABC-123').to(:issue_attachments_list) }
|
21
|
+
it { routes_command('jira issue attachments ABC-123 http://example.com').to(:issue_attachments_set) }
|
22
|
+
it { routes_command('jira issue comments ABC-123').to(:issue_comments_list) }
|
23
|
+
it { routes_command('jira issue comments ABC-123 Some text').to(:issue_comments_add) }
|
24
|
+
it { routes_command('jira issue details ABC-123').to(:issue_details) }
|
25
|
+
it { routes_command('jira issue issuetype ABC-123').to(:issue_issuetype_list) }
|
26
|
+
it { routes_command('jira issue issuetype ABC-123 4').to(:issue_issuetype_set) }
|
27
|
+
it { routes_command('jira issue new ABC some:thing').to(:issue_new) }
|
28
|
+
it { routes_command('jira issue notify ABC-123').to(:issue_notify_list) }
|
29
|
+
it { routes_command('jira issue notify ABC-123 foo@example.com').to(:issue_notify_set) }
|
30
|
+
it { routes_command('jira issue priority ABC-123').to(:issue_priority_list) }
|
31
|
+
it { routes_command('jira issue priority ABC-123 9').to(:issue_priority_set) }
|
32
|
+
it { routes_command('jira issue summary ABC-123').to(:issue_summary_list) }
|
33
|
+
it { routes_command('jira issue summary ABC-123 Some text!').to(:issue_summary_set) }
|
34
|
+
it { routes_command('jira issue watchers ABC-123').to(:issue_watchers_list) }
|
35
|
+
it { routes_command('jira issue watchers ABC-123 foo@example.com').to(:issue_watchers_set) }
|
36
|
+
it { routes_command('jira issuetype list ABC').to(:issuetype_list) }
|
37
|
+
it { routes_command('jira search Some text').to(:search_full) }
|
38
|
+
it { routes_command('jira search ABC Some text').to(:search_project) }
|
39
|
+
it { routes_command('jira identify foo@example.com').to(:identify) }
|
40
|
+
it { routes_command('jira forget').to(:forget) }
|
41
|
+
it { routes_command('jira whoami').to(:whoami) }
|
42
|
+
it { routes_command('jira default project ABC').to(:default_project) }
|
43
|
+
it { routes_command('jira default priority 9').to(:default_priority) }
|
44
|
+
|
45
|
+
describe '.default_config' do
|
46
|
+
it 'sets username to nil' do
|
47
|
+
expect(Lita.config.handlers.jira.username).to be_nil
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'sets password to nil' do
|
51
|
+
expect(Lita.config.handlers.jira.password).to be_nil
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'sets site to nil' do
|
55
|
+
expect(Lita.config.handlers.jira.site).to be_nil
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'sets context to nil' do
|
59
|
+
expect(Lita.config.handlers.jira.context).to be_nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#issue_summary' do
|
64
|
+
it 'with valid issue ID shows summary' do
|
65
|
+
grab_issue_request('XYZ-987', open_issue)
|
66
|
+
send_command('jira XYZ-987')
|
67
|
+
expect(replies.last).to eq('XYZ-987: Some summary text')
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'without valid issue ID shows an error' do
|
71
|
+
grab_issue_request('XYZ-987', nil)
|
72
|
+
send_command('jira XYZ-987')
|
73
|
+
expect(replies.last).to eq('Error fetching JIRA issue')
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#issue_details' do
|
78
|
+
it 'with valid issue ID shows details' do
|
79
|
+
grab_issue_request('XYZ-987', open_issue)
|
80
|
+
send_command('jira XYZ-987 details')
|
81
|
+
expect(replies.last).to eq('XYZ-987: Some summary text, assigned to: ' \
|
82
|
+
'A Person, priority: P0, status: In Progress')
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'without valid issue ID shows an error' do
|
86
|
+
grab_issue_request('XYZ-987', nil)
|
87
|
+
send_command('jira XYZ-987 details')
|
88
|
+
expect(replies.last).to eq('Error fetching JIRA issue')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#todo' do
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '#issue_assignee_list' do
|
96
|
+
it 'with valid issue ID shows the current assignees'
|
97
|
+
|
98
|
+
it 'without valid issue ID shows an error'
|
99
|
+
end
|
100
|
+
|
101
|
+
describe '#issue_assignee_set' do
|
102
|
+
it 'with valid issue ID sets an assignee'
|
103
|
+
|
104
|
+
it 'without valid issue ID shows an error'
|
105
|
+
end
|
106
|
+
|
107
|
+
describe '#issue_attachments_list' do
|
108
|
+
it 'with valid issue ID shows the current attachments'
|
109
|
+
|
110
|
+
it 'without valid issue ID shows an error'
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#issue_attachments_set' do
|
114
|
+
it 'without valid issue ID shows an error'
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#issue_comments_list' do
|
118
|
+
it 'without valid issue ID shows an error'
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#issue_comments_add' do
|
122
|
+
it 'without valid issue ID shows an error'
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '#issue_issuetype_list' do
|
126
|
+
it 'without valid issue ID shows an error'
|
127
|
+
end
|
128
|
+
|
129
|
+
describe '#issue_issuetype_set' do
|
130
|
+
it 'without valid issue ID shows an error'
|
131
|
+
end
|
132
|
+
|
133
|
+
describe '#issue_new' do
|
134
|
+
end
|
135
|
+
|
136
|
+
describe '#issue_notify_list' do
|
137
|
+
it 'without valid issue ID shows an error'
|
138
|
+
end
|
139
|
+
|
140
|
+
describe '#issue_notify_set' do
|
141
|
+
it 'without valid issue ID shows an error'
|
142
|
+
end
|
143
|
+
|
144
|
+
describe '#issue_priority_list' do
|
145
|
+
it 'without valid issue ID shows an error'
|
146
|
+
end
|
147
|
+
|
148
|
+
describe '#issue_priority_set' do
|
149
|
+
it 'without valid issue ID shows an error'
|
150
|
+
end
|
151
|
+
|
152
|
+
describe '#issue_summary_list' do
|
153
|
+
it 'without valid issue ID shows an error'
|
154
|
+
end
|
155
|
+
|
156
|
+
describe '#issue_summary_set' do
|
157
|
+
it 'without valid issue ID shows an error'
|
158
|
+
end
|
159
|
+
|
160
|
+
describe '#issue_watchers_list' do
|
161
|
+
it 'without valid issue ID shows an error'
|
162
|
+
end
|
163
|
+
|
164
|
+
describe '#issue_watchers_set' do
|
165
|
+
it 'without valid issue ID shows an error'
|
166
|
+
end
|
167
|
+
|
168
|
+
describe '#issuetype_list' do
|
169
|
+
it 'without valid issuetype shows an error'
|
170
|
+
end
|
171
|
+
|
172
|
+
describe '#search_full' do
|
173
|
+
end
|
174
|
+
|
175
|
+
describe '#search_project' do
|
176
|
+
end
|
177
|
+
|
178
|
+
describe '#identify' do
|
179
|
+
end
|
180
|
+
|
181
|
+
describe '#forget' do
|
182
|
+
end
|
183
|
+
|
184
|
+
describe '#whoami' do
|
185
|
+
end
|
186
|
+
|
187
|
+
describe '#default_project' do
|
188
|
+
end
|
189
|
+
|
190
|
+
describe '#default_priority' do
|
191
|
+
end
|
192
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'coveralls'
|
3
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
4
|
+
SimpleCov::Formatter::HTMLFormatter,
|
5
|
+
Coveralls::SimpleCov::Formatter
|
6
|
+
]
|
7
|
+
SimpleCov.start { add_filter '/spec/' }
|
8
|
+
|
9
|
+
require 'lita-jira'
|
10
|
+
require 'lita/rspec'
|
metadata
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lita-jira
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Eric Sigler
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: lita
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: jira-ruby
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.1.8
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.1.8
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.0.0.beta2
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.0.0.beta2
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov
|
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'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: coveralls
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description: A Lita handler for interacting with a JIRA ticket tracker.
|
126
|
+
email:
|
127
|
+
- me@esigler.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- ".gitignore"
|
133
|
+
- ".rubocop.yml"
|
134
|
+
- ".travis.yml"
|
135
|
+
- CONTRIBUTING.md
|
136
|
+
- Gemfile
|
137
|
+
- LICENSE
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- lib/lita-jira.rb
|
141
|
+
- lib/lita/handlers/jira.rb
|
142
|
+
- lita-jira.gemspec
|
143
|
+
- locales/en.yml
|
144
|
+
- spec/lita/handlers/jira_spec.rb
|
145
|
+
- spec/spec_helper.rb
|
146
|
+
homepage: https://github.com/esigler/lita-jira
|
147
|
+
licenses:
|
148
|
+
- MIT
|
149
|
+
metadata:
|
150
|
+
lita_plugin_type: handler
|
151
|
+
post_install_message:
|
152
|
+
rdoc_options: []
|
153
|
+
require_paths:
|
154
|
+
- lib
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
requirements: []
|
166
|
+
rubyforge_project:
|
167
|
+
rubygems_version: 2.2.2
|
168
|
+
signing_key:
|
169
|
+
specification_version: 4
|
170
|
+
summary: A Lita handler for interacting with a JIRA ticket tracker.
|
171
|
+
test_files:
|
172
|
+
- spec/lita/handlers/jira_spec.rb
|
173
|
+
- spec/spec_helper.rb
|