jira-ruby 1.2.0 → 2.3.0
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.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/.travis.yml +5 -3
- data/Gemfile +7 -1
- data/Guardfile +1 -1
- data/README.md +452 -0
- data/Rakefile +6 -7
- data/example.rb +23 -1
- data/http-basic-example.rb +13 -12
- data/jira-ruby.gemspec +13 -13
- data/lib/jira/base.rb +53 -52
- data/lib/jira/base_factory.rb +3 -6
- data/lib/jira/client.rb +127 -30
- data/lib/jira/has_many_proxy.rb +0 -1
- data/lib/jira/http_client.rb +54 -16
- data/lib/jira/http_error.rb +3 -5
- data/lib/jira/jwt_client.rb +67 -0
- data/lib/jira/oauth_client.rb +47 -17
- data/lib/jira/request_client.rb +16 -5
- data/lib/jira/resource/agile.rb +34 -9
- data/lib/jira/resource/applinks.rb +5 -8
- data/lib/jira/resource/attachment.rb +41 -3
- data/lib/jira/resource/board.rb +91 -0
- data/lib/jira/resource/board_configuration.rb +9 -0
- data/lib/jira/resource/comment.rb +0 -2
- data/lib/jira/resource/component.rb +1 -3
- data/lib/jira/resource/createmeta.rb +12 -14
- data/lib/jira/resource/field.rb +22 -22
- data/lib/jira/resource/filter.rb +2 -2
- data/lib/jira/resource/issue.rb +69 -38
- data/lib/jira/resource/issue_picker_suggestions.rb +24 -0
- data/lib/jira/resource/issue_picker_suggestions_issue.rb +10 -0
- data/lib/jira/resource/issuelink.rb +3 -5
- data/lib/jira/resource/issuelinktype.rb +0 -1
- data/lib/jira/resource/issuetype.rb +1 -3
- data/lib/jira/resource/priority.rb +1 -3
- data/lib/jira/resource/project.rb +5 -7
- data/lib/jira/resource/rapidview.rb +28 -7
- data/lib/jira/resource/remotelink.rb +1 -4
- data/lib/jira/resource/resolution.rb +2 -4
- data/lib/jira/resource/serverinfo.rb +1 -2
- data/lib/jira/resource/sprint.rb +86 -17
- data/lib/jira/resource/sprint_report.rb +8 -0
- data/lib/jira/resource/status.rb +1 -3
- data/lib/jira/resource/suggested_issue.rb +9 -0
- data/lib/jira/resource/transition.rb +2 -6
- data/lib/jira/resource/user.rb +12 -2
- data/lib/jira/resource/version.rb +1 -3
- data/lib/jira/resource/watcher.rb +35 -0
- data/lib/jira/resource/webhook.rb +3 -6
- data/lib/jira/resource/worklog.rb +3 -5
- data/lib/jira/version.rb +1 -1
- data/lib/jira-ruby.rb +12 -2
- data/lib/tasks/generate.rake +4 -4
- data/spec/integration/attachment_spec.rb +17 -8
- data/spec/integration/comment_spec.rb +31 -34
- data/spec/integration/component_spec.rb +21 -24
- data/spec/integration/field_spec.rb +15 -18
- data/spec/integration/issue_spec.rb +45 -46
- data/spec/integration/issuelinktype_spec.rb +8 -11
- data/spec/integration/issuetype_spec.rb +5 -7
- data/spec/integration/priority_spec.rb +5 -8
- data/spec/integration/project_spec.rb +13 -20
- data/spec/integration/rapidview_spec.rb +17 -10
- data/spec/integration/resolution_spec.rb +7 -10
- data/spec/integration/status_spec.rb +5 -8
- data/spec/integration/transition_spec.rb +17 -20
- data/spec/integration/user_spec.rb +24 -8
- data/spec/integration/version_spec.rb +21 -25
- data/spec/integration/watcher_spec.rb +62 -0
- data/spec/integration/webhook.rb +8 -17
- data/spec/integration/worklog_spec.rb +30 -34
- data/spec/jira/base_factory_spec.rb +11 -12
- data/spec/jira/base_spec.rb +216 -229
- data/spec/jira/client_spec.rb +227 -159
- data/spec/jira/has_many_proxy_spec.rb +11 -12
- data/spec/jira/http_client_spec.rb +254 -31
- data/spec/jira/http_error_spec.rb +7 -9
- data/spec/jira/jwt_uri_builder_spec.rb +59 -0
- data/spec/jira/oauth_client_spec.rb +110 -39
- data/spec/jira/request_client_spec.rb +36 -9
- data/spec/jira/resource/agile_spec.rb +135 -0
- data/spec/jira/resource/attachment_spec.rb +127 -9
- data/spec/jira/resource/board_spec.rb +224 -0
- data/spec/jira/resource/createmeta_spec.rb +29 -32
- data/spec/jira/resource/field_spec.rb +42 -48
- data/spec/jira/resource/filter_spec.rb +40 -40
- data/spec/jira/resource/issue_picker_suggestions_spec.rb +79 -0
- data/spec/jira/resource/issue_spec.rb +88 -85
- data/spec/jira/resource/issuelink_spec.rb +1 -1
- data/spec/jira/resource/jira_picker_suggestions_issue_spec.rb +18 -0
- data/spec/jira/resource/project_factory_spec.rb +2 -4
- data/spec/jira/resource/project_spec.rb +33 -33
- data/spec/jira/resource/sprint_spec.rb +90 -0
- data/spec/jira/resource/user_factory_spec.rb +6 -8
- data/spec/jira/resource/worklog_spec.rb +9 -11
- data/spec/mock_responses/board/1.json +33 -0
- data/spec/mock_responses/board/1_issues.json +62 -0
- data/spec/mock_responses/empty_issues.json +8 -0
- data/spec/mock_responses/issue/10002/watchers.json +13 -0
- data/spec/mock_responses/issue.json +1 -1
- data/spec/mock_responses/sprint/1_issues.json +125 -0
- data/spec/spec_helper.rb +8 -9
- data/spec/support/clients_helper.rb +4 -4
- data/spec/support/shared_examples/integration.rb +60 -77
- metadata +115 -55
- data/.ruby-version +0 -1
- data/README.rdoc +0 -333
- /data/spec/mock_responses/{attachment → issue/10002/attachments}/10000.json +0 -0
@@ -1,6 +1,5 @@
|
|
1
1
|
module JIRA
|
2
2
|
module Resource
|
3
|
-
|
4
3
|
class CreatemetaFactory < JIRA::BaseFactory # :nodoc:
|
5
4
|
end
|
6
5
|
|
@@ -9,36 +8,35 @@ module JIRA
|
|
9
8
|
'/issue/createmeta'
|
10
9
|
end
|
11
10
|
|
12
|
-
def self.all(client, params={})
|
13
|
-
|
14
|
-
|
15
|
-
values = Array(params[:projectKeys]).map{|i| (i.is_a?(JIRA::Resource::Project) ? i.key : i)}
|
11
|
+
def self.all(client, params = {})
|
12
|
+
if params.key?(:projectKeys)
|
13
|
+
values = Array(params[:projectKeys]).map { |i| (i.is_a?(JIRA::Resource::Project) ? i.key : i) }
|
16
14
|
params[:projectKeys] = values.join(',')
|
17
15
|
end
|
18
16
|
|
19
|
-
if params.
|
20
|
-
values = Array(params[:projectIds]).map{|i| (i.is_a?(JIRA::Resource::Project) ? i.id : i)}
|
17
|
+
if params.key?(:projectIds)
|
18
|
+
values = Array(params[:projectIds]).map { |i| (i.is_a?(JIRA::Resource::Project) ? i.id : i) }
|
21
19
|
params[:projectIds] = values.join(',')
|
22
20
|
end
|
23
21
|
|
24
|
-
if params.
|
25
|
-
values = Array(params[:issuetypeNames]).map{|i| (i.is_a?(JIRA::Resource::Issuetype) ? i.name : i)}
|
22
|
+
if params.key?(:issuetypeNames)
|
23
|
+
values = Array(params[:issuetypeNames]).map { |i| (i.is_a?(JIRA::Resource::Issuetype) ? i.name : i) }
|
26
24
|
params[:issuetypeNames] = values.join(',')
|
27
25
|
end
|
28
26
|
|
29
|
-
if params.
|
30
|
-
values = Array(params[:issuetypeIds]).map{|i| (i.is_a?(JIRA::Resource::Issuetype) ? i.id : i)}
|
27
|
+
if params.key?(:issuetypeIds)
|
28
|
+
values = Array(params[:issuetypeIds]).map { |i| (i.is_a?(JIRA::Resource::Issuetype) ? i.id : i) }
|
31
29
|
params[:issuetypeIds] = values.join(',')
|
32
30
|
end
|
33
31
|
|
34
|
-
create_meta_url = client.options[:rest_base_path] +
|
32
|
+
create_meta_url = client.options[:rest_base_path] + endpoint_name
|
35
33
|
params = hash_to_query_string(params)
|
36
34
|
|
37
|
-
response = params.empty? ? client.get(
|
35
|
+
response = params.empty? ? client.get(create_meta_url.to_s) : client.get("#{create_meta_url}?#{params}")
|
38
36
|
|
39
37
|
json = parse_json(response.body)
|
40
38
|
json['projects'].map do |attrs|
|
41
|
-
|
39
|
+
new(client, attrs: attrs)
|
42
40
|
end
|
43
41
|
end
|
44
42
|
end
|
data/lib/jira/resource/field.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
module JIRA
|
2
2
|
module Resource
|
3
|
-
|
4
3
|
class FieldFactory < JIRA::BaseFactory # :nodoc:
|
5
|
-
|
4
|
+
delegate_to_target_class :map_fields, :name_to_id, :field_map
|
6
5
|
end
|
7
6
|
|
8
7
|
class Field < JIRA::Base
|
9
|
-
|
10
|
-
#translate a custom field description to a method-safe name
|
8
|
+
# translate a custom field description to a method-safe name
|
11
9
|
def self.safe_name(description)
|
12
|
-
description.gsub(/[^a-zA-Z0-9]/,'_')
|
10
|
+
description.gsub(/[^a-zA-Z0-9]/, '_')
|
13
11
|
end
|
14
12
|
|
15
13
|
# safe_name plus disambiguation if it fails it uses the original jira id (customfield_#####)
|
16
14
|
def self.safer_name(description, jira_id)
|
17
|
-
"#{safe_name(description)}_#{jira_id.split('_')[1]}"
|
15
|
+
"#{safe_name(description)}_#{jira_id.split('_')[1]}"
|
16
|
+
rescue StandardError
|
17
|
+
jira_id
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.map_fields(client)
|
@@ -34,17 +34,17 @@ module JIRA
|
|
34
34
|
fields.each do |f|
|
35
35
|
next unless f.custom
|
36
36
|
name = if field_map.key? f.name
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
renamed = safer_name(f.name, f.id)
|
38
|
+
warn "Duplicate Field name #{f.name} #{f.id} - renaming as #{renamed}"
|
39
|
+
renamed
|
40
|
+
else
|
41
|
+
safe_name(f.name)
|
42
42
|
end
|
43
43
|
field_map_reverse[f.id] = [f.name, name] # capture both the official name, and the mapped name
|
44
44
|
field_map[name] = f.id
|
45
45
|
end
|
46
46
|
|
47
|
-
client.cache.field_map_reverse = field_map_reverse
|
47
|
+
client.cache.field_map_reverse = field_map_reverse # not sure where this will be used yet, but sure to be useful
|
48
48
|
client.cache.field_map = field_map
|
49
49
|
end
|
50
50
|
|
@@ -58,8 +58,8 @@ module JIRA
|
|
58
58
|
client.cache.field_map[field_name]
|
59
59
|
end
|
60
60
|
|
61
|
-
def respond_to?(method_name,
|
62
|
-
if [method_name.to_s, client.Field.name_to_id(method_name)].any? {|k| attrs.key?(k)}
|
61
|
+
def respond_to?(method_name, _include_all = false)
|
62
|
+
if [method_name.to_s, client.Field.name_to_id(method_name)].any? { |k| attrs.key?(k) }
|
63
63
|
true
|
64
64
|
else
|
65
65
|
super(method_name)
|
@@ -67,16 +67,16 @@ module JIRA
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def method_missing(method_name, *args, &block)
|
70
|
-
|
71
|
-
|
70
|
+
if attrs.key?(method_name.to_s)
|
71
|
+
attrs[method_name.to_s]
|
72
|
+
else
|
73
|
+
official_name = client.Field.name_to_id(method_name)
|
74
|
+
if attrs.key?(official_name)
|
75
|
+
attrs[official_name]
|
72
76
|
else
|
73
|
-
|
74
|
-
if attrs.keys.include?(official_name)
|
75
|
-
attrs[official_name]
|
76
|
-
else
|
77
|
-
super(method_name, *args, &block)
|
78
|
-
end
|
77
|
+
super(method_name, *args, &block)
|
79
78
|
end
|
79
|
+
end
|
80
80
|
end
|
81
81
|
end
|
82
82
|
end
|
data/lib/jira/resource/filter.rb
CHANGED
@@ -4,11 +4,11 @@ module JIRA
|
|
4
4
|
end
|
5
5
|
|
6
6
|
class Filter < JIRA::Base
|
7
|
-
has_one :owner, :
|
7
|
+
has_one :owner, class: JIRA::Resource::User
|
8
8
|
|
9
9
|
# Returns all the issues for this filter
|
10
10
|
def issues
|
11
|
-
Issue.jql(
|
11
|
+
Issue.jql(client, jql)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
data/lib/jira/resource/issue.rb
CHANGED
@@ -1,69 +1,85 @@
|
|
1
1
|
require 'cgi'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
module JIRA
|
4
5
|
module Resource
|
5
|
-
|
6
6
|
class IssueFactory < JIRA::BaseFactory # :nodoc:
|
7
7
|
end
|
8
8
|
|
9
9
|
class Issue < JIRA::Base
|
10
|
+
has_one :reporter, class: JIRA::Resource::User,
|
11
|
+
nested_under: 'fields'
|
12
|
+
has_one :assignee, class: JIRA::Resource::User,
|
13
|
+
nested_under: 'fields'
|
14
|
+
has_one :project, nested_under: 'fields'
|
10
15
|
|
11
|
-
has_one :
|
12
|
-
:nested_under => 'fields'
|
13
|
-
has_one :assignee, :class => JIRA::Resource::User,
|
14
|
-
:nested_under => 'fields'
|
15
|
-
has_one :project, :nested_under => 'fields'
|
16
|
-
|
17
|
-
has_one :issuetype, :nested_under => 'fields'
|
16
|
+
has_one :issuetype, nested_under: 'fields'
|
18
17
|
|
19
|
-
has_one :priority, :
|
18
|
+
has_one :priority, nested_under: 'fields'
|
20
19
|
|
21
|
-
has_one :status, :
|
20
|
+
has_one :status, nested_under: 'fields'
|
22
21
|
|
23
22
|
has_many :transitions
|
24
23
|
|
25
|
-
has_many :components, :
|
24
|
+
has_many :components, nested_under: 'fields'
|
25
|
+
|
26
|
+
has_many :comments, nested_under: %w[fields comment]
|
27
|
+
|
28
|
+
has_many :attachments, nested_under: 'fields',
|
29
|
+
attribute_key: 'attachment'
|
26
30
|
|
27
|
-
has_many :
|
31
|
+
has_many :versions, nested_under: 'fields'
|
32
|
+
has_many :fixVersions, class: JIRA::Resource::Version,
|
33
|
+
nested_under: 'fields'
|
28
34
|
|
29
|
-
has_many :
|
30
|
-
|
35
|
+
has_many :worklogs, nested_under: %w[fields worklog]
|
36
|
+
has_one :sprint, class: JIRA::Resource::Sprint,
|
37
|
+
nested_under: 'fields'
|
31
38
|
|
32
|
-
has_many :
|
33
|
-
|
34
|
-
:nested_under => 'fields'
|
39
|
+
has_many :closed_sprints, class: JIRA::Resource::Sprint,
|
40
|
+
nested_under: 'fields', attribute_key: 'closedSprints'
|
35
41
|
|
36
|
-
has_many :
|
42
|
+
has_many :issuelinks, nested_under: 'fields'
|
37
43
|
|
38
|
-
has_many :
|
44
|
+
has_many :remotelink, class: JIRA::Resource::Remotelink
|
39
45
|
|
40
|
-
has_many :
|
46
|
+
has_many :watchers, attribute_key: 'watches',
|
47
|
+
nested_under: %w[fields watches]
|
41
48
|
|
42
49
|
def self.all(client)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
client.
|
50
|
+
start_at = 0
|
51
|
+
max_results = 1000
|
52
|
+
result = []
|
53
|
+
loop do
|
54
|
+
url = client.options[:rest_base_path] +
|
55
|
+
"/search?expand=transitions.fields&maxResults=#{max_results}&startAt=#{start_at}"
|
56
|
+
response = client.get(url)
|
57
|
+
json = parse_json(response.body)
|
58
|
+
json['issues'].map do |issue|
|
59
|
+
result.push(client.Issue.build(issue))
|
60
|
+
end
|
61
|
+
break if json['issues'].empty?
|
62
|
+
start_at += json['issues'].size
|
48
63
|
end
|
64
|
+
result
|
49
65
|
end
|
50
66
|
|
51
|
-
def self.jql(client, jql, options = {fields: nil, start_at: nil, max_results: nil, expand: nil, validate_query: true})
|
67
|
+
def self.jql(client, jql, options = { fields: nil, start_at: nil, max_results: nil, expand: nil, validate_query: true })
|
52
68
|
url = client.options[:rest_base_path] + "/search?jql=#{CGI.escape(jql)}"
|
53
69
|
|
54
|
-
url << "&fields=#{options[:fields].map{ |value| CGI.escape(client.Field.name_to_id(value)) }.join(',')}" if options[:fields]
|
70
|
+
url << "&fields=#{options[:fields].map { |value| CGI.escape(client.Field.name_to_id(value)) }.join(',')}" if options[:fields]
|
55
71
|
url << "&startAt=#{CGI.escape(options[:start_at].to_s)}" if options[:start_at]
|
56
72
|
url << "&maxResults=#{CGI.escape(options[:max_results].to_s)}" if options[:max_results]
|
57
|
-
url <<
|
73
|
+
url << '&validateQuery=false' if options[:validate_query] === false
|
58
74
|
|
59
75
|
if options[:expand]
|
60
76
|
options[:expand] = [options[:expand]] if options[:expand].is_a?(String)
|
61
|
-
url << "&expand=#{options[:expand].to_a.map{ |value| CGI.escape(value.to_s) }.join(',')}"
|
77
|
+
url << "&expand=#{options[:expand].to_a.map { |value| CGI.escape(value.to_s) }.join(',')}"
|
62
78
|
end
|
63
79
|
|
64
80
|
response = client.get(url)
|
65
81
|
json = parse_json(response.body)
|
66
|
-
if options[:max_results]
|
82
|
+
if options[:max_results] && (options[:max_results] == 0)
|
67
83
|
return json['total']
|
68
84
|
end
|
69
85
|
json['issues'].map do |issue|
|
@@ -71,6 +87,23 @@ module JIRA
|
|
71
87
|
end
|
72
88
|
end
|
73
89
|
|
90
|
+
# Fetches the attributes for the specified resource from JIRA unless
|
91
|
+
# the resource is already expanded and the optional force reload flag
|
92
|
+
# is not set
|
93
|
+
def fetch(reload = false, query_params = {})
|
94
|
+
return if expanded? && !reload
|
95
|
+
response = client.get(url_with_query_params(url, query_params))
|
96
|
+
set_attrs_from_response(response)
|
97
|
+
if @attrs && @attrs['fields'] && @attrs['fields']['worklog'] && (@attrs['fields']['worklog']['total'] > @attrs['fields']['worklog']['maxResults'])
|
98
|
+
worklog_url = client.options[:rest_base_path] + "/#{self.class.endpoint_name}/#{id}/worklog"
|
99
|
+
response = client.get(worklog_url)
|
100
|
+
unless response.body.nil? || (response.body.length < 2)
|
101
|
+
set_attrs({ 'fields' => { 'worklog' => self.class.parse_json(response.body) } }, false)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
@expanded = true
|
105
|
+
end
|
106
|
+
|
74
107
|
def editmeta
|
75
108
|
editmeta_url = client.options[:rest_base_path] + "/#{self.class.endpoint_name}/#{key}/editmeta"
|
76
109
|
|
@@ -79,8 +112,8 @@ module JIRA
|
|
79
112
|
json['fields']
|
80
113
|
end
|
81
114
|
|
82
|
-
def respond_to?(method_name,
|
83
|
-
if attrs.
|
115
|
+
def respond_to?(method_name, _include_all = false)
|
116
|
+
if attrs.key?('fields') && [method_name.to_s, client.Field.name_to_id(method_name)].any? { |k| attrs['fields'].key?(k) }
|
84
117
|
true
|
85
118
|
else
|
86
119
|
super(method_name)
|
@@ -88,12 +121,12 @@ module JIRA
|
|
88
121
|
end
|
89
122
|
|
90
123
|
def method_missing(method_name, *args, &block)
|
91
|
-
if attrs.
|
92
|
-
if attrs['fields'].
|
124
|
+
if attrs.key?('fields')
|
125
|
+
if attrs['fields'].key?(method_name.to_s)
|
93
126
|
attrs['fields'][method_name.to_s]
|
94
127
|
else
|
95
|
-
official_name=client.Field.name_to_id(method_name)
|
96
|
-
if attrs['fields'].
|
128
|
+
official_name = client.Field.name_to_id(method_name)
|
129
|
+
if attrs['fields'].key?(official_name)
|
97
130
|
attrs['fields'][official_name]
|
98
131
|
else
|
99
132
|
super(method_name, *args, &block)
|
@@ -103,8 +136,6 @@ module JIRA
|
|
103
136
|
super(method_name, *args, &block)
|
104
137
|
end
|
105
138
|
end
|
106
|
-
|
107
139
|
end
|
108
|
-
|
109
140
|
end
|
110
141
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module JIRA
|
2
|
+
module Resource
|
3
|
+
class IssuePickerSuggestionsFactory < JIRA::BaseFactory # :nodoc:
|
4
|
+
end
|
5
|
+
|
6
|
+
class IssuePickerSuggestions < JIRA::Base
|
7
|
+
has_many :sections, class: JIRA::Resource::IssuePickerSuggestionsIssue
|
8
|
+
|
9
|
+
def self.all(client, query = '', options = { current_jql: nil, current_issue_key: nil, current_project_id: nil, show_sub_tasks: nil, show_sub_tasks_parent: nil })
|
10
|
+
url = client.options[:rest_base_path] + "/issue/picker?query=#{CGI.escape(query)}"
|
11
|
+
|
12
|
+
url << "¤tJQL=#{CGI.escape(options[:current_jql])}" if options[:current_jql]
|
13
|
+
url << "¤tIssueKey=#{CGI.escape(options[:current_issue_key])}" if options[:current_issue_key]
|
14
|
+
url << "¤tProjectId=#{CGI.escape(options[:current_project_id])}" if options[:current_project_id]
|
15
|
+
url << "&showSubTasks=#{options[:show_sub_tasks]}" if options[:show_sub_tasks]
|
16
|
+
url << "&showSubTaskParent=#{options[:show_sub_task_parent]}" if options[:show_sub_task_parent]
|
17
|
+
|
18
|
+
response = client.get(url)
|
19
|
+
json = parse_json(response.body)
|
20
|
+
client.IssuePickerSuggestions.build(json)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module JIRA
|
2
2
|
module Resource
|
3
|
-
|
4
3
|
class IssuelinkFactory < JIRA::BaseFactory # :nodoc:
|
5
4
|
end
|
6
5
|
|
@@ -9,14 +8,13 @@ module JIRA
|
|
9
8
|
class Issue < JIRA::Base; end
|
10
9
|
|
11
10
|
class Issuelink < JIRA::Base
|
12
|
-
has_one :type, :
|
13
|
-
has_one :inwardIssue, :
|
14
|
-
has_one :outwardIssue, :
|
11
|
+
has_one :type, class: JIRA::Resource::Issuelinktype
|
12
|
+
has_one :inwardIssue, class: JIRA::Resource::Issue
|
13
|
+
has_one :outwardIssue, class: JIRA::Resource::Issue
|
15
14
|
|
16
15
|
def self.endpoint_name
|
17
16
|
'issueLink'
|
18
17
|
end
|
19
|
-
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
@@ -1,14 +1,12 @@
|
|
1
1
|
module JIRA
|
2
2
|
module Resource
|
3
|
-
|
4
3
|
class ProjectFactory < JIRA::BaseFactory # :nodoc:
|
5
4
|
end
|
6
5
|
|
7
6
|
class Project < JIRA::Base
|
8
|
-
|
9
|
-
has_one :lead, :class => JIRA::Resource::User
|
7
|
+
has_one :lead, class: JIRA::Resource::User
|
10
8
|
has_many :components
|
11
|
-
has_many :issuetypes, :
|
9
|
+
has_many :issuetypes, attribute_key: 'issueTypes'
|
12
10
|
has_many :versions
|
13
11
|
|
14
12
|
def self.key_attribute
|
@@ -16,9 +14,9 @@ module JIRA
|
|
16
14
|
end
|
17
15
|
|
18
16
|
# Returns all the issues for this project
|
19
|
-
def issues(options={})
|
17
|
+
def issues(options = {})
|
20
18
|
search_url = client.options[:rest_base_path] + '/search'
|
21
|
-
query_params = {:
|
19
|
+
query_params = { jql: "project=\"#{key}\"" }
|
22
20
|
query_params.update Base.query_params_for_search(options)
|
23
21
|
response = client.get(url_with_query_params(search_url, query_params))
|
24
22
|
json = self.class.parse_json(response.body)
|
@@ -29,7 +27,7 @@ module JIRA
|
|
29
27
|
|
30
28
|
def users(start_at: nil, max_results: nil)
|
31
29
|
users_url = client.options[:rest_base_path] + '/user/assignable/search'
|
32
|
-
query_params = { project:
|
30
|
+
query_params = { project: key_value }
|
33
31
|
query_params['startAt'] = start_at if start_at
|
34
32
|
query_params['maxResults'] = max_results if max_results
|
35
33
|
response = client.get(url_with_query_params(users_url, query_params))
|
@@ -2,12 +2,10 @@ require 'cgi'
|
|
2
2
|
|
3
3
|
module JIRA
|
4
4
|
module Resource
|
5
|
-
|
6
5
|
class RapidViewFactory < JIRA::BaseFactory # :nodoc:
|
7
6
|
end
|
8
7
|
|
9
8
|
class RapidView < JIRA::Base
|
10
|
-
|
11
9
|
def self.all(client)
|
12
10
|
response = client.get(path_base(client) + '/rapidview')
|
13
11
|
json = parse_json(response.body)
|
@@ -16,18 +14,43 @@ module JIRA
|
|
16
14
|
end
|
17
15
|
end
|
18
16
|
|
19
|
-
def self.find(client, key,
|
17
|
+
def self.find(client, key, _options = {})
|
20
18
|
response = client.get(path_base(client) + "/rapidview/#{key}")
|
21
19
|
json = parse_json(response.body)
|
22
20
|
client.RapidView.build(json)
|
23
21
|
end
|
24
22
|
|
25
|
-
def issues
|
23
|
+
def issues(options = {})
|
26
24
|
response = client.get(path_base(client) + "/xboard/plan/backlog/data?rapidViewId=#{id}")
|
27
25
|
json = self.class.parse_json(response.body)
|
28
26
|
# To get Issue objects with the same structure as for Issue.all
|
29
27
|
issue_ids = json['issues'].map { |issue| issue['id'] }
|
30
|
-
|
28
|
+
|
29
|
+
# First we have to get all IDs of parent and sub tasks
|
30
|
+
jql = "id IN(#{issue_ids.join(', ')})"
|
31
|
+
|
32
|
+
# Filtering options
|
33
|
+
jql << ' AND sprint IS NOT EMPTY' unless options[:include_backlog_items]
|
34
|
+
|
35
|
+
parent_issues = client.Issue.jql(jql)
|
36
|
+
subtask_ids = parent_issues.map { |t| t.subtasks.map { |sub| sub['id'] } }.flatten
|
37
|
+
|
38
|
+
parent_and_sub_ids = parent_issues.map(&:id) + subtask_ids
|
39
|
+
jql = "id IN(#{parent_and_sub_ids.join(', ')})"
|
40
|
+
jql << " and updated >= '#{options.delete(:updated)}'" if options[:updated]
|
41
|
+
|
42
|
+
client.Issue.jql(jql)
|
43
|
+
end
|
44
|
+
|
45
|
+
def sprints(options = {})
|
46
|
+
params = { includeHistoricSprints: options.fetch(:include_historic, false),
|
47
|
+
includeFutureSprints: options.fetch(:include_future, false) }
|
48
|
+
response = client.get(path_base(client) + "/sprintquery/#{id}?#{params.to_query}")
|
49
|
+
json = self.class.parse_json(response.body)
|
50
|
+
json['sprints'].map do |sprint|
|
51
|
+
sprint['rapidview_id'] = id
|
52
|
+
client.Sprint.build(sprint)
|
53
|
+
end
|
31
54
|
end
|
32
55
|
|
33
56
|
private
|
@@ -39,8 +62,6 @@ module JIRA
|
|
39
62
|
def path_base(client)
|
40
63
|
self.class.path_base(client)
|
41
64
|
end
|
42
|
-
|
43
65
|
end
|
44
|
-
|
45
66
|
end
|
46
67
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module JIRA
|
2
2
|
module Resource
|
3
|
-
|
4
3
|
class RemotelinkFactory < JIRA::BaseFactory # :nodoc:
|
5
4
|
end
|
6
5
|
|
@@ -13,9 +12,7 @@ module JIRA
|
|
13
12
|
|
14
13
|
def self.all(client, options = {})
|
15
14
|
issue = options[:issue]
|
16
|
-
unless issue
|
17
|
-
raise ArgumentError.new("parent issue is required")
|
18
|
-
end
|
15
|
+
raise ArgumentError, 'parent issue is required' unless issue
|
19
16
|
|
20
17
|
path = "#{issue.self}/#{endpoint_name}"
|
21
18
|
response = client.get(path)
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module JIRA
|
2
2
|
module Resource
|
3
|
-
|
4
3
|
class ServerInfoFactory < JIRA::BaseFactory # :nodoc:
|
5
4
|
end
|
6
5
|
|
@@ -12,7 +11,7 @@ module JIRA
|
|
12
11
|
def self.all(client, options = {})
|
13
12
|
response = client.get(collection_path(client))
|
14
13
|
json = parse_json(response.body)
|
15
|
-
|
14
|
+
new(client, { attrs: json }.merge(options))
|
16
15
|
end
|
17
16
|
end
|
18
17
|
end
|