pivotal-api 0.3.1
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 +7 -0
- data/lib/pivotal-api.rb +51 -0
- data/lib/pivotal_api/client.rb +218 -0
- data/lib/pivotal_api/endpoints/comments.rb +42 -0
- data/lib/pivotal_api/endpoints/epics.rb +26 -0
- data/lib/pivotal_api/endpoints/iterations.rb +20 -0
- data/lib/pivotal_api/endpoints/labels.rb +36 -0
- data/lib/pivotal_api/endpoints/memberships.rb +26 -0
- data/lib/pivotal_api/endpoints/projects.rb +50 -0
- data/lib/pivotal_api/endpoints/stories.rb +54 -0
- data/lib/pivotal_api/endpoints/tasks.rb +26 -0
- data/lib/pivotal_api/endpoints/webhooks.rb +42 -0
- data/lib/pivotal_api/error.rb +18 -0
- data/lib/pivotal_api/logger.rb +31 -0
- data/lib/pivotal_api/resources/account.rb +18 -0
- data/lib/pivotal_api/resources/comment.rb +20 -0
- data/lib/pivotal_api/resources/epic.rb +19 -0
- data/lib/pivotal_api/resources/iteration.rb +20 -0
- data/lib/pivotal_api/resources/label.rb +14 -0
- data/lib/pivotal_api/resources/me.rb +23 -0
- data/lib/pivotal_api/resources/membership_summary.rb +17 -0
- data/lib/pivotal_api/resources/person.rb +16 -0
- data/lib/pivotal_api/resources/project.rb +49 -0
- data/lib/pivotal_api/resources/project_membership.rb +18 -0
- data/lib/pivotal_api/resources/story.rb +41 -0
- data/lib/pivotal_api/resources/task.rb +19 -0
- data/lib/pivotal_api/resources/time_zone.rb +13 -0
- data/lib/pivotal_api/resources/webhook.rb +16 -0
- data/lib/pivotal_api/version.rb +3 -0
- metadata +171 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f8eb153b9cf748c9d9d0f2ecbdeec3ef341963f1
|
4
|
+
data.tar.gz: 02383e644883c0bf292e1cfb5e58bfc223c2c58b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 32dd22449130691138f408a00626ef3a0826903b23f2a5017583619a4f8d7f06adc831f3d30abd2db08e41b2d0fb553ae4d389bd720bd49e42ee3aed1b0fce9d
|
7
|
+
data.tar.gz: 03716a31c4bf552241b0c3940db729483843662efb31d33461a4d57d52b4dbef6f8b3e6501ec600c4046c2b6f064be5f7ef12be95b532992305c9a9e769d76f7
|
data/lib/pivotal-api.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative './pivotal_api/version.rb'
|
2
|
+
|
3
|
+
# dependencies
|
4
|
+
require 'virtus'
|
5
|
+
require 'faraday'
|
6
|
+
require 'faraday_middleware'
|
7
|
+
|
8
|
+
# stdlib
|
9
|
+
require 'addressable/uri'
|
10
|
+
require 'forwardable'
|
11
|
+
require 'logger'
|
12
|
+
|
13
|
+
module PivotalApi
|
14
|
+
autoload :Error, 'pivotal_api/error'
|
15
|
+
autoload :Client, 'pivotal_api/client'
|
16
|
+
autoload :Logger, 'pivotal_api/logger'
|
17
|
+
|
18
|
+
module Errors
|
19
|
+
class UnexpectedData < StandardError; end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Endpoints
|
23
|
+
autoload :Comments, 'pivotal_api/endpoints/comments'
|
24
|
+
autoload :Epics, 'pivotal_api/endpoints/epics'
|
25
|
+
autoload :Iterations, 'pivotal_api/endpoints/iterations'
|
26
|
+
autoload :Labels, 'pivotal_api/endpoints/labels'
|
27
|
+
autoload :Me, 'pivotal_api/endpoints/me'
|
28
|
+
autoload :Memberships, 'pivotal_api/endpoints/memberships'
|
29
|
+
autoload :Projects, 'pivotal_api/endpoints/projects'
|
30
|
+
autoload :Stories, 'pivotal_api/endpoints/stories'
|
31
|
+
autoload :Tasks, 'pivotal_api/endpoints/tasks'
|
32
|
+
autoload :Webhooks, 'pivotal_api/endpoints/webhooks'
|
33
|
+
end
|
34
|
+
|
35
|
+
module Resources
|
36
|
+
autoload :Account, 'pivotal_api/resources/account'
|
37
|
+
autoload :Comment, 'pivotal_api/resources/comment'
|
38
|
+
autoload :Epic, 'pivotal_api/resources/epic'
|
39
|
+
autoload :Iteration, 'pivotal_api/resources/iteration'
|
40
|
+
autoload :Me, 'pivotal_api/resources/me'
|
41
|
+
autoload :MembershipSummary, 'pivotal_api/resources/membership_summary'
|
42
|
+
autoload :Label, 'pivotal_api/resources/label'
|
43
|
+
autoload :Person, 'pivotal_api/resources/person'
|
44
|
+
autoload :Project, 'pivotal_api/resources/project'
|
45
|
+
autoload :ProjectMembership, 'pivotal_api/resources/project_membership'
|
46
|
+
autoload :Story, 'pivotal_api/resources/story'
|
47
|
+
autoload :Task, 'pivotal_api/resources/task'
|
48
|
+
autoload :TimeZone, 'pivotal_api/resources/time_zone'
|
49
|
+
autoload :Webhook, 'pivotal_api/resources/webhook'
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
class Client
|
3
|
+
USER_AGENT = "Ruby/#{RUBY_VERSION} (#{RUBY_PLATFORM}; #{RUBY_ENGINE}) PivotalApi/#{PivotalApi::VERSION} Faraday/#{Faraday::VERSION}".freeze
|
4
|
+
|
5
|
+
# Header keys that can be passed in options hash to {#get},{#paginate}
|
6
|
+
CONVENIENCE_HEADERS = Set.new([:accept, :content_type])
|
7
|
+
|
8
|
+
attr_reader :url, :api_version, :token, :logger, :connection, :auto_paginate, :last_response
|
9
|
+
|
10
|
+
# Create Pivotal Tracker API client.
|
11
|
+
#
|
12
|
+
# @param [Hash] options the connection options
|
13
|
+
# @option options [String] :token API token to use for requests
|
14
|
+
# @option options [String] :url Main HTTP API root
|
15
|
+
# @option options [Boolean] :auto_paginate Client should perform pagination automatically. Default true.
|
16
|
+
# @option options [String] :api_version The API version URL path
|
17
|
+
# @option options [String] :logger Custom logger
|
18
|
+
# @option options [String] :adapter Custom http adapter to configure Faraday with
|
19
|
+
# @option options [String] :connection_options Connection options to pass to Faraday
|
20
|
+
#
|
21
|
+
# @example Creating a Client
|
22
|
+
# Client.new token: 'my-super-special-token'
|
23
|
+
def initialize(options={})
|
24
|
+
url = options.fetch(:url, 'https://www.pivotaltracker.com')
|
25
|
+
@url = Addressable::URI.parse(url).to_s
|
26
|
+
@api_version = options.fetch(:api_version, '/services/v5')
|
27
|
+
@logger = options.fetch(:logger, ::Logger.new(nil))
|
28
|
+
adapter = options.fetch(:adapter, :excon)
|
29
|
+
connection_options = options.fetch(:connection_options, { ssl: { verify: true } })
|
30
|
+
@auto_paginate = options.fetch(:auto_paginate, true)
|
31
|
+
@token = options[:token]
|
32
|
+
raise 'Missing required options: :token' unless @token
|
33
|
+
|
34
|
+
@connection = Faraday.new({ url: @url }.merge(connection_options)) do |builder|
|
35
|
+
# response
|
36
|
+
builder.use Faraday::Response::RaiseError
|
37
|
+
builder.response :json
|
38
|
+
|
39
|
+
# request
|
40
|
+
builder.request :multipart
|
41
|
+
builder.request :json
|
42
|
+
|
43
|
+
builder.use PivotalApi::Logger, @logger
|
44
|
+
builder.adapter adapter
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Make a HTTP GET request
|
49
|
+
#
|
50
|
+
# @param path [String] The path, relative to api endpoint
|
51
|
+
# @param options [Hash] Query and header params for request
|
52
|
+
# @return [Faraday::Response]
|
53
|
+
def get(path, options = {})
|
54
|
+
request(:get, parse_query_and_convenience_headers(path, options))
|
55
|
+
end
|
56
|
+
|
57
|
+
# Make a HTTP DELETE request
|
58
|
+
#
|
59
|
+
# @param path [String] The path, relative to api endpoint
|
60
|
+
# @param options [Hash] Query and header params for request
|
61
|
+
# @return [Faraday::Response]
|
62
|
+
def delete(path, options = {})
|
63
|
+
request(:delete, parse_query_and_convenience_headers(path, options))
|
64
|
+
end
|
65
|
+
|
66
|
+
# Make a HTTP POST request
|
67
|
+
#
|
68
|
+
# @param path [String] The path, relative to api endpoint
|
69
|
+
# @param options [Hash] Query and header params for request
|
70
|
+
# @return nil
|
71
|
+
def post(path, options = {})
|
72
|
+
request(:post, parse_query_and_convenience_headers(path, options))
|
73
|
+
end
|
74
|
+
|
75
|
+
# Make a HTTP PUT request
|
76
|
+
#
|
77
|
+
# @param path [String] The path, relative to api endpoint
|
78
|
+
# @param options [Hash] Query and header params for request
|
79
|
+
# @return nil
|
80
|
+
def put(path, options = {})
|
81
|
+
request(:put, parse_query_and_convenience_headers(path, options))
|
82
|
+
end
|
83
|
+
|
84
|
+
# Make one or more HTTP GET requests, optionally fetching
|
85
|
+
# the next page of results from information passed back in headers
|
86
|
+
# based on value in {#auto_paginate}.
|
87
|
+
#
|
88
|
+
# @param path [String] The path, relative to {#api_endpoint}
|
89
|
+
# @param options [Hash] Query and header params for request
|
90
|
+
# @param block [Block] Block to perform the data concatenation of the
|
91
|
+
# multiple requests. The block is called with two parameters, the first
|
92
|
+
# contains the contents of the requests so far and the second parameter
|
93
|
+
# contains the latest response.
|
94
|
+
# @return [Array]
|
95
|
+
def paginate(path, options = {}, &block)
|
96
|
+
opts = parse_query_and_convenience_headers path, options.dup
|
97
|
+
auto_paginate = opts[:params].delete(:auto_paginate) { |k| @auto_paginate }
|
98
|
+
@last_response = request :get, opts
|
99
|
+
data = @last_response.body
|
100
|
+
raise PivotalApi::Errors::UnexpectedData, 'Array expected' unless data.is_a? Array
|
101
|
+
|
102
|
+
if auto_paginate
|
103
|
+
pager = Pagination.new @last_response.headers
|
104
|
+
|
105
|
+
while pager.more?
|
106
|
+
opts[:params].update(pager.next_page_params)
|
107
|
+
|
108
|
+
@last_response = request :get, opts
|
109
|
+
pager = Pagination.new @last_response.headers
|
110
|
+
if block_given?
|
111
|
+
yield(data, @last_response)
|
112
|
+
else
|
113
|
+
data.concat(@last_response.body) if @last_response.body.is_a?(Array)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
data
|
119
|
+
end
|
120
|
+
|
121
|
+
# Get projects
|
122
|
+
#
|
123
|
+
# @return [PivotalApi::Endpoints::Projects]
|
124
|
+
def projects
|
125
|
+
Endpoints::Projects.new(self)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Get information about the authenticated user
|
129
|
+
#
|
130
|
+
# @return [PivotalApi::Resources::Me]
|
131
|
+
def me
|
132
|
+
data = get("/me").body
|
133
|
+
|
134
|
+
Resources::Me.new({ client: self }.merge(data))
|
135
|
+
end
|
136
|
+
|
137
|
+
# Get information about a client story without knowing what project the story belongs to
|
138
|
+
#
|
139
|
+
# @param [String] story_id
|
140
|
+
# @return [PivotalApi::Resources::Story]
|
141
|
+
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
def parse_query_and_convenience_headers(path, options)
|
146
|
+
raise 'Path can not be blank.' if path.to_s.empty?
|
147
|
+
|
148
|
+
opts = { body: options[:body] }
|
149
|
+
|
150
|
+
opts[:url] = options[:url] || File.join(@url, @api_version, path.to_s)
|
151
|
+
opts[:method] = options[:method] || :get
|
152
|
+
opts[:params] = options[:params] || {}
|
153
|
+
opts[:token] = options[:token] || @token
|
154
|
+
headers = { 'User-Agent' => USER_AGENT,
|
155
|
+
'X-TrackerToken' => opts.fetch(:token) }.merge(options.fetch(:headers, {}))
|
156
|
+
|
157
|
+
CONVENIENCE_HEADERS.each do |h|
|
158
|
+
if header = options[h]
|
159
|
+
headers[h] = header
|
160
|
+
end
|
161
|
+
end
|
162
|
+
opts[:headers] = headers
|
163
|
+
|
164
|
+
opts
|
165
|
+
end
|
166
|
+
|
167
|
+
def request(method, options = {})
|
168
|
+
url = options.fetch(:url)
|
169
|
+
params = options[:params] || {}
|
170
|
+
body = options[:body]
|
171
|
+
headers = options[:headers]
|
172
|
+
|
173
|
+
@last_response = response = connection.send(method) do |req|
|
174
|
+
req.url(url)
|
175
|
+
req.headers.merge!(headers)
|
176
|
+
req.params.merge!(params)
|
177
|
+
req.body = body
|
178
|
+
end
|
179
|
+
response
|
180
|
+
rescue Faraday::Error::ClientError => e
|
181
|
+
raise PivotalApi::Error.new(e)
|
182
|
+
end
|
183
|
+
|
184
|
+
class Pagination
|
185
|
+
attr_accessor :headers, :total, :limit, :offset, :returned
|
186
|
+
|
187
|
+
def initialize(headers)
|
188
|
+
@headers = headers
|
189
|
+
@total = headers['x-tracker-pagination-total'].to_i
|
190
|
+
@limit = headers['x-tracker-pagination-limit'].to_i
|
191
|
+
@offset = headers['x-tracker-pagination-offset'].to_i
|
192
|
+
@returned = headers['x-tracker-pagination-returned'].to_i
|
193
|
+
|
194
|
+
# if offset is negative (e.g. Iterations Endpoint).
|
195
|
+
# For the 'Done' scope, negative numbers can be passed, which
|
196
|
+
# specifies the number of iterations preceding the 'Current' iteration.
|
197
|
+
# then need to adjust the negative offset to account for a smaller total,
|
198
|
+
# and set total to zero since we are paginating from -X to 0.
|
199
|
+
if @offset < 0
|
200
|
+
@offset = -@total if @offset.abs > @total
|
201
|
+
@total = 0
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def more?
|
206
|
+
(offset + limit) < total
|
207
|
+
end
|
208
|
+
|
209
|
+
def next_offset
|
210
|
+
offset + limit
|
211
|
+
end
|
212
|
+
|
213
|
+
def next_page_params
|
214
|
+
{ limit: limit, offset: next_offset }
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Endpoints
|
3
|
+
class Comments
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def all(project_id, story_id, params={})
|
11
|
+
data = client.paginate("/projects/#{project_id}/stories/#{story_id}/comments", params: params)
|
12
|
+
raise PivotalApi::Errors::UnexpectedData, 'Array of stories expected' unless data.is_a? Array
|
13
|
+
|
14
|
+
data.map do |story|
|
15
|
+
Resources::Comment.new({ project_id: project_id }.merge(story))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(project_id, story_id, id)
|
20
|
+
data = client.get("/projects/#{project_id}/stories/#{story_id}/comments/#{id}").body
|
21
|
+
|
22
|
+
Resources::Comment.new({ project_id: project_id }.merge(data))
|
23
|
+
end
|
24
|
+
|
25
|
+
def create(project_id, story_id, params)
|
26
|
+
data = client.post("/projects/#{project_id}/stories/#{story_id}/comments", params: params).body
|
27
|
+
|
28
|
+
Resources::Comment.new({ project_id: project_id }.merge(data))
|
29
|
+
end
|
30
|
+
|
31
|
+
def update(project_id, story_id, id, params)
|
32
|
+
data = client.put("/projects/#{project_id}/stories/#{story_id}/comments/#{id}", params: params).body
|
33
|
+
|
34
|
+
Resources::Comment.new({ }.merge(data))
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete(project_id, story_id, id)
|
38
|
+
client.delete("/projects/#{project_id}/stories/#{story_id}/comments/#{id}").body
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Endpoints
|
3
|
+
class Epics
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def all(project_id, params={})
|
11
|
+
data = client.paginate("/projects/#{project_id}/epics", params: params)
|
12
|
+
raise PivotalApi::Errors::UnexpectedData, 'Array of epics expected' unless data.is_a? Array
|
13
|
+
|
14
|
+
data.map do |epic|
|
15
|
+
Resources::Epic.new({ project_id: project_id }.merge(epic))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(project_id, id)
|
20
|
+
data = client.get("/projects/#{project_id}/epics/#{id}").body
|
21
|
+
|
22
|
+
Resources::Epic.new({ project_id: project_id }.merge(data))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Endpoints
|
3
|
+
class Iterations
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def all(project_id, params={})
|
11
|
+
data = client.paginate("/projects/#{project_id}/iterations", params: params)
|
12
|
+
raise PivotalApi::Errors::UnexpectedData, 'Array of iterations expected' unless data.is_a? Array
|
13
|
+
|
14
|
+
data.map do |iteration|
|
15
|
+
Resources::Iteration.new({ project_id: project_id }.merge(iteration))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Endpoints
|
3
|
+
class Labels
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def all(project_id, story_id, params={})
|
11
|
+
data = client.paginate("/projects/#{project_id}/stories/#{story_id}/labels", params: params)
|
12
|
+
raise PivotalApi::Errors::UnexpectedData, 'Array of stories expected' unless data.is_a? Array
|
13
|
+
|
14
|
+
data.map do |story|
|
15
|
+
Resources::Label.new({ project_id: project_id }.merge(story))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def create(project_id, story_id, params)
|
20
|
+
data = client.post("/projects/#{project_id}/stories/#{story_id}/labels", params: params).body
|
21
|
+
|
22
|
+
Resources::Label.new({ project_id: project_id }.merge(data))
|
23
|
+
end
|
24
|
+
|
25
|
+
def update(project_id, story_id, id, params)
|
26
|
+
data = client.put("/projects/#{project_id}/stories/#{story_id}/labels/#{id}", params: params).body
|
27
|
+
|
28
|
+
Resources::Label.new({ }.merge(data))
|
29
|
+
end
|
30
|
+
|
31
|
+
def delete(project_id, story_id, id)
|
32
|
+
client.delete("/projects/#{project_id}/stories/#{story_id}/labels/#{id}").body
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Endpoints
|
3
|
+
class Memberships
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def all(project_id, params={})
|
11
|
+
data = client.paginate("/projects/#{project_id}/memberships", params: params)
|
12
|
+
raise PivotalApi::Errors::UnexpectedData, 'Array of memberships expected' unless data.is_a? Array
|
13
|
+
|
14
|
+
data.map do |membership|
|
15
|
+
Resources::ProjectMembership.new({ project_id: project_id }.merge(membership))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(project_id, id)
|
20
|
+
data = client.get("/projects/#{project_id}/memberships/#{id}").body
|
21
|
+
|
22
|
+
Resources::ProjectMembership.new({ project_id: project_id }.merge(data))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Endpoints
|
3
|
+
class Projects
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
# @param [Hash] params
|
11
|
+
# @return [Array[PivotalApi::Resources::Project]]
|
12
|
+
def all(params={})
|
13
|
+
data = client.paginate('/projects', params: params)
|
14
|
+
raise PivotalApi::Errors::UnexpectedData, 'Array of projects expected' unless data.is_a? Array
|
15
|
+
|
16
|
+
data.map { |project| Resources::Project.new({ }.merge(project)) }
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
# @param [Hash] params
|
21
|
+
# @return [PivotalApi::Resources::Project]
|
22
|
+
def get(id, params={})
|
23
|
+
# Endpoints::Project.new(self).get(id, params)
|
24
|
+
data = client.get("/projects/#{id}", params: params).body
|
25
|
+
|
26
|
+
Resources::Project.new({ }.merge(data))
|
27
|
+
end
|
28
|
+
|
29
|
+
def epics
|
30
|
+
Endpoints::Epics.new(client)
|
31
|
+
end
|
32
|
+
|
33
|
+
def iterations
|
34
|
+
Endpoints::Iterations.new(client)
|
35
|
+
end
|
36
|
+
|
37
|
+
def stories
|
38
|
+
Endpoints::Stories.new(client)
|
39
|
+
end
|
40
|
+
|
41
|
+
def memberships
|
42
|
+
Endpoints::Memberships.new(client)
|
43
|
+
end
|
44
|
+
|
45
|
+
def webhooks
|
46
|
+
Endpoints::Webhooks.new(client)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Endpoints
|
3
|
+
class Stories
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def all(project_id, params={})
|
11
|
+
data = client.paginate("/projects/#{project_id}/stories", params: params)
|
12
|
+
raise PivotalApi::Errors::UnexpectedData, 'Array of stories expected' unless data.is_a? Array
|
13
|
+
|
14
|
+
data.map do |story|
|
15
|
+
Resources::Story.new({ project_id: project_id }.merge(story))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(project_id, id)
|
20
|
+
data = client.get("/projects/#{project_id}/stories/#{id}").body
|
21
|
+
|
22
|
+
Resources::Story.new({ project_id: project_id }.merge(data))
|
23
|
+
end
|
24
|
+
|
25
|
+
def create(project_id, params)
|
26
|
+
data = client.post("/projects/#{project_id}/stories", params: params).body
|
27
|
+
|
28
|
+
Resources::Story.new({ }.merge(data))
|
29
|
+
end
|
30
|
+
|
31
|
+
def update(project_id, id, params)
|
32
|
+
data = client.put("/projects/#{project_id}/stories/#{id}", params: params).body
|
33
|
+
|
34
|
+
Resources::Story.new({ }.merge(data))
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete(project_id, id)
|
38
|
+
client.delete("/projects/#{project_id}/stories/#{id}").body
|
39
|
+
end
|
40
|
+
|
41
|
+
def tasks
|
42
|
+
Endpoints::Tasks.new(client)
|
43
|
+
end
|
44
|
+
|
45
|
+
def comments
|
46
|
+
Endpoints::Comments.new(client)
|
47
|
+
end
|
48
|
+
|
49
|
+
def labels
|
50
|
+
Endpoints::Labels.new(client)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Endpoints
|
3
|
+
class Tasks
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def all(project_id, story_id, params={})
|
11
|
+
data = client.paginate("/projects/#{project_id}/stories/#{story_id}/tasks", params: params)
|
12
|
+
raise PivotalApi::Errors::UnexpectedData, 'Array of tasks expected' unless data.is_a? Array
|
13
|
+
|
14
|
+
data.map do |task|
|
15
|
+
Resources::Task.new({project_id: project_id }.merge(task))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(project_id, story_id, id)
|
20
|
+
data = client.get("/projects/#{project_id}/stories/#{story_id}/tasks/#{id}").body
|
21
|
+
|
22
|
+
Resources::Task.new({project_id: project_id }.merge(data))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Endpoints
|
3
|
+
class Webhooks
|
4
|
+
attr_accessor :client
|
5
|
+
|
6
|
+
def initialize(client)
|
7
|
+
@client = client
|
8
|
+
end
|
9
|
+
|
10
|
+
def all(project_id, params={})
|
11
|
+
data = client.paginate("/projects/#{project_id}/webhooks", params: params)
|
12
|
+
raise PivotalApi::Errors::UnexpectedData, 'Array of webhooks expected' unless data.is_a? Array
|
13
|
+
|
14
|
+
data.map do |story|
|
15
|
+
Resources::Webhook.new({ project_id: project_id }.merge(story))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get(project_id, id)
|
20
|
+
data = client.get("/projects/#{project_id}/webhooks/#{id}").body
|
21
|
+
|
22
|
+
Resources::Webhook.new({ project_id: project_id }.merge(data))
|
23
|
+
end
|
24
|
+
|
25
|
+
def create(project_id, params)
|
26
|
+
data = client.post("/projects/#{project_id}/webhooks", params: params).body
|
27
|
+
|
28
|
+
Resources::Webhook.new({ }.merge(data))
|
29
|
+
end
|
30
|
+
|
31
|
+
def update(project_id, id, params)
|
32
|
+
data = client.put("/projects/#{project_id}/webhooks/#{id}", params: params).body
|
33
|
+
|
34
|
+
Resources::Webhook.new({ }.merge(data))
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete(project_id, id)
|
38
|
+
client.delete("/projects/#{project_id}/webhooks/#{id}").body
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
class Error < StandardError
|
3
|
+
attr_reader :wrapped_exception, :response
|
4
|
+
|
5
|
+
def initialize(wrapped_exception)
|
6
|
+
@wrapped_exception = wrapped_exception
|
7
|
+
@response = wrapped_exception.response
|
8
|
+
message = if wrapped_exception.is_a?(Faraday::Error::ParsingError)
|
9
|
+
wrapped_exception.message
|
10
|
+
elsif wrapped_exception.is_a?(Faraday::Error::ClientError)
|
11
|
+
wrapped_exception.response.inspect
|
12
|
+
else
|
13
|
+
wrapped_exception.instance_variable_get(:@wrapped_exception).inspect
|
14
|
+
end
|
15
|
+
super(message)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
class Logger < Faraday::Response::Middleware
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
def initialize(app, logger = nil)
|
6
|
+
super(app)
|
7
|
+
@logger = logger || ::Logger.new(STDOUT)
|
8
|
+
end
|
9
|
+
|
10
|
+
def_delegators :@logger, :debug, :info, :warn, :error, :fatal
|
11
|
+
|
12
|
+
def call(env)
|
13
|
+
info("#{env[:method]} => #{env[:url].to_s}")
|
14
|
+
debug('request') { dump_headers env[:request_headers] }
|
15
|
+
debug('request.body') { env[:body] }
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_complete(env)
|
20
|
+
info("#{env[:status]} <= #{env[:url].to_s}")
|
21
|
+
debug('response') { dump_headers env[:response_headers] }
|
22
|
+
debug('response.body') { env[:body] }
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def dump_headers(headers)
|
28
|
+
headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class Account
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
attribute :id, Integer
|
7
|
+
attribute :created_at, DateTime
|
8
|
+
attribute :status, String
|
9
|
+
attribute :kind, String
|
10
|
+
attribute :name, String
|
11
|
+
attribute :updated_at, DateTime
|
12
|
+
attribute :url, String
|
13
|
+
attribute :plan, String
|
14
|
+
attribute :days_left, Integer
|
15
|
+
attribute :over_the_limit, Boolean
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class Comment
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
attribute :id, Integer
|
7
|
+
attribute :story_id, Integer
|
8
|
+
attribute :epic_id, Integer
|
9
|
+
attribute :text, String
|
10
|
+
attribute :person_id, Integer
|
11
|
+
attribute :created_at, DateTime
|
12
|
+
attribute :updated_at, DateTime
|
13
|
+
attribute :file_attachment_ids, Array[Integer]
|
14
|
+
attribute :google_attachment_ids, Array[Integer]
|
15
|
+
attribute :commit_identifier, String
|
16
|
+
attribute :commit_type, String
|
17
|
+
attribute :kind, String
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class Epic
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
# attribute :client
|
7
|
+
|
8
|
+
attribute :id, Integer
|
9
|
+
attribute :created_at, DateTime
|
10
|
+
attribute :description, String
|
11
|
+
attribute :kind, String
|
12
|
+
attribute :label, PivotalApi::Resources::Label
|
13
|
+
attribute :name, String
|
14
|
+
attribute :project_id, Integer
|
15
|
+
attribute :updated_at, DateTime
|
16
|
+
attribute :url, String
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class Iteration
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
# attribute :client
|
7
|
+
|
8
|
+
attribute :finish, DateTime
|
9
|
+
attribute :kind, String
|
10
|
+
attribute :length, Integer
|
11
|
+
attribute :number, Integer
|
12
|
+
attribute :planned, Boolean
|
13
|
+
attribute :project_id, Integer
|
14
|
+
attribute :start, DateTime
|
15
|
+
attribute :stories, [PivotalApi::Resources::Story]
|
16
|
+
attribute :story_ids, [Integer]
|
17
|
+
attribute :team_strength, Float
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class Label
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
attribute :id, Integer
|
7
|
+
attribute :created_at, DateTime
|
8
|
+
attribute :kind, String
|
9
|
+
attribute :name, String
|
10
|
+
attribute :project_id, Integer
|
11
|
+
attribute :updated_at, DateTime
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class Me
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
# attribute :client
|
7
|
+
|
8
|
+
attribute :id, Integer
|
9
|
+
attribute :name, String
|
10
|
+
attribute :initials, String
|
11
|
+
attribute :username, String
|
12
|
+
attribute :time_zone, PivotalApi::Resources::TimeZone
|
13
|
+
attribute :api_token, String
|
14
|
+
attribute :has_google_identity, Boolean
|
15
|
+
attribute :project_ids, Array[Integer]
|
16
|
+
attribute :projects, [PivotalApi::Resources::MembershipSummary]
|
17
|
+
attribute :workspace_ids, Array[Integer]
|
18
|
+
attribute :email, String
|
19
|
+
attribute :receives_in_app_notifications, Boolean
|
20
|
+
attribute :kind, String
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class MembershipSummary
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
# attribute :client
|
7
|
+
|
8
|
+
attribute :id, Integer
|
9
|
+
attribute :kind, String
|
10
|
+
attribute :last_viewed_at, DateTime
|
11
|
+
attribute :project_color, String
|
12
|
+
attribute :project_id, Integer
|
13
|
+
attribute :project_name, String
|
14
|
+
attribute :role, String
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class Person
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
# attribute :client
|
7
|
+
|
8
|
+
attribute :kind, String
|
9
|
+
attribute :id, Integer
|
10
|
+
attribute :name, String
|
11
|
+
attribute :email, String
|
12
|
+
attribute :initials, String
|
13
|
+
attribute :username, String
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class Project
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
# attribute :client
|
7
|
+
|
8
|
+
attribute :account, PivotalApi::Resources::Account
|
9
|
+
attribute :account_id, Integer
|
10
|
+
attribute :atom_enabled, Boolean
|
11
|
+
attribute :bugs_and_chores_are_estimatable, Boolean
|
12
|
+
attribute :created_at, DateTime
|
13
|
+
attribute :current_iteration_number, Integer
|
14
|
+
attribute :current_velocity, Integer
|
15
|
+
attribute :description, String
|
16
|
+
attribute :enable_following, Boolean
|
17
|
+
attribute :enable_incoming_emails, Boolean
|
18
|
+
attribute :enable_planned_mode, Boolean
|
19
|
+
attribute :enable_tasks, Boolean
|
20
|
+
attribute :epic_ids, Array[Integer]
|
21
|
+
attribute :epics, Array[PivotalApi::Resources::Epic]
|
22
|
+
attribute :has_google_domain, Boolean
|
23
|
+
attribute :id, Integer
|
24
|
+
attribute :initial_velocity, Integer
|
25
|
+
attribute :iteration_length, Integer
|
26
|
+
attribute :kind, String
|
27
|
+
attribute :label_ids, Array[Integer]
|
28
|
+
attribute :labels, Array[PivotalApi::Resources::Label]
|
29
|
+
attribute :name, String
|
30
|
+
attribute :number_of_done_iterations_to_show, Integer
|
31
|
+
attribute :point_scale, String
|
32
|
+
attribute :point_scale_is_custom, Boolean
|
33
|
+
attribute :profile_content, String
|
34
|
+
attribute :public, Boolean
|
35
|
+
attribute :start_date, DateTime
|
36
|
+
attribute :start_time, DateTime
|
37
|
+
attribute :time_zone, PivotalApi::Resources::TimeZone
|
38
|
+
attribute :updated_at, DateTime
|
39
|
+
attribute :velocity_averaged_over, Integer
|
40
|
+
attribute :version, Integer
|
41
|
+
attribute :week_start_day, String
|
42
|
+
|
43
|
+
# @return [String] comma separated list of labels
|
44
|
+
def label_list
|
45
|
+
@label_list ||= labels.collect(&:name).join(',')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class ProjectMembership
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
# attribute :client
|
7
|
+
|
8
|
+
attribute :id, Integer
|
9
|
+
attribute :person_id, Integer
|
10
|
+
attribute :project_id, Integer
|
11
|
+
attribute :role, String
|
12
|
+
attribute :project_color, String
|
13
|
+
attribute :wants_comment_notification_emails, Boolean
|
14
|
+
attribute :kind, String
|
15
|
+
attribute :person, PivotalApi::Resources::Person
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class Story
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
# attribute :client
|
7
|
+
|
8
|
+
attribute :accepted_at, DateTime
|
9
|
+
attribute :comment_ids, Array[Integer]
|
10
|
+
attribute :created_at, DateTime
|
11
|
+
attribute :current_state, String # (accepted, delivered, finished, started, rejected, planned, unstarted, unscheduled)
|
12
|
+
attribute :deadline, DateTime
|
13
|
+
attribute :description, String
|
14
|
+
attribute :estimate, Float
|
15
|
+
attribute :external_id, String
|
16
|
+
attribute :follower_ids, Array[Integer]
|
17
|
+
attribute :id, Integer
|
18
|
+
attribute :integration_id, Integer
|
19
|
+
attribute :kind, String
|
20
|
+
attribute :label_ids, Array[Integer]
|
21
|
+
attribute :labels, Array[PivotalApi::Resources::Label]
|
22
|
+
attribute :name, String
|
23
|
+
attribute :owned_by_id, Integer # deprecated!
|
24
|
+
attribute :owner_ids, Array[Integer]
|
25
|
+
attribute :owners, Array[PivotalApi::Resources::Person]
|
26
|
+
attribute :planned_iteration_number, Integer
|
27
|
+
attribute :project_id, Integer
|
28
|
+
attribute :requested_by_id, Integer
|
29
|
+
attribute :story_type, String # (feature, bug, chore, release)
|
30
|
+
attribute :task_ids, Array[Integer]
|
31
|
+
attribute :tasks, Array[PivotalApi::Resources::Task]
|
32
|
+
attribute :updated_at, DateTime
|
33
|
+
attribute :url, String
|
34
|
+
|
35
|
+
# @return [String] Comma separated list of labels.
|
36
|
+
def label_list
|
37
|
+
@label_list ||= labels.collect(&:name).join(',')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class Task
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
# attribute :client
|
7
|
+
|
8
|
+
attribute :id, Integer
|
9
|
+
attribute :story_id, Integer
|
10
|
+
attribute :project_id, Integer
|
11
|
+
attribute :description, String
|
12
|
+
attribute :complete, Boolean
|
13
|
+
attribute :position, Integer
|
14
|
+
attribute :created_at, DateTime
|
15
|
+
attribute :updated_at, DateTime
|
16
|
+
attribute :kind, String
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module PivotalApi
|
2
|
+
module Resources
|
3
|
+
class Webhook
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
attribute :id, Integer
|
7
|
+
attribute :project_id, Integer
|
8
|
+
attribute :webhook_url, String
|
9
|
+
attribute :webhook_version, String, default: 'v5'
|
10
|
+
attribute :created_at, DateTime
|
11
|
+
attribute :updated_at, DateTime
|
12
|
+
attribute :kind, String
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pivotal-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maciej Skierkowski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: addressable
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: virtus
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: faraday
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.9.0
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.9.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: faraday_middleware
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: excon
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: This gem allows you to easily use the Pivotal Tracker v5 API.
|
112
|
+
email:
|
113
|
+
- maciej@factor.io
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- "./lib/pivotal-api.rb"
|
119
|
+
- "./lib/pivotal_api/client.rb"
|
120
|
+
- "./lib/pivotal_api/endpoints/comments.rb"
|
121
|
+
- "./lib/pivotal_api/endpoints/epics.rb"
|
122
|
+
- "./lib/pivotal_api/endpoints/iterations.rb"
|
123
|
+
- "./lib/pivotal_api/endpoints/labels.rb"
|
124
|
+
- "./lib/pivotal_api/endpoints/memberships.rb"
|
125
|
+
- "./lib/pivotal_api/endpoints/projects.rb"
|
126
|
+
- "./lib/pivotal_api/endpoints/stories.rb"
|
127
|
+
- "./lib/pivotal_api/endpoints/tasks.rb"
|
128
|
+
- "./lib/pivotal_api/endpoints/webhooks.rb"
|
129
|
+
- "./lib/pivotal_api/error.rb"
|
130
|
+
- "./lib/pivotal_api/logger.rb"
|
131
|
+
- "./lib/pivotal_api/resources/account.rb"
|
132
|
+
- "./lib/pivotal_api/resources/comment.rb"
|
133
|
+
- "./lib/pivotal_api/resources/epic.rb"
|
134
|
+
- "./lib/pivotal_api/resources/iteration.rb"
|
135
|
+
- "./lib/pivotal_api/resources/label.rb"
|
136
|
+
- "./lib/pivotal_api/resources/me.rb"
|
137
|
+
- "./lib/pivotal_api/resources/membership_summary.rb"
|
138
|
+
- "./lib/pivotal_api/resources/person.rb"
|
139
|
+
- "./lib/pivotal_api/resources/project.rb"
|
140
|
+
- "./lib/pivotal_api/resources/project_membership.rb"
|
141
|
+
- "./lib/pivotal_api/resources/story.rb"
|
142
|
+
- "./lib/pivotal_api/resources/task.rb"
|
143
|
+
- "./lib/pivotal_api/resources/time_zone.rb"
|
144
|
+
- "./lib/pivotal_api/resources/webhook.rb"
|
145
|
+
- "./lib/pivotal_api/version.rb"
|
146
|
+
homepage: https://github.com/factor-io/pivotal-api
|
147
|
+
licenses:
|
148
|
+
- MIT
|
149
|
+
metadata: {}
|
150
|
+
post_install_message:
|
151
|
+
rdoc_options: []
|
152
|
+
require_paths:
|
153
|
+
- lib
|
154
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: '0'
|
164
|
+
requirements: []
|
165
|
+
rubyforge_project:
|
166
|
+
rubygems_version: 2.2.2
|
167
|
+
signing_key:
|
168
|
+
specification_version: 4
|
169
|
+
summary: API client for the Pivotal Tracker v5 API
|
170
|
+
test_files: []
|
171
|
+
has_rdoc:
|