rally-wsapi 0.5.1 → 0.5.2

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.
Files changed (8) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +44 -38
  4. data/README.md +15 -3
  5. data/Rakefile +4 -4
  6. data/VERSION +1 -1
  7. data/lib/wsapi/session.rb +111 -106
  8. metadata +7 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 07d34602eae173bb8a79afe4b517bd834bdba6ac
4
- data.tar.gz: 1b4ce42d2bfb6efbad0715ec7cc46e055a526907
3
+ metadata.gz: 04672bd9cda1627d271b34af07819da21109d52e
4
+ data.tar.gz: 5134b235bdbccb0730cb1df86751d34fdd79b72b
5
5
  SHA512:
6
- metadata.gz: 548bb40f0074dfb5ce2f456765d33b0779ece40f189dc906d5209bc027bc2f53a1d37239cbebbbfc948b644dde1adb3ca4765d1a10ca202672e3cd86225d2b00
7
- data.tar.gz: 041f1e80d24a43893e1546be46ca3ee0e669718ae0f26b9bc76ed3e2cc2e63bbfb7695be3095bfacdf52a34649529388d196024e81d5d732aab0121db8d4df49
6
+ metadata.gz: c4e0dcdac647d9b54d4f1aeecbfa31d7f03ea09e4da025a132f4a78511c05514df81fbfcde2755d06acfb1fa398f4b23ba04f8b0d0abec38e530f7cff5b02a7d
7
+ data.tar.gz: 951d40919c3b1df204ca1a5ca126f27e4694b327a5b4564cea5c7cb2af2d0a6450028d31a7d562538938fd01df4038ff356c046e2244082c4cd4aa3f25cb13b2
data/Gemfile CHANGED
@@ -12,5 +12,6 @@ end
12
12
 
13
13
  group :test do
14
14
  gem 'rspec'
15
+ gem 'byebug'
15
16
  gem 'webmock'
16
17
  end
@@ -1,29 +1,32 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
- addressable (2.3.6)
4
+ addressable (2.4.0)
5
5
  builder (3.2.2)
6
- crack (0.4.2)
6
+ byebug (5.0.0)
7
+ columnize (= 0.9.0)
8
+ columnize (0.9.0)
9
+ crack (0.4.3)
7
10
  safe_yaml (~> 1.0.0)
8
11
  descendants_tracker (0.0.4)
9
12
  thread_safe (~> 0.3, >= 0.3.1)
10
13
  diff-lcs (1.2.5)
11
- excon (0.42.1)
12
- faraday (0.9.0)
14
+ excon (0.45.4)
15
+ faraday (0.9.2)
13
16
  multipart-post (>= 1.2, < 3)
14
- faraday_middleware (0.9.1)
17
+ faraday_middleware (0.10.0)
15
18
  faraday (>= 0.7.4, < 0.10)
16
- git (1.2.8)
17
- github_api (0.12.2)
18
- addressable (~> 2.3)
19
+ git (1.2.9.1)
20
+ github_api (0.13.1)
21
+ addressable (~> 2.4.0)
19
22
  descendants_tracker (~> 0.0.4)
20
23
  faraday (~> 0.8, < 0.10)
21
- hashie (>= 3.3)
24
+ hashie (>= 3.4)
22
25
  multi_json (>= 1.7.5, < 2.0)
23
- nokogiri (~> 1.6.3)
24
26
  oauth2
25
- hashie (3.3.2)
26
- highline (1.6.21)
27
+ hashdiff (0.2.3)
28
+ hashie (3.4.3)
29
+ highline (1.7.8)
27
30
  jeweler (2.0.1)
28
31
  builder
29
32
  bundler (>= 1.0)
@@ -33,46 +36,49 @@ GEM
33
36
  nokogiri (>= 1.5.10)
34
37
  rake
35
38
  rdoc
36
- json (1.8.1)
37
- jwt (1.2.0)
38
- mini_portile (0.6.2)
39
- multi_json (1.10.1)
39
+ json (1.8.3)
40
+ jwt (1.5.1)
41
+ mini_portile2 (2.0.0)
42
+ multi_json (1.11.2)
40
43
  multi_xml (0.5.5)
41
44
  multipart-post (2.0.0)
42
- nokogiri (1.6.5)
43
- mini_portile (~> 0.6.0)
44
- oauth2 (1.0.0)
45
+ nokogiri (1.6.7.2)
46
+ mini_portile2 (~> 2.0.0.rc2)
47
+ oauth2 (1.1.0)
45
48
  faraday (>= 0.8, < 0.10)
46
- jwt (~> 1.0)
49
+ jwt (~> 1.0, < 1.5.2)
47
50
  multi_json (~> 1.3)
48
51
  multi_xml (~> 0.5)
49
- rack (~> 1.2)
50
- rack (1.6.0)
51
- rake (10.4.2)
52
- rdoc (4.2.0)
52
+ rack (>= 1.2, < 3)
53
+ rack (1.6.4)
54
+ rake (10.5.0)
55
+ rdoc (4.2.1)
53
56
  json (~> 1.4)
54
- rspec (3.1.0)
55
- rspec-core (~> 3.1.0)
56
- rspec-expectations (~> 3.1.0)
57
- rspec-mocks (~> 3.1.0)
58
- rspec-core (3.1.7)
59
- rspec-support (~> 3.1.0)
60
- rspec-expectations (3.1.2)
57
+ rspec (3.4.0)
58
+ rspec-core (~> 3.4.0)
59
+ rspec-expectations (~> 3.4.0)
60
+ rspec-mocks (~> 3.4.0)
61
+ rspec-core (3.4.2)
62
+ rspec-support (~> 3.4.0)
63
+ rspec-expectations (3.4.0)
61
64
  diff-lcs (>= 1.2.0, < 2.0)
62
- rspec-support (~> 3.1.0)
63
- rspec-mocks (3.1.3)
64
- rspec-support (~> 3.1.0)
65
- rspec-support (3.1.2)
65
+ rspec-support (~> 3.4.0)
66
+ rspec-mocks (3.4.1)
67
+ diff-lcs (>= 1.2.0, < 2.0)
68
+ rspec-support (~> 3.4.0)
69
+ rspec-support (3.4.1)
66
70
  safe_yaml (1.0.4)
67
- thread_safe (0.3.4)
68
- webmock (1.20.4)
71
+ thread_safe (0.3.5)
72
+ webmock (1.22.6)
69
73
  addressable (>= 2.3.6)
70
74
  crack (>= 0.3.2)
75
+ hashdiff
71
76
 
72
77
  PLATFORMS
73
78
  ruby
74
79
 
75
80
  DEPENDENCIES
81
+ byebug
76
82
  excon
77
83
  faraday
78
84
  faraday_middleware
@@ -83,4 +89,4 @@ DEPENDENCIES
83
89
  webmock
84
90
 
85
91
  BUNDLED WITH
86
- 1.10.3
92
+ 1.10.6
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # rally-wsapi
2
2
 
3
- Rally WSAPI client written in Ruby.
3
+ CA Agile Central (formerly Rally) WSAPI client written in Ruby.
4
4
 
5
5
  ## Usage
6
6
 
@@ -90,9 +90,21 @@ get_team_members(project_id, opts = {})
90
90
  get_editors(project_id, opts = {})
91
91
  ```
92
92
 
93
- ### Update any artifact with parameters hash
93
+ ### Update any object with parameters hash
94
+ This method replaces #update_artifact, which has been deprecated.
94
95
  ```
95
- update_artifact(artifact_type, artifact_id, parameters)
96
+ update(object_type, object_id, parameters)
97
+ ```
98
+
99
+ ### Create an object with a fields hash
100
+ ```
101
+ create(object_type, object_fields)
102
+ ```
103
+
104
+ ### Build a wsapi object url
105
+ This URL could be used when associating artifacts in the #create or #update methods
106
+ ```
107
+ build_object_url(object_type, object_id)
96
108
  ```
97
109
 
98
110
  ### Setup refresh token to be used with OAuth2
data/Rakefile CHANGED
@@ -2,11 +2,11 @@ require 'jeweler'
2
2
 
3
3
  Jeweler::Tasks.new do |s|
4
4
  s.name = "rally-wsapi"
5
- s.summary = "Simple client for Rally WSAPI"
6
- s.email = "antti@flowdock.com"
5
+ s.summary = "Simple client for CA Agile Central (formerly Rally) WSAPI"
6
+ s.email = "team@flowdock.com"
7
7
  s.homepage = "http://github.com/flowdock/rally-wsapi"
8
- s.description = "Simple client for Rally WSAPI"
9
- s.authors = ["Antti Pitkänen", "Oskari Virtanen"]
8
+ s.description = "Simple client for CA Agile Central (formerly Rally) WSAPI"
9
+ s.authors = ["CA Flowdock"]
10
10
  s.files = FileList["[A-Z]*", "{bin,generators,lib,test}/**/*"]
11
11
  s.licenses = ["MIT"]
12
12
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.1
1
+ 0.5.2
@@ -44,20 +44,37 @@ module Wsapi
44
44
  @conn = connection(session_id)
45
45
  end
46
46
 
47
- def setup_refresh_token(client_id, client_secret, refresh_token, &block)
48
- @oauth2 = {
49
- client_id: client_id,
50
- client_secret: client_secret,
51
- refresh_token: refresh_token,
52
- refresh_token_updated: block
53
- }
47
+ def build_object_url(type, id)
48
+ wsapi_resource_url("#{type}/#{id}").sub('userstory', 'hierarchicalrequirement')
54
49
  end
55
50
 
56
- def get_user_subscription
57
- response = wsapi_get(wsapi_resource_url("Subscription"))
51
+ def create(type, fields)
52
+ response = wsapi_request(:put, wsapi_resource_url("#{type}/create"), type => fields)
53
+ Mapper.get_object(response)
54
+ end
55
+
56
+ def get_current_user
57
+ response = wsapi_get(wsapi_resource_url("User"))
58
+ Mapper.get_object(response)
59
+ end
60
+
61
+ def get_editors(project_id, opts = {})
62
+ fetch_with_pages(opts) do |page_query|
63
+ wsapi_get(wsapi_resource_url("Project/#{project_id}/Editors"), opts.merge(page_query))
64
+ end
65
+ end
66
+
67
+ def get_project(id)
68
+ response = wsapi_get(wsapi_resource_url("Project/#{id}"))
58
69
  Mapper.get_object(response)
59
70
  end
60
71
 
72
+ def get_projects(opts = {})
73
+ fetch_with_pages(opts) do |page_query|
74
+ wsapi_get(wsapi_resource_url("Project"), opts.merge(page_query))
75
+ end
76
+ end
77
+
61
78
  def get_subscription(id)
62
79
  response = wsapi_get(wsapi_resource_url("Subscription/#{id}"))
63
80
  Mapper.get_object(response)
@@ -68,19 +85,24 @@ module Wsapi
68
85
  (Mapper.get_objects(response) ||[]).first
69
86
  end
70
87
 
71
- def get_projects(opts = {})
88
+ def get_team_members(project_id, opts = {})
72
89
  fetch_with_pages(opts) do |page_query|
73
- wsapi_get(wsapi_resource_url("Project"), opts.merge(page_query))
90
+ wsapi_get(wsapi_resource_url("Project/#{project_id}/TeamMembers"), opts.merge(page_query))
74
91
  end
75
92
  end
76
93
 
77
- def get_project(id)
78
- response = wsapi_get(wsapi_resource_url("Project/#{id}"))
94
+ def get_user(id)
95
+ response = wsapi_get(wsapi_resource_url("User/#{id}"))
79
96
  Mapper.get_object(response)
80
97
  end
81
98
 
82
- def get_current_user
83
- response = wsapi_get(wsapi_resource_url("User"))
99
+ def get_user_by_username(username)
100
+ response = wsapi_get(wsapi_resource_url("User"), query: "(UserName = \"#{username}\")", pagesize: 1)
101
+ (Mapper.get_objects(response) ||[]).first
102
+ end
103
+
104
+ def get_user_subscription
105
+ response = wsapi_get(wsapi_resource_url("Subscription"))
84
106
  Mapper.get_object(response)
85
107
  end
86
108
 
@@ -95,35 +117,37 @@ module Wsapi
95
117
  end
96
118
  end
97
119
 
98
- def get_user(id)
99
- response = wsapi_get(wsapi_resource_url("User/#{id}"))
100
- Mapper.get_object(response)
101
- end
102
-
103
- def get_user_by_username(username)
104
- response = wsapi_get(wsapi_resource_url("User"), query: "(UserName = \"#{username}\")", pagesize: 1)
105
- (Mapper.get_objects(response) ||[]).first
106
- end
107
-
108
- def get_team_members(project_id, opts = {})
109
- fetch_with_pages(opts) do |page_query|
110
- wsapi_get(wsapi_resource_url("Project/#{project_id}/TeamMembers"), opts.merge(page_query))
111
- end
120
+ def setup_refresh_token(client_id, client_secret, refresh_token, &block)
121
+ @oauth2 = {
122
+ client_id: client_id,
123
+ client_secret: client_secret,
124
+ refresh_token: refresh_token,
125
+ refresh_token_updated: block
126
+ }
112
127
  end
113
128
 
114
- def get_editors(project_id, opts = {})
115
- fetch_with_pages(opts) do |page_query|
116
- wsapi_get(wsapi_resource_url("Project/#{project_id}/Editors"), opts.merge(page_query))
117
- end
129
+ def update(type, id, update_hash)
130
+ response = wsapi_request(:post, wsapi_resource_url("#{type}/#{id}"), type => update_hash)
131
+ Mapper.get_object(response)
118
132
  end
119
133
 
134
+ # This method is deprecated and will be removed in a future release.
120
135
  def update_artifact(type, id, update_hash)
121
- response = wsapi_post(wsapi_resource_url("#{type}/#{id}"), "#{type}" => update_hash)
122
- Mapper.get_object(response)
136
+ puts "WsapiAuthentication::Session#update_artifact has been deprecated. Please use #update instead."
137
+ update(type, id, update_hash)
123
138
  end
124
139
 
125
140
  private
126
141
 
142
+ def check_response_for_errors!(response)
143
+ raise BadRequestError.new("Bad request", response) if response.status == 400
144
+ raise AuthorizationError.new("Unauthorized", response) if response.status == 401 || response.status == 403
145
+ raise ApiError.new("Internal server error", response) if response.status == 500
146
+ raise ApiError.new("Service unavailable", response) if response.status == 503
147
+ raise ObjectNotFoundError.new("Object not found") if object_not_found?(response)
148
+ raise IpAddressLimited.new("IP Address limited", response) if ip_address_limited?(response)
149
+ end
150
+
127
151
  def connection(session_id)
128
152
  Faraday.new(ssl: {version: :TLSv1}) do |faraday|
129
153
  faraday.request :json
@@ -132,48 +156,38 @@ module Wsapi
132
156
  end
133
157
  end
134
158
 
135
- def workspace_url
136
- wsapi_resource_url("Workspace/#{@workspace_id}")
137
- end
138
-
139
- def wsapi_resource_url(resource)
140
- File.join(WSAPI_URL, "v#{@api_version}", resource)
141
- end
142
-
143
- def wsapi_post(url, opts = {})
144
- response = wsapi_request_with_refresh_token(:post, url, opts)
145
- check_response_for_errors!(response)
146
-
147
- response
159
+ def fetch_with_pages(opts = {}, &block)
160
+ page_query = {
161
+ start: opts[:start] || 1,
162
+ pagesize: opts[:pagesize] || 100
163
+ }
164
+ resultCount = nil
165
+ objects = []
166
+ while(!resultCount || resultCount > objects.size) do
167
+ response = yield(page_query)
168
+ resultCount = MultiJson.load(response.body)["QueryResult"]["TotalResultCount"]
169
+ objects += Mapper.get_objects(response)
170
+ page_query[:start] += page_query[:pagesize]
171
+ end
172
+ objects
148
173
  end
149
174
 
150
- def wsapi_get(url, opts = {})
151
- request_options = {}
152
- request_options['workspace'] = workspace_url if @workspace_id
153
- request_options['query'] = opts[:query] if opts[:query]
154
- request_options['start'] = opts[:start] || 1
155
- request_options['pagesize'] = opts[:pagesize] || 200
156
- request_options['fetch'] = opts[:fetch] || true # by default, fetch full objects
157
-
158
- response = wsapi_request_with_refresh_token(:get, url, request_options)
159
- check_response_for_errors!(response)
160
-
161
- response
175
+ def ip_address_limited?(response)
176
+ limit_message = /Your IP address, (?:\d+\.?)+, is not within the allowed range that your subscription administrator has configured./
177
+ response.status > 401 && response.body.match(limit_message)
162
178
  end
163
179
 
164
- def wsapi_request_with_refresh_token(method, url, opts = {})
165
- response = @conn.send(method, url, opts) { |req| req.options.timeout = @timeout }
166
- if defined?(@oauth2) && response.status == 401
167
- refresh_token_response = refresh_token!
168
-
169
- access_token = MultiJson.load(refresh_token_response.body)["access_token"]
170
- @conn = connection(access_token)
171
- response = @conn.send(method, url, opts) { |req| req.options.timeout = @timeout } # Try again with fresh token
180
+ def object_not_found?(response)
181
+ if response.status == 200
182
+ result = MultiJson.load(response.body)["OperationResult"]
183
+ if result && error = result["Errors"].first
184
+ error.match("Cannot find object to read")
185
+ else
186
+ false
187
+ end
188
+ else
189
+ false
172
190
  end
173
-
174
- response
175
- rescue Faraday::TimeoutError
176
- raise TimeoutError.new("Request timed out")
177
191
  end
178
192
 
179
193
  def refresh_token!
@@ -202,47 +216,38 @@ module Wsapi
202
216
  response
203
217
  end
204
218
 
205
- def check_response_for_errors!(response)
206
- raise BadRequestError.new("Bad request", response) if response.status == 400
207
- raise AuthorizationError.new("Unauthorized", response) if response.status == 401 || response.status == 403
208
- raise ApiError.new("Internal server error", response) if response.status == 500
209
- raise ApiError.new("Service unavailable", response) if response.status == 503
210
- raise ObjectNotFoundError.new("Object not found") if object_not_found?(response)
211
- raise IpAddressLimited.new("IP Address limited", response) if ip_address_limited?(response)
219
+ def workspace_url
220
+ wsapi_resource_url("Workspace/#{@workspace_id}")
212
221
  end
213
222
 
214
- def ip_address_limited?(response)
215
- limit_message = /Your IP address, (?:\d+\.?)+, is not within the allowed range that your subscription administrator has configured./
216
- response.status > 401 && response.body.match(limit_message)
223
+ def wsapi_resource_url(resource)
224
+ File.join(WSAPI_URL, "v#{@api_version}", resource)
217
225
  end
226
+
227
+ def wsapi_get(url, opts = {})
228
+ request_options = {}
229
+ request_options['workspace'] = workspace_url if @workspace_id
230
+ request_options['query'] = opts[:query] if opts[:query]
231
+ request_options['start'] = opts[:start] || 1
232
+ request_options['pagesize'] = opts[:pagesize] || 200
233
+ request_options['fetch'] = opts[:fetch] || true # by default, fetch full objects
218
234
 
219
- def object_not_found?(response)
220
- if response.status == 200
221
- result = MultiJson.load(response.body)["OperationResult"]
222
- if result && error = result["Errors"].first
223
- error.match("Cannot find object to read")
224
- else
225
- false
226
- end
227
- else
228
- false
229
- end
235
+ wsapi_request(:get, url, request_options)
230
236
  end
231
237
 
232
- def fetch_with_pages(opts = {}, &block)
233
- page_query = {
234
- start: opts[:start] || 1,
235
- pagesize: opts[:pagesize] || 100
236
- }
237
- resultCount = nil
238
- objects = []
239
- while(!resultCount || resultCount > objects.size) do
240
- response = yield(page_query)
241
- resultCount = MultiJson.load(response.body)["QueryResult"]["TotalResultCount"]
242
- objects += Mapper.get_objects(response)
243
- page_query[:start] += page_query[:pagesize]
238
+ def wsapi_request(method, url, opts = {})
239
+ response = @conn.send(method, url, opts) { |req| req.options.timeout = @timeout }
240
+ if defined?(@oauth2) && response.status == 401
241
+ refresh_token_response = refresh_token!
242
+
243
+ access_token = MultiJson.load(refresh_token_response.body)["access_token"]
244
+ @conn = connection(access_token)
245
+ response = @conn.send(method, url, opts) { |req| req.options.timeout = @timeout } # Try again with fresh token
244
246
  end
245
- objects
247
+ check_response_for_errors!(response)
248
+ response
249
+ rescue Faraday::TimeoutError
250
+ raise TimeoutError.new("Request timed out")
246
251
  end
247
252
  end
248
253
  end
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rally-wsapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
- - Antti Pitkänen
8
- - Oskari Virtanen
7
+ - CA Flowdock
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2015-06-09 00:00:00.000000000 Z
11
+ date: 2017-06-16 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rake
@@ -81,8 +80,8 @@ dependencies:
81
80
  - - ">="
82
81
  - !ruby/object:Gem::Version
83
82
  version: '0'
84
- description: Simple client for Rally WSAPI
85
- email: antti@flowdock.com
83
+ description: Simple client for CA Agile Central (formerly Rally) WSAPI
84
+ email: team@flowdock.com
86
85
  executables: []
87
86
  extensions: []
88
87
  extra_rdoc_files:
@@ -122,8 +121,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
121
  version: '0'
123
122
  requirements: []
124
123
  rubyforge_project:
125
- rubygems_version: 2.4.5
124
+ rubygems_version: 2.6.8
126
125
  signing_key:
127
126
  specification_version: 4
128
- summary: Simple client for Rally WSAPI
127
+ summary: Simple client for CA Agile Central (formerly Rally) WSAPI
129
128
  test_files: []