jira-ruby 0.1.16 → 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2e40d5ee749de621839801a5e80f92e4cda3325d
4
- data.tar.gz: 35a5726e608c149b40ee31fbbd5d262876bfc710
3
+ metadata.gz: 2ff744bcd9ad2d2787f07ecf627888484805cadf
4
+ data.tar.gz: ae9c78df7d9b0de9fb35bdfb0671119240211a91
5
5
  SHA512:
6
- metadata.gz: cdc3298da60ff9bd8553253c6abe2d87c7402bd970678d49e889f6b642f774654f80a234ab2a58ae2d066db84d9c1e5d329d72c59ac6c48a87226eba15e0ca8f
7
- data.tar.gz: 42c0599010e58238193759fd88d0ad8b4a529311862432610f8e175fa3e584f8e3264dbebca71a029c1be791341aa280e6ebe6c2521e5045699cecb18ecda002
6
+ metadata.gz: d118f8da88f23970bb406d4cfabec43eb19fc4178fddc4c9ec9e9c893933dff4b0aa6c3aa56fdcfc92a1ee43817f8ba39d1b03d2a1645c950528bf104eebcbcd
7
+ data.tar.gz: 4a9a20b2c3ecb34c7ff79c87cbf0546ec5bbb89700a3655066fd4060d5b9fa4e8dbaf68e66d40f7a8ec02b36c96712be8af4889d6618f50a603ed85f91611c6f
@@ -1,6 +1,6 @@
1
1
  = JIRA API Gem
2
2
  {<img src="https://codeclimate.com/github/sumoheavy/jira-ruby.png" />}[https://codeclimate.com/github/sumoheavy/jira-ruby]
3
- {<img src="https://travis-ci.org/sumoheavy/jira-ruby.png?branch=master"}[https://travis-ci.org/sumoheavy/jira-ruby]
3
+ {<img src="https://travis-ci.org/sumoheavy/jira-ruby.png?branch=master" />}[https://travis-ci.org/sumoheavy/jira-ruby]
4
4
 
5
5
  This gem provides access to the Atlassian JIRA REST API.
6
6
 
@@ -80,7 +80,7 @@ of JIRA.
80
80
  require 'pp'
81
81
  require 'jira'
82
82
 
83
- # Consider the use of :use_ssl and :ssl_verify_mode options if running locally
83
+ # Consider the use of :use_ssl and :ssl_verify_mode options if running locally
84
84
  # for tests.
85
85
 
86
86
  username = "myremoteuser"
@@ -91,14 +91,15 @@ of JIRA.
91
91
  :password => password,
92
92
  :site => 'http://localhost:8080/',
93
93
  :context_path => '/myjira',
94
- :auth_type => :basic
94
+ :auth_type => :basic,
95
+ :read_timeout => 120
95
96
  }
96
97
 
97
98
  client = JIRA::Client.new(options)
98
99
 
99
100
  # Show all projects
100
101
  projects = client.Project.all
101
-
102
+
102
103
  projects.each do |project|
103
104
  puts "Project -> key: #{project.key}, name: #{project.name}"
104
105
  end
@@ -135,7 +136,7 @@ errors are handled gracefully
135
136
  private
136
137
 
137
138
  def get_jira_client
138
-
139
+
139
140
  # add any extra configuration options for your instance of JIRA,
140
141
  # e.g. :use_ssl, :ssl_verify_mode, :context_path, :site
141
142
  options = {
@@ -148,8 +149,8 @@ errors are handled gracefully
148
149
  # Add AccessToken if authorised previously.
149
150
  if session[:jira_auth]
150
151
  @jira_client.set_access_token(
151
- session[:jira_auth][:access_token],
152
- session[:jira_auth][:access_key]
152
+ session[:jira_auth]['access_token'],
153
+ session[:jira_auth]['access_key']
153
154
  )
154
155
  end
155
156
  end
@@ -253,7 +254,7 @@ Here's the same example as a Sinatra application:
253
254
  if !session[:jira_auth]
254
255
  # not logged in
255
256
  <<-eos
256
- <h1>jira-ruby (JIRA 5 Ruby Gem) demo </h1>You're not signed in. Why don't you
257
+ <h1>jira-ruby (JIRA 5 Ruby Gem) demo </h1>You're not signed in. Why don't you
257
258
  <a href=/signin>sign in</a> first.
258
259
  eos
259
260
  else
@@ -262,25 +263,25 @@ Here's the same example as a Sinatra application:
262
263
 
263
264
  # HTTP response inlined with bind data below...
264
265
  <<-eos
265
- You're now signed in. There #{@issues.count == 1 ? "is" : "are"} #{@issues.count}
266
+ You're now signed in. There #{@issues.count == 1 ? "is" : "are"} #{@issues.count}
266
267
  issue#{@issues.count == 1 ? "" : "s"} in this JIRA instance. <a href='/signout'>Signout</a>
267
268
  eos
268
269
  end
269
270
  end
270
271
 
271
272
  # http://<yourserver>/signin
272
- # Initiates the OAuth dance by first requesting a token then redirecting to
273
+ # Initiates the OAuth dance by first requesting a token then redirecting to
273
274
  # http://<yourserver>/auth to get the @access_token
274
275
  get '/signin' do
275
276
  request_token = @jira_client.request_token
276
277
  session[:request_token] = request_token.token
277
278
  session[:request_secret] = request_token.secret
278
279
 
279
- redirect request_token.authorize_url
280
+ redirect request_token.authorize_url
280
281
  end
281
282
 
282
283
  # http://<yourserver>/callback
283
- # Retrieves the @access_token then stores it inside a session cookie. In a real app,
284
+ # Retrieves the @access_token then stores it inside a session cookie. In a real app,
284
285
  # you'll want to persist the token in a datastore associated with the user.
285
286
  get "/callback/" do
286
287
  request_token = @jira_client.set_request_token(
data/example.rb CHANGED
@@ -117,3 +117,60 @@ pp issue
117
117
  # # Update an existing comment
118
118
  # # --------------------------
119
119
  # issue.comments.first.save({"body" => "an updated comment frome example.rb"})
120
+
121
+ # List all available link types
122
+ # ------------------------------
123
+ pp client.Issuelinktype.all
124
+
125
+ # List issue's links
126
+ # -------------------------
127
+ issue = client.Issue.find("10002")
128
+ pp issue.issuelinks
129
+
130
+ # Link two issues (on the same Jira instance)
131
+ # --------------------------------------------
132
+ link = client.Issuelink.build
133
+ link.save(
134
+ {
135
+ :type => {:name => 'Relates'},
136
+ :inwardIssue => {:key => 'AL-1'},
137
+ :outwardIssue => {:key => 'AL-2'}
138
+ }
139
+ )
140
+
141
+ # List issue's remote links
142
+ # -------------------------
143
+ pp issue.remotelink.all
144
+
145
+ # Link two remote issues (on the different Jira instance)
146
+ # In order to add remote links, you have to add
147
+ # Application Links between two Jira instances first.
148
+ # More information:
149
+ # https://developer.atlassian.com/jiradev/jira-platform/guides/other/guide-jira-remote-issue-links/fields-in-remote-issue-links
150
+ # http://stackoverflow.com/questions/29850252/jira-api-issuelink-connect-two-different-instances
151
+ # -------------------------------------------------------
152
+ client_1 = JIRA::Client.new(options)
153
+ client_2 = JIRA::Client.new(options)
154
+
155
+ # you have to search for your app id here, instead of getting the first
156
+ client_2_app_link = client_2.ApplicationLink.manifest
157
+ issue_1 = client_1.Issue.find('BB-2')
158
+ issue_2 = client_2.Issue.find('AA-1')
159
+
160
+ remote_link = issue_2.remotelink.build
161
+
162
+ remote_link.save(
163
+ {
164
+ :globalId => "appId=#{client_2_app_link.id}&issueId=#{issue_1.id}",
165
+ :application => {
166
+ :type => 'com.atlassian.jira',
167
+ :name => client_2_app_link['name']
168
+ },
169
+ :relationship => 'relates to',
170
+
171
+ :object => {
172
+ :url => client_1.options[:site] + client_1.options[:context_path] + "/browse/#{issue_1.key}",
173
+ :title => issue_1.key,
174
+ }
175
+ }
176
+ )
@@ -21,10 +21,15 @@ require 'jira/resource/project'
21
21
  require 'jira/resource/priority'
22
22
  require 'jira/resource/comment'
23
23
  require 'jira/resource/worklog'
24
+ require 'jira/resource/applinks'
25
+ require 'jira/resource/issuelinktype'
26
+ require 'jira/resource/issuelink'
27
+ require 'jira/resource/remotelink'
24
28
  require 'jira/resource/issue'
25
29
  require 'jira/resource/filter'
26
30
  require 'jira/resource/field'
27
31
  require 'jira/resource/rapidview'
32
+ require 'jira/resource/serverinfo'
28
33
 
29
34
  require 'jira/request_client'
30
35
  require 'jira/oauth_client'
@@ -365,7 +365,16 @@ module JIRA
365
365
  save_status = save!(attrs)
366
366
  rescue JIRA::HTTPError => exception
367
367
  puts ">>>>>>>>> Exception response: #{exception.response.body}"
368
- set_attrs_from_response(exception.response) rescue JSON::ParserError # Merge error status generated by JIRA REST API
368
+ begin
369
+ set_attrs_from_response(exception.response) # Merge error status generated by JIRA REST API
370
+ rescue JSON::ParserError => parse_exception
371
+ set_attrs("exception" => {
372
+ "class" => exception.response.class.name,
373
+ "code" => exception.response.code,
374
+ "message" => exception.response.message
375
+ }
376
+ )
377
+ end
369
378
  save_status = false
370
379
  end
371
380
  save_status
@@ -129,6 +129,26 @@ module JIRA
129
129
  JIRA::Resource::RapidViewFactory.new(self)
130
130
  end
131
131
 
132
+ def ServerInfo
133
+ JIRA::Resource::ServerInfoFactory.new(self)
134
+ end
135
+
136
+ def ApplicationLink
137
+ JIRA::Resource::ApplicationLinkFactory.new(self)
138
+ end
139
+
140
+ def Issuelink
141
+ JIRA::Resource::IssuelinkFactory.new(self)
142
+ end
143
+
144
+ def Issuelinktype
145
+ JIRA::Resource::IssuelinktypeFactory.new(self)
146
+ end
147
+
148
+ def Remotelink
149
+ JIRA::Resource::RemotelinkFactory.new(self)
150
+ end
151
+
132
152
  # HTTP methods without a body
133
153
  def delete(path, headers = {})
134
154
  request(:delete, path, nil, merge_default_headers(headers))
@@ -40,6 +40,7 @@ module JIRA
40
40
  http_conn = http_class.new(uri.host, uri.port)
41
41
  http_conn.use_ssl = @options[:use_ssl]
42
42
  http_conn.verify_mode = @options[:ssl_verify_mode]
43
+ http_conn.read_timeout = @options[:read_timeout]
43
44
  http_conn
44
45
  end
45
46
 
@@ -0,0 +1,42 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class ApplicationLinkFactory < JIRA::BaseFactory # :nodoc:
5
+ delegate_to_target_class :manifest
6
+ end
7
+
8
+ class ApplicationLink < JIRA::Base
9
+
10
+ REST_BASE_PATH = '/rest/applinks/1.0'
11
+
12
+ def self.endpoint_name
13
+ 'listApplicationlinks'
14
+ end
15
+
16
+ def self.full_url(client)
17
+ client.options[:context_path] + REST_BASE_PATH
18
+ end
19
+
20
+ def self.collection_path(client, prefix = '/')
21
+ self.full_url(client) + prefix + self.endpoint_name
22
+ end
23
+
24
+ def self.all(client, options = {})
25
+ response = client.get(collection_path(client))
26
+ json = parse_json(response.body)
27
+ json = json['list']
28
+ json.map do |attrs|
29
+ self.new(client, {:attrs => attrs}.merge(options))
30
+ end
31
+ end
32
+
33
+ def self.manifest(client)
34
+ url = self.full_url(client) + '/manifest'
35
+ response = client.get(url)
36
+ json = parse_json(response.body)
37
+ JIRA::Base.new(client, {:attrs => json})
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -35,6 +35,10 @@ module JIRA
35
35
 
36
36
  has_many :worklogs, :nested_under => ['fields','worklog']
37
37
 
38
+ has_many :issuelinks, :nested_under => 'fields'
39
+
40
+ has_many :remotelink, :class => JIRA::Resource::Remotelink
41
+
38
42
  def self.all(client)
39
43
  url = client.options[:rest_base_path] + "/search?expand=transitions.fields"
40
44
  response = client.get(url)
@@ -0,0 +1,22 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class IssuelinkFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ # Because of circular dependency Issue->IssueLink->Issue
8
+ # we have to declare JIRA::Resource::Issue class.
9
+ class Issue < JIRA::Base; end
10
+
11
+ class Issuelink < JIRA::Base
12
+ has_one :type, :class => JIRA::Resource::Issuelinktype
13
+ has_one :inwardIssue, :class => JIRA::Resource::Issue
14
+ has_one :outwardIssue, :class => JIRA::Resource::Issue
15
+
16
+ def self.endpoint_name
17
+ 'issueLink'
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class IssuelinktypeFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Issuelinktype < JIRA::Base
8
+ nested_collections true
9
+
10
+ def self.endpoint_name
11
+ 'issueLinkType'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class RemotelinkFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class Remotelink < JIRA::Base
8
+ belongs_to :issue
9
+
10
+ def self.endpoint_name
11
+ 'remotelink'
12
+ end
13
+
14
+ def self.all(client, options = {})
15
+ issue = options[:issue]
16
+ unless issue
17
+ raise ArgumentError.new("parent issue is required")
18
+ end
19
+
20
+ path = "#{issue.self}/#{endpoint_name}"
21
+ response = client.get(path)
22
+ json = parse_json(response.body)
23
+ json.map do |link|
24
+ issue.remotelink.build(link)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ module JIRA
2
+ module Resource
3
+
4
+ class ServerInfoFactory < JIRA::BaseFactory # :nodoc:
5
+ end
6
+
7
+ class ServerInfo < JIRA::Base
8
+ def self.endpoint_name
9
+ 'serverInfo'
10
+ end
11
+
12
+ def self.all(client, options = {})
13
+ response = client.get(collection_path(client))
14
+ json = parse_json(response.body)
15
+ self.new(client, {:attrs => json}.merge(options))
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
1
  module JIRA
2
- VERSION = "0.1.16"
2
+ VERSION = "0.1.17"
3
3
  end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe JIRA::Resource::Issuelinktype do
4
+
5
+ with_each_client do |site_url, client|
6
+ let(:client) { client }
7
+ let(:site_url) { site_url }
8
+
9
+
10
+ let(:key) { "10000" }
11
+
12
+ let(:expected_attributes) do
13
+ {
14
+ 'id' => key,
15
+ "self"=>"http://localhost:2990/jira/rest/api/2/issueLinkType/10000",
16
+ "name"=>"Blocks",
17
+ "inward"=>"is blocked by",
18
+ "outward"=>"blocks"
19
+ }
20
+ end
21
+
22
+ let(:expected_collection_length) { 3 }
23
+
24
+ it_should_behave_like "a resource"
25
+ it_should_behave_like "a resource with a collection GET endpoint"
26
+ it_should_behave_like "a resource with a singular GET endpoint"
27
+
28
+ end
29
+ end
@@ -270,6 +270,13 @@ describe JIRA::Base do
270
270
  expect(subject.save("invalid_field" => "foobar")).to be_falsey
271
271
  end
272
272
 
273
+ it "returns false with exception details when non json response body (unauthorized)" do # Unauthorized requests return a non-json body. This makes sure we can handle non-json bodies on HTTPError
274
+ response = double("Response", body: 'totally invalid json', code: 401, message: "Unauthorized")
275
+ expect(client).to receive(:post).with('/foo/bar','{"foo":"bar"}').and_raise(JIRA::HTTPError.new(response))
276
+ expect(subject.save("foo" => "bar")).to be_falsey
277
+ expect(subject.attrs["exception"]["code"]).to eq(401)
278
+ expect(subject.attrs["exception"]["message"]).to eq("Unauthorized")
279
+ end
273
280
  end
274
281
 
275
282
  describe "save!" do
@@ -96,6 +96,7 @@ describe JIRA::HttpClient do
96
96
  expect(Net::HTTP).to receive(:new).with(host, port).and_return(http_conn)
97
97
  expect(http_conn).to receive(:use_ssl=).with(basic_client.options[:use_ssl]).and_return(http_conn)
98
98
  expect(http_conn).to receive(:verify_mode=).with(basic_client.options[:ssl_verify_mode]).and_return(http_conn)
99
+ expect(http_conn).to receive(:read_timeout=).with(basic_client.options[:read_timeout]).and_return(http_conn)
99
100
  expect(basic_client.http_conn(uri)).to eq(http_conn)
100
101
  end
101
102
 
@@ -0,0 +1,14 @@
1
+ # require 'spec_helper'
2
+ #
3
+ # describe JIRA::Resource::Issuelink do
4
+ # let(:client) { double() }
5
+ #
6
+ # describe "links" do
7
+ # subject {
8
+ # JIRA::Resource::Issuelink.new(client, :attrs => {
9
+ #
10
+ # }
11
+ # )
12
+ # }
13
+ # end
14
+ # end
@@ -0,0 +1,25 @@
1
+ {
2
+ "issueLinkTypes": [
3
+ {
4
+ "id": "10000",
5
+ "name": "Blocks",
6
+ "inward": "is blocked by",
7
+ "outward": "blocks",
8
+ "self": "http://localhost:2990/jira/rest/api/2/issueLinkType/10000"
9
+ },
10
+ {
11
+ "id": "10400",
12
+ "name": "Cloners",
13
+ "inward": "is cloned by",
14
+ "outward": "clones",
15
+ "self": "http://localhost:2990/jira/rest/api/2/issueLinkType/10400"
16
+ },
17
+ {
18
+ "id": "10401",
19
+ "name": "Duplicate",
20
+ "inward": "is duplicated by",
21
+ "outward": "duplicates",
22
+ "self": "http://localhost:2990/jira/rest/api/2/issueLinkType/10401"
23
+ }
24
+ ]
25
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "id": "10000",
3
+ "self": "http://localhost:2990/jira/rest/api/2/issueLinkType/10000",
4
+ "name": "Blocks",
5
+ "inward": "is blocked by",
6
+ "outward": "blocks"
7
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jira-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.16
4
+ version: 0.1.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - SUMO Heavy Industries
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-27 00:00:00.000000000 Z
11
+ date: 2015-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -119,16 +119,21 @@ files:
119
119
  - lib/jira/oauth_client.rb
120
120
  - lib/jira/railtie.rb
121
121
  - lib/jira/request_client.rb
122
+ - lib/jira/resource/applinks.rb
122
123
  - lib/jira/resource/attachment.rb
123
124
  - lib/jira/resource/comment.rb
124
125
  - lib/jira/resource/component.rb
125
126
  - lib/jira/resource/field.rb
126
127
  - lib/jira/resource/filter.rb
127
128
  - lib/jira/resource/issue.rb
129
+ - lib/jira/resource/issuelink.rb
130
+ - lib/jira/resource/issuelinktype.rb
128
131
  - lib/jira/resource/issuetype.rb
129
132
  - lib/jira/resource/priority.rb
130
133
  - lib/jira/resource/project.rb
131
134
  - lib/jira/resource/rapidview.rb
135
+ - lib/jira/resource/remotelink.rb
136
+ - lib/jira/resource/serverinfo.rb
132
137
  - lib/jira/resource/status.rb
133
138
  - lib/jira/resource/transition.rb
134
139
  - lib/jira/resource/user.rb
@@ -142,6 +147,7 @@ files:
142
147
  - spec/integration/component_spec.rb
143
148
  - spec/integration/field_spec.rb
144
149
  - spec/integration/issue_spec.rb
150
+ - spec/integration/issuelinktype_spec.rb
145
151
  - spec/integration/issuetype_spec.rb
146
152
  - spec/integration/priority_spec.rb
147
153
  - spec/integration/project_spec.rb
@@ -162,6 +168,7 @@ files:
162
168
  - spec/jira/resource/attachment_spec.rb
163
169
  - spec/jira/resource/filter_spec.rb
164
170
  - spec/jira/resource/issue_spec.rb
171
+ - spec/jira/resource/issuelink_spec.rb
165
172
  - spec/jira/resource/project_factory_spec.rb
166
173
  - spec/jira/resource/project_spec.rb
167
174
  - spec/jira/resource/worklog_spec.rb
@@ -187,6 +194,8 @@ files:
187
194
  - spec/mock_responses/issue/10002/worklog.post.json
188
195
  - spec/mock_responses/issue/10002/worklog/10000.json
189
196
  - spec/mock_responses/issue/10002/worklog/10000.put.json
197
+ - spec/mock_responses/issueLinkType.json
198
+ - spec/mock_responses/issueLinkType/10000.json
190
199
  - spec/mock_responses/issuetype.json
191
200
  - spec/mock_responses/issuetype/5.json
192
201
  - spec/mock_responses/priority.json
@@ -241,6 +250,7 @@ test_files:
241
250
  - spec/integration/component_spec.rb
242
251
  - spec/integration/field_spec.rb
243
252
  - spec/integration/issue_spec.rb
253
+ - spec/integration/issuelinktype_spec.rb
244
254
  - spec/integration/issuetype_spec.rb
245
255
  - spec/integration/priority_spec.rb
246
256
  - spec/integration/project_spec.rb
@@ -261,6 +271,7 @@ test_files:
261
271
  - spec/jira/resource/attachment_spec.rb
262
272
  - spec/jira/resource/filter_spec.rb
263
273
  - spec/jira/resource/issue_spec.rb
274
+ - spec/jira/resource/issuelink_spec.rb
264
275
  - spec/jira/resource/project_factory_spec.rb
265
276
  - spec/jira/resource/project_spec.rb
266
277
  - spec/jira/resource/worklog_spec.rb
@@ -286,6 +297,8 @@ test_files:
286
297
  - spec/mock_responses/issue/10002/worklog.post.json
287
298
  - spec/mock_responses/issue/10002/worklog/10000.json
288
299
  - spec/mock_responses/issue/10002/worklog/10000.put.json
300
+ - spec/mock_responses/issueLinkType.json
301
+ - spec/mock_responses/issueLinkType/10000.json
289
302
  - spec/mock_responses/issuetype.json
290
303
  - spec/mock_responses/issuetype/5.json
291
304
  - spec/mock_responses/priority.json