jiraSOAP 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -50,20 +50,7 @@ Get the [Gist](http://gist.github.com/612186).
50
50
  Notes About Using This Gem
51
51
  --------------------------
52
52
 
53
- To get a reference for the API, you can look at the JavaDoc stuff provided by Atalssian [here](http://docs.atlassian.com/software/jira/docs/api/rpc-jira-plugin/latest/com/atlassian/jira/rpc/soap/JiraSoapService.html).
54
-
55
- 1. All method names have been made to feel more natural in a Ruby setting. Consult the `jiraSOAP` documentation for specifics.
56
-
57
- 2. If an API call fails with a method missing error it is because the method has not been implement, yet. I started by implementing only the methods that I needed in order to port some old scripts that ran on jira4r; other methods will be added as them gem matures (or you could add it for me :D).
58
-
59
- 3. URESOLVED issues have a Resolution with a value of `nil`.
60
-
61
- 4. To empty a field (set it to nil) you can use this pattern:
62
- jira.update_issue 'JIRA-1', JIRA::FieldValue.fieldValueWithNilValues 'description'
63
-
64
- 5. Issue creation, using #create_issue_with_issue does not make use of all the fields in a JIRA::Issue. Which fields are used seems to depend on the version of JIRA you are connecting to.
65
-
66
- 6. RemoteAPI#update_issue wants an id for each field that you pass it, but it really wants the name of the field that you want to update. See this [Gist](http://gist.github.com/612562).
53
+ 1. URESOLVED issues have a Resolution with a value of `nil`.
67
54
 
68
55
 
69
56
  TODO
@@ -71,11 +58,9 @@ TODO
71
58
 
72
59
  - Performance optimizations; there are a number of places that can be optimized
73
60
  + Using GCD/Threads for parsing arrays of results; a significant speed up for large types and large arrays (ie. creating issues from JQL searches)
74
- - Refactor for a smaller code base
75
61
  - Fix type hacks;. dates should be `NSDate`s and URLs should be `NSURL`s, right now they are all strings
76
62
  - Public test suite
77
63
  + Needs a mock server
78
- - Documentation
79
64
  - Error handling
80
65
  - Finish implementing all of the API
81
66
 
@@ -1,15 +1,33 @@
1
+ # All the remote entities as well as the SOAP service client.
1
2
  module JIRA
3
+
4
+ # Interface to the JIRA endpoint server; set at initialization.
5
+ #
6
+ # Due to limitations in Handsoap::Service, there can only be one endpoint.
7
+ # You can have multiple instances of that one endpoint if you would
8
+ # like; but if you try to set a differnt endpoint for a new instance you
9
+ # will end up messing up any other instances currently being used.
10
+ #
11
+ # It is best to treat this class as a singleton. There should only be one.
12
+ #
13
+ # HTTPS is not supported in this version.
2
14
  class JIRAService < Handsoap::Service
3
15
  include RemoteAPI
4
16
 
5
17
  attr_reader :auth_token, :user
6
18
 
19
+ # Factory method to initialize and login.
20
+ #@param [String] url URL for the JIRA server
21
+ #@param [String] user JIRA user name to login with
22
+ #@param [String] password
7
23
  def self.instance_at_url(url, user, password)
8
24
  jira = JIRAService.new url
9
25
  jira.login user, password
10
26
  jira
11
27
  end
12
28
 
29
+ # Slightly hacky in order to set the endpoint at the initialization.
30
+ #@param endpoint_url URL for the JIRA server
13
31
  def initialize(endpoint_url)
14
32
  super
15
33
 
@@ -23,8 +41,10 @@ class JIRAService < Handsoap::Service
23
41
 
24
42
  #PONDER: a finalizer that will try to logout
25
43
 
44
+ # Something to help users out until the rest of the API is implemented.
26
45
  def method_missing(method, *args)
27
- $stderr.puts "#{method} is not a defined method in the API...yet"
46
+ message = 'Check the documentation; the method may not be implemented yet.'
47
+ raise NoMethodError, message, caller
28
48
  end
29
49
 
30
50
  protected
@@ -1,14 +1,24 @@
1
- #PONDER: send upstream for consideration
1
+ #Some simple extensions to Handsoap.
2
2
  module Handsoap
3
+ #Some simple extensions to XmlMason. Currently, this only includes methods to
4
+ #make it easier to build SOAP messages that contain arrays.
3
5
  module XmlMason
6
+ #Represents a node in an XML document
4
7
  class Node
5
- #TODO: make recursive
8
+ #@todo Make this method recursive
9
+ #@param [String] node_name
10
+ #@param [Array] array
11
+ #@param [Hash] options
6
12
  def add_simple_array(node_name, array = [], options = {})
7
13
  prefix, name = parse_ns(node_name)
8
14
  node = append_child Element.new(self, prefix, name, nil, options)
9
15
  array.each { |element| node.add node_name, element }
10
16
  end
11
17
 
18
+ #@todo Make this method recursive
19
+ #@param [String] node_name
20
+ #@param [Array] array
21
+ #@param [Hash] options
12
22
  def add_complex_array(node_name, array = [], options = {})
13
23
  prefix, name = parse_ns(node_name)
14
24
  node = append_child Element.new(self, prefix, name, nil, options)
@@ -1,18 +1,31 @@
1
+ # Contains the API defined by Atlassian for the JIRA SOAP service. The JavaDoc
2
+ # for the SOAP API is located at http://docs.atlassian.com/software/jira/docs/api/rpc-jira-plugin/latest/com/atlassian/jira/rpc/soap/JiraSoapService.html.
3
+ #@todo exception handling
4
+ #@todo code refactoring and de-duplication
1
5
  module RemoteAPI
6
+ #XPath constant to get a node containing a response array.
7
+ #This could be used for all responses, but is only used in cases where we
8
+ #cannot use a more blunt XPath expression.
2
9
  RESPONSE_XPATH = '/node()[1]/node()[1]/node()[1]/node()[2]'
3
10
 
11
+ #The first method to call. No other method will work unless you are logged in.
12
+ #@param [String] user JIRA user name to login with
13
+ #@param [String] password
14
+ #@return [boolean] true if successful, otherwise false
4
15
  def login(user, password)
5
16
  response = invoke('soap:login') { |msg|
6
17
  msg.add 'soap:in0', user
7
18
  msg.add 'soap:in1', password
8
19
  }
9
- #TODO: error handling (catch the exception and look at the Response node?)
10
20
  #cache now that we know it is safe to do so
11
21
  @user = user
12
22
  @auth_token = response.document.xpath('//loginReturn').first.to_s
13
23
  true
14
24
  end
15
25
 
26
+ #You only need to call this to make an exlicit logout; normally, a session
27
+ #willautomatically expire after a set time (configured on the server).
28
+ #@return [boolean] true if successful, otherwise false
16
29
  def logout
17
30
  response = invoke('soap:logout') { |msg|
18
31
  msg.add 'soap:in0', @auth_token
@@ -20,6 +33,8 @@ module RemoteAPI
20
33
  response.document.xpath('//logoutReturn').first.to_s == 'true'
21
34
  end
22
35
 
36
+ #Get the global listing for types of priorities.
37
+ #@return [[JIRA::Priority]]
23
38
  def get_priorities
24
39
  response = invoke('soap:getPriorities') { |msg|
25
40
  msg.add 'soap:in0', @auth_token
@@ -30,6 +45,8 @@ module RemoteAPI
30
45
  }
31
46
  end
32
47
 
48
+ #Get the global listing for types of resolutions.
49
+ #@return [[JIRA::Resolution]]
33
50
  def get_resolutions
34
51
  response = invoke('soap:getResolutions') { |msg|
35
52
  msg.add 'soap:in0', @auth_token
@@ -40,6 +57,8 @@ module RemoteAPI
40
57
  }
41
58
  end
42
59
 
60
+ #Get the global listing for types of custom fields.
61
+ #@return [[JIRA::Field]]
43
62
  def get_custom_fields
44
63
  response = invoke('soap:getCustomFields') { |msg|
45
64
  msg.add 'soap:in0', @auth_token
@@ -50,6 +69,8 @@ module RemoteAPI
50
69
  }
51
70
  end
52
71
 
72
+ #Get the global listing for types of issues.
73
+ #@return [[JIRA::IssueType]]
53
74
  def get_issue_types
54
75
  response = invoke('soap:getIssueTypes') { |msg|
55
76
  msg.add 'soap:in0', @auth_token
@@ -60,6 +81,8 @@ module RemoteAPI
60
81
  }
61
82
  end
62
83
 
84
+ #Get the global listing of status type.
85
+ #@return [[JIRA::Status]]
63
86
  def get_statuses
64
87
  response = invoke('soap:getStatuses') { |msg|
65
88
  msg.add 'soap:in0', @auth_token
@@ -70,6 +93,8 @@ module RemoteAPI
70
93
  }
71
94
  end
72
95
 
96
+ #Get the global listing for notification schemes.
97
+ #@return [[JIRA::Scheme]]
73
98
  def get_notification_schemes
74
99
  response = invoke('soap:getNotificationSchemes') { |msg|
75
100
  msg.add 'soap:in0', @auth_token
@@ -80,6 +105,9 @@ module RemoteAPI
80
105
  }
81
106
  end
82
107
 
108
+ #Get all the versions associated with a project.
109
+ #@param [String] project_key
110
+ #@return [[JIRA::Version]]
83
111
  def get_versions_for_project(project_key)
84
112
  response = invoke('soap:getVersions') { |msg|
85
113
  msg.add 'soap:in0', @auth_token
@@ -91,6 +119,9 @@ module RemoteAPI
91
119
  }
92
120
  end
93
121
 
122
+ #Get the information for a project with a given key.
123
+ #@param [String] project_key
124
+ #@return [JIRA::Project]
94
125
  def get_project_with_key(project_key)
95
126
  response = invoke('soap:getProjectByKey') { |msg|
96
127
  msg.add 'soap:in0', @auth_token
@@ -100,6 +131,9 @@ module RemoteAPI
100
131
  JIRA::Project.project_with_xml_fragment frag
101
132
  end
102
133
 
134
+ #This will only give you basic information about a user.
135
+ #@param [String] user_name
136
+ #@return [JIRA::User]
103
137
  def get_user_with_name(user_name)
104
138
  response = invoke('soap:getUser') { |msg|
105
139
  msg.add 'soap:in0', @auth_token
@@ -108,6 +142,10 @@ module RemoteAPI
108
142
  JIRA::User.user_with_xml_fragment response.document.xpath '//getUserReturn'
109
143
  end
110
144
 
145
+ #Gives you the default avatar image for a project; if you want all
146
+ #the avatars for a project, use {#get_project_avatars_for_key}.
147
+ #@param [String] project_key
148
+ #@return [JIRA::Avatar]
111
149
  def get_project_avatar_for_key(project_key)
112
150
  response = invoke('soap:getProjectAvatar') { |msg|
113
151
  msg.add 'soap:in0', @auth_token
@@ -116,6 +154,27 @@ module RemoteAPI
116
154
  JIRA::Avatar.avatar_with_xml_fragment response.document.xpath '//getProjectAvatarReturn'
117
155
  end
118
156
 
157
+ #Gives ALL avatars for a given project use this method; if you
158
+ #just want the default avatar, use {#get_project_avatar_for_key}.
159
+ #@param [String] project_key
160
+ #@return [[JIRA::Avatar]]
161
+ def get_project_avatars_for_key(project_key)
162
+ response = invoke('soap:getProjectAvatars') { |msg|
163
+ msg.add 'soap:in0', @auth_token
164
+ msg.add 'soap:in1', project_key
165
+ }
166
+ response.document.xpath("#{RESPONSE_XPATH}/getProjectAvatarsReturn").map {
167
+ |frag|
168
+ JIRA::Avatar.avatar_with_xml_fragment frag
169
+ }
170
+ end
171
+
172
+ #This method is the equivalent of making an advanced search from the
173
+ #web interface.
174
+ #@param [String] jql_query JQL query as a string
175
+ #@param [Fixnum] max_results limit on number of returned results;
176
+ # the value may be overridden by the server if max_results is too large
177
+ #@return [[JIRA::Issue]]
119
178
  def get_issues_from_jql_search(jql_query, max_results = 500)
120
179
  response = invoke('soap:getIssuesFromJqlSearch') { |msg|
121
180
  msg.add 'soap:in0', @auth_token
@@ -128,6 +187,29 @@ module RemoteAPI
128
187
  }
129
188
  end
130
189
 
190
+ #This method can update most, but not all, issue fields.
191
+ #
192
+ #Fields known to not update via this method:
193
+ # - status - use {#progress_workflow_action}
194
+ # - attachments - use {#add_base64_encoded_attachment_to_issue}
195
+ #
196
+ #Though JIRA::FieldValue objects have an id field, they do not expect
197
+ #to be given id values. You must use the name of the field you wish to update.
198
+ #@example Usage With A Normal Field
199
+ # summary = JIRA::FieldValue.new
200
+ # summary.id = 'summary'
201
+ # summary.values = ['My new summary']
202
+ #@example Usage With A Custom Field
203
+ # custom_field = JIRA::FieldValue.new
204
+ # custom_field.id = 'customfield_10060'
205
+ # custom_field.values = ['123456']
206
+ #@example Setting a field to be blank/nil
207
+ # description = JIRA::FieldValue.field_value_with_nil_values 'description'
208
+ #@example Calling the method to update an issue
209
+ # jira_service_instance.update_issue 'PROJECT-1', description, custom_field
210
+ #@param [String] issue_key
211
+ #@param [JIRA::FieldValue] *field_values
212
+ #@return [JIRA::Issue]
131
213
  def update_issue(issue_key, *field_values)
132
214
  response = invoke('soap:updateIssue') { |msg|
133
215
  msg.add 'soap:in0', @auth_token
@@ -140,6 +222,16 @@ module RemoteAPI
140
222
  JIRA::Issue.issue_with_xml_fragment frag
141
223
  end
142
224
 
225
+ #Some fields will be ignored when an issue is created:
226
+ # - reporter - you cannot override this value at creation
227
+ # - due date - I think this is a bug in jiraSOAP or JIRA
228
+ # - attachments
229
+ # - votes
230
+ # - status
231
+ # - resolution
232
+ # - environment - I think this is a bug in jiraSOAP or JIRA
233
+ #@param [JIRA::Issue] issue
234
+ #@return [JIRA::Issue]
143
235
  def create_issue_with_issue(issue)
144
236
  response = invoke('soap:createIssue') { |msg|
145
237
  msg.add 'soap:in0', @auth_token
@@ -175,7 +267,6 @@ end
175
267
  # getIssuesFromFilterWithLimit
176
268
  # getIssuesFromTextSearchWithLimit
177
269
  # getIssueTypesForProject
178
- # getProjectAvatars
179
270
  # getProjectById
180
271
  # getServerInfo
181
272
  # getSubTaskIssueTypes
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 1
9
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Mark Rada