jirarest2 0.0.7 → 0.0.8
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.tar.gz.sig +0 -0
- data/History.txt +14 -0
- data/README.txt +1 -1
- data/bin/jira_create_issue +79 -21
- data/lib/jirarest2.rb +1 -1
- data/lib/jirarest2/connect.rb +1 -1
- data/lib/jirarest2/exceptions.rb +11 -1
- data/lib/jirarest2/issue.rb +4 -4
- data/lib/jirarest2/result.rb +1 -1
- data/lib/jirarest2/services/issuelink.rb +1 -2
- data/test/test_connect.rb +8 -4
- data/test/test_issue.rb +10 -0
- metadata +3 -3
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
=== 0.0.8 / 2012-07-25
|
2
|
+
|
3
|
+
* 1 minor enhancement:
|
4
|
+
|
5
|
+
* jira_create_issue : Extended the possibilities with the -C paramter. You can now just pass on the content data or use an extended JSON to add project, issue, watchers and links. See --help-C . fixes #9 fixes #10
|
6
|
+
|
7
|
+
* 1 bug fix:
|
8
|
+
|
9
|
+
* Fixed #17 and added a test to catch that behaviour in the future
|
10
|
+
|
11
|
+
* 1 unknown:
|
12
|
+
|
13
|
+
* Fixed bugs with mocked tests.
|
14
|
+
|
1
15
|
=== 0.0.7 / 2012-07-23
|
2
16
|
|
3
17
|
* 2 major enhancements:
|
data/README.txt
CHANGED
@@ -10,7 +10,7 @@ It is intended to be called within the shell to create and verify JIRA(tm) issue
|
|
10
10
|
|
11
11
|
This implementation is still a for cry from others like http://rubygems.org/gems/jira-ruby which required oauth authentification.
|
12
12
|
|
13
|
-
The script allows you to create new issues with watchers and link those to existing issues
|
13
|
+
The script allows you to create new issues with watchers and link those to existing issues.
|
14
14
|
|
15
15
|
*Use it at your own risk. Most of the API features are not implemented.*
|
16
16
|
|
data/bin/jira_create_issue
CHANGED
@@ -33,6 +33,39 @@ require "uri"
|
|
33
33
|
require "pp"
|
34
34
|
|
35
35
|
class ParseOptions
|
36
|
+
|
37
|
+
#print to Variants of a JSON file that we both take in as input with -C
|
38
|
+
def self.print_json_input
|
39
|
+
fullExample = '{
|
40
|
+
"metadata":{
|
41
|
+
"project":"SP",
|
42
|
+
"issue":"Bug",
|
43
|
+
"link":{ "SP-13":"blocks" },
|
44
|
+
"watcher":["test","admin"]
|
45
|
+
},
|
46
|
+
"content":{
|
47
|
+
"Summary":"Your Summary",
|
48
|
+
"Priority":"Trivial"
|
49
|
+
}
|
50
|
+
}'
|
51
|
+
smallExample = '{
|
52
|
+
"Summary" : "Your Summary",
|
53
|
+
"Priority" : "Trivial"
|
54
|
+
}'
|
55
|
+
division = '--------------------------------------------------------'
|
56
|
+
puts division
|
57
|
+
puts "There are two ways you can input data via -C ."
|
58
|
+
puts "Here are two examples to build from. "
|
59
|
+
puts division
|
60
|
+
puts "Using the command line parameters -p, -i, -l and/or -w :"
|
61
|
+
puts smallExample
|
62
|
+
puts division
|
63
|
+
puts "Without the need for any other command line parameters:"
|
64
|
+
puts fullExample
|
65
|
+
puts '"watcher" always needs to be an array. No matter how many entries you got.'
|
66
|
+
puts "You can even mix command line and -C . In this case -C will take precendence."
|
67
|
+
end
|
68
|
+
|
36
69
|
|
37
70
|
def self.required_argument(name)
|
38
71
|
puts "Argument \"#{name}\" is mandatory."
|
@@ -76,7 +109,7 @@ class ParseOptions
|
|
76
109
|
issueopts.content = list
|
77
110
|
end
|
78
111
|
|
79
|
-
opts.on("-C", "--content-file FILENAME", "JSON formatted file (or \"-\" for STDIN)
|
112
|
+
opts.on("-C", "--content-file FILENAME", "JSON formatted file (or \"-\" for STDIN). The file can contain just -c or -c, -i and -p. (Pipes only work if URL,username AND password are in the CONFIGFILE!)") do |contentfile|
|
80
113
|
scriptopts.contentfile = contentfile
|
81
114
|
end
|
82
115
|
|
@@ -85,7 +118,7 @@ class ParseOptions
|
|
85
118
|
end
|
86
119
|
|
87
120
|
opts.on("-l", "--link ISSUEKEY=LINKTYPE", "Key of an Issue this issue should be linked to" ) do |l|
|
88
|
-
|
121
|
+
scriptopts.linkdestkey, scriptopts.linktype = l.split("=")
|
89
122
|
end
|
90
123
|
|
91
124
|
opts.on("-F", "--field-seperator CHAR", "A fieldseperator if one of the fields is an array (Default \"|\")") do |fs|
|
@@ -121,6 +154,10 @@ class ParseOptions
|
|
121
154
|
scriptopts.url = url
|
122
155
|
end
|
123
156
|
|
157
|
+
opts.on_tail("--help-C", "Example input for -C") do
|
158
|
+
print_json_input
|
159
|
+
exit
|
160
|
+
end
|
124
161
|
opts.on_tail("-h", "--help", "Display this screen") do
|
125
162
|
puts opts
|
126
163
|
exit
|
@@ -134,13 +171,6 @@ class ParseOptions
|
|
134
171
|
|
135
172
|
|
136
173
|
opts.parse!(args)
|
137
|
-
|
138
|
-
if issueopts.project.nil? && scriptopts.writeconf.nil? then
|
139
|
-
required_argument("project")
|
140
|
-
end
|
141
|
-
if issueopts.issue.nil? && scriptopts.writeconf.nil? then
|
142
|
-
required_argument("issue")
|
143
|
-
end
|
144
174
|
return issueopts, scriptopts
|
145
175
|
end #parse()
|
146
176
|
|
@@ -184,7 +214,6 @@ def get_credentials
|
|
184
214
|
end
|
185
215
|
@scriptopts.url = @scriptopts.url + "/rest/api/2/"
|
186
216
|
|
187
|
-
|
188
217
|
if @scriptopts.pass.nil? && !( @scriptopts.username.nil?) then
|
189
218
|
@scriptopts.pass = get_password
|
190
219
|
end
|
@@ -224,6 +253,12 @@ end
|
|
224
253
|
=end
|
225
254
|
def open_issue
|
226
255
|
begin
|
256
|
+
if @issueopts.project.nil? then
|
257
|
+
ParseOptions::required_argument("project")
|
258
|
+
end
|
259
|
+
if @issueopts.issue.nil? then
|
260
|
+
ParseOptions::required_argument("issue")
|
261
|
+
end
|
227
262
|
credentials = get_credentials
|
228
263
|
issue=Issue.new(@issueopts.project,@issueopts.issue,get_connection)
|
229
264
|
rescue Jirarest2::AuthentificationError => e
|
@@ -272,16 +307,37 @@ def split_content(issue)
|
|
272
307
|
return fields
|
273
308
|
end
|
274
309
|
|
310
|
+
# interpret input from file or STDIN
|
311
|
+
def get_jsondata_from_file
|
312
|
+
data = MadbitConfig::read_configfile(@scriptopts.contentfile)
|
313
|
+
content = Hash.new
|
314
|
+
if data["metadata"] then # We have metadata and content
|
315
|
+
content = data["content"]
|
316
|
+
pp "metadata"
|
317
|
+
@issueopts.project = data["metadata"]["project"] if data["metadata"]["project"]
|
318
|
+
@issueopts.issue = data["metadata"]["issue"] if data["metadata"]["issue"]
|
319
|
+
pp data["metadata"]["watcher"].class
|
320
|
+
pp data["metadata"]["watcher"]
|
321
|
+
@issueopts.watchers = data["metadata"]["watcher"] if data["metadata"]["watcher"]
|
322
|
+
pp data["metadata"]["link"]
|
323
|
+
@scriptopts.linkdestkey, @scriptopts.linktype = data["metadata"]["link"].flatten if data["metadata"]["link"]
|
324
|
+
else # We have the simple format that carries only the content
|
325
|
+
content = data
|
326
|
+
end
|
327
|
+
return content
|
328
|
+
end
|
329
|
+
|
275
330
|
# Prepare a new ticket. It will not be persisted yet.
|
276
331
|
def prepare_new_ticket
|
277
332
|
begin
|
278
|
-
issue = open_issue
|
279
333
|
if @scriptopts.contentfile then
|
280
334
|
#Input from file or STDIN
|
281
335
|
puts "Your Input now"
|
282
|
-
fields =
|
336
|
+
fields = get_jsondata_from_file
|
337
|
+
issue = open_issue
|
283
338
|
else
|
284
339
|
#Input from the command line
|
340
|
+
issue = open_issue
|
285
341
|
fields = split_content(issue)
|
286
342
|
end
|
287
343
|
valueNotAllowedRaised = false
|
@@ -293,15 +349,14 @@ def prepare_new_ticket
|
|
293
349
|
rescue Jirarest2::WrongFieldnameException => e
|
294
350
|
no_issue("field",e)
|
295
351
|
rescue Jirarest2::ValueNotAllowedException => e
|
296
|
-
puts "Value #{
|
297
|
-
puts "Please use one of: \"" + e.
|
352
|
+
puts "Value #{e} not allowed for field #{e.fieldname}."
|
353
|
+
puts "Please use one of: \"" + e.allowed.join("\", \"") + "\""
|
298
354
|
valueNotAllowedRaised = true
|
299
355
|
end
|
300
|
-
|
301
|
-
}
|
302
|
-
=end
|
356
|
+
|
303
357
|
if valueNotAllowedRaised then
|
304
|
-
|
358
|
+
puts "Exiting before trying to create an issue."
|
359
|
+
exit 1
|
305
360
|
end
|
306
361
|
return issue
|
307
362
|
end
|
@@ -334,16 +389,19 @@ def create_new_ticket(issue)
|
|
334
389
|
puts "Watchers could not be set though."
|
335
390
|
end
|
336
391
|
begin
|
337
|
-
if @
|
392
|
+
if @scriptopts.linkdestkey then
|
338
393
|
link = IssueLink.new(connection)
|
339
|
-
|
340
|
-
linkresult = link.link(result["key"],remoteIssue,linktype)
|
394
|
+
linkresult = link.link(result["key"],@scriptopts.linkdestkey,@scriptopts.linktype)
|
341
395
|
end
|
342
396
|
rescue Jirarest2::ValueNotAllowedException => e
|
343
397
|
puts "Link not created. Issuetype \"#{e.message}\" not valid."
|
344
398
|
puts "Please use one of the these:"
|
345
399
|
puts link.valid_issuelinktypes("\n")
|
346
400
|
exit 1
|
401
|
+
rescue Jirarest2::NotFoundError => e
|
402
|
+
puts "Link not created. One of the issues not found. Jira says:"
|
403
|
+
puts e.to_s
|
404
|
+
exit 1
|
347
405
|
end
|
348
406
|
return 0
|
349
407
|
elsif result["errors"] then
|
data/lib/jirarest2.rb
CHANGED
data/lib/jirarest2/connect.rb
CHANGED
@@ -77,7 +77,7 @@ class Connect
|
|
77
77
|
result.get_fields("x-authentication-denied-reason")[0] =~ /.*login-url=(.*)/
|
78
78
|
raise Jirarest2::AuthentificationCaptchaError, $1
|
79
79
|
when Net::HTTPNotFound
|
80
|
-
raise Jirarest2::NotFoundError, result
|
80
|
+
raise Jirarest2::NotFoundError, result.body
|
81
81
|
end
|
82
82
|
|
83
83
|
return Jirarest2::Result.new(result)
|
data/lib/jirarest2/exceptions.rb
CHANGED
@@ -43,7 +43,17 @@ module Jirarest2
|
|
43
43
|
# There is no field with this name for the given issue type
|
44
44
|
class WrongFieldnameException < ArgumentError; end
|
45
45
|
# value is not allowed for this type of fields
|
46
|
-
class ValueNotAllowedException < ArgumentError
|
46
|
+
class ValueNotAllowedException < ArgumentError
|
47
|
+
# The name of the field the value does not match to
|
48
|
+
attr_reader :fieldname
|
49
|
+
# Matching values
|
50
|
+
attr_reader :allowed
|
51
|
+
|
52
|
+
def initialize(fieldname,allowed)
|
53
|
+
@fieldname = fieldname
|
54
|
+
@allowed = allowed
|
55
|
+
end
|
56
|
+
end
|
47
57
|
# A field that is defined as "required" has not been given a value
|
48
58
|
class RequiredFieldNotSetException < ArgumentError; end
|
49
59
|
|
data/lib/jirarest2/issue.rb
CHANGED
@@ -49,7 +49,7 @@ class Issue
|
|
49
49
|
@project = value["key"]
|
50
50
|
value["issuetypes"].each { |value1|
|
51
51
|
@issuetype = value1["name"]
|
52
|
-
value1["fields"].delete("project") #The project key is duplicate and will make
|
52
|
+
value1["fields"].delete("project") #The project key is duplicate and will make our live harder afterwards. It is marked as required but nothing happens if this key is not set.
|
53
53
|
value1["fields"].each { |key,value2|
|
54
54
|
fields = Hash.new
|
55
55
|
fields["id"] = key
|
@@ -59,7 +59,7 @@ class Issue
|
|
59
59
|
name = key
|
60
60
|
end
|
61
61
|
# If the allowed reponses are limited we want to know them.
|
62
|
-
if
|
62
|
+
if value2["allowedValues"] then
|
63
63
|
# With custom fields the identifier is "value" with the built in ones it's "name"
|
64
64
|
identifier = "name"
|
65
65
|
if value2["schema"]["custom"] then
|
@@ -160,8 +160,8 @@ class Issue
|
|
160
160
|
if @issuefields[key]["allowedValues"].include?(value)
|
161
161
|
return true
|
162
162
|
else
|
163
|
-
|
164
|
-
|
163
|
+
# puts "Value #{value} not allowed for field #{key}."
|
164
|
+
raise Jirarest2::ValueNotAllowedException.new(key, @issuefields[key]["allowedValues"]), value
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
data/lib/jirarest2/result.rb
CHANGED
@@ -44,7 +44,7 @@ module Jirarest2
|
|
44
44
|
@header = httpResponse.to_hash
|
45
45
|
@body = httpResponse.body
|
46
46
|
#pp @body
|
47
|
-
if httpResponse.instance_of?(Net::HTTPNoContent) or httpResponse.body == "" then # If there is nothing in the body it would be hard to parse it.
|
47
|
+
if httpResponse.instance_of?(Net::HTTPNoContent) or httpResponse.body == "" or httpResponse.body.nil? then # If there is nothing in the body it would be hard to parse it.
|
48
48
|
@result = @body
|
49
49
|
else
|
50
50
|
@result = JSON.parse(@body)
|
@@ -67,7 +67,7 @@ class IssueLink < Services
|
|
67
67
|
if ! @linktype.internal_name?(type) then # time to find the correct name and see if we have to exchange tickets
|
68
68
|
realname = @linktype.name(type)
|
69
69
|
if realname.nil? then
|
70
|
-
raise Jirarest2::ValueNotAllowedException, type
|
70
|
+
raise Jirarest2::ValueNotAllowedException.new(type,valid_issuelinktypes), type
|
71
71
|
else
|
72
72
|
type = realname[0]
|
73
73
|
if realname[1] == "inward" then # we have to change the issues as jira only knows one direction.
|
@@ -85,7 +85,6 @@ class IssueLink < Services
|
|
85
85
|
json["inwardIssue"] = { "key" => inwardIssue }
|
86
86
|
json["outwardIssue"] = { "key" => outwardIssue }
|
87
87
|
json["comment"] = { "body" => comment} if comment
|
88
|
-
|
89
88
|
return post(json)
|
90
89
|
end
|
91
90
|
|
data/test/test_connect.rb
CHANGED
@@ -14,15 +14,19 @@ class TestConnect < MiniTest::Unit::TestCase
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def test_executeGET
|
17
|
-
stub_request(:get, "http://test:1234@localhost:2990/jira/rest/api/2/issue/createmeta/").with(:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/json;charset=UTF-8', 'User-Agent'=>'Ruby'}).to_return(:status => 200, :body => "", :headers => {})
|
18
|
-
|
17
|
+
stub_request(:get, "http://test:1234@localhost:2990/jira/rest/api/2/issue/createmeta/").with(:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/json;charset=UTF-8', 'User-Agent'=>'Ruby'}).to_return(:status => 200, :body => '{"expand":"projects"}', :headers => {})
|
18
|
+
assert_equal "projects", @con.execute("Get","issue/createmeta/","").result["expand"]
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_executePOST
|
22
|
-
stub_request(:post, "http://test:1234@localhost:2990/jira/rest/api/2/search/").with(:body => "{\"jql\":\"project = MFTP\",\"startAt\":0,\"maxResults\":4}",:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/json;charset=UTF-8', 'User-Agent'=>'Ruby'}).to_return(:status => 200, :body => "", :headers => {})
|
22
|
+
stub_request(:post, "http://test:1234@localhost:2990/jira/rest/api/2/search/").with(:body => "{\"jql\":\"project = MFTP\",\"startAt\":0,\"maxResults\":4}",:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/json;charset=UTF-8', 'User-Agent'=>'Ruby'}).to_return(:status => 200, :body => '{"expand":"schema,names","startAt":0,"maxResults":4,"total":9,"issues":[{"expand":"editmeta,renderedFields,transitions,changelog,operations","id":"10102","self":"http://localhost:2990/jira/rest/api/2/issue/10102","key":"MFTP-9","fields":{"summary":"AnotherissueatSunJul1516","progress":{"progress":0,"total":0}}}]}', :headers => {})
|
23
|
+
# WebMock.disable!
|
23
24
|
|
24
25
|
query={"jql"=>"project = MFTP", "startAt"=>0, "maxResults"=>4 }
|
25
|
-
|
26
|
+
assert_equal 4, @con.execute("Post","search/",query).result["maxResults"]
|
27
|
+
# WebMock.enable!
|
28
|
+
|
29
|
+
pp @con.execute("Post","search/",query).result["maxResults"]
|
26
30
|
end
|
27
31
|
|
28
32
|
def test_check_uri_true
|
data/test/test_issue.rb
CHANGED
@@ -54,5 +54,15 @@ class TestIssue < MiniTest::Unit::TestCase
|
|
54
54
|
assert_equal "Summary Text", issue.get_field("Summary")
|
55
55
|
end
|
56
56
|
|
57
|
+
|
58
|
+
def test_persist
|
59
|
+
issue = @existentIssue
|
60
|
+
issue.set_field("Summary","Summary Text")
|
61
|
+
issue.set_field("Priority","Trivial")
|
62
|
+
stub_request(:post, "http://test:1234@localhost:2990/jira/rest/api/2/issue/").with(:body => "{\"fields\":{\"project\":{\"key\":\"MFTP\"},\"summary\":\"Summary Text\",\"priority\":{\"name\":\"Trivial\"},\"issuetype\":{\"name\":\"My issue type\"}}}",:headers => {'Accept'=>'*/*', 'Content-Type'=>'application/json;charset=UTF-8', 'User-Agent'=>'Ruby'}).to_return(:status => 201, :body => '{"id":"10608","key":"MFTP-11","self":"http://localhost:2990/jira/rest/api/2/issue/10608"}', :headers => {})
|
63
|
+
|
64
|
+
issue.persist(@connect)
|
65
|
+
end
|
66
|
+
|
57
67
|
|
58
68
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jirarest2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -50,7 +50,7 @@ cert_chain:
|
|
50
50
|
-----END CERTIFICATE-----
|
51
51
|
|
52
52
|
'
|
53
|
-
date: 2012-07-
|
53
|
+
date: 2012-07-24 00:00:00.000000000 Z
|
54
54
|
dependencies:
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: json
|
@@ -138,7 +138,7 @@ description: ! "jirarest2 is yet another implementation of the JIRA(tm) REST-API
|
|
138
138
|
for perfomance at the time of writing.\n\nThis implementation is still a for cry
|
139
139
|
from others like http://rubygems.org/gems/jira-ruby which required oauth authentification.
|
140
140
|
\n\nThe script allows you to create new issues with watchers and link those to existing
|
141
|
-
issues
|
141
|
+
issues.\n\n *Use it at your own risk. Most of the API features are not implemented.*\n\n
|
142
142
|
*Ruby1.9.1 is needed. Ruby1.8 doesn't work!*"
|
143
143
|
email:
|
144
144
|
- cebit-jirarest@gunnet.de
|
metadata.gz.sig
CHANGED
Binary file
|