pivotal-api 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|