jirarest2 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/History.txt +18 -0
- data/Manifest.txt +1 -1
- data/README.md +8 -1
- data/README.txt +13 -5
- data/Rakefile +1 -1
- data/bin/create_issue.rb +36 -11
- data/{header.copyright → copyright} +0 -1
- data/lib/connect.rb +46 -0
- data/lib/exceptions.rb +5 -0
- data/lib/issue.rb +4 -11
- data/lib/jirarest2.rb +1 -1
- data/test/test_connect.rb +37 -0
- data/test/test_issue.rb +4 -3
- metadata +12 -11
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
=== 0.0.4 / 2012-07-17
|
2
|
+
|
3
|
+
* 1 major enhancement:
|
4
|
+
|
5
|
+
* All the methods that took Credential objects before now take Conenction objects
|
6
|
+
|
7
|
+
* 2 minor enhancements:
|
8
|
+
|
9
|
+
* added heal_uri and heal_uri! methods to try to find the right url if wanted.
|
10
|
+
* passes Connection to all other classes now and no longer credentials.
|
11
|
+
|
12
|
+
* 3 bug fixes:
|
13
|
+
|
14
|
+
* -H in create_connection works now as intended. It's even better as you can give the login URL from you browser and it will automagically exract the correct API uri in usual cases. closes #3
|
15
|
+
* Shebang should work now (please remember this gem depends on ruby1.9.1 to work, gem2deb is not able to reflect that.) closes #2
|
16
|
+
* reduced the extension of the url to "/api/rest/2" closes #1
|
17
|
+
|
18
|
+
|
1
19
|
=== 0.0.3 / 2012-07-16
|
2
20
|
|
3
21
|
* 2 major enhancements:
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -5,4 +5,11 @@ Another ruby gem for the REST2 interface of JIRA(tm)
|
|
5
5
|
|
6
6
|
This is still a very early alpha state and a lot of features are not yet implemented. Classes and their work might undergo major changes. (especially "Issue")
|
7
7
|
|
8
|
-
What works
|
8
|
+
What works?
|
9
|
+
|
10
|
+
* creation of issues
|
11
|
+
* add watchers to the issues
|
12
|
+
* link new issues to issues that are already there
|
13
|
+
* ruby script (create-issue.rb) that enables you to do this from the command line
|
14
|
+
|
15
|
+
Ruby1.9.1 is needed! Ruby1.8 will fail.
|
data/README.txt
CHANGED
@@ -4,15 +4,23 @@
|
|
4
4
|
|
5
5
|
== DESCRIPTION:
|
6
6
|
|
7
|
-
jirarest2 is yet another implementation of the JIRA(tm) REST
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
jirarest2 is yet another implementation of the JIRA(tm) REST-API[https://developer.atlassian.com/display/JIRADEV/JIRA+Remote+API+Reference] . This one for Ruby1.9.1
|
8
|
+
|
9
|
+
It is intended to be called within the shell to create and verify JIRA(tm) issues fast without a browser. There was no particular need for perfomance at the time of writing.
|
10
|
+
|
11
|
+
This implementation is still a for cry from others like http://rubygems.org/gems/jira-ruby which required oauth authentification.
|
12
|
+
|
13
|
+
The script allows you to create new issues with watchers and link those to existing issues
|
14
|
+
|
15
|
+
*Use it at your own risk. Most of the API features are not implemented.*
|
16
|
+
|
17
|
+
*Ruby1.9.1 is needed. Ruby1.8 doesn't work!*
|
11
18
|
|
12
19
|
|
13
20
|
== FEATURES/PROBLEMS:
|
14
21
|
|
15
|
-
Still in the very first alpha stages.
|
22
|
+
* Still in the very first alpha stages. The classes are still pretty volatile.
|
23
|
+
* The script allows you to create new issues with watchers and link those to existing issues
|
16
24
|
|
17
25
|
== SYNOPSIS:
|
18
26
|
|
data/Rakefile
CHANGED
data/bin/create_issue.rb
CHANGED
@@ -97,9 +97,15 @@ class ParseOptions
|
|
97
97
|
scriptopts.username = u
|
98
98
|
end
|
99
99
|
|
100
|
-
opts.on("-H", "--jira-url URL", "URL to
|
101
|
-
uri = URI(
|
102
|
-
|
100
|
+
opts.on("-H", "--jira-url URL", "URL to rest api (without \"/rest/api/2\").") do |url|
|
101
|
+
uri = URI(url)
|
102
|
+
splitURI = URI.split(url)
|
103
|
+
if splitURI[3] then
|
104
|
+
url = splitURI[0].to_s + "://" + splitURI[2].to_s + ":" + splitURI[3].to_s + splitURI[5].to_s
|
105
|
+
else
|
106
|
+
url = splitURI[0].to_s + "://" + splitURI[2].to_s + splitURI[5].to_s
|
107
|
+
end
|
108
|
+
scriptopts.url = url
|
103
109
|
end
|
104
110
|
|
105
111
|
opts.on_tail("-h", "--help", "Display this screen") do
|
@@ -131,8 +137,6 @@ end # class ParseOptions
|
|
131
137
|
@issueopts, @scriptopts = ParseOptions.parse(ARGV)
|
132
138
|
|
133
139
|
|
134
|
-
|
135
|
-
|
136
140
|
def no_issue(type,issue)
|
137
141
|
puts "The #{type}type you entered (\"#{issue}\") does no exist."
|
138
142
|
puts "Maybe you entered the wrong type or made a typo? (Case is relevant!)"
|
@@ -153,8 +157,9 @@ def get_credentials
|
|
153
157
|
@scriptopts.pass = fileconf["password"] if ( @scriptopts.pass.nil? && fileconf["password"] )
|
154
158
|
if ( @scriptopts.url.nil? && fileconf["URL"] ) then
|
155
159
|
@scriptopts.url = fileconf["URL"]
|
156
|
-
@scriptopts.url = @scriptopts.url + "/jira/rest/api/2/"
|
157
160
|
end
|
161
|
+
@scriptopts.url = @scriptopts.url + "/rest/api/2/"
|
162
|
+
|
158
163
|
if @scriptopts.pass.nil? then
|
159
164
|
@scriptopts.pass = get_password
|
160
165
|
end
|
@@ -162,14 +167,34 @@ def get_credentials
|
|
162
167
|
return Credentials.new(@scriptopts.url, @scriptopts.username, @scriptopts.pass)
|
163
168
|
end
|
164
169
|
|
170
|
+
=begin
|
171
|
+
If there is already a conenction known returns that connection. If not or if the parameter is true it tries to create a new Connect object
|
172
|
+
=end
|
173
|
+
def get_connection(reconnect = false)
|
174
|
+
if ! @connection || reconnect then
|
175
|
+
begin
|
176
|
+
@connection = Connect.new(get_credentials)
|
177
|
+
@connection.heal_uri! # We want to be sure so we try to heal the connection_url if possible
|
178
|
+
return @connection
|
179
|
+
rescue Jirarest2::CouldNotHealURIError => e
|
180
|
+
puts "REST API not found at #{e.to_s}"
|
181
|
+
exit 3
|
182
|
+
end
|
183
|
+
else
|
184
|
+
return @connection
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
|
190
|
+
|
165
191
|
=begin
|
166
192
|
create the issue on our side
|
167
193
|
=end
|
168
194
|
def open_issue
|
169
195
|
begin
|
170
196
|
credentials = get_credentials
|
171
|
-
issue=Issue.new(@issueopts.project,@issueopts.issue,
|
172
|
-
# issue=Issue.new(@issueopts.project,@issueopts.issue,@scriptopts.pass,@scriptopts.username)
|
197
|
+
issue=Issue.new(@issueopts.project,@issueopts.issue,get_connection)
|
173
198
|
rescue Jirarest2::AuthentificationError => e
|
174
199
|
puts "Password not accepted."
|
175
200
|
@scriptopts.pass = get_password
|
@@ -231,10 +256,11 @@ end
|
|
231
256
|
|
232
257
|
def create_new_ticket(issue)
|
233
258
|
begin
|
234
|
-
|
259
|
+
connection = get_connection # We need it so often in the next few lines that I prefer to get the result in a variable
|
260
|
+
result = issue.persist(connection).result
|
235
261
|
# Set the watchers
|
236
262
|
if @issueopts.watchers then
|
237
|
-
watcherssuccess = issue.add_watchers(
|
263
|
+
watcherssuccess = issue.add_watchers(connection,@issueopts.watchers)
|
238
264
|
end
|
239
265
|
rescue Jirarest2::RequiredFieldNotSetException => e
|
240
266
|
puts "Required field \"#{e.to_s}\" not set."
|
@@ -246,7 +272,6 @@ def create_new_ticket(issue)
|
|
246
272
|
puts "Watchers could not be set though."
|
247
273
|
end
|
248
274
|
if @issueopts.link then
|
249
|
-
connection = Connect.new(get_credentials)
|
250
275
|
link = IssueLink.new(connection)
|
251
276
|
remoteIssue,linktype = @issueopts.link.split("=")
|
252
277
|
linkresult = link.link(result["key"],remoteIssue,linktype)
|
data/lib/connect.rb
CHANGED
@@ -78,14 +78,60 @@ class Connect
|
|
78
78
|
# Result: ["CAPTCHA_CHALLENGE; login-url=http://localhost:8080/login.jsp"]
|
79
79
|
result.get_fields("x-authentication-denied-reason")[0] =~ /.*login-url=(.*)/
|
80
80
|
raise Jirarest2::AuthentificationCaptchaError, $1
|
81
|
+
when Net::HTTPNotFound
|
82
|
+
raise Jirarest2::NotFoundError, result
|
81
83
|
end
|
82
84
|
|
83
85
|
return Jirarest2::Result.new(result)
|
84
86
|
end # execute
|
85
87
|
|
88
|
+
=begin
|
89
|
+
Is the rest API really at the destination we think it is?
|
90
|
+
=end
|
91
|
+
def check_uri
|
92
|
+
begin
|
93
|
+
begin
|
94
|
+
ret = (execute("Get","dashboard","").code == "200")
|
95
|
+
rescue Jirarest2::NotFoundError
|
96
|
+
return false
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
86
100
|
|
101
|
+
=begin
|
102
|
+
Try to be nice. Parse the URI and see if you can find a pattern to the problem
|
103
|
+
=end
|
104
|
+
def heal_uri(url = @CONNECTURL)
|
105
|
+
splitURI = URI.split(url) # [Scheme,Userinfo,Host,Port,Registry,Path,Opaque,Query,Fragment]
|
106
|
+
splitURI[5].gsub!(/^(.*)2$/,'\12/')
|
107
|
+
splitURI[5].gsub!(/\/+/,'/') # get rid of duplicate /
|
108
|
+
splitURI[5].gsub!(/(rest\/api\/2\/)+/,'\1') # duplicate path to rest
|
109
|
+
splitURI[5].gsub!(/^(.*)\/login.jsp(\/rest\/api\/2\/)$/,'\1\2') # dedicated login page
|
110
|
+
splitURI[5].gsub!(/^(.*)\/secure\/Dashboard.jspa(\/rest\/api\/2\/)$/,'\1\2') # copied the dashboard URL (or the login Page)
|
111
|
+
if splitURI[3] then
|
112
|
+
url = splitURI[0].to_s + "://" + splitURI[2].to_s + ":" + splitURI[3].to_s + splitURI[5].to_s
|
113
|
+
else
|
114
|
+
url = splitURI[0].to_s + "://" + splitURI[2].to_s + splitURI[5].to_s
|
115
|
+
end
|
116
|
+
return url
|
117
|
+
end
|
87
118
|
end # class
|
88
119
|
|
120
|
+
=begin
|
121
|
+
try to fix the connecteurl of this instance
|
122
|
+
=end
|
123
|
+
public
|
124
|
+
def heal_uri!
|
125
|
+
if ! check_uri then
|
126
|
+
@CONNECTURL = heal_uri(@CONNECTURL)
|
127
|
+
end
|
128
|
+
if check_uri then
|
129
|
+
return @CONNECTURL
|
130
|
+
else
|
131
|
+
raise Jirarest2::CouldNotHealURIError, @CONNECTURL
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
89
135
|
=begin
|
90
136
|
|
91
137
|
|
data/lib/exceptions.rb
CHANGED
@@ -25,6 +25,11 @@ module Jirarest2
|
|
25
25
|
class AuthentificationError < StandardError ; end
|
26
26
|
# Authentification failed and JIRA(tm) requires a login with captcha to continue
|
27
27
|
class AuthentificationCaptchaError < StandardError ; end
|
28
|
+
# 404 - Results in HTML body - not JSON
|
29
|
+
class NotFoundError < StandardError ; end
|
30
|
+
# Could not heal URI
|
31
|
+
class CouldNotHealURIError < StandardError ; end
|
32
|
+
|
28
33
|
|
29
34
|
## credentials.rb
|
30
35
|
|
data/lib/issue.rb
CHANGED
@@ -15,14 +15,11 @@
|
|
15
15
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
16
|
#
|
17
17
|
|
18
|
-
# TODO always recreating Connection is not really DRY - Find a way to fix it.
|
19
|
-
|
20
18
|
=begin
|
21
19
|
An Issue object contains all the data of an issue
|
22
20
|
=end
|
23
21
|
class Issue
|
24
22
|
|
25
|
-
require "connect"
|
26
23
|
|
27
24
|
# issue type of the issue
|
28
25
|
attr_reader :issuetype
|
@@ -32,11 +29,10 @@ class Issue
|
|
32
29
|
attr_reader :issuekey
|
33
30
|
|
34
31
|
=begin
|
35
|
-
New initialize method we take the project and the type we want to use and
|
32
|
+
New initialize method we take the project and the type we want to use and a connection
|
36
33
|
project Name of the project this issue is to live in
|
37
34
|
=end
|
38
|
-
def initialize (project,type,
|
39
|
-
connection = Connect.new(credentials)
|
35
|
+
def initialize (project,type,connection)
|
40
36
|
query = {:projectKeys => project, :issuetypeNames => type, :expand => "projects.issuetypes.fields" }
|
41
37
|
answer = connection.execute("Get","issue/createmeta/",query)
|
42
38
|
jhash = answer.result
|
@@ -229,15 +225,13 @@ TODO We are not yet able to work with "Cascading Select" fields ( "custom": "com
|
|
229
225
|
=begin
|
230
226
|
create a new ticket
|
231
227
|
=end
|
232
|
-
def persist(
|
228
|
+
def persist(connection)
|
233
229
|
get_requireds.each { |fieldname|
|
234
230
|
if @issuefields[fieldname]["value"].nil? then
|
235
231
|
raise Jirarest2::RequiredFieldNotSetException, fieldname
|
236
232
|
end
|
237
233
|
}
|
238
|
-
connection = Connect.new(credentials)
|
239
234
|
hash = jirahash
|
240
|
-
# TODO we changed the returning Value here - it's an Result object and no longer just the equivalent of Result.result
|
241
235
|
ret = connection.execute("Post","issue/",hash)
|
242
236
|
if ret.code == "201" then # Ticket sucessfully created
|
243
237
|
@issuekey = ret.result["key"]
|
@@ -250,9 +244,8 @@ TODO We are not yet able to work with "Cascading Select" fields ( "custom": "com
|
|
250
244
|
Set the watchers for this Ticket
|
251
245
|
watchers has to be an Array
|
252
246
|
=end
|
253
|
-
def add_watchers(
|
247
|
+
def add_watchers(connection,watchers)
|
254
248
|
success = false # Return whether we were successful with the watchers
|
255
|
-
connection = Connect.new(credentials)
|
256
249
|
watch = Watcher.new(connection,@issuekey)
|
257
250
|
watchers.each { |person|
|
258
251
|
success = watch.add_watcher(person)
|
data/lib/jirarest2.rb
CHANGED
data/test/test_connect.rb
CHANGED
@@ -17,5 +17,42 @@ class TestConnect < MiniTest::Unit::TestCase
|
|
17
17
|
query={"jql"=>"project = MFTP", "startAt"=>0, "maxResults"=>4 }
|
18
18
|
assert 4, @con.execute("Post","search/",query).result["maxResults"]
|
19
19
|
end
|
20
|
+
|
21
|
+
def test_check_uri
|
22
|
+
assert_equal true,@con.check_uri
|
23
|
+
cred = Credentials.new("http://localhost:2990/rest/api/2/","test","1234")
|
24
|
+
con1 = Connect.new(cred)
|
25
|
+
assert_equal false,con1.check_uri
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_heal_uri
|
29
|
+
cred = Credentials.new("http://localhost:2990/jira//rest/api//2//","test","1234")
|
30
|
+
con = Connect.new(cred)
|
31
|
+
assert_equal "http://localhost:2990/jira/rest/api/2/",con.heal_uri
|
32
|
+
assert_equal "http://localhost:2990/jira/rest/api/2/",con.heal_uri("http://localhost:2990/jira/rest/api/2/rest/api/2/")
|
33
|
+
assert_equal "http://localhost:2990/jira/rest/api/2/",con.heal_uri("http://localhost:2990/jira/secure/Dashboard.jspa/rest/api/2/")
|
34
|
+
assert_equal "http://localhost:2990/rest/api/2/",con.heal_uri("http://localhost:2990/secure/Dashboard.jspa/rest/api/2/")
|
35
|
+
assert_equal "http://localhost:2990/jira/rest/api/2/",con.heal_uri("http://localhost:2990/jira/login.jsp/rest/api/2/")
|
36
|
+
assert_equal "http://localhost:2990/rest/api/2/",con.heal_uri("http://localhost:2990/login.jsp/rest/api/2/")
|
37
|
+
assert_equal "http://localhost/rest/api/2/",con.heal_uri("http://localhost/login.jsp/rest/api/2")
|
38
|
+
assert_equal "http://localhost:2990/rest/api/2/",con.heal_uri("http://localhost:2990/login.jsp/rest/api/2")
|
39
|
+
assert_equal "http://localhost:2990/jira/secure/Dashboard.jspa",con.heal_uri("http://localhost:2990/jira/secure/Dashboard.jspa") # If there is no Rest-Path at this point we have a problem
|
40
|
+
assert_equal "http://localhost:2990/secure/Dashboard.jspa",con.heal_uri("http://localhost:2990/secure/Dashboard.jspa") # If there is no Rest-Path at this point we have a problem
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_heal_uri!
|
44
|
+
## First an URL we can fix
|
45
|
+
cred = Credentials.new("http://localhost:2990/jira//rest/api//2//","test","1234")
|
46
|
+
con = Connect.new(cred)
|
47
|
+
assert_equal false,con.check_uri
|
48
|
+
assert_equal "http://localhost:2990/jira/rest/api/2/", con.heal_uri!
|
49
|
+
assert_equal true,con.check_uri
|
50
|
+
## And now one we cant't fix
|
51
|
+
cred = Credentials.new("http://localhost:2990/secure/Dashboard.jspa","test","1234")
|
52
|
+
con = Connect.new(cred)
|
53
|
+
assert_equal false,con.check_uri
|
54
|
+
assert_raises(Jirarest2::CouldNotHealURIError){ con.heal_uri! }
|
55
|
+
assert_equal false,con.check_uri
|
56
|
+
end
|
20
57
|
|
21
58
|
end
|
data/test/test_issue.rb
CHANGED
@@ -5,18 +5,19 @@ require "jirarest2"
|
|
5
5
|
class TestIssue < MiniTest::Unit::TestCase
|
6
6
|
def setup
|
7
7
|
@credentials = Credentials.new("http://localhost:2990/jira/rest/api/2/","test","1234")
|
8
|
-
@
|
8
|
+
@connect = Connect.new(@credentials)
|
9
|
+
@existentIssue = Issue.new("MFTP","My issue type",@connect)
|
9
10
|
end
|
10
11
|
|
11
12
|
def testNonExistentProject
|
12
13
|
assert_raises(Jirarest2::WrongProjectException) {
|
13
|
-
nonexistentProject = Issue.new("blubber","fasel",@
|
14
|
+
nonexistentProject = Issue.new("blubber","fasel",@connect)
|
14
15
|
}
|
15
16
|
end
|
16
17
|
|
17
18
|
def testNonExistentIssuetype
|
18
19
|
assert_raises(Jirarest2::WrongIssuetypeException) {
|
19
|
-
nonexistentIssue = Issue.new("MFTP","fasel",@
|
20
|
+
nonexistentIssue = Issue.new("MFTP","fasel",@connect)
|
20
21
|
}
|
21
22
|
end
|
22
23
|
|
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.4
|
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-16 00:00:00.000000000 Z
|
54
54
|
dependencies:
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: json
|
@@ -100,12 +100,14 @@ dependencies:
|
|
100
100
|
- - ! '>='
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: 2.9.4
|
103
|
-
description: ! "jirarest2 is yet another implementation of the JIRA(tm) REST
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
http://rubygems.org/gems/jira-ruby which required oauth authentification.
|
108
|
-
|
103
|
+
description: ! "jirarest2 is yet another implementation of the JIRA(tm) REST-API[https://developer.atlassian.com/display/JIRADEV/JIRA+Remote+API+Reference]
|
104
|
+
. This one for Ruby1.9.1\n\nIt is intended to be called within the shell to create
|
105
|
+
and verify JIRA(tm) issues fast without a browser. There was no particular need
|
106
|
+
for perfomance at the time of writing.\n\nThis implementation is still a for cry
|
107
|
+
from others like http://rubygems.org/gems/jira-ruby which required oauth authentification.
|
108
|
+
\n\nThe script allows you to create new issues with watchers and link those to existing
|
109
|
+
issues\n\n *Use it at your own risk. Most of the API features are not implemented.*\n\n
|
110
|
+
*Ruby1.9.1 is needed. Ruby1.8 doesn't work!*"
|
109
111
|
email:
|
110
112
|
- cebit-jirarest@gunnet.de
|
111
113
|
executables:
|
@@ -124,7 +126,7 @@ files:
|
|
124
126
|
- README.txt
|
125
127
|
- Rakefile
|
126
128
|
- bin/create_issue.rb
|
127
|
-
-
|
129
|
+
- copyright
|
128
130
|
- lib/config.rb
|
129
131
|
- lib/connect.rb
|
130
132
|
- lib/credentials.rb
|
@@ -170,8 +172,7 @@ rubyforge_project: jirarest2
|
|
170
172
|
rubygems_version: 1.8.24
|
171
173
|
signing_key:
|
172
174
|
specification_version: 3
|
173
|
-
summary: jirarest2 is yet another implementation of the JIRA(tm) REST
|
174
|
-
)
|
175
|
+
summary: jirarest2 is yet another implementation of the JIRA(tm) REST-API[https://developer.atlassian.com/display/JIRADEV/JIRA+Remote+API+Reference]
|
175
176
|
test_files:
|
176
177
|
- test/test_connect.rb
|
177
178
|
- test/test_issuelinktype.rb
|
metadata.gz.sig
CHANGED
Binary file
|