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 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
 
@@ -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) with the contents of -c which will be ignored (Pipes work only if URL,username AND password are in the CONFIGFILE!)") do |contentfile|
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
- issueopts.link = l
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 = MadbitConfig::read_configfile(@scriptopts.contentfile)
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 #{split[1]} not allowed for field #{split[0]}."
297
- puts "Please use one of: \"" + e.message.join("\", \"") + "\""
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
- =begin
301
- }
302
- =end
356
+
303
357
  if valueNotAllowedRaised then
304
- raise Jirarest2::ValueNotAllowedException
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 @issueopts.link then
392
+ if @scriptopts.linkdestkey then
338
393
  link = IssueLink.new(connection)
339
- remoteIssue,linktype = @issueopts.link.split("=")
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
@@ -17,7 +17,7 @@
17
17
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
18
  #
19
19
 
20
- VERSION = "0.0.7"
20
+ VERSION = "0.0.8"
21
21
 
22
22
  require_relative "jirarest2/connect"
23
23
  require_relative "jirarest2/issue"
@@ -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)
@@ -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; end
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
 
@@ -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 us live harder afterwards. It is marked as required but nothing happens if this key is not set.
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 value["allowedValues"] then
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
- raise Jirarest2::ValueNotAllowedException, @issuefields[key]["allowedValues"]
164
- puts "Value #{value} not allowed for field #{key}."
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
 
@@ -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
- assert "projects", @con.execute("Get","issue/createmeta/","").result["expand"]
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
- assert 4, @con.execute("Post","search/",query).result["maxResults"]
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.7
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-23 00:00:00.000000000 Z
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\n\n *Use it at your own risk. Most of the API features are not implemented.*\n\n
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