tracker_api 1.8.0 → 1.12.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/.travis.yml +2 -1
- data/README.md +4 -0
- data/lib/tracker_api.rb +12 -0
- data/lib/tracker_api/client.rb +8 -6
- data/lib/tracker_api/endpoints/blockers.rb +20 -0
- data/lib/tracker_api/endpoints/iteration.rb +35 -0
- data/lib/tracker_api/endpoints/release.rb +17 -0
- data/lib/tracker_api/endpoints/releases.rb +20 -0
- data/lib/tracker_api/endpoints/review.rb +21 -0
- data/lib/tracker_api/endpoints/reviews.rb +21 -0
- data/lib/tracker_api/endpoints/search.rb +1 -1
- data/lib/tracker_api/endpoints/stories.rb +10 -0
- data/lib/tracker_api/error.rb +12 -2
- data/lib/tracker_api/resources/blocker.rb +18 -0
- data/lib/tracker_api/resources/cycle_time_details.rb +21 -0
- data/lib/tracker_api/resources/daily_history_container.rb +13 -0
- data/lib/tracker_api/resources/iteration.rb +14 -0
- data/lib/tracker_api/resources/project.rb +13 -0
- data/lib/tracker_api/resources/release.rb +29 -0
- data/lib/tracker_api/resources/review.rb +35 -0
- data/lib/tracker_api/resources/review_type.rb +15 -0
- data/lib/tracker_api/resources/story.rb +26 -0
- data/lib/tracker_api/version.rb +1 -1
- data/test/client_test.rb +52 -52
- data/test/comment_test.rb +13 -13
- data/test/error_test.rb +8 -2
- data/test/file_attachment_test.rb +4 -4
- data/test/iteration_test.rb +31 -0
- data/test/minitest_helper.rb +5 -2
- data/test/project_test.rb +59 -47
- data/test/release_test.rb +22 -0
- data/test/review_test.rb +27 -0
- data/test/story_test.rb +65 -48
- data/test/task_test.rb +3 -3
- data/test/vcr/cassettes/create_attachments.json +1 -1
- data/test/vcr/cassettes/create_comment_with_attachment.json +1 -1
- data/test/vcr/cassettes/delete_an_attachment.json +1 -1
- data/test/vcr/cassettes/delete_attachments.json +1 -1
- data/test/vcr/cassettes/get_current_iteration.json +1 -1
- data/test/vcr/cassettes/get_cycle_time_details.json +1 -0
- data/test/vcr/cassettes/get_daily_history_container.json +1 -0
- data/test/vcr/cassettes/get_releases.json +1 -0
- data/test/vcr/cassettes/get_story_reviews.json +1 -0
- data/test/vcr/cassettes/release_stories.json +1 -0
- data/test/vcr/cassettes/save_review.json +1 -0
- data/test/vcr/cassettes/search_project.json +1 -1
- data/test/workspace_test.rb +5 -5
- data/tracker_api.gemspec +1 -1
- metadata +35 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7d0c3f349c8d57bc33c44401068ae359892d33a8d8ed2c5c20ed96110fe02b3b
|
4
|
+
data.tar.gz: adac66edc9ddf17883734c6908b1cce46cbac8b932702a7c3f31573b0ad38b13
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea30f0006b6dff8684c3d46381d65ddfc00d3a481fbcea3489f844c7bb2c687b065e618114af8cd4392c63d770fcf1ad1ea86aad1305a5c8fca4f95ba58d7150
|
7
|
+
data.tar.gz: e67ea8cd72e9947862bdd58230aecea038e311a14ecb081f65545003f2fb3d7924c680c55a4d34a1711492f9509a2da6c368d1c93689c7b9f92f2a91e8faf267
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -86,6 +86,10 @@ task = story.tasks.first # Get
|
|
86
86
|
task.complete = true
|
87
87
|
task.save # Mark a task complete
|
88
88
|
|
89
|
+
review = story.reviews.first # Mark a review as complete
|
90
|
+
review.status = 'pass'
|
91
|
+
review.save
|
92
|
+
|
89
93
|
epics = project.epics # Get all epics for a project
|
90
94
|
epic = epics.first
|
91
95
|
label = epic.label # Get an epic's label
|
data/lib/tracker_api.rb
CHANGED
@@ -38,8 +38,10 @@ module TrackerApi
|
|
38
38
|
|
39
39
|
module Endpoints
|
40
40
|
autoload :Activity, 'tracker_api/endpoints/activity'
|
41
|
+
autoload :Blockers, 'tracker_api/endpoints/blockers'
|
41
42
|
autoload :Epic, 'tracker_api/endpoints/epic'
|
42
43
|
autoload :Epics, 'tracker_api/endpoints/epics'
|
44
|
+
autoload :Iteration, 'tracker_api/endpoints/iteration'
|
43
45
|
autoload :Iterations, 'tracker_api/endpoints/iterations'
|
44
46
|
autoload :Labels, 'tracker_api/endpoints/labels'
|
45
47
|
autoload :Me, 'tracker_api/endpoints/me'
|
@@ -62,6 +64,10 @@ module TrackerApi
|
|
62
64
|
autoload :StoryTransitions, 'tracker_api/endpoints/story_transitions'
|
63
65
|
autoload :Attachment, 'tracker_api/endpoints/attachment'
|
64
66
|
autoload :Attachments, 'tracker_api/endpoints/attachments'
|
67
|
+
autoload :Releases, 'tracker_api/endpoints/releases'
|
68
|
+
autoload :Release, 'tracker_api/endpoints/release'
|
69
|
+
autoload :Review, 'tracker_api/endpoints/review'
|
70
|
+
autoload :Reviews, 'tracker_api/endpoints/reviews'
|
65
71
|
end
|
66
72
|
|
67
73
|
module Resources
|
@@ -71,6 +77,7 @@ module TrackerApi
|
|
71
77
|
end
|
72
78
|
autoload :Activity, 'tracker_api/resources/activity'
|
73
79
|
autoload :Account, 'tracker_api/resources/account'
|
80
|
+
autoload :Blocker, 'tracker_api/resources/blocker'
|
74
81
|
autoload :Change, 'tracker_api/resources/change'
|
75
82
|
autoload :Epic, 'tracker_api/resources/epic'
|
76
83
|
autoload :EpicsSearchResult, 'tracker_api/resources/epics_search_result'
|
@@ -93,5 +100,10 @@ module TrackerApi
|
|
93
100
|
autoload :Webhook, 'tracker_api/resources/webhook'
|
94
101
|
autoload :StoryTransition, 'tracker_api/resources/story_transition'
|
95
102
|
autoload :FileAttachment, 'tracker_api/resources/file_attachment'
|
103
|
+
autoload :Release, 'tracker_api/resources/release'
|
104
|
+
autoload :CycleTimeDetails, 'tracker_api/resources/cycle_time_details'
|
105
|
+
autoload :DailyHistoryContainer, 'tracker_api/resources/daily_history_container'
|
106
|
+
autoload :Review, 'tracker_api/resources/review'
|
107
|
+
autoload :ReviewType, 'tracker_api/resources/review_type'
|
96
108
|
end
|
97
109
|
end
|
data/lib/tracker_api/client.rb
CHANGED
@@ -25,7 +25,7 @@ module TrackerApi
|
|
25
25
|
@url = Addressable::URI.parse(url).to_s
|
26
26
|
@api_version = options.fetch(:api_version, '/services/v5')
|
27
27
|
@logger = options.fetch(:logger, ::Logger.new(nil))
|
28
|
-
adapter = options.fetch(:adapter
|
28
|
+
adapter = options.fetch(:adapter) { defined?(JRUBY_VERSION) ? :net_http : :excon }
|
29
29
|
connection_options = options.fetch(:connection_options, { ssl: { verify: true } })
|
30
30
|
@auto_paginate = options.fetch(:auto_paginate, true)
|
31
31
|
@token = options[:token]
|
@@ -36,7 +36,7 @@ module TrackerApi
|
|
36
36
|
@connection = Faraday.new({ url: @url }.merge(connection_options)) do |builder|
|
37
37
|
# response
|
38
38
|
builder.use Faraday::Response::RaiseError
|
39
|
-
builder.response :json
|
39
|
+
builder.response :json, content_type: /\bjson/ # e.g., 'application/json; charset=utf-8'
|
40
40
|
|
41
41
|
# request
|
42
42
|
builder.request :multipart
|
@@ -190,7 +190,8 @@ module TrackerApi
|
|
190
190
|
opts[:params] = options[:params] || {}
|
191
191
|
opts[:token] = options[:token] || @token
|
192
192
|
headers = { 'User-Agent' => USER_AGENT,
|
193
|
-
'X-TrackerToken' => opts.fetch(:token)
|
193
|
+
'X-TrackerToken' => opts.fetch(:token),
|
194
|
+
'Accept' => 'application/json' }.merge(options.fetch(:headers, {}))
|
194
195
|
|
195
196
|
CONVENIENCE_HEADERS.each do |h|
|
196
197
|
if header = options[h]
|
@@ -222,11 +223,12 @@ module TrackerApi
|
|
222
223
|
req.body = body
|
223
224
|
end
|
224
225
|
response
|
225
|
-
rescue Faraday::
|
226
|
-
|
226
|
+
rescue Faraday::ClientError, Faraday::ServerError => e
|
227
|
+
status_code = e.response[:status]
|
228
|
+
case status_code
|
227
229
|
when 400..499 then raise TrackerApi::Errors::ClientError.new(e)
|
228
230
|
when 500..599 then raise TrackerApi::Errors::ServerError.new(e)
|
229
|
-
else raise "Expected 4xx or 5xx HTTP status code"
|
231
|
+
else raise "Expected 4xx or 5xx HTTP status code; got #{status_code} instead."
|
230
232
|
end
|
231
233
|
end
|
232
234
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module TrackerApi
|
2
|
+
module Endpoints
|
3
|
+
class Blockers
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def get(project_id, story_id, params = {})
|
11
|
+
data = client.get("/projects/#{project_id}/stories/#{story_id}/blockers", params: params).body
|
12
|
+
raise Errors::UnexpectedData, 'Array of Blockers expected' unless data.is_a? Array
|
13
|
+
|
14
|
+
data.map do |blocker|
|
15
|
+
Resources::Blocker.new({ client: client, project_id: project_id }.merge(blocker))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module TrackerApi
|
2
|
+
module Endpoints
|
3
|
+
class Iteration
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def get(project_id, iteration_number)
|
11
|
+
data = client.get("/projects/#{project_id}/iterations/#{iteration_number}").body
|
12
|
+
|
13
|
+
Resources::Iteration.new({ client: client, project_id: project_id }.merge(data))
|
14
|
+
end
|
15
|
+
|
16
|
+
def get_analytics_cycle_time_details(project_id, iteration_number)
|
17
|
+
data = client.paginate("/projects/#{project_id}/iterations/#{iteration_number}/analytics/cycle_time_details")
|
18
|
+
raise Errors::UnexpectedData, 'Array of cycle time details expected' unless data.is_a? Array
|
19
|
+
|
20
|
+
data.map do |cycle_time_details|
|
21
|
+
Resources::CycleTimeDetails.new(
|
22
|
+
{ project_id: project_id, iteration_number: iteration_number }.merge(cycle_time_details)
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_history(project_id, iteration_number)
|
28
|
+
data = client.get("/projects/#{project_id}/history/iterations/#{iteration_number}/days").body
|
29
|
+
raise Errors::UnexpectedData, 'Hash of history data expected' unless data.is_a? Hash
|
30
|
+
|
31
|
+
Resources::DailyHistoryContainer.new({ project_id: project_id, iteration_number: iteration_number }.merge(data))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module TrackerApi
|
2
|
+
module Endpoints
|
3
|
+
class Release
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def get(project_id, id, params={})
|
11
|
+
data = client.get("/projects/#{project_id}/releases/#{id}", params: params).body
|
12
|
+
|
13
|
+
Resources::Release.new({ client: client }.merge(data))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module TrackerApi
|
2
|
+
module Endpoints
|
3
|
+
class Releases
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def get(project_id, params={})
|
11
|
+
data = client.paginate("/projects/#{project_id}/releases", params: params)
|
12
|
+
raise Errors::UnexpectedData, 'Array of releases expected' unless data.is_a? Array
|
13
|
+
|
14
|
+
data.map do |release|
|
15
|
+
Resources::Release.new({ client: client, project_id: project_id }.merge(release))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module TrackerApi
|
2
|
+
module Endpoints
|
3
|
+
class Review
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def update(review, params = {})
|
11
|
+
raise ArgumentError, 'Valid review required to update.' unless review.instance_of?(Resources::Review)
|
12
|
+
|
13
|
+
data = client.put("/projects/#{review.project_id}/stories/#{review.story_id}/reviews/#{review.id}", params: params).body
|
14
|
+
|
15
|
+
review.attributes = data
|
16
|
+
review.clean!
|
17
|
+
review
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module TrackerApi
|
2
|
+
module Endpoints
|
3
|
+
class Reviews
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def get(project_id, story_id, params={})
|
11
|
+
params[:fields] ||= ":default,review_type"
|
12
|
+
data = client.paginate("/projects/#{project_id}/stories/#{story_id}/reviews", params: params)
|
13
|
+
raise Errors::UnexpectedData, 'Successful responses to this request return an array containing zero or more instances of the review resource. This response was not an array.' unless data.is_a? Array
|
14
|
+
|
15
|
+
data.map do |review|
|
16
|
+
Resources::Review.new({ client: client, project_id: project_id }.merge(review))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -10,7 +10,7 @@ module TrackerApi
|
|
10
10
|
def get(project_id, query, options={})
|
11
11
|
raise ArgumentError, 'Valid query string required to search' unless query.is_a?(String)
|
12
12
|
|
13
|
-
options
|
13
|
+
options[:params] = { query: query }
|
14
14
|
data = client.get("/projects/#{project_id}/search", options).body
|
15
15
|
|
16
16
|
raise Errors::UnexpectedData, 'Hash of search results expect' unless data.is_a? Hash
|
@@ -17,6 +17,16 @@ module TrackerApi
|
|
17
17
|
Resources::Story.new({ client: client, project_id: project_id }.merge(story))
|
18
18
|
end
|
19
19
|
end
|
20
|
+
|
21
|
+
def get_release(project_id, release_id, params={})
|
22
|
+
data = client.paginate("/projects/#{project_id}/releases/#{release_id}/stories", params: params)
|
23
|
+
|
24
|
+
raise Errors::UnexpectedData, 'Array of stories expected' unless data.is_a? Array
|
25
|
+
|
26
|
+
data.map do |story|
|
27
|
+
Resources::Story.new({ client: client, project_id: project_id }.merge(story))
|
28
|
+
end
|
29
|
+
end
|
20
30
|
end
|
21
31
|
end
|
22
32
|
end
|
data/lib/tracker_api/error.rb
CHANGED
@@ -5,14 +5,24 @@ module TrackerApi
|
|
5
5
|
def initialize(wrapped_exception)
|
6
6
|
@wrapped_exception = wrapped_exception
|
7
7
|
@response = wrapped_exception.response
|
8
|
-
message = if wrapped_exception.is_a?(Faraday::
|
8
|
+
message = if wrapped_exception.is_a?(Faraday::ParsingError)
|
9
9
|
wrapped_exception.message
|
10
|
-
elsif
|
10
|
+
elsif faraday_response_error?(wrapped_exception)
|
11
11
|
wrapped_exception.response.inspect
|
12
12
|
else
|
13
13
|
wrapped_exception.instance_variable_get(:@wrapped_exception).inspect
|
14
14
|
end
|
15
15
|
super(message)
|
16
16
|
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
# faraday 16.0 re-organized their errors. The errors we're interested in,
|
21
|
+
# Faraday::ClientError before 16.0 and Faraday::ServerError introduced in
|
22
|
+
# 16.0, are represented by this conditional.
|
23
|
+
def faraday_response_error?(wrapped_exception)
|
24
|
+
wrapped_exception.is_a?(Faraday::Error) &&
|
25
|
+
wrapped_exception.respond_to?(:response)
|
26
|
+
end
|
17
27
|
end
|
18
28
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module TrackerApi
|
2
|
+
module Resources
|
3
|
+
class Blocker
|
4
|
+
include Shared::Base
|
5
|
+
|
6
|
+
attribute :client
|
7
|
+
attribute :project_id, Integer
|
8
|
+
|
9
|
+
attribute :story_id, Integer
|
10
|
+
attribute :person_id, Integer
|
11
|
+
attribute :description, String
|
12
|
+
attribute :resolved, Boolean
|
13
|
+
attribute :created_at, DateTime
|
14
|
+
attribute :updated_at, DateTime
|
15
|
+
attribute :kind, String
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module TrackerApi
|
2
|
+
module Resources
|
3
|
+
class CycleTimeDetails
|
4
|
+
include Shared::Base
|
5
|
+
|
6
|
+
attribute :project_id, Integer
|
7
|
+
attribute :iteration_number, Integer
|
8
|
+
attribute :total_cycle_time, Integer
|
9
|
+
attribute :started_time, Integer
|
10
|
+
attribute :started_count, Integer
|
11
|
+
attribute :finished_time, Integer
|
12
|
+
attribute :finished_count, Integer
|
13
|
+
attribute :delivered_time, Integer
|
14
|
+
attribute :delivered_count, Integer
|
15
|
+
attribute :rejected_time, Integer
|
16
|
+
attribute :rejected_count, Integer
|
17
|
+
attribute :story_id, Integer
|
18
|
+
attribute :kind, String
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module TrackerApi
|
2
|
+
module Resources
|
3
|
+
class DailyHistoryContainer
|
4
|
+
include Shared::Base
|
5
|
+
|
6
|
+
attribute :project_id, Integer
|
7
|
+
attribute :iteration_number, Integer
|
8
|
+
attribute :header, [String]
|
9
|
+
attribute :data, [Enumerable]
|
10
|
+
attribute :kind, String
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -24,6 +24,20 @@ module TrackerApi
|
|
24
24
|
def stories=(data)
|
25
25
|
super.each { |s| s.client = client }
|
26
26
|
end
|
27
|
+
|
28
|
+
# Provides a list of all the cycle_time_details of each story in the iteration.
|
29
|
+
#
|
30
|
+
# @return [Array[CycleTimeDetails]] array of cycle_time_details of iterations in this project
|
31
|
+
def cycle_time_details
|
32
|
+
Endpoints::Iteration.new(client).get_analytics_cycle_time_details(project_id, number)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns per day information of story points and counts by state for the given iteration.
|
36
|
+
#
|
37
|
+
# @return [DailyHistoryContainer]
|
38
|
+
def get_history
|
39
|
+
Endpoints::Iteration.new(client).get_history(project_id, number)
|
40
|
+
end
|
27
41
|
end
|
28
42
|
end
|
29
43
|
end
|
@@ -131,6 +131,19 @@ module TrackerApi
|
|
131
131
|
Endpoints::Stories.new(client).get(id, params)
|
132
132
|
end
|
133
133
|
|
134
|
+
# Provides a list of all the releases in the project.
|
135
|
+
#
|
136
|
+
# @param [Hash] params
|
137
|
+
# @option params [String] :with_state A release's current_state which all returned releases must match.
|
138
|
+
# Valid enumeration values: accepted, delivered, finished, started, rejected, unstarted, unscheduled
|
139
|
+
# @option params [Integer] :offset With the first release in your priority list as 0,
|
140
|
+
# the index of the first release you want returned.
|
141
|
+
# @option params [Integer] :limit The number of releases you want returned.
|
142
|
+
# @return [Array[Release]] releases associated with this project
|
143
|
+
def releases(params={})
|
144
|
+
Endpoints::Releases.new(client).get(id, params)
|
145
|
+
end
|
146
|
+
|
134
147
|
# Provides a list of all the memberships in the project.
|
135
148
|
#
|
136
149
|
# @param [Hash] params
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module TrackerApi
|
2
|
+
module Resources
|
3
|
+
class Release
|
4
|
+
include Shared::Base
|
5
|
+
|
6
|
+
attribute :client
|
7
|
+
|
8
|
+
attribute :project_id, Integer
|
9
|
+
attribute :name, String
|
10
|
+
attribute :description, String
|
11
|
+
attribute :current_state, String # (accepted, delivered, finished, started, rejected, planned, unstarted, unscheduled)
|
12
|
+
attribute :accepted_at, DateTime
|
13
|
+
attribute :deadline, DateTime
|
14
|
+
attribute :labels, [Label]
|
15
|
+
attribute :created_at, DateTime
|
16
|
+
attribute :updated_at, DateTime
|
17
|
+
attribute :url, String
|
18
|
+
attribute :kind, String
|
19
|
+
|
20
|
+
# Provides a list of all the stories in the release.
|
21
|
+
#
|
22
|
+
# @param [Hash] params
|
23
|
+
# @return [Array[Story]] stories of this release
|
24
|
+
def stories(params={})
|
25
|
+
Endpoints::Stories.new(client).get_release(project_id, id, params)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|