rct_jira 0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/jira +39 -0
  2. data/lib/rct_jira.rb +376 -0
  3. 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: []