rct_jira 0.3
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.
- data/bin/jira +39 -0
- data/lib/rct_jira.rb +376 -0
- metadata +70 -0
data/bin/jira
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright 2014-2015 Jyri J. Virkki <jyri@virkki.com>
|
5
|
+
#
|
6
|
+
# This file is part of rct_jira.
|
7
|
+
#
|
8
|
+
# rct_jira is free software: you can redistribute it and/or modify it
|
9
|
+
# under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# rct_jira is distributed in the hope that it will be useful, but
|
14
|
+
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
16
|
+
# General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with rct_jira. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
#
|
21
|
+
|
22
|
+
|
23
|
+
#
|
24
|
+
# Convenience script for running jira CLI directly.
|
25
|
+
#
|
26
|
+
# Run:
|
27
|
+
#
|
28
|
+
# jira OPERATION PARAMS
|
29
|
+
#
|
30
|
+
# This is equivalent to running rct directly as follows:
|
31
|
+
#
|
32
|
+
# rct --req rct_jira Jira.OPERATION PARAMS
|
33
|
+
#
|
34
|
+
|
35
|
+
require 'rct_jira'
|
36
|
+
|
37
|
+
$RCT_CLI_APP_CLASS = "Jira"
|
38
|
+
|
39
|
+
require 'rct_cli_app'
|
data/lib/rct_jira.rb
ADDED
@@ -0,0 +1,376 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013-2015 Jyri J. Virkki <jyri@virkki.com>
|
3
|
+
#
|
4
|
+
# This file is part of rct_jira.
|
5
|
+
#
|
6
|
+
# rct_jira is free software: you can redistribute it and/or modify it
|
7
|
+
# under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# rct_jira is distributed in the hope that it will be useful, but
|
12
|
+
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
+
# General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU General Public License
|
17
|
+
# along with rct_jira. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
#
|
19
|
+
|
20
|
+
|
21
|
+
#
|
22
|
+
# Implements an rct client for JIRA APIs.
|
23
|
+
#
|
24
|
+
# Only a tiny subset supported. Expand as needed.
|
25
|
+
#
|
26
|
+
# https://developer.atlassian.com/display/JIRADEV/JIRA+REST+API+Tutorials
|
27
|
+
# https://docs.atlassian.com/jira/REST/latest/
|
28
|
+
#
|
29
|
+
|
30
|
+
|
31
|
+
require 'rct_client'
|
32
|
+
|
33
|
+
class Jira < RCTClient
|
34
|
+
|
35
|
+
BASE_PATH = '/rest/api/2'
|
36
|
+
|
37
|
+
|
38
|
+
#----------------------------------------------------------------------------
|
39
|
+
# Class description, for automated help.
|
40
|
+
#
|
41
|
+
def description
|
42
|
+
"The RCT Jira class implements access to some of the common Jira\n" +
|
43
|
+
"(http://en.wikipedia.org/wiki/JIRA) APIs."
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
#----------------------------------------------------------------------------
|
48
|
+
# CLI definition. Used by the rct framework to determine what CLI
|
49
|
+
# commands are available here. This maps the operation name to a
|
50
|
+
# Hash of info about that operation.
|
51
|
+
#
|
52
|
+
# Note that this needs to list only those operations which can be
|
53
|
+
# invoked in CLI mode. Not all operations supported by an rct client
|
54
|
+
# module are necessarily CLI-compatible so this may be a subset of
|
55
|
+
# the operations available here.
|
56
|
+
#
|
57
|
+
def cli
|
58
|
+
return {
|
59
|
+
'server_info' => ServerInfo,
|
60
|
+
'not_watching' => NotWatching,
|
61
|
+
'add_my_watch' => AddMyWatch,
|
62
|
+
'watch_category' => WatchCategory,
|
63
|
+
'mine' => Mine
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
#----------------------------------------------------------------------------
|
69
|
+
# Retrieve server info (really only useful to test API/connection).
|
70
|
+
# No authentication required.
|
71
|
+
#
|
72
|
+
# https://docs.atlassian.com/jira/REST/latest/#idp1713744
|
73
|
+
#
|
74
|
+
# Required: none
|
75
|
+
# Optional: none
|
76
|
+
# Saves to state: nothing
|
77
|
+
#
|
78
|
+
ServerInfo = {
|
79
|
+
'description' => "Retrieve server info (mainly for testing connection)",
|
80
|
+
'required' => { },
|
81
|
+
'optional' => { }
|
82
|
+
}
|
83
|
+
|
84
|
+
def server_info
|
85
|
+
ssettmp(SERVER_PROTOCOL, 'https')
|
86
|
+
ssettmp(REQ_METHOD, 'GET')
|
87
|
+
ssettmp(REQ_PATH, "#{BASE_PATH}/serverInfo")
|
88
|
+
yield
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
#----------------------------------------------------------------------------
|
93
|
+
# Retrieve a list of issues which I (user authenticating) am not watching.
|
94
|
+
#
|
95
|
+
# Note this may not be a full list of unwatched issues if the list is larger
|
96
|
+
# than the limit, which defaults to 100. The server may also impose a limit
|
97
|
+
# which might be smaller than the requested limit.
|
98
|
+
#
|
99
|
+
# Required:
|
100
|
+
# username : Authenticate as this user.
|
101
|
+
# password : Password of username.
|
102
|
+
# project : JIRA project name to search.
|
103
|
+
# Optional:
|
104
|
+
# limit : Return up to this many results (default: 100)
|
105
|
+
# Saves to state:
|
106
|
+
# not_watching_result : Hash of key => description of all issues found
|
107
|
+
#
|
108
|
+
NotWatching = {
|
109
|
+
'description' => "Retrieve list of issues I am not watching",
|
110
|
+
'required' => {
|
111
|
+
'username' => [ '-u', '--user', 'User name' ],
|
112
|
+
'password' => [ '-P', '--password', 'Password' ],
|
113
|
+
'project' => [ '-c' , '--project', 'Project name (category)' ],
|
114
|
+
},
|
115
|
+
'optional' => {
|
116
|
+
'limit' => [ '-l', '--limit', 'Limit result set size to this number'],
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
def not_watching
|
121
|
+
user = sget('username')
|
122
|
+
password = sget('password')
|
123
|
+
project = sget('project')
|
124
|
+
|
125
|
+
limit = sget('limit')
|
126
|
+
limit = '100' if (limit == nil)
|
127
|
+
|
128
|
+
ssettmp(SERVER_PROTOCOL, 'https')
|
129
|
+
ssettmp(REQ_METHOD, 'GET')
|
130
|
+
ssettmp(REQ_AUTH_TYPE, REQ_AUTH_TYPE_BASIC)
|
131
|
+
ssettmp(REQ_AUTH_NAME, user)
|
132
|
+
ssettmp(REQ_AUTH_PWD, password)
|
133
|
+
ssettmp(REQ_PATH, "#{BASE_PATH}/search")
|
134
|
+
|
135
|
+
params = add_param(nil, 'maxResults', limit)
|
136
|
+
params = add_param(params, 'fields', 'summary')
|
137
|
+
params = add_param(params, 'jql',
|
138
|
+
"project=#{project} and watcher != currentUser()")
|
139
|
+
ssettmp(REQ_PARAMS, params)
|
140
|
+
|
141
|
+
result = yield
|
142
|
+
|
143
|
+
if (result.ok)
|
144
|
+
# On success, create a simple key->description hash with the results
|
145
|
+
if (is_cli) then cli_output = "\n" end
|
146
|
+
unwatched = Hash.new()
|
147
|
+
json = JSON.parse(result.body)
|
148
|
+
|
149
|
+
issues = json['issues']
|
150
|
+
if (issues != nil)
|
151
|
+
issues.each { |h|
|
152
|
+
key = h['key']
|
153
|
+
summary = h['fields']['summary']
|
154
|
+
unwatched[key] = summary
|
155
|
+
if (is_cli) then cli_output += "#{key} : #{summary}\n" end
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
sset('not_watching_result', unwatched)
|
160
|
+
if (is_cli)
|
161
|
+
sset(CLI_OUTPUT, cli_output)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
return result
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
#----------------------------------------------------------------------------
|
170
|
+
# Retrieve a list of issues which I (user authenticating) own.
|
171
|
+
#
|
172
|
+
# Note this may not be a full list of if the list is larger than the
|
173
|
+
# limit, which defaults to 100. The server may also impose a limit
|
174
|
+
# which might be smaller than the requested limit.
|
175
|
+
#
|
176
|
+
# Required:
|
177
|
+
# username : Authenticate as this user.
|
178
|
+
# password : Password of username.
|
179
|
+
# Optional:
|
180
|
+
# limit : Return up to this many results (default: 100)
|
181
|
+
# project : Limit results to this project.
|
182
|
+
# Saves to state:
|
183
|
+
# my_bugs : Hash of key => description of all issues found
|
184
|
+
#
|
185
|
+
Mine = {
|
186
|
+
'description' => "Retrieve list of issues I own",
|
187
|
+
'required' => {
|
188
|
+
'username' => [ '-u', '--user', 'User name' ],
|
189
|
+
'password' => [ '-P', '--password', 'Password' ],
|
190
|
+
},
|
191
|
+
'optional' => {
|
192
|
+
'limit' => [ '-l', '--limit', 'Limit result set size to this number'],
|
193
|
+
'project' => [ '-c' , '--project', 'Project name (category)' ],
|
194
|
+
}
|
195
|
+
}
|
196
|
+
|
197
|
+
def mine
|
198
|
+
user = sget('username')
|
199
|
+
password = sget('password')
|
200
|
+
project = sget('project')
|
201
|
+
|
202
|
+
limit = sget('limit')
|
203
|
+
limit = '100' if (limit == nil)
|
204
|
+
|
205
|
+
ssettmp(SERVER_PROTOCOL, 'https')
|
206
|
+
ssettmp(REQ_METHOD, 'GET')
|
207
|
+
ssettmp(REQ_AUTH_TYPE, REQ_AUTH_TYPE_BASIC)
|
208
|
+
ssettmp(REQ_AUTH_NAME, user)
|
209
|
+
ssettmp(REQ_AUTH_PWD, password)
|
210
|
+
ssettmp(REQ_PATH, "#{BASE_PATH}/search")
|
211
|
+
|
212
|
+
params = add_param(nil, 'maxResults', limit)
|
213
|
+
params = add_param(params, 'fields', 'summary')
|
214
|
+
|
215
|
+
jql = ""
|
216
|
+
if (project != nil)
|
217
|
+
jql = "project=#{project} AND "
|
218
|
+
end
|
219
|
+
jql = "#{jql}assignee = currentUser() AND (status=\"Open\" OR status=\"In Progress\")"
|
220
|
+
|
221
|
+
params = add_param(params, 'jql', jql)
|
222
|
+
ssettmp(REQ_PARAMS, params)
|
223
|
+
|
224
|
+
result = yield
|
225
|
+
|
226
|
+
if (result.ok)
|
227
|
+
# On success, create a simple key->description hash with the results
|
228
|
+
if (is_cli) then cli_output = "\n" end
|
229
|
+
list = Hash.new()
|
230
|
+
json = JSON.parse(result.body)
|
231
|
+
issues = json['issues']
|
232
|
+
issues.each { |h|
|
233
|
+
key = h['key']
|
234
|
+
summary = h['fields']['summary']
|
235
|
+
list[key] = summary
|
236
|
+
if (is_cli) then cli_output += "#{key} : #{summary}\n" end
|
237
|
+
}
|
238
|
+
sset('my_bugs', list)
|
239
|
+
if (is_cli)
|
240
|
+
sset(CLI_OUTPUT, cli_output)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
return result
|
245
|
+
end
|
246
|
+
|
247
|
+
|
248
|
+
#----------------------------------------------------------------------------
|
249
|
+
# Add myself as a watcher to one issue.
|
250
|
+
#
|
251
|
+
# https://docs.atlassian.com/jira/REST/latest/#idp1831280
|
252
|
+
#
|
253
|
+
# Required:
|
254
|
+
# username : Authenticate as this user.
|
255
|
+
# password : Password of username.
|
256
|
+
# project : JIRA project name to search.
|
257
|
+
# key : JIRA issue key to update.
|
258
|
+
# Optional:
|
259
|
+
# none
|
260
|
+
# Saves to state:
|
261
|
+
# nothing
|
262
|
+
#
|
263
|
+
AddMyWatch = {
|
264
|
+
'description' => "Add myself as a watcher to one issue",
|
265
|
+
'required' => {
|
266
|
+
'username' => [ '-u', '--user', 'User name' ],
|
267
|
+
'password' => [ '-P', '--password', 'Password' ],
|
268
|
+
'project' => [ '-c' , '--project', 'Project name (category)' ],
|
269
|
+
'key' => [ '-k', '--issuekey', 'Issue to add myself as watcher'],
|
270
|
+
},
|
271
|
+
'optional' => { }
|
272
|
+
}
|
273
|
+
|
274
|
+
def add_my_watch
|
275
|
+
user = sget('username')
|
276
|
+
password = sget('password')
|
277
|
+
project = sget('project')
|
278
|
+
key = sget('key')
|
279
|
+
|
280
|
+
ssettmp(SERVER_PROTOCOL, 'https')
|
281
|
+
ssettmp(REQ_METHOD, 'POST')
|
282
|
+
ssettmp(REQ_AUTH_TYPE, REQ_AUTH_TYPE_BASIC)
|
283
|
+
ssettmp(REQ_AUTH_NAME, user)
|
284
|
+
ssettmp(REQ_AUTH_PWD, password)
|
285
|
+
ssettmp(REQ_PATH, "#{BASE_PATH}/issue/#{key}/watchers")
|
286
|
+
ssettmp(REQ_BODY, "\"#{user}\"")
|
287
|
+
|
288
|
+
headers = Hash.new()
|
289
|
+
headers['Content-type'] = 'application/json'
|
290
|
+
ssettmp(REQ_HEADERS, headers)
|
291
|
+
|
292
|
+
result = yield
|
293
|
+
|
294
|
+
if (result.status == 204)
|
295
|
+
if (is_cli)
|
296
|
+
sset(CLI_OUTPUT, "Added #{user} as a watcher to #{key}")
|
297
|
+
end
|
298
|
+
else
|
299
|
+
result.add_error("Unable to add #{user} to #{key}")
|
300
|
+
end
|
301
|
+
|
302
|
+
return result
|
303
|
+
end
|
304
|
+
|
305
|
+
|
306
|
+
#----------------------------------------------------------------------------
|
307
|
+
# Add myself as a watcher to all unwatched issues in a given category.
|
308
|
+
#
|
309
|
+
# This is a wrapper function which combines NotWatching and AddMyWatch
|
310
|
+
# for convenience.
|
311
|
+
#
|
312
|
+
# Note this may not be able to add me to all unwatched issues if there
|
313
|
+
# are more than the server list limit. In that case one may need to run
|
314
|
+
# this multiple times.
|
315
|
+
#
|
316
|
+
# Required:
|
317
|
+
# username : Authenticate as this user.
|
318
|
+
# password : Password of username.
|
319
|
+
# project : JIRA project name to watch.
|
320
|
+
# Optional:
|
321
|
+
# none
|
322
|
+
# Saves to state:
|
323
|
+
# nothing
|
324
|
+
#
|
325
|
+
WatchCategory = {
|
326
|
+
'description' => "Add myself as a watcher to all issues in category",
|
327
|
+
'required' => {
|
328
|
+
'username' => [ '-u', '--user', 'User name' ],
|
329
|
+
'password' => [ '-P', '--password', 'Password' ],
|
330
|
+
'project' => [ '-c' , '--project', 'Project name (category)' ],
|
331
|
+
},
|
332
|
+
'optional' => { }
|
333
|
+
}
|
334
|
+
|
335
|
+
def watch_category
|
336
|
+
|
337
|
+
project = sget('project')
|
338
|
+
|
339
|
+
# Pretend we're not in CLI mode even if we are to avoid duplicate output
|
340
|
+
# from the functions we're wrapping.
|
341
|
+
|
342
|
+
mode = RCT.sget(RCT_MODE)
|
343
|
+
RCT.sdelete(RCT_MODE)
|
344
|
+
|
345
|
+
result = not_watching { $HTTP.handle_request() }
|
346
|
+
if (!result.ok)
|
347
|
+
result.add_error("Unable to get list of unwatched issues")
|
348
|
+
RCT.sset(RCT_MODE, mode)
|
349
|
+
return result
|
350
|
+
end
|
351
|
+
|
352
|
+
issues = RCT.sget('not_watching_result')
|
353
|
+
count = 0
|
354
|
+
|
355
|
+
issues.each { |key, desc|
|
356
|
+
RCT.log(RESULT, "#{key}: #{desc}")
|
357
|
+
RCT.sset('key', key)
|
358
|
+
result = add_my_watch { $HTTP.handle_request() }
|
359
|
+
if (!result.ok)
|
360
|
+
result.add_error("Unable to add watcher to #{key}")
|
361
|
+
RCT.sset(RCT_MODE, mode)
|
362
|
+
return result
|
363
|
+
end
|
364
|
+
count = count + 1
|
365
|
+
}
|
366
|
+
|
367
|
+
RCT.sset(RCT_MODE, mode)
|
368
|
+
if (is_cli)
|
369
|
+
sset(CLI_OUTPUT, "Added #{count} bugs to watch in #{project}")
|
370
|
+
end
|
371
|
+
|
372
|
+
return result
|
373
|
+
end
|
374
|
+
|
375
|
+
|
376
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rct_jira
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.3'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jyri J. Virkki
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-02-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rct
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.7'
|
22
|
+
- - <
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '1.0'
|
25
|
+
type: :runtime
|
26
|
+
prerelease: false
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0.7'
|
33
|
+
- - <
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '1.0'
|
36
|
+
description: wip
|
37
|
+
email: jyri@virkki.com
|
38
|
+
executables:
|
39
|
+
- jira
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- lib/rct_jira.rb
|
44
|
+
- bin/jira
|
45
|
+
homepage: https://github.com/jvirkki/rct_jira
|
46
|
+
licenses:
|
47
|
+
- GPLv3
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ! '>='
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '0'
|
58
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
60
|
+
requirements:
|
61
|
+
- - ! '>='
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
requirements: []
|
65
|
+
rubyforge_project: nowarning
|
66
|
+
rubygems_version: 1.8.23
|
67
|
+
signing_key:
|
68
|
+
specification_version: 3
|
69
|
+
summary: rct client support for jira
|
70
|
+
test_files: []
|