Skip to content
This repository was archived by the owner on Apr 13, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/tracker_api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ module Endpoints
autoload :StoryTransitions, 'tracker_api/endpoints/story_transitions'
autoload :Attachment, 'tracker_api/endpoints/attachment'
autoload :Attachments, 'tracker_api/endpoints/attachments'
autoload :Releases, 'tracker_api/endpoints/releases'
autoload :Release, 'tracker_api/endpoints/release'
end

module Resources
Expand Down Expand Up @@ -93,5 +95,6 @@ module Shared
autoload :Webhook, 'tracker_api/resources/webhook'
autoload :StoryTransition, 'tracker_api/resources/story_transition'
autoload :FileAttachment, 'tracker_api/resources/file_attachment'
autoload :Release, 'tracker_api/resources/release'
end
end
17 changes: 17 additions & 0 deletions lib/tracker_api/endpoints/release.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module TrackerApi
module Endpoints
class Release
attr_accessor :client

def initialize(client)
@client = client
end

def get(project_id, id, params={})
data = client.get("/projects/#{project_id}/releases/#{id}", params: params).body

Resources::Release.new({ client: client }.merge(data))
end
end
end
end
20 changes: 20 additions & 0 deletions lib/tracker_api/endpoints/releases.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module TrackerApi
module Endpoints
class Releases
attr_accessor :client

def initialize(client)
@client = client
end

def get(project_id, params={})
data = client.paginate("/projects/#{project_id}/releases", params: params)
raise Errors::UnexpectedData, 'Array of releases expected' unless data.is_a? Array

data.map do |release|
Resources::Release.new({ client: client, project_id: project_id }.merge(release))
end
end
end
end
end
10 changes: 10 additions & 0 deletions lib/tracker_api/endpoints/stories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ def get(project_id, params={})
Resources::Story.new({ client: client, project_id: project_id }.merge(story))
end
end

def get_release(project_id, release_id, params={})
data = client.paginate("/projects/#{project_id}/releases/#{release_id}/stories", params: params)

raise Errors::UnexpectedData, 'Array of stories expected' unless data.is_a? Array

data.map do |story|
Resources::Story.new({ client: client, project_id: project_id }.merge(story))
end
end
end
end
end
13 changes: 13 additions & 0 deletions lib/tracker_api/resources/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,19 @@ def stories(params={})
Endpoints::Stories.new(client).get(id, params)
end

# Provides a list of all the releases in the project.
#
# @param [Hash] params
# @option params [String] :with_state A release's current_state which all returned releases must match.
# Valid enumeration values: accepted, delivered, finished, started, rejected, unstarted, unscheduled
# @option params [Integer] :offset With the first release in your priority list as 0,
# the index of the first release you want returned.
# @option params [Integer] :limit The number of releases you want returned.
# @return [Array[Release]] releases associated with this project
def releases(params={})
Endpoints::Releases.new(client).get(id, params)
end

# Provides a list of all the memberships in the project.
#
# @param [Hash] params
Expand Down
29 changes: 29 additions & 0 deletions lib/tracker_api/resources/release.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module TrackerApi
module Resources
class Release
include Shared::Base

attribute :client

attribute :project_id, Integer
attribute :name, String
attribute :description, String
attribute :current_state, String # (accepted, delivered, finished, started, rejected, planned, unstarted, unscheduled)
attribute :accepted_at, DateTime
attribute :deadline, DateTime
attribute :labels, [Label]
attribute :created_at, DateTime
attribute :updated_at, DateTime
attribute :url, String
attribute :kind, String

# Provides a list of all the stories in the release.
#
# @param [Hash] params
# @return [Array[Story]] stories of this release
def stories(params={})
Endpoints::Stories.new(client).get_release(project_id, id, params)
end
end
end
end
12 changes: 12 additions & 0 deletions test/project_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,16 @@
end
end
end

describe '.releases' do
it 'gets all of the releases for the project' do
VCR.use_cassette('get releases', record: :new_episodes) do
releases = project.releases

releases.wont_be_empty
releases.size.must_equal 3
releases.first.must_be_instance_of TrackerApi::Resources::Release
end
end
end
end
22 changes: 22 additions & 0 deletions test/release_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
require_relative 'minitest_helper'

describe TrackerApi::Resources::Release do
let(:pt_user) { PT_USER_1 }
let(:client) { TrackerApi::Client.new token: pt_user[:token] }
let(:project_id) { pt_user[:project_id] }
let(:project) { VCR.use_cassette('get project') { client.project(project_id) } }

describe '.stories' do
it 'returns all the stories related to a release' do
releases = VCR.use_cassette('get releases') { project.releases }
release = releases.find { |release| release.name == 'Beta launch' }

VCR.use_cassette('release stories', record: :new_episodes) do
stories = release.stories

stories.size.must_equal 9
stories.first.must_be_instance_of TrackerApi::Resources::Story
end
end
end
end
1 change: 1 addition & 0 deletions test/vcr/cassettes/get_releases.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"http_interactions":[{"request":{"method":"get","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488","body":{"encoding":"US-ASCII","string":""},"headers":{"User-Agent":["Ruby/2.4.1 (x86_64-darwin15; ruby) TrackerApi/1.9.0 Faraday/0.15.2"],"X-TrackerToken":["d55c3bc1f74346b843ca84ba340b29bf"],"Accept":["application/json"]}},"response":{"status":{"code":200,"message":null},"headers":{"Access-Control-Allow-Credentials":["false"],"Access-Control-Allow-Headers":["X-TrackerToken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Tracker-Warn-Unless-Project-Version-Is"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Origin":["*"],"Cache-Control":["max-age=0, private, must-revalidate"],"Content-Type":["application/json; charset=utf-8"],"Date":["Tue, 31 Jul 2018 17:55:31 GMT"],"Etag":["W/\"4e54e943972c892eae56a18d566f173e\""],"Server":["nginx + Phusion Passenger"],"Status":["200 OK"],"Strict-Transport-Security":["max-age=31536000; includeSubDomains; preload"],"X-Content-Type-Options":["nosniff, nosniff"],"X-Frame-Options":["SAMEORIGIN"],"X-Powered-By":["Phusion Passenger Enterprise"],"X-Request-Id":["f89b2a3b-b4d8-432c-a0ed-016065dab143"],"X-Runtime":["0.044165"],"X-Tracker-Client-Pinger-Interval":["20"],"X-Tracker-Project-Version":["493"],"X-Vcap-Request-Id":["acf8b574-3947-48a5-66a4-3036e9a4e4ee"],"X-Xss-Protection":["1; mode=block"],"Content-Length":["847"],"Via":["1.1 google"],"Alt-Svc":["clear"]},"body":{"encoding":"ASCII-8BIT","string":"{\"id\":1027488,\"kind\":\"project\",\"name\":\"My Sample Project\",\"version\":493,\"iteration_length\":1,\"week_start_day\":\"Monday\",\"point_scale\":\"0,1,2,3\",\"point_scale_is_custom\":false,\"bugs_and_chores_are_estimatable\":false,\"automatic_planning\":true,\"enable_tasks\":true,\"time_zone\":{\"kind\":\"time_zone\",\"olson_name\":\"America/Los_Angeles\",\"offset\":\"-07:00\"},\"velocity_averaged_over\":3,\"number_of_done_iterations_to_show\":12,\"has_google_domain\":false,\"profile_content\":\"This is a demo project, created by Tracker, with example stories for a simple shopping web site.\",\"enable_incoming_emails\":true,\"initial_velocity\":10,\"public\":false,\"atom_enabled\":false,\"project_type\":\"demo\",\"start_time\":\"2014-02-10T08:00:00Z\",\"created_at\":\"2014-03-02T07:11:04Z\",\"updated_at\":\"2014-03-02T07:11:04Z\",\"account_id\":621384,\"current_iteration_number\":234,\"enable_following\":true}"},"http_version":null},"recorded_at":"Tue, 31 Jul 2018 17:55:31 GMT"},{"request":{"method":"get","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488/releases","body":{"encoding":"US-ASCII","string":""},"headers":{"User-Agent":["Ruby/2.4.1 (x86_64-darwin15; ruby) TrackerApi/1.9.0 Faraday/0.15.2"],"X-TrackerToken":["d55c3bc1f74346b843ca84ba340b29bf"],"Accept":["application/json"]}},"response":{"status":{"code":200,"message":null},"headers":{"Access-Control-Allow-Credentials":["false"],"Access-Control-Allow-Headers":["X-TrackerToken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Tracker-Warn-Unless-Project-Version-Is"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Origin":["*"],"Cache-Control":["max-age=0, private, must-revalidate"],"Content-Type":["application/json; charset=utf-8"],"Date":["Tue, 31 Jul 2018 17:55:31 GMT"],"Etag":["W/\"0bfcc7249b18fb7b53a6b16bd0386774\""],"Server":["nginx + Phusion Passenger"],"Status":["200 OK"],"Strict-Transport-Security":["max-age=31536000; includeSubDomains; preload"],"X-Content-Type-Options":["nosniff, nosniff"],"X-Frame-Options":["SAMEORIGIN"],"X-Powered-By":["Phusion Passenger Enterprise"],"X-Request-Id":["dfa70eae-1373-4717-927d-59493403fd39"],"X-Runtime":["0.049638"],"X-Tracker-Client-Pinger-Interval":["20"],"X-Tracker-Pagination-Limit":["100"],"X-Tracker-Pagination-Offset":["0"],"X-Tracker-Pagination-Returned":["3"],"X-Tracker-Pagination-Total":["3"],"X-Tracker-Project-Version":["493"],"X-Vcap-Request-Id":["41ba3959-d631-4ee3-595e-e643bb4b8a0f"],"X-Xss-Protection":["1; mode=block"],"Content-Length":["798"],"Via":["1.1 google"],"Alt-Svc":["clear"]},"body":{"encoding":"ASCII-8BIT","string":"[{\"kind\":\"release\",\"id\":66728012,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2014-03-02T07:11:05Z\",\"name\":\"Initial demo to investors\",\"current_state\":\"unstarted\",\"url\":\"https://www.pivotaltracker.com/story/show/66728012\",\"project_id\":1027488,\"labels\":[]},{\"kind\":\"release\",\"id\":66728034,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2014-03-02T07:11:06Z\",\"deadline\":\"2014-03-17T00:00:00Z\",\"name\":\"Beta launch\",\"current_state\":\"unstarted\",\"url\":\"https://www.pivotaltracker.com/story/show/66728034\",\"project_id\":1027488,\"labels\":[]},{\"kind\":\"release\",\"id\":66728082,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2014-03-02T07:11:07Z\",\"name\":\"Full production launch\",\"current_state\":\"unstarted\",\"url\":\"https://www.pivotaltracker.com/story/show/66728082\",\"project_id\":1027488,\"labels\":[]}]"},"http_version":null},"recorded_at":"Tue, 31 Jul 2018 17:55:31 GMT"}],"recorded_with":"VCR 4.0.0"}
1 change: 1 addition & 0 deletions test/vcr/cassettes/release_stories.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"http_interactions":[{"request":{"method":"get","uri":"https://www.pivotaltracker.com/services/v5/projects/1027488/releases/66728034/stories","body":{"encoding":"US-ASCII","string":""},"headers":{"User-Agent":["Ruby/2.4.1 (x86_64-darwin15; ruby) TrackerApi/1.9.0 Faraday/0.15.2"],"X-TrackerToken":["d55c3bc1f74346b843ca84ba340b29bf"],"Accept":["application/json"]}},"response":{"status":{"code":200,"message":null},"headers":{"Access-Control-Allow-Credentials":["false"],"Access-Control-Allow-Headers":["X-TrackerToken,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-Tracker-Warn-Unless-Project-Version-Is"],"Access-Control-Allow-Methods":["GET, POST, PUT, DELETE, OPTIONS"],"Access-Control-Allow-Origin":["*"],"Cache-Control":["max-age=0, private, must-revalidate"],"Content-Type":["application/json; charset=utf-8"],"Date":["Tue, 31 Jul 2018 18:08:51 GMT"],"Etag":["W/\"a760df243b5eeb972f6f861c6e86fcfd\""],"Server":["nginx + Phusion Passenger"],"Status":["200 OK"],"Strict-Transport-Security":["max-age=31536000; includeSubDomains; preload"],"X-Content-Type-Options":["nosniff, nosniff"],"X-Frame-Options":["SAMEORIGIN"],"X-Powered-By":["Phusion Passenger Enterprise"],"X-Request-Id":["2465f4db-8382-4655-beba-92a7a1c9f9b3"],"X-Runtime":["0.050357"],"X-Tracker-Client-Pinger-Interval":["20"],"X-Tracker-Project-Version":["493"],"X-Vcap-Request-Id":["973dcd63-0081-447d-6557-720c240b7ab6"],"X-Xss-Protection":["1; mode=block"],"Via":["1.1 google"],"Alt-Svc":["clear"]},"body":{"encoding":"ASCII-8BIT","string":"[{\"kind\":\"story\",\"id\":66728014,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2017-05-03T23:34:05Z\",\"estimate\":1,\"story_type\":\"feature\",\"name\":\"Shopper should be able to enter credit card information and shipping address\",\"current_state\":\"unstarted\",\"requested_by_id\":1266314,\"url\":\"https://www.pivotaltracker.com/story/show/66728014\",\"project_id\":1027488,\"owner_ids\":[],\"labels\":[{\"id\":7849090,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"checkout\",\"created_at\":\"2014-03-02T07:11:05Z\",\"updated_at\":\"2014-03-02T07:11:05Z\"},{\"id\":7849082,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"shopping\",\"created_at\":\"2014-03-02T07:11:04Z\",\"updated_at\":\"2014-03-02T07:11:04Z\"}]},{\"kind\":\"story\",\"id\":66728016,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2014-03-02T07:11:05Z\",\"story_type\":\"chore\",\"name\":\"Integrate with payment gateway\",\"current_state\":\"unstarted\",\"requested_by_id\":1266314,\"url\":\"https://www.pivotaltracker.com/story/show/66728016\",\"project_id\":1027488,\"owner_ids\":[],\"labels\":[{\"id\":7849090,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"checkout\",\"created_at\":\"2014-03-02T07:11:05Z\",\"updated_at\":\"2014-03-02T07:11:05Z\"},{\"id\":7849082,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"shopping\",\"created_at\":\"2014-03-02T07:11:04Z\",\"updated_at\":\"2014-03-02T07:11:04Z\"}]},{\"kind\":\"story\",\"id\":66728018,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2014-03-02T07:11:05Z\",\"estimate\":3,\"story_type\":\"feature\",\"name\":\"When shopper submits order, authorize total product amount from payment gateway\",\"current_state\":\"unstarted\",\"requested_by_id\":1266314,\"url\":\"https://www.pivotaltracker.com/story/show/66728018\",\"project_id\":1027488,\"owner_ids\":[],\"labels\":[{\"id\":7849090,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"checkout\",\"created_at\":\"2014-03-02T07:11:05Z\",\"updated_at\":\"2014-03-02T07:11:05Z\"},{\"id\":7849092,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"needs discussion\",\"created_at\":\"2014-03-02T07:11:05Z\",\"updated_at\":\"2014-03-02T07:11:05Z\"},{\"id\":7849082,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"shopping\",\"created_at\":\"2014-03-02T07:11:04Z\",\"updated_at\":\"2014-03-02T07:11:04Z\"}]},{\"kind\":\"story\",\"id\":66728020,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2014-03-02T07:11:05Z\",\"estimate\":1,\"story_type\":\"feature\",\"name\":\"If system fails to authorize payment amount, display error message to shopper\",\"current_state\":\"unstarted\",\"requested_by_id\":1266314,\"url\":\"https://www.pivotaltracker.com/story/show/66728020\",\"project_id\":1027488,\"owner_ids\":[],\"labels\":[{\"id\":7849090,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"checkout\",\"created_at\":\"2014-03-02T07:11:05Z\",\"updated_at\":\"2014-03-02T07:11:05Z\"},{\"id\":7849082,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"shopping\",\"created_at\":\"2014-03-02T07:11:04Z\",\"updated_at\":\"2014-03-02T07:11:04Z\"}]},{\"kind\":\"story\",\"id\":66728022,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2014-03-02T07:11:05Z\",\"estimate\":1,\"story_type\":\"feature\",\"name\":\"If authorization is successful, show order number and confirmation message to shopper\",\"current_state\":\"unstarted\",\"requested_by_id\":1266314,\"url\":\"https://www.pivotaltracker.com/story/show/66728022\",\"project_id\":1027488,\"owner_ids\":[],\"labels\":[{\"id\":7849090,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"checkout\",\"created_at\":\"2014-03-02T07:11:05Z\",\"updated_at\":\"2014-03-02T07:11:05Z\"},{\"id\":7849082,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"shopping\",\"created_at\":\"2014-03-02T07:11:04Z\",\"updated_at\":\"2014-03-02T07:11:04Z\"}]},{\"kind\":\"story\",\"id\":66728024,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2017-05-03T23:32:55Z\",\"estimate\":1,\"story_type\":\"feature\",\"name\":\"Send notification email of order placement to admin\",\"current_state\":\"unstarted\",\"requested_by_id\":1266314,\"url\":\"https://www.pivotaltracker.com/story/show/66728024\",\"project_id\":1027488,\"owner_ids\":[1266314],\"labels\":[{\"id\":7849080,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"admin\",\"created_at\":\"2014-03-02T07:11:04Z\",\"updated_at\":\"2014-03-02T07:11:04Z\"},{\"id\":7849090,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"checkout\",\"created_at\":\"2014-03-02T07:11:05Z\",\"updated_at\":\"2014-03-02T07:11:05Z\"},{\"id\":7849082,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"shopping\",\"created_at\":\"2014-03-02T07:11:04Z\",\"updated_at\":\"2014-03-02T07:11:04Z\"}],\"owned_by_id\":1266314},{\"kind\":\"story\",\"id\":66728026,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2014-03-02T07:11:05Z\",\"estimate\":2,\"story_type\":\"feature\",\"name\":\"Shopper should be able to check status of order by entering name and order number\",\"current_state\":\"unstarted\",\"requested_by_id\":1266314,\"url\":\"https://www.pivotaltracker.com/story/show/66728026\",\"project_id\":1027488,\"owner_ids\":[],\"labels\":[{\"id\":7849094,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"orders\",\"created_at\":\"2014-03-02T07:11:05Z\",\"updated_at\":\"2014-03-02T07:11:05Z\"}]},{\"kind\":\"story\",\"id\":66728028,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2014-03-02T07:11:05Z\",\"estimate\":1,\"story_type\":\"feature\",\"name\":\"Shopper should be able to ask question about order\",\"description\":\"When checking status of order, shopper should have the option to ask a question. This should send email to admin.\",\"current_state\":\"unstarted\",\"requested_by_id\":1266314,\"url\":\"https://www.pivotaltracker.com/story/show/66728028\",\"project_id\":1027488,\"owner_ids\":[],\"labels\":[{\"id\":7849094,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"orders\",\"created_at\":\"2014-03-02T07:11:05Z\",\"updated_at\":\"2014-03-02T07:11:05Z\"}]},{\"kind\":\"story\",\"id\":66728032,\"created_at\":\"2014-02-17T00:00:00Z\",\"updated_at\":\"2014-03-02T07:11:06Z\",\"story_type\":\"chore\",\"name\":\"Set up Engine Yard production environment\",\"current_state\":\"unstarted\",\"requested_by_id\":1266314,\"url\":\"https://www.pivotaltracker.com/story/show/66728032\",\"project_id\":1027488,\"owner_ids\":[],\"labels\":[{\"id\":7849078,\"project_id\":1027488,\"kind\":\"label\",\"name\":\"deployment\",\"created_at\":\"2014-03-02T07:11:04Z\",\"updated_at\":\"2014-03-02T07:11:04Z\"}]}]"},"http_version":null},"recorded_at":"Tue, 31 Jul 2018 18:08:51 GMT"}],"recorded_with":"VCR 4.0.0"}