├── .gitignore
├── Rakefile
├── config
└── routes.rb
├── spec
├── factories
│ ├── issue_status.rb
│ ├── tracker.rb
│ ├── project.rb
│ ├── user.rb
│ ├── issue.rb
│ └── mapping.rb
├── fixtures
│ ├── custom_fields_projects.yml
│ ├── trackers.yml
│ ├── issue_priorities.yml
│ ├── issue_statuses.yml
│ ├── custom_fields_trackers.yml
│ ├── mappings.yml
│ ├── projects_trackers.yml
│ ├── json
│ │ ├── story_subject_update.json
│ │ ├── story_description_update.json
│ │ ├── story_restarted.json
│ │ ├── story_status_update.json
│ │ └── story_started.json
│ ├── email_addresses.yml
│ ├── projects.yml
│ ├── issues.yml
│ ├── custom_values.yml
│ ├── custom_fields.yml
│ └── users.yml
├── unit
│ ├── project_patch_spec.rb
│ ├── issue_patch_spec.rb
│ ├── lib
│ │ ├── trackmine
│ │ │ ├── issues_creator_spec.rb
│ │ │ ├── activity_spec.rb
│ │ │ ├── story_finisher_spec.rb
│ │ │ ├── pivotal_project_spec.rb
│ │ │ ├── issues_updater_spec.rb
│ │ │ ├── activity_reader_spec.rb
│ │ │ └── issue_creator_spec.rb
│ │ ├── pivotal_handler_spec.rb
│ │ └── trackmine_spec.rb
│ ├── trackmine_mailer_spec.rb
│ └── mapping_spec.rb
├── spec_helper.rb
└── cassettes
│ ├── projects.yml
│ ├── finish_story.yml
│ ├── updating_story.yml
│ ├── participant_email.yml
│ ├── trackmine_activity.yml
│ ├── issue_creator.yml
│ ├── restarting_story.yml
│ ├── pivotal_project.yml
│ └── issues_creator.yml
├── app
├── views
│ ├── trackmine_mailer
│ │ └── error_mail.html.erb
│ └── mappings
│ │ ├── edit.html.erb
│ │ ├── _config.html.erb
│ │ ├── new.html.erb
│ │ └── index.html.erb
├── models
│ ├── trackmine_mailer.rb
│ └── mapping.rb
└── controllers
│ └── mappings_controller.rb
├── lib
├── project_patch.rb
├── trackmine
│ ├── credentials.rb
│ ├── issues_creator.rb
│ ├── story_finisher.rb
│ ├── issues_restarter.rb
│ ├── configuration.rb
│ ├── activity_reader.rb
│ ├── authentication.rb
│ ├── issues_updater.rb
│ ├── pivotal_project.rb
│ ├── activity.rb
│ ├── custom_values_creator.rb
│ └── issue_creator.rb
├── pivotal_handler.rb
├── trackmine.rb
└── issue_patch.rb
├── db
└── migrate
│ ├── 002_add_estimations_to_mappings.rb
│ ├── 003_add_story_types_to_mappings.rb
│ ├── 005_add_issue_id_to_story_projects.rb
│ ├── 004_create_story_projects.rb
│ ├── 006_remove_story_project.rb
│ └── 001_create_mappings.rb
├── Gemfile
├── assets
└── javascripts
│ └── mappings.js
├── init.rb
├── LICENSE
└── README.rdoc
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require 'rake'
2 | require 'rake/testtask'
3 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | resources :mappings, except: :show
2 |
3 | get 'mappings/update_labels', to: 'mappings#update_labels'
--------------------------------------------------------------------------------
/spec/factories/issue_status.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :issue_status do
3 | sequence(:name) { |n| "Status #{n}" }
4 | end
5 | end
6 |
7 |
--------------------------------------------------------------------------------
/app/views/trackmine_mailer/error_mail.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | Got error from Trackmine:
4 | <%=h @error_message %>
5 |
6 |
7 |
--------------------------------------------------------------------------------
/spec/factories/tracker.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :tracker do
3 | sequence(:name) { |n| "Tracker #{n}" }
4 | default_status factory: :issue_status
5 | end
6 | end
7 |
8 |
--------------------------------------------------------------------------------
/spec/factories/project.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :project do
3 | sequence(:name) { |n| "Redmine project #{n}" }
4 | sequence(:identifier) { |n| "project#{n}"}
5 | end
6 | end
7 |
8 |
--------------------------------------------------------------------------------
/spec/factories/user.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :user do
3 | sequence(:login) { |n| "user#{n}"}
4 | sequence(:firstname) { |n| "foo#{n}"}
5 | sequence(:lastname) { |n| "bar#{n}"}
6 | admin false
7 | end
8 |
9 | end
10 |
11 |
--------------------------------------------------------------------------------
/lib/project_patch.rb:
--------------------------------------------------------------------------------
1 | require_dependency 'project'
2 |
3 | module ProjectPatch
4 |
5 | def self.included(klass) # :nodoc:
6 | klass.class_eval do
7 | unloadable
8 | has_many :mappings, dependent: :destroy
9 | end
10 | end
11 |
12 | end
13 |
--------------------------------------------------------------------------------
/db/migrate/002_add_estimations_to_mappings.rb:
--------------------------------------------------------------------------------
1 | class AddEstimationsToMappings < ActiveRecord::Migration
2 | def self.up
3 | add_column :mappings, :estimations, :text
4 | end
5 |
6 | def self.down
7 | remove_column :mappings, :estimations
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/003_add_story_types_to_mappings.rb:
--------------------------------------------------------------------------------
1 | class AddStoryTypesToMappings < ActiveRecord::Migration
2 | def self.up
3 | add_column :mappings, :story_types, :text
4 | end
5 |
6 | def self.down
7 | remove_column :mappings, :story_types
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/spec/fixtures/custom_fields_projects.yml:
--------------------------------------------------------------------------------
1 | ---
2 | custom_fields_projects_001:
3 | custom_field_id: 9
4 | project_id: 1
5 | custom_fields_projects_002:
6 | custom_field_id: 12
7 | project_id: 1
8 | custom_fields_projects_003:
9 | custom_field_id: 13
10 | project_id: 1
11 |
--------------------------------------------------------------------------------
/db/migrate/005_add_issue_id_to_story_projects.rb:
--------------------------------------------------------------------------------
1 | class AddIssueIdToStoryProjects < ActiveRecord::Migration
2 | def self.up
3 | add_column :story_projects, :issue_id, :integer
4 | end
5 |
6 | def self.down
7 | remove_column :story_projects, :issue_id
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/views/mappings/edit.html.erb:
--------------------------------------------------------------------------------
1 | <%= form_for @mapping, :url => { :controller => :mappings, :action => :update, :id => @mapping } do |f|%>
2 | <%= render :partial => 'config' %>
3 |
4 | <%= f.submit 'Update' %>
5 | <%= link_to 'Cancel', :action => :index %>
6 |
7 | <% end %>
8 |
9 |
--------------------------------------------------------------------------------
/spec/factories/issue.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :issue do
3 | project_id 1
4 | sequence(:subject) { |n| "Foo subject #{n}"}
5 | author_id 1
6 | sequence(:description) { |n| "Factory description #{n}"}
7 | priority_id 5
8 | tracker_id 1
9 | end
10 | end
11 |
12 |
--------------------------------------------------------------------------------
/spec/unit/project_patch_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 |
3 | describe 'ProjectPatch' do
4 | context 'After loading init.rb' do
5 | context 'Project' do
6 | subject { Project.first }
7 | it { should have_many(:mappings) }
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | gem 'sinatra'
4 | gem 'pivotal-tracker', '~>0.5.13'
5 | gem 'unicode'
6 |
7 | group :development, :test do
8 | gem 'pry'
9 | end
10 |
11 | group :test do
12 | gem 'vcr'
13 | gem 'rspec'
14 | gem 'factory_girl'
15 | gem 'shoulda-matchers'
16 | gem 'webmock'
17 | end
18 |
--------------------------------------------------------------------------------
/spec/unit/issue_patch_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 |
3 | describe 'IssuePatch' do
4 | context 'After loading init.rb' do
5 | context 'Issue' do
6 | it 'has find_by_story_id method' do
7 | expect(Issue.respond_to? :find_by_story_id)
8 | end
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/004_create_story_projects.rb:
--------------------------------------------------------------------------------
1 | class CreateStoryProjects < ActiveRecord::Migration
2 | def self.up
3 | create_table :story_projects do |t|
4 | t.column :story_id, :integer
5 | t.column :tracker_project_id, :integer
6 | end
7 | end
8 |
9 | def self.down
10 | drop_table :story_projects
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/models/trackmine_mailer.rb:
--------------------------------------------------------------------------------
1 | class TrackmineMailer < ActionMailer::Base
2 |
3 | def error_mail(error_message)
4 | @error_message = error_message
5 |
6 | mail(
7 | to: Trackmine.error_notification['recipient'],
8 | subject: 'Trackmine error occurred',
9 | from: Trackmine.error_notification['from']
10 | )
11 | end
12 | end
13 |
14 |
15 |
--------------------------------------------------------------------------------
/db/migrate/006_remove_story_project.rb:
--------------------------------------------------------------------------------
1 | class RemoveStoryProject < ActiveRecord::Migration
2 | def self.up
3 | drop_table :story_projects
4 | end
5 |
6 | def self.down
7 | create_table :story_projects do |t|
8 | t.column :story_id, :integer
9 | t.column :tracker_project_id, :integer
10 | t.column :issue_id, :integer
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/fixtures/trackers.yml:
--------------------------------------------------------------------------------
1 | ---
2 | trackers_001:
3 | name: Bug
4 | id: 1
5 | is_in_chlog: true
6 | default_status_id: 1
7 | position: 1
8 | trackers_002:
9 | name: Feature
10 | id: 2
11 | is_in_chlog: true
12 | default_status_id: 1
13 | position: 2
14 | trackers_003:
15 | name: Support
16 | id: 3
17 | is_in_chlog: false
18 | default_status_id: 1
19 | position: 3
20 |
--------------------------------------------------------------------------------
/db/migrate/001_create_mappings.rb:
--------------------------------------------------------------------------------
1 | class CreateMappings < ActiveRecord::Migration
2 | def self.up
3 | create_table :mappings do |t|
4 | t.column :project_id, :integer
5 | t.column :tracker_project_id, :integer
6 | t.column :tracker_project_name, :text
7 | t.column :label, :text
8 | end
9 | end
10 |
11 | def self.down
12 | drop_table :mappings
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/spec/factories/mapping.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :mapping do
3 | project_id 1
4 | sequence(:tracker_project_id) { |n| n}
5 | sequence(:tracker_project_name) { |n| "Foo tracker project #{n}"}
6 | sequence(:label){|n| "foolabel#{n}"}
7 | estimations { |e| e = { '1' => '1', '2' => '4', '3' => '10' } }
8 | story_types { |st| st = { 'feature' => 'Feature', 'bug' => 'Bug', 'chore' => 'Support' } }
9 | end
10 | end
11 |
12 |
--------------------------------------------------------------------------------
/assets/javascripts/mappings.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function ($) {
2 | $('#tracker_project_id').on('change', function() {
3 | var tracker_project_id = $(this).val();
4 | $.ajax('/mappings/update_labels', {
5 | success: function(response) {
6 | $.each(response, function(index, label){
7 | $('#mapping_label').append("");
8 | });
9 | },
10 | data: { 'tracker_project_id': tracker_project_id }
11 | });
12 | });
13 | });
--------------------------------------------------------------------------------
/app/models/mapping.rb:
--------------------------------------------------------------------------------
1 | class Mapping < ActiveRecord::Base
2 | unloadable
3 |
4 | attr_accessible :project_id, :label, :estimations, :story_types, :tracker_project_id
5 |
6 | belongs_to :project
7 |
8 | validates :project_id, presence:true
9 | validates :tracker_project_id, presence:true
10 | validates :estimations, presence:true
11 | validates :story_types, presence:true
12 |
13 | validates_uniqueness_of :tracker_project_id, scope: :label
14 |
15 | serialize :estimations
16 | serialize :story_types
17 | end
18 |
--------------------------------------------------------------------------------
/lib/trackmine/credentials.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | class Credentials
3 |
4 | def initialize(user, configuration)
5 | self.user = user
6 | self.configuration = configuration
7 | end
8 |
9 | def password
10 | credentials_for_user['password']
11 | end
12 |
13 | def token
14 | credentials_for_user['token']
15 | end
16 |
17 | def email
18 | credentials_for_user['email']
19 | end
20 |
21 | private
22 |
23 | attr_accessor :user, :configuration
24 |
25 | def credentials_for_user
26 | configuration[user]
27 | end
28 | end
29 | end
--------------------------------------------------------------------------------
/spec/unit/lib/trackmine/issues_creator_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../../spec_helper'
2 |
3 | describe Trackmine::IssuesCreator, vcr: { cassette_name: 'issues_creator' } do
4 | let(:activity_body) { JSON.parse(File.read(json_path(activity_name))) }
5 | let(:activity) { Trackmine::Activity.new(activity_body) }
6 | let(:creator) { Trackmine::IssuesCreator.new(activity) }
7 |
8 | describe '#run' do
9 | let(:activity_name) { 'story_started' }
10 | let(:project) { Project.find(1) }
11 |
12 | it 'create issues' do
13 | expect{ creator.run }.to change { Issue.count }.by(3)
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/spec/fixtures/issue_priorities.yml:
--------------------------------------------------------------------------------
1 | ---
2 | issue_priority_01:
3 | id: 1
4 | name: 'Low'
5 | position: 1
6 | is_default: false
7 | type: 'IssuePriority'
8 | active: true
9 | project_id: nil
10 | parent_id: nil
11 | position_name: 'lowest'
12 | issue_priority_02:
13 | name: 'Normal'
14 | position: 1
15 | is_default: false
16 | type: 'IssuePriority'
17 | active: true
18 | project_id: nil
19 | parent_id: nil
20 | position_name: 'lowest'
21 | issue_priority_03:
22 | name: 'High'
23 | position: 3
24 | is_default: false
25 | type: 'IssuePriority'
26 | active: true
27 | project_id: nil
28 | parent_id: nil
29 | position_name: 'highest'
30 |
--------------------------------------------------------------------------------
/lib/trackmine/issues_creator.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | class IssuesCreator
3 |
4 | def initialize(activity)
5 | self.activity = activity
6 | end
7 |
8 | def story
9 | activity.story
10 | end
11 |
12 | def labels
13 | story.labels.to_s.split(',') || ['']
14 | end
15 |
16 | def issue_attributes
17 | {
18 | project_id: activity.project_id,
19 | story: story,
20 | author: activity.author
21 | }
22 | end
23 |
24 | def run
25 | labels.each { |label| IssueCreator.new(label, issue_attributes).run }
26 | end
27 |
28 | private
29 |
30 | attr_accessor :activity
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/lib/trackmine/story_finisher.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | class StoryFinisher
3 |
4 | def initialize(story)
5 | self.story = story
6 | end
7 |
8 | def run
9 | finish_story
10 | rescue => e
11 | raise PivotalTrackerError, "Can't finish the story id:#{story_id}. #{e}"
12 | end
13 |
14 | def finish_story
15 | case story.story_type
16 | when 'feature' then story.update(current_state: 'finished')
17 | when 'bug' then story.update(current_state: 'finished')
18 | when 'chore' then story.update(current_state: 'accepted')
19 | end
20 | end
21 |
22 | private
23 |
24 | attr_accessor :story
25 | end
26 | end
--------------------------------------------------------------------------------
/lib/trackmine/issues_restarter.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | class IssuesRestarter
3 |
4 | def initialize(issues, activity)
5 | self.issues = issues
6 | self.activity = activity
7 | end
8 |
9 | def run
10 | issues_updater.update_issues(params)
11 | end
12 |
13 | def issues_updater
14 | Trackmine::IssuesUpdater.new(issues, activity)
15 | end
16 |
17 | private
18 |
19 | attr_accessor :issues, :activity
20 |
21 | def author
22 | activity.author
23 | end
24 |
25 | def status
26 | IssueStatus.find_by_name(ACCEPTED_STATUS)
27 | end
28 |
29 | def params
30 | {status: status, assigned_to: author}
31 | end
32 | end
33 | end
--------------------------------------------------------------------------------
/spec/fixtures/issue_statuses.yml:
--------------------------------------------------------------------------------
1 | ---
2 | issue_statuses_001:
3 | id: 1
4 | name: New
5 | is_closed: false
6 | position: 1
7 | issue_statuses_002:
8 | id: 2
9 | name: Assigned
10 | is_closed: false
11 | position: 2
12 | issue_statuses_003:
13 | id: 3
14 | name: Resolved
15 | is_closed: false
16 | position: 3
17 | issue_statuses_004:
18 | name: Feedback
19 | id: 4
20 | is_closed: false
21 | position: 4
22 | issue_statuses_005:
23 | id: 5
24 | name: Closed
25 | is_closed: true
26 | position: 5
27 | issue_statuses_006:
28 | id: 6
29 | name: Rejected
30 | is_closed: true
31 | position: 6
32 | issue_statuses_007:
33 | id: 7
34 | name: Accepted
35 | is_closed: true
36 | position: 7
37 |
--------------------------------------------------------------------------------
/spec/unit/trackmine_mailer_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../spec_helper'
2 |
3 | describe TrackmineMailer do
4 | describe '.error_email' do
5 | let(:error_message) { 'Something went wrong' }
6 | let(:email) { TrackmineMailer.error_mail(error_message) }
7 |
8 | it 'delivers email' do
9 | expect {email.deliver }.to change { ActionMailer::Base.deliveries.count }
10 | end
11 |
12 | it 'has right content' do
13 | expect(email.to.first).to eql Trackmine.error_notification['recipient']
14 | expect(email.subject).to eql 'Trackmine error occurred'
15 | expect(email.body).to match /Got error from Trackmine/
16 | expect(email.body).to match /Something went wrong/
17 | end
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/fixtures/custom_fields_trackers.yml:
--------------------------------------------------------------------------------
1 | ---
2 | custom_fields_trackers_001:
3 | custom_field_id: 1
4 | tracker_id: 1
5 | custom_fields_trackers_002:
6 | custom_field_id: 2
7 | tracker_id: 1
8 | custom_fields_trackers_003:
9 | custom_field_id: 2
10 | tracker_id: 3
11 | custom_fields_trackers_004:
12 | custom_field_id: 6
13 | tracker_id: 1
14 | custom_fields_trackers_005:
15 | custom_field_id: 6
16 | tracker_id: 2
17 | custom_fields_trackers_006:
18 | custom_field_id: 6
19 | tracker_id: 3
20 | custom_fields_trackers_007:
21 | custom_field_id: 8
22 | tracker_id: 1
23 | custom_fields_trackers_008:
24 | custom_field_id: 8
25 | tracker_id: 2
26 | custom_fields_trackers_009:
27 | custom_field_id: 8
28 | tracker_id: 3
29 |
--------------------------------------------------------------------------------
/lib/trackmine/configuration.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | class Configuration
3 |
4 | def initialize
5 | load_configuration
6 | end
7 |
8 | def trackmine_path
9 | @trackmine_path ||= File.join(Rails.root, 'config', 'trackmine.yml')
10 | end
11 |
12 | def load_configuration
13 | unless File.exist?(trackmine_path)
14 | raise MissingTrackmineConfig, 'Missing trackmine.yml configuration file in /config'
15 | end
16 | self.config = YAML.load_file(trackmine_path)
17 | end
18 |
19 | def error_notification
20 | config['error_notification']
21 | end
22 |
23 | def credentials(user)
24 | Trackmine::Credentials.new(user, config)
25 | end
26 |
27 | private
28 |
29 | attr_accessor :config
30 | end
31 | end
--------------------------------------------------------------------------------
/init.rb:
--------------------------------------------------------------------------------
1 | require 'redmine'
2 | require 'pivotal_tracker'
3 | require 'unicode'
4 |
5 | Rails.logger.info 'Starting Trackmine Plugin for Redmine'
6 |
7 | require_dependency 'project_patch'
8 | require_dependency 'issue_patch'
9 |
10 | Rails.application.config.middleware.insert_before(Rack::Runtime, 'PivotalHandler' )
11 |
12 | Issue.send(:include, IssuePatch)
13 | Project.send(:include, ProjectPatch)
14 |
15 | Trackmine.set_error_notification
16 |
17 | Redmine::Plugin.register :redmine_trackmine do
18 | name 'Redmine Trackmine plugin'
19 | author 'Piotr Brudny'
20 | description 'This plugin integrates Redmine projects with Pivotal Tracker'
21 | version '2.0.1'
22 |
23 | menu :admin_menu, :mapping, {controller: :mappings, action: 'index'}, caption: 'Trackmine', last: true
24 | end
25 |
--------------------------------------------------------------------------------
/lib/trackmine/activity_reader.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | class ActivityReader
3 |
4 | def initialize(activity)
5 | self.activity = activity
6 | end
7 |
8 | def run
9 | if issues.present?
10 | update_issues
11 | elsif activity.story_started?
12 | Trackmine::IssuesCreator.new(activity).run
13 | end
14 | end
15 |
16 | def update_issues
17 | if activity.story_started?
18 | Trackmine::IssuesRestarter.new(issues, activity).run
19 | elsif activity.story_edited?
20 | Trackmine::IssuesUpdater.new(issues, activity).run
21 | end
22 | end
23 |
24 | def issues
25 | @issues ||= Issue.find_by_story_id(activity.story_id)
26 | end
27 |
28 | private
29 |
30 | attr_accessor :activity
31 | end
32 | end
33 |
34 |
--------------------------------------------------------------------------------
/spec/unit/mapping_spec.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../../spec_helper', __FILE__)
2 |
3 | describe Mapping do
4 | let(:mapping) { create :mapping }
5 |
6 | it { should belong_to(:project) }
7 |
8 | describe 'validations' do
9 | it { should validate_presence_of(:project_id) }
10 | it { should validate_presence_of(:tracker_project_id) }
11 | it { should validate_uniqueness_of(:tracker_project_id).scoped_to(:label) }
12 | it { should validate_presence_of(:estimations) }
13 | it { should validate_presence_of(:story_types) }
14 | end
15 |
16 | it 'stores hash in estimations attribute' do
17 | expect(mapping.estimations['2']).to eql '4'
18 | end
19 |
20 | it 'stores hash in story_types attribute' do
21 | expect(mapping.story_types['feature']).to eql 'Feature'
22 | end
23 | end
24 |
25 |
--------------------------------------------------------------------------------
/spec/unit/lib/trackmine/activity_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../../spec_helper'
2 |
3 | describe Trackmine::Activity, vcr: { cassette_name: 'trackmine_activity' } do
4 | let(:activity_body) { JSON.parse(File.read(json_path(activity_name))) }
5 | let(:activity) { Trackmine::Activity.new(activity_body) }
6 | let(:creator) { Trackmine::IssuesCreator.new(activity) }
7 |
8 | describe '#story' do
9 | context 'correct activity data' do
10 | let(:activity_name) { 'story_started' }
11 |
12 | it 'returns Story object' do
13 | expect(activity.story).to be_kind_of(PivotalTracker::Story)
14 | end
15 | end
16 |
17 | context 'wrong activity data' do
18 | let(:activity_body) { { a:1 }.to_json }
19 | it { expect { activity.story }.to raise_error(Trackmine::PivotalTrackerError) }
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/spec/fixtures/mappings.yml:
--------------------------------------------------------------------------------
1 | ---
2 | mappings_001:
3 | project_id: 1
4 | tracker_project_id: 1327280
5 | tracker_project_name:
6 | label: 'sank'
7 | estimations:
8 | '1': '1'
9 | '2': '4'
10 | '3': '10'
11 | story_types:
12 | feature: 'Feature'
13 | bug: 'Bug'
14 | chore: 'Support'
15 | mappings_002:
16 | project_id: 2
17 | tracker_project_id: 1327280
18 | tracker_project_name:
19 | label: 'snieg'
20 | estimations:
21 | '1': '1'
22 | '2': '4'
23 | '3': '10'
24 | story_types:
25 | feature: 'Feature'
26 | bug: 'Bug'
27 | chore: 'Support'
28 | mappings_003:
29 | project_id: 3
30 | tracker_project_id: 1327280
31 | tracker_project_name:
32 | label: 'zima'
33 | estimations:
34 | '1': '1'
35 | '2': '4'
36 | '3': '10'
37 | story_types:
38 | feature: 'Feature'
39 | bug: 'Bug'
40 | chore: 'Support'
--------------------------------------------------------------------------------
/lib/trackmine/authentication.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | module Authentication
3 | class << self
4 |
5 | def set_token(email)
6 | credentials = Trackmine::Configuration.new.credentials(email) ||
7 | raise(MissingCredentials, "Missing credentials for #{email} in trackmine.yml")
8 |
9 | credentials.token ? set_token_from_config(credentials) : set_token_from_email(credentials)
10 | PivotalTracker::Client.use_ssl = true
11 | rescue => e
12 | raise WrongCredentials.new("Wrong Pivotal Tracker credentials in trackmine.yml. #{e}")
13 | end
14 |
15 | def set_token_from_config(credentials)
16 | @token = credentials.token
17 | PivotalTracker::Client.token = @token
18 | end
19 |
20 | def set_token_from_email(credentials)
21 | @token = PivotalTracker::Client.token(credentials.email, credentials.password)
22 | end
23 |
24 | end
25 | end
26 | end
27 |
28 |
--------------------------------------------------------------------------------
/spec/unit/lib/trackmine/story_finisher_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../../spec_helper'
2 |
3 | describe Trackmine::StoryFinisher do
4 | let(:story) { double :story, story_type: story_type }
5 | let(:finisher) { Trackmine::StoryFinisher.new(story) }
6 |
7 | context 'when feature' do
8 | let(:story_type) { 'feature' }
9 | it 'changes story state to finished' do
10 | expect(story).to receive(:update).with(current_state: 'finished')
11 | finisher.run
12 | end
13 | end
14 |
15 | context 'when bug' do
16 | let(:story_type) { 'bug' }
17 | it 'changes story state to finished' do
18 | expect(story).to receive(:update).with(current_state: 'finished')
19 | finisher.run
20 | end
21 | end
22 |
23 | context 'when chore' do
24 | let(:story_type) { 'chore' }
25 | it 'changes story state to accepted' do
26 | expect(story).to receive(:update).with(current_state: 'accepted')
27 | finisher.run
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/app/views/mappings/_config.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Pivotal Tracker estimation points to Redmine estimated hours
5 |
6 |
7 | <% unless @mapping.estimations.blank? %>
8 | <% @mapping.estimations.each do |pair| %>
9 |
10 |
11 | Estimation points: <%= label_tag pair[0] %> =>
12 | <%= text_field_tag "estimations[#{pair[0]}]", pair[1], :size => 1 %> hours
13 |
14 |
15 | <% end %>
16 | <% end %>
17 |
18 |
19 |
20 |
21 |
22 |
23 | Pivotal Tracker story type to Redmine tracker name
24 |
25 |
26 | <% unless @mapping.story_types.blank? %>
27 | <% @mapping.story_types.each do |pair| %>
28 |
29 |
30 |
"<%= label_tag pair[0] %>"
to
31 | <%= select_tag "story_types[#{pair[0]}]", options_for_select(Tracker.all.map { |t| [t.name, t.name] }, pair[1] ) %>
32 |
33 |
34 | <% end %>
35 | <% end %>
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/spec/fixtures/projects_trackers.yml:
--------------------------------------------------------------------------------
1 | ---
2 | projects_trackers_001:
3 | project_id: 4
4 | tracker_id: 3
5 | projects_trackers_002:
6 | project_id: 1
7 | tracker_id: 1
8 | projects_trackers_003:
9 | project_id: 5
10 | tracker_id: 1
11 | projects_trackers_004:
12 | project_id: 1
13 | tracker_id: 2
14 | projects_trackers_005:
15 | project_id: 5
16 | tracker_id: 2
17 | projects_trackers_006:
18 | project_id: 5
19 | tracker_id: 3
20 | projects_trackers_007:
21 | project_id: 2
22 | tracker_id: 1
23 | projects_trackers_008:
24 | project_id: 2
25 | tracker_id: 2
26 | projects_trackers_009:
27 | project_id: 2
28 | tracker_id: 3
29 | projects_trackers_010:
30 | project_id: 3
31 | tracker_id: 2
32 | projects_trackers_011:
33 | project_id: 3
34 | tracker_id: 3
35 | projects_trackers_012:
36 | project_id: 4
37 | tracker_id: 1
38 | projects_trackers_013:
39 | project_id: 4
40 | tracker_id: 2
41 | projects_trackers_014:
42 | project_id: 1
43 | tracker_id: 3
44 | projects_trackers_015:
45 | project_id: 6
46 | tracker_id: 1
47 |
--------------------------------------------------------------------------------
/spec/unit/lib/trackmine/pivotal_project_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../../spec_helper'
2 |
3 | describe Trackmine::PivotalProject, vcr: { cassette_name: 'pivotal_project' } do
4 | let(:pivotal_project) { Trackmine::PivotalProject.new(1325832) }
5 |
6 | describe '#labels' do
7 | let(:labels) { pivotal_project.labels }
8 |
9 | it 'returns an array' do
10 | expect(labels).to be_kind_of(Array)
11 | end
12 |
13 | it 'returns an array of project labels' do
14 | expect(%w(deployment admin epic).in?(labels))
15 | end
16 | end
17 |
18 | describe '#participant_email', vcr: { cassette_name: 'participant_email' } do
19 | context 'with wrong attributes' do
20 | it 'raises error' do
21 | expect { pivotal_project.participant_email('noname') }
22 | .to raise_error(Trackmine::PivotalTrackerError)
23 | end
24 | end
25 |
26 | context 'with correct attributes' do
27 | it 'returns authors email' do
28 | expect(pivotal_project.participant_email('Pedro')).to eq 'pbrudny@gmail.com'
29 | end
30 | end
31 | end
32 | end
33 |
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010 Capita Unternehmensberatung GmbH
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/app/views/mappings/new.html.erb:
--------------------------------------------------------------------------------
1 | <%= javascript_include_tag 'mappings', plugin: 'redmine_trackmine' %>
2 |
3 | Map Redmine project to Pivotal Tracker project and labels.
4 | <%= form_for :mapping , :url => { controller: :mappings, action: :create } do |f| %>
5 |
6 |
7 |
8 |
11 |
12 |
13 | <%= f.select :project_id, options_for_select(@projects.map { |p| [p.name, p.id]}) %>
14 |
15 |
16 |
17 |
18 |
19 | <%= select_tag 'tracker_project_id', options_for_select(@tracker_projects.map { |p| [p.name, p.id] } ) %>
20 |
21 |
22 |
23 |
24 |
25 | <%= f.select :label, @labels %>
26 |
27 |
28 |
29 |
30 | <%= render :partial => 'config' %>
31 |
32 |
33 |
34 |
35 | <%= submit_tag 'Add mapping',:name=>'save' %>
36 | <%= link_to 'Cancel', :action => :index %>
37 |
38 |
39 | <% end %>
40 |
41 |
--------------------------------------------------------------------------------
/lib/pivotal_handler.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper')
2 | require 'sinatra'
3 |
4 | class PivotalHandler < Sinatra::Base
5 |
6 | post '/pivotal_activity.json' do
7 | pivotal_body = JSON.parse(request.body.read.to_s)
8 | return [202, 'It is not a correct Pivotal Tracker message'] if pivotal_body['kind'].nil?
9 | if pivotal_body['kind'] == 'story_update_activity'
10 | begin
11 | handler_logger 'Got the post request from PivotalTracker'
12 | Trackmine.read_activity(Trackmine::Activity.new(pivotal_body))
13 | rescue => e
14 | handler_logger("Can't consume the request from PivotalTracker: #{e}")
15 | TrackmineMailer.error_mail("Error while reading activity message from Pivotal Tracker: #{e}").deliver
16 |
17 | return [202, 'Not supported activity']
18 | end
19 | return [200, 'Got the activity']
20 | else
21 | return [202, 'Not supported event_type']
22 | end
23 | end
24 |
25 | private
26 |
27 | def handler_logger(message)
28 | Rails.logger.tagged('PivotalHandler') { Rails.logger.info message }
29 | end
30 |
31 | end
--------------------------------------------------------------------------------
/spec/unit/lib/trackmine/issues_updater_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../../spec_helper'
2 |
3 | describe Trackmine::IssuesUpdater, vcr: { cassette_name: 'issues_updater' } do
4 | let(:project) { Project.find 1 }
5 | let(:issue) { Issue.find 1 }
6 | let(:activity) { double :activity, project_id: 888 }
7 | let(:issues_updater) { Trackmine::IssuesUpdater.new([issue], activity) }
8 |
9 | describe '#run' do
10 | context 'with mapping' do
11 | let!(:mapping) { create :mapping, project: project, tracker_project_id: 888 }
12 |
13 | context 'description changed' do
14 | let(:params) { { description: 'new description' } }
15 |
16 | it 'update issues description' do
17 | issues_updater.update_issues(params)
18 | expect(issue.description).to eq 'new description'
19 | end
20 | end
21 |
22 | context 'subject changed' do
23 | let(:params) { { subject: 'new subject' } }
24 |
25 | it 'update issues subject' do
26 | issues_updater.update_issues(params)
27 | expect(issue.subject).to eq 'new subject'
28 | end
29 | end
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/app/views/mappings/index.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= link_to 'New mapping', {:action => 'new'}, :class => 'icon icon-add' %>
3 |
4 |
5 | All mappings between Redmine projects and Pivotal Tracker projects (or labels)
6 |
7 |
8 |
9 |
10 |
11 | |
12 | Redmine project
13 | |
14 |
15 | Pivotal Tracker project
16 | |
17 |
18 | Label
19 | |
20 |
21 | |
22 |
23 |
24 |
25 |
26 | <% @mappings.each do |mapping|%>
27 |
28 | |
29 | <%= mapping.project.name %>
30 | |
31 |
32 | <%= mapping.tracker_project_name%>
33 | |
34 |
35 | <%= mapping.label %>
36 | |
37 |
38 |
39 | <%= link_to image_tag('/images/edit.png')+'Edit', edit_mapping_path(mapping) %> |
40 | <%= link_to image_tag('/images/delete.png')+'Delete', mapping_path(mapping), :method => :delete %>
41 |
42 | |
43 |
44 | <% end %>
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/lib/trackmine/issues_updater.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | class IssuesUpdater
3 |
4 | def initialize(issues, activity)
5 | self.issues = issues
6 | self.activity = activity
7 | end
8 |
9 | def run
10 | story_update
11 | end
12 |
13 | def story_update
14 | update_issues(params_changed)
15 | end
16 |
17 | def params_changed
18 | if new_value['description'].present?
19 | { description: "#{story_url}\r\n#{new_value['description']}" }
20 | elsif new_value['name'].present?
21 | { subject: new_value['name'] }
22 | end
23 | end
24 |
25 | def update_issues(params)
26 | issues.each { |issue| issue.update_attributes!(params) if mapping_still_exists?(issue) }
27 | end
28 |
29 | def mapping_still_exists?(issue)
30 | issue.project.mappings.where(tracker_project_id: pivotal_project_id).present?
31 | end
32 |
33 | private
34 |
35 | attr_accessor :issues, :activity
36 |
37 | def story_url
38 | activity.story.url
39 | end
40 |
41 | def new_value
42 | activity.new_value
43 | end
44 |
45 | def pivotal_project_id
46 | activity.project_id
47 | end
48 | end
49 | end
--------------------------------------------------------------------------------
/spec/fixtures/json/story_subject_update.json:
--------------------------------------------------------------------------------
1 | {
2 | "kind": "story_update_activity",
3 | "guid": "1327280_9",
4 | "project_version": 9,
5 | "message": "Pedro edited this feature",
6 | "highlight": "edited",
7 | "changes": [
8 | {
9 | "kind": "story",
10 | "change_type": "update",
11 | "id": 94184406,
12 | "original_values": {
13 | "name": "jazda na sankach",
14 | "updated_at": 1431098967000
15 | },
16 | "new_values": {
17 | "name": "jazda na sankach w parach",
18 | "updated_at": 1431099317000
19 | },
20 | "name": "jazda na sankach w parach",
21 | "story_type": "feature"
22 | }
23 | ],
24 | "primary_resources": [
25 | {
26 | "kind": "story",
27 | "id": 94184406,
28 | "name": "jazda na sankach w parach",
29 | "story_type": "feature",
30 | "url": "https://www.pivotaltracker.com/story/show/94184406"
31 | }
32 | ],
33 | "project": {
34 | "kind": "project",
35 | "id": 1327280,
36 | "name": "ziomal"
37 | },
38 | "performed_by": {
39 | "kind": "person",
40 | "id": 1651216,
41 | "name": "Pedro",
42 | "initials": "PE"
43 | },
44 | "occurred_at": 1431099317000
45 | }
--------------------------------------------------------------------------------
/lib/trackmine/pivotal_project.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | class PivotalProject
3 |
4 | def initialize(project_id)
5 | self.project_id = project_id
6 | set_super_token
7 | end
8 |
9 | def project
10 | PivotalTracker::Project.find(project_id)
11 | rescue => e
12 | raise PivotalTrackerError, "Can't get Pivotal Project id: #{project_id}. #{e}"
13 | end
14 |
15 | def story(story_id)
16 | project.stories.find(story_id)
17 | rescue => e
18 | raise PivotalTrackerError, "Can't get story: #{story_id} from Pivotal Tracker project: #{project_id}. #{e}"
19 | end
20 |
21 | def labels
22 | project.stories.all
23 | .select { |s| !s.labels.nil?}
24 | .map { |s| Unicode.downcase(s.labels) }.join(',').split(',').uniq
25 | end
26 |
27 | def participant_email(name)
28 | project.memberships.all.select { |m| m.name == name }[0].email
29 | rescue => e
30 | raise PivotalTrackerError, "Can't get Tracker user: #{name} in project id: #{project_id}. #{e}"
31 | end
32 |
33 | private
34 |
35 | attr_accessor :project_id
36 |
37 | def set_super_token
38 | Trackmine::Authentication.set_token('super_user') if @token.nil?
39 | end
40 | end
41 | end
--------------------------------------------------------------------------------
/spec/unit/lib/trackmine/activity_reader_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../../spec_helper'
2 |
3 | describe Trackmine::ActivityReader, vcr: { cassette_name: 'activity_reader' } do
4 | let(:reader) { Trackmine::ActivityReader.new(activity) }
5 |
6 | context 'story started' do
7 | context 'no issues yet' do
8 | let(:activity) { double :activity, :'story_edited?'=> false, story_id: 1, :'story_started?'=> true }
9 | it 'runs Trackmine::IssuesCreator' do
10 | expect_any_instance_of(Trackmine::IssuesCreator).to receive(:run)
11 | reader.run
12 | end
13 | end
14 |
15 | context 'issues exist' do
16 | let(:activity) { double :activity, :'story_edited?'=> false, story_id: 92844256, :'story_started?'=> true }
17 | it 'runs Trackmine::IssuesRestarter' do
18 | expect_any_instance_of(Trackmine::IssuesRestarter).to receive(:run)
19 | reader.run
20 | end
21 | end
22 | end
23 |
24 | context 'story edited' do
25 | let(:activity) { double :activity, :'story_edited?'=> true, story_id: 92844256, :'story_started?'=> false }
26 | it 'runs Trackmine::IssuesUpdater' do
27 | expect_any_instance_of(Trackmine::IssuesUpdater).to receive(:run)
28 | reader.run
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/spec/fixtures/json/story_description_update.json:
--------------------------------------------------------------------------------
1 | {
2 | "kind": "story_update_activity",
3 | "guid": "1327280_10",
4 | "project_version": 10,
5 | "message": "Pedro edited this feature",
6 | "highlight": "edited",
7 | "changes": [
8 | {
9 | "kind": "story",
10 | "change_type": "update",
11 | "id": 94184406,
12 | "original_values": {
13 | "description": "jazda z gorki w dol po sniegu",
14 | "updated_at": 1431099317000
15 | },
16 | "new_values": {
17 | "description": "jazda z gorki w dol po sniegu w parach czyli we dwoje\n",
18 | "updated_at": 1431099420000
19 | },
20 | "name": "jazda na sankach w parach",
21 | "story_type": "feature"
22 | }
23 | ],
24 | "primary_resources": [
25 | {
26 | "kind": "story",
27 | "id": 94184406,
28 | "name": "jazda na sankach w parach",
29 | "story_type": "feature",
30 | "url": "https://www.pivotaltracker.com/story/show/94184406"
31 | }
32 | ],
33 | "project": {
34 | "kind": "project",
35 | "id": 1327280,
36 | "name": "ziomal"
37 | },
38 | "performed_by": {
39 | "kind": "person",
40 | "id": 1651216,
41 | "name": "Pedro",
42 | "initials": "PE"
43 | },
44 | "occurred_at": 1431099420000
45 | }
--------------------------------------------------------------------------------
/lib/trackmine/activity.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | class Activity
3 |
4 | def initialize(activity)
5 | self.activity = activity
6 | end
7 |
8 | def project_id
9 | activity['project']['id'] if activity['project']
10 | end
11 |
12 | def story_id
13 | activity['primary_resources'].select { |r| r['kind'] == 'story' }.first['id'] if activity['primary_resources']
14 | end
15 |
16 | def story_started?
17 | activity['highlight'] == 'started' && activity['kind'] == 'story_update_activity'
18 | end
19 |
20 | def story_edited?
21 | activity['highlight'] == 'edited' && activity['kind'] == 'story_update_activity'
22 | end
23 |
24 | def author_name
25 | activity['performed_by']['name']
26 | end
27 |
28 | def author
29 | email = project.participant_email(author_name)
30 | User.find_by_mail(email)
31 | end
32 |
33 | def project
34 | @pivotal_project ||= Trackmine::PivotalProject.new(project_id)
35 | end
36 |
37 | def new_value
38 | activity['changes'].select { |r| r['kind'] == 'story' }.first['new_values'] if activity['changes']
39 | end
40 |
41 | def story
42 | @story ||= project.story(story_id)
43 | end
44 |
45 | private
46 |
47 | attr_accessor :activity
48 |
49 | end
50 | end
--------------------------------------------------------------------------------
/spec/unit/lib/pivotal_handler_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 | require 'rack/test'
3 |
4 | describe PivotalHandler do
5 | include Rack::Test::Methods
6 |
7 | def app
8 | PivotalHandler.new
9 | end
10 |
11 | context 'pivotal_callback' do
12 |
13 | describe 'POST /pivotal_activity.json' do
14 |
15 | context 'when wrong body' do
16 | let!(:post_request) { post '/pivotal_activity.json', { a:1 }.to_json }
17 |
18 | it 'returns 202' do
19 | expect(last_response.status).to be == 202
20 | end
21 |
22 | it 'returns wrong message' do
23 | expect(last_response.body).to be == 'It is not a correct Pivotal Tracker message'
24 | end
25 | end
26 |
27 | context 'when proper body' do
28 | before { expect(Trackmine).to receive(:read_activity) }
29 |
30 | let(:story_update) do
31 | { kind: 'story_update_activity', highlight: 'started', guid: '1327280_10' }
32 | end
33 |
34 | let!(:post_request) { post('/pivotal_activity.json', story_update.to_json, content_type: :json) }
35 |
36 | it 'returns 200' do
37 | expect(last_response.status).to be == 200
38 | end
39 |
40 | it 'returns success message' do
41 | expect(last_response.body).to be == 'Got the activity'
42 | end
43 | end
44 | end
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/lib/trackmine/custom_values_creator.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | class CustomValuesCreator
3 |
4 | def initialize(project_id, story_id, issue_id)
5 | self.project_id = project_id
6 | self.story_id = story_id
7 | self.issue_id = issue_id
8 | end
9 |
10 | def run
11 | create_custom_values
12 | end
13 |
14 | def custom_field_pivotal_story_id
15 | CustomField.find_by(name: 'Pivotal Story ID').id
16 | end
17 |
18 | def custom_field_pivotal_project_id
19 | CustomField.find_by(name: 'Pivotal Project ID').id
20 | end
21 |
22 | def create_custom_values
23 | CustomValue.create!(
24 | customized_type: Issue,
25 | custom_field_id: custom_field_pivotal_project_id,
26 | customized_id: issue_id,
27 | value: project_id
28 | )
29 |
30 | CustomValue.create!(
31 | customized_type: Issue,
32 | custom_field_id: custom_field_pivotal_story_id,
33 | customized_id: issue_id,
34 | value: story_id
35 | )
36 | end
37 |
38 | def add_comments
39 | story.notes.all.each do |note|
40 | user = User.find_by_mail(get_user_email(story.project_id, note.author))
41 | journal = issue.journals.new(notes: note.text)
42 | journal.user_id = user.id unless user.nil?
43 | journal.save
44 | end
45 | end
46 |
47 | private
48 |
49 | attr_accessor :project_id, :story_id, :issue_id
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # Load test_helper from Redmine main project
2 | require File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper')
3 | require 'bundler'
4 | Bundler.setup(:default, :spec)
5 | require 'factory_girl'
6 | require 'rack/test'
7 | require 'vcr'
8 |
9 | # load factories manually. Otherwise load it from redmine app.
10 | # if (!FactoryGirl.factories || FactoryGirl.factories.empty?)
11 | Dir.glob(File.dirname(__FILE__) + "/factories/*.rb").each do |factory|
12 | require factory
13 | end
14 |
15 | RSpec.configure do |config|
16 | config.color = true
17 | config.tty = true
18 | config.formatter = :documentation
19 | config.include FactoryGirl::Syntax::Methods
20 | config.treat_symbols_as_metadata_keys_with_true_values = true
21 | end
22 |
23 | VCR.configure do |c|
24 | c.cassette_library_dir = File.dirname(__FILE__) + '/cassettes'
25 | c.hook_into :webmock
26 | c.configure_rspec_metadata!
27 | end
28 |
29 | def json_path(fixture)
30 | File.dirname(__FILE__) + "/fixtures/json/#{fixture}.json"
31 | end
32 |
33 |
34 | def fixtures
35 | %i(
36 | users
37 | email_addresses
38 | projects
39 | custom_fields
40 | custom_fields_projects
41 | custom_fields_trackers
42 | custom_values
43 | trackers
44 | projects_trackers
45 | issue_statuses
46 | issue_priorities
47 | issues
48 | mappings
49 | )
50 | end
51 |
52 | ActiveRecord::FixtureSet.create_fixtures(File.dirname(__FILE__) + '/fixtures/', fixtures)
53 |
--------------------------------------------------------------------------------
/spec/fixtures/email_addresses.yml:
--------------------------------------------------------------------------------
1 | ---
2 | email_address_001:
3 | id: 1
4 | user_id: 1
5 | address: admin@somenet.foo
6 | is_default: true
7 | created_on: 2006-07-19 19:34:07 +02:00
8 | updated_on: 2006-07-19 19:34:07 +02:00
9 | email_address_002:
10 | id: 2
11 | user_id: 2
12 | address: pbrudny@gmail.com
13 | is_default: true
14 | created_on: 2006-07-19 19:34:07 +02:00
15 | updated_on: 2006-07-19 19:34:07 +02:00
16 | email_address_003:
17 | id: 3
18 | user_id: 3
19 | address: dlopper@somenet.foo
20 | is_default: true
21 | created_on: 2006-07-19 19:34:07 +02:00
22 | updated_on: 2006-07-19 19:34:07 +02:00
23 | email_address_004:
24 | id: 4
25 | user_id: 4
26 | address: rhill@somenet.foo
27 | is_default: true
28 | created_on: 2006-07-19 19:34:07 +02:00
29 | updated_on: 2006-07-19 19:34:07 +02:00
30 | email_address_005:
31 | id: 5
32 | user_id: 5
33 | address: dlopper2@somenet.foo
34 | is_default: true
35 | created_on: 2006-07-19 19:34:07 +02:00
36 | updated_on: 2006-07-19 19:34:07 +02:00
37 | email_address_007:
38 | id: 7
39 | user_id: 7
40 | address: someone@foo.bar
41 | is_default: true
42 | created_on: 2006-07-19 19:34:07 +02:00
43 | updated_on: 2006-07-19 19:34:07 +02:00
44 | email_address_008:
45 | id: 8
46 | user_id: 8
47 | address: miscuser8@foo.bar
48 | is_default: true
49 | created_on: 2006-07-19 19:34:07 +02:00
50 | updated_on: 2006-07-19 19:34:07 +02:00
51 | email_address_009:
52 | id: 9
53 | user_id: 9
54 | address: miscuser9@foo.bar
55 | is_default: true
56 | created_on: 2006-07-19 19:34:07 +02:00
57 | updated_on: 2006-07-19 19:34:07 +02:00
58 |
--------------------------------------------------------------------------------
/spec/unit/lib/trackmine/issue_creator_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../../spec_helper'
2 |
3 | describe Trackmine::IssueCreator, vcr: { cassette_name: 'issue_creator' } do
4 | let(:label) { 'zima' }
5 | let(:author) { User.find(2) }
6 | let(:project_id) { '1327280' }
7 | let(:story) { Trackmine::PivotalProject.new(project_id).story(94184406) }
8 | let(:issue_attributes) do
9 | {
10 | project_id: '1327280',
11 | story: story,
12 | author: author
13 | }
14 | end
15 | let(:creator) { Trackmine::IssueCreator.new(label, issue_attributes) }
16 |
17 | describe '#run' do
18 | let(:issue) { Issue.find_by_story_id(94184406).last }
19 | it 'creates custom values' do
20 | expect{ creator.run }.to change { CustomValue.count }.by(4)
21 | end
22 |
23 | it 'runs CustomValueCreator' do
24 | expect_any_instance_of(Trackmine::CustomValuesCreator).to receive(:run)
25 | creator.run
26 | end
27 |
28 | it 'create a proper Feature issue' do
29 | expect(issue).to be_an_instance_of Issue
30 | expect(issue.subject).to eq 'jazda na sankach w trojkach'
31 | expect(issue.description).to eq "https://www.pivotaltracker.com/story/show/94184406\r\njazda z gorki w dol po sniegu w parach czyli w trzy osoby\r\n"
32 | expect(issue.tracker.name).to eq 'Feature'
33 | expect(issue.status.name).to eq 'Accepted'
34 | expect(issue.estimated_hours).to eq 1.0
35 | expect(issue.author.mail).to eq 'pbrudny@gmail.com'
36 | expect(issue.author_id).to eq issue.assigned_to_id
37 | expect(issue.pivotal_project_id).to eq 1327280
38 | expect(issue.pivotal_story_id).to eq 94184406
39 | expect(issue.journals.size).to eq 0
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/lib/trackmine.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | ACCEPTED_STATUS = 'Accepted'
3 |
4 | WrongActivityData = Class.new(StandardError)
5 | MissingTrackmineConfig = Class.new(StandardError)
6 | MissingCredentials = Class.new(StandardError)
7 | WrongCredentials = Class.new(StandardError)
8 | MissingTrackmineMapping = Class.new(StandardError)
9 | WrongTrackmineConfiguration = Class.new(StandardError)
10 | PivotalTrackerError = Class.new(StandardError)
11 |
12 | class << self
13 | attr_writer :error_notification
14 |
15 | def set_error_notification
16 | @error_notification = Trackmine::Configuration.new.error_notification
17 | end
18 |
19 | def error_notification
20 | @error_notification
21 | end
22 |
23 | def projects
24 | PivotalTracker::Project.all
25 | end
26 |
27 | def set_token(email)
28 | Trackmine::Authentication.set_token(email)
29 | end
30 |
31 | def project_labels(tracker_project_id)
32 | Trackmine::PivotalProject.new(tracker_project_id).labels
33 | end
34 |
35 | def read_activity(activity)
36 | Trackmine::ActivityReader.new(activity).run
37 | end
38 |
39 | def create_issues(activity)
40 | Trackmine::IssuesCreator.new(activity).run
41 | end
42 |
43 | def get_user_email(project_id, name)
44 | Trackmine::PivotalProject.new(project_id).participant_email(name)
45 | end
46 |
47 | def get_mapping(tracker_project_id, label)
48 | Mapping.where(['tracker_project_id=? AND label=? ', tracker_project_id, label.to_s]).first
49 | end
50 |
51 | def finish_story(project_id, story_id)
52 | story = Trackmine::PivotalProject.new(project_id).story(story_id)
53 | Trackmine::StoryFinisher.new(story).run
54 | end
55 | end
56 | end
57 |
58 |
--------------------------------------------------------------------------------
/lib/issue_patch.rb:
--------------------------------------------------------------------------------
1 | require_dependency 'issue'
2 |
3 | module IssuePatch
4 |
5 | def self.included(klass) # :nodoc:
6 |
7 | klass.class_eval do
8 | unloadable # Send unloadable so it will not be unloaded in development
9 |
10 | before_update :finish_story_when_closed_or_rejected
11 |
12 | def self.find_by_story_id(story_id)
13 | Issue.joins({custom_values: :custom_field})
14 | .where("custom_fields.name=? AND custom_values.value=?", 'Pivotal Story ID', story_id.to_s)
15 | end
16 |
17 | def pivotal_custom_value(name)
18 | CustomValue.joins(:custom_field).where(custom_fields: {name: name}, customized_id: self.id).first
19 | end
20 |
21 | def pivotal_project_id=(project_id)
22 | pivotal_custom_value('Pivotal Project ID').update_attributes!(value: project_id.to_s)
23 | end
24 |
25 | def pivotal_project_id
26 | pivotal_custom_value('Pivotal Project ID').try(:value).to_i
27 | end
28 |
29 | def pivotal_story_id=(story_id)
30 | pivotal_custom_value('Pivotal Story ID').update_attributes!(value: story_id.to_s)
31 | end
32 |
33 | def pivotal_story_id
34 | pivotal_custom_value('Pivotal Story ID').try(:value).to_i
35 | end
36 |
37 | def finish_story_when_closed_or_rejected
38 | Trackmine.finish_story(pivotal_project_id, pivotal_story_id) if issue_closed? && pivotal_assigned?
39 | rescue => e
40 | error_message = "Error while closing Story ID:'#{pivotal_story_id}' in Project ID:'#{pivotal_project_id}' : #{e}"
41 | TrackmineMailer.deliver_error_mail(error_message)
42 | end
43 |
44 | def issue_closed?
45 | status_id_changed? && status.is_closed?
46 | end
47 |
48 | def pivotal_assigned?
49 | pivotal_story_id != 0 || pivotal_project_id != 0
50 | end
51 | end
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/spec/fixtures/projects.yml:
--------------------------------------------------------------------------------
1 | ---
2 | projects_001:
3 | created_on: 2006-07-19 19:13:59 +02:00
4 | name: eCookbook
5 | updated_on: 2006-07-19 22:53:01 +02:00
6 | id: 1
7 | description: Recipes management application
8 | homepage: http://ecookbook.somenet.foo/
9 | is_public: true
10 | identifier: ecookbook
11 | parent_id:
12 | lft: 1
13 | rgt: 10
14 | projects_002:
15 | created_on: 2006-07-19 19:14:19 +02:00
16 | name: OnlineStore
17 | updated_on: 2006-07-19 19:14:19 +02:00
18 | id: 2
19 | description: E-commerce web site
20 | homepage: ""
21 | is_public: false
22 | identifier: onlinestore
23 | parent_id:
24 | lft: 11
25 | rgt: 12
26 | projects_003:
27 | created_on: 2006-07-19 19:15:21 +02:00
28 | name: eCookbook Subproject 1
29 | updated_on: 2006-07-19 19:18:12 +02:00
30 | id: 3
31 | description: eCookBook Subproject 1
32 | homepage: ""
33 | is_public: true
34 | identifier: subproject1
35 | parent_id: 1
36 | lft: 6
37 | rgt: 7
38 | projects_004:
39 | created_on: 2006-07-19 19:15:51 +02:00
40 | name: eCookbook Subproject 2
41 | updated_on: 2006-07-19 19:17:07 +02:00
42 | id: 4
43 | description: eCookbook Subproject 2
44 | homepage: ""
45 | is_public: true
46 | identifier: subproject2
47 | parent_id: 1
48 | lft: 8
49 | rgt: 9
50 | projects_005:
51 | created_on: 2006-07-19 19:15:51 +02:00
52 | name: Private child of eCookbook
53 | updated_on: 2006-07-19 19:17:07 +02:00
54 | id: 5
55 | description: This is a private subproject of a public project
56 | homepage: ""
57 | is_public: false
58 | identifier: private-child
59 | parent_id: 1
60 | lft: 2
61 | rgt: 5
62 | projects_006:
63 | created_on: 2006-07-19 19:15:51 +02:00
64 | name: Child of private child
65 | updated_on: 2006-07-19 19:17:07 +02:00
66 | id: 6
67 | description: This is a public subproject of a private project
68 | homepage: ""
69 | is_public: true
70 | identifier: project6
71 | parent_id: 5
72 | lft: 3
73 | rgt: 4
74 |
--------------------------------------------------------------------------------
/spec/fixtures/issues.yml:
--------------------------------------------------------------------------------
1 | ---
2 | issues_001:
3 | created_on: <%= 3.days.ago.to_s(:db) %>
4 | project_id: 1
5 | updated_on: <%= 1.day.ago.to_s(:db) %>
6 | priority_id: 4
7 | subject: Cannot print recipes
8 | id: 1
9 | fixed_version_id:
10 | category_id: 1
11 | description: Unable to print recipes
12 | tracker_id: 1
13 | assigned_to_id:
14 | author_id: 2
15 | status_id: 1
16 | start_date: <%= 1.day.ago.to_date.to_s(:db) %>
17 | due_date: <%= 10.day.from_now.to_date.to_s(:db) %>
18 | root_id: 1
19 | lft: 1
20 | rgt: 2
21 | lock_version: 3
22 | issues_002:
23 | created_on: 2006-07-19 21:04:21 +02:00
24 | project_id: 1
25 | updated_on: 2006-07-19 21:09:50 +02:00
26 | priority_id: 5
27 | subject: Add ingredients categories
28 | id: 2
29 | fixed_version_id: 2
30 | category_id:
31 | description: Ingredients of the recipe should be classified by categories
32 | tracker_id: 2
33 | assigned_to_id: 3
34 | author_id: 2
35 | status_id: 2
36 | start_date: <%= 2.day.ago.to_date.to_s(:db) %>
37 | due_date:
38 | root_id: 2
39 | lft: 1
40 | rgt: 2
41 | lock_version: 3
42 | done_ratio: 30
43 | issues_003:
44 | created_on: 2006-07-19 21:07:27 +02:00
45 | project_id: 1
46 | updated_on: 2006-07-19 21:07:27 +02:00
47 | priority_id: 4
48 | subject: Error 281 when updating a recipe
49 | id: 3
50 | fixed_version_id:
51 | category_id:
52 | description: Error 281 is encountered when saving a recipe
53 | tracker_id: 1
54 | assigned_to_id: 3
55 | author_id: 2
56 | status_id: 1
57 | start_date: <%= 15.day.ago.to_date.to_s(:db) %>
58 | due_date: <%= 5.day.ago.to_date.to_s(:db) %>
59 | root_id: 3
60 | lft: 1
61 | rgt: 2
62 | issues_004:
63 | created_on: <%= 5.days.ago.to_s(:db) %>
64 | project_id: 2
65 | updated_on: <%= 2.days.ago.to_s(:db) %>
66 | priority_id: 4
67 | subject: Issue on project 2
68 | id: 4
69 | fixed_version_id:
70 | category_id:
71 | description: Issue on project 2
72 | tracker_id: 1
73 | assigned_to_id: 2
74 | author_id: 2
75 | status_id: 1
76 | root_id: 4
77 | lft: 1
78 | rgt: 2
--------------------------------------------------------------------------------
/lib/trackmine/issue_creator.rb:
--------------------------------------------------------------------------------
1 | module Trackmine
2 | class IssueCreator
3 |
4 | def initialize(label, issue_attributes)
5 | self.label = label
6 | self.issue_attributes = issue_attributes
7 | end
8 |
9 | def run
10 | create_issue
11 | add_comments
12 | end
13 |
14 | def description
15 | story.url + "\r\n" + story.description
16 | end
17 |
18 | def status
19 | IssueStatus.find_by(name: ACCEPTED_STATUS) ||
20 | raise(WrongTrackmineConfiguration, "Can't find Redmine IssueStatus: #{ACCEPTED_STATUS} ")
21 | end
22 |
23 | def issue_params
24 | {
25 | subject: story.name,
26 | description: description,
27 | author_id: author.id,
28 | assigned_to_id: author.id,
29 | status_id: status.id,
30 | priority_id: 1,
31 | }
32 | end
33 |
34 | def story
35 | issue_attributes[:story]
36 | end
37 |
38 | def project_id
39 | issue_attributes[:project_id]
40 | end
41 |
42 | def author
43 | issue_attributes[:author]
44 | end
45 |
46 | def mapping_params
47 | {
48 | tracker_id: tracker.id,
49 | estimated_hours: estimated_hours
50 | }
51 | end
52 |
53 | def mapping
54 | @mapping ||= Trackmine.get_mapping(project_id, Unicode.downcase(label))
55 | end
56 |
57 | def tracker
58 | Tracker.find_by_name(mapping.story_types[story.story_type])
59 | end
60 |
61 | def estimated_hours
62 | mapping.estimations[story.estimate.to_s].to_i
63 | end
64 |
65 | def add_comments
66 | story.notes.all.each do |note|
67 | user = User.find_by_mail(get_user_email(story.project_id, note.author))
68 | journal = issue.journals.create(notes: note.text, user: user)
69 | end
70 | end
71 |
72 | def create_issue
73 | return if mapping.try(:project).nil?
74 | return if tracker.nil?
75 | issue = mapping.project.issues.create!(issue_params.merge(mapping_params))
76 | Trackmine::CustomValuesCreator.new(project_id, story.id, issue.id).run
77 | end
78 |
79 | private
80 |
81 | attr_accessor :label, :issue_attributes
82 | end
83 | end
84 |
--------------------------------------------------------------------------------
/app/controllers/mappings_controller.rb:
--------------------------------------------------------------------------------
1 | class MappingsController < ApplicationController
2 | unloadable
3 |
4 | before_filter :require_admin
5 | before_filter :set_token
6 | before_filter :set_mapping, only: [:edit, :update, :destroy]
7 |
8 | def index
9 | @mappings = Mapping.all
10 | end
11 |
12 | def new
13 | @mapping = Mapping.new
14 | @mapping.estimations = { 1 => 1, 2 => 4, 3 => 10 }
15 | @mapping.story_types = { 'feature' => 'Feature', 'bug' => 'Bug', 'chore' => 'Support' }
16 | @projects = Project.all
17 | @tracker_projects = Trackmine.projects
18 | @labels = [['..choose..','']]
19 | end
20 |
21 | def edit
22 | end
23 |
24 | def create
25 | @mapping = Mapping.new(mapping_params)
26 |
27 | @mapping.tracker_project_id = tracker_project_id
28 | @mapping.tracker_project_name = PivotalTracker::Project.find(tracker_project_id.to_i).name
29 | if @mapping.save
30 | flash[:notice] = 'Mapping was successfully added.'
31 | redirect_to action: 'index'
32 | else
33 | flash[:error] = "Can't map these projects. #{error_message}"
34 | redirect_to action: 'new'
35 | end
36 | end
37 |
38 | def update
39 | if @mapping.update_attributes(estimations: params[:estimations], story_types: params[:story_types])
40 | flash[:notice] = 'Updated successfully.'
41 | redirect_to action: 'index'
42 | else
43 | flash[:error] = "Can't save that configuration. #{error_message}"
44 | redirect_to action: 'new'
45 | end
46 | end
47 |
48 | def destroy
49 | if @mapping.destroy
50 | flash[:notice] = 'Mapping removed.'
51 | else
52 | flash[:error] = 'Mapping could not be removed.'
53 | end
54 | redirect_to action: 'index', project_id: @project
55 | end
56 |
57 | def update_labels
58 | @labels = Trackmine.project_labels(tracker_project_id.to_i)
59 | respond_to do |format|
60 | format.json { render json: @labels }
61 | end
62 | end
63 |
64 | private
65 |
66 | def set_token
67 | Trackmine::Authentication.set_token(User.current.mail)
68 | end
69 |
70 | def mapping_params
71 | params.require(:mapping).merge(estimations: params[:estimations], story_types: params[:story_types])
72 | end
73 |
74 | def tracker_project_id
75 | params.require(:tracker_project_id)
76 | end
77 |
78 | def set_mapping
79 | @mapping = Mapping.find(params[:id])
80 | end
81 |
82 | def error_message
83 | @mapping.errors.full_messages.to_sentence
84 | end
85 |
86 | end
87 |
--------------------------------------------------------------------------------
/spec/fixtures/custom_values.yml:
--------------------------------------------------------------------------------
1 | ---
2 | custom_values_006:
3 | customized_type: Issue
4 | custom_field_id: 2
5 | customized_id: 3
6 | id: 6
7 | value: "125"
8 | custom_values_007:
9 | customized_type: Project
10 | custom_field_id: 3
11 | customized_id: 1
12 | id: 7
13 | value: Stable
14 | custom_values_001:
15 | customized_type: Principal
16 | custom_field_id: 4
17 | customized_id: 3
18 | id: 1
19 | value: ""
20 | custom_values_002:
21 | customized_type: Principal
22 | custom_field_id: 4
23 | customized_id: 4
24 | id: 2
25 | value: 01 23 45 67 89
26 | custom_values_003:
27 | customized_type: Principal
28 | custom_field_id: 4
29 | customized_id: 2
30 | id: 3
31 | value: "01 42 50 00 00"
32 | custom_values_004:
33 | customized_type: Issue
34 | custom_field_id: 2
35 | customized_id: 1
36 | id: 4
37 | value: "125"
38 | custom_values_005:
39 | customized_type: Issue
40 | custom_field_id: 2
41 | customized_id: 2
42 | id: 5
43 | value: ""
44 | custom_values_008:
45 | customized_type: Issue
46 | custom_field_id: 1
47 | customized_id: 3
48 | id: 8
49 | value: "MySQL"
50 | custom_values_009:
51 | customized_type: Issue
52 | custom_field_id: 2
53 | customized_id: 7
54 | id: 9
55 | value: "this is a stringforcustomfield search"
56 | custom_values_010:
57 | customized_type: Issue
58 | custom_field_id: 6
59 | customized_id: 1
60 | id: 10
61 | value: "2.1"
62 | custom_values_011:
63 | customized_type: Issue
64 | custom_field_id: 6
65 | customized_id: 2
66 | id: 11
67 | value: "2.05"
68 | custom_values_012:
69 | customized_type: Issue
70 | custom_field_id: 6
71 | customized_id: 3
72 | id: 12
73 | value: "11.65"
74 | custom_values_013:
75 | customized_type: Issue
76 | custom_field_id: 6
77 | customized_id: 7
78 | id: 13
79 | value: ""
80 | custom_values_014:
81 | customized_type: Issue
82 | custom_field_id: 6
83 | customized_id: 5
84 | id: 14
85 | value: "-7.6"
86 | custom_values_015:
87 | customized_type: Enumeration
88 | custom_field_id: 7
89 | customized_id: 10
90 | id: 15
91 | value: true
92 | custom_values_016:
93 | customized_type: Enumeration
94 | custom_field_id: 7
95 | customized_id: 11
96 | id: 16
97 | value: '1'
98 | custom_values_017:
99 | customized_type: Issue
100 | custom_field_id: 8
101 | customized_id: 1
102 | id: 17
103 | value: '2009-12-01'
104 | custom_values_018:
105 | customized_type: Issue
106 | custom_field_id: 12
107 | customized_id: 1
108 | id: 18
109 | value: '1327280'
110 | custom_values_019:
111 | customized_type: Issue
112 | custom_field_id: 13
113 | customized_id: 1
114 | id: 19
115 | value: '94184406'
116 | custom_values_020:
117 | customized_type: Issue
118 | custom_field_id: 12
119 | customized_id: 2
120 | id: 20
121 | value: '1327280'
122 | custom_values_021:
123 | customized_type: Issue
124 | custom_field_id: 13
125 | customized_id: 2
126 | id: 21
127 | value: '94184406'
128 | custom_values_022:
129 | customized_type: Issue
130 | custom_field_id: 12
131 | customized_id: 3
132 | id: 22
133 | value: '1327280'
134 | custom_values_023:
135 | customized_type: Issue
136 | custom_field_id: 13
137 | customized_id: 3
138 | id: 23
139 | value: '92844256'
140 |
--------------------------------------------------------------------------------
/spec/unit/lib/trackmine_spec.rb:
--------------------------------------------------------------------------------
1 | require File.dirname(__FILE__) + '/../../spec_helper'
2 |
3 | describe Trackmine do
4 | let(:activity_body) { JSON.parse(File.read(json_path(activity_name))) }
5 | let(:activity) { Trackmine::Activity.new(activity_body) }
6 | let(:read_activity) { Trackmine.read_activity(activity) }
7 |
8 | describe '.projects', vcr: { cassette_name: 'projects' } do
9 | before { Trackmine::Authentication.set_token('pbrudny@gmail.com') }
10 | let(:projects) { Trackmine.projects }
11 |
12 | it 'returns an array of available projects' do
13 | expect(projects).to be_kind_of(Array)
14 | end
15 |
16 | it 'be a project instance' do
17 | expect(projects.first).to be_an_instance_of(PivotalTracker::Project)
18 | end
19 | end
20 |
21 | describe '.get_mapping' do
22 | context 'when no Redmine project mapped' do
23 | it 'does not raise an error' do
24 | expect(Trackmine.get_mapping(1325832, 'match')).not_to raise_exception
25 | end
26 | end
27 |
28 | context 'when there is a mapping for the Redmine project' do
29 | let(:mapping) { create(:mapping, label: '') }
30 |
31 | it('return a mapping object') do
32 | expect(Trackmine.get_mapping(mapping.tracker_project_id, '')).to eq mapping
33 | end
34 | end
35 | end
36 |
37 | context 'finish_story', vcr: { cassette_name: 'finish_story' } do
38 | let(:story_id) { 94184406 }
39 | let(:project_id) { 1327280 }
40 | let(:wrong_id) { -1 }
41 | let(:story) { PivotalTracker::Story.find(story_id, project_id) }
42 |
43 | it("get response with a current_state 'finished'") do
44 | expect_any_instance_of(PivotalTracker::Story).to receive(:update).with({current_state: 'finished'})
45 | Trackmine.finish_story(project_id, story_id)
46 | end
47 |
48 | it('raise an errors when wrong story_id given') do
49 | expect {Trackmine.finish_story(wrong_id, wrong_id)}.to raise_error(Trackmine::PivotalTrackerError)
50 | end
51 | end
52 |
53 | describe 'updating story', vcr: { cassette_name: 'updating_story' } do
54 | let(:issues) { Issue.find([2])}
55 |
56 | context 'description' do
57 | let(:activity_name) { 'story_description_update' }
58 | let(:new_description) do
59 | "https://www.pivotaltracker.com/story/show/94184406" +"\r\n"+ "jazda z gorki w dol po sniegu w parach czyli we dwoje\r\n"
60 | end
61 |
62 | it 'change an issue description in each issue' do
63 | read_activity
64 |
65 | issues.each do |issue|
66 | expect(issue.reload.description).to eq new_description
67 | end
68 | end
69 | end
70 | end
71 |
72 | describe 'restarting a story', vcr: { cassette_name: 'restarting_story' } do
73 | let(:activity_name) { 'story_restarted' }
74 |
75 | context 'there is an associated Redmine issue' do
76 | let(:issues) { Issue.find([3])}
77 |
78 | it 'change an issues status for "Accepted" in each issue' do
79 | read_activity
80 | issues.each do |issue|
81 | expect(issue.reload.status.name).to eq 'Accepted'
82 | end
83 | end
84 |
85 | it 'assigned issue to user who restarted a story' do
86 | issues.each do |issue|
87 | expect(issue.reload.assigned_to.try(:mail)).to eq 'pbrudny@gmail.com'
88 | end
89 | end
90 | end
91 | end
92 | end
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/spec/cassettes/projects.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: get
5 | uri: https://www.pivotaltracker.com/services/v3/projects
6 | body:
7 | encoding: US-ASCII
8 | string: ''
9 | headers:
10 | Accept:
11 | - "*/*; q=0.5, application/xml"
12 | Accept-Encoding:
13 | - gzip, deflate
14 | X-Trackertoken:
15 | - b545bcaeafc773ced5b1a853fffd1fc9
16 | Content-Type:
17 | - application/xml
18 | User-Agent:
19 | - Ruby
20 | response:
21 | status:
22 | code: 200
23 | message: OK
24 | headers:
25 | Content-Type:
26 | - application/xml; charset=utf-8
27 | Transfer-Encoding:
28 | - chunked
29 | Status:
30 | - 200 OK
31 | X-Ua-Compatible:
32 | - IE=Edge,chrome=1
33 | Cache-Control:
34 | - max-age=0, private, must-revalidate
35 | Set-Cookie:
36 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTIwNTc2YzM2YjBmYWZlN2NkZjRjYmZkZjhhMTEyOTI1BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgNz7O78KOg1uYW5vX251bWkCuQM6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgeVMDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxVnpCbUsrdGVhNDRwVGV4VTh1MEJ6WFdjRWNQQkR6eW80aDRtekNyTkk0OD0GOwBG--a4ebaa53212295b92e5455c2bff063ced53ace91;
37 | path=/; HttpOnly
38 | X-Request-Id:
39 | - b6507eb6bbe029c0bdd77ec1fabf9960
40 | X-Runtime:
41 | - '0.275097'
42 | Date:
43 | - Thu, 28 May 2015 09:47:52 GMT
44 | X-Rack-Cache:
45 | - miss
46 | X-Powered-By:
47 | - Phusion Passenger 4.0.41
48 | Server:
49 | - nginx/1.6.0 + Phusion Passenger 4.0.41
50 | X-Tracker-Client-Pinger-Interval:
51 | - '12'
52 | Content-Encoding:
53 | - gzip
54 | body:
55 | encoding: ASCII-8BIT
56 | string: !binary |-
57 | H4sIAAAAAAAAA+xY3ZPbJhB/z1/B+JkGWbbvbI9OaZtp3zK9mSTPGiStZWoE
58 | GkB39f31XQH+ODvXtL3mpZFHM4ZlWZb9+LGQvfujleQBjBVa3U2mb5MJAVXp
59 | WqjmbvL5068/LCfv8jdZZ/TvUDlL3L6Duwk3hu8n+RtCDiNDG3uizqezdLGc
60 | pRnDdiAq3kL+YU8+8raTQO6DrIx5epznwHCHOhQSVOO2cR2hHDRgJvkUxV2w
61 | xJmPALvCOm5cUfN9/kEr/MvYBTms0mkUWNiKS8gTOqUpnWXsnBjYeFXpXrn8
62 | Z8MfgLz3xsjYgRp4NsJYV5x0Cho40UJUveYOhu4kT5PpgiUzNktIkqz9Rz5/
63 | ep+xl2XEvVW9MYAan5ZRfVuCubTOKmMvsUZJoHgpoXDc7g4+LLWWwNUkd6aH
64 | jJ1zxEkPIHUl3B4ttgV01U8YJ7wBojdkRo462YxdMgYTHVQ6jObT5KTnkRj9
65 | r4QTXBbPeMUlMYaTt0GhN0WtFZyMYwunC7vVj/kUoy9Y6q+4gjTJS5A253Ur
66 | FC2lbmiFsURxx9VO947W0Em9b9EN2LSiURQ6UdENcNcbqAlmRt1jZlABN1QB
67 | 1JbUwla9HTKKalNjblEDnTYOw4ha4KbaUlSz69CRMahsIHgGXKLvCCNDA1Xq
68 | LS+FRC9gCyc0oIZMwYUrjcmhXMbiDg7bwbDklRMPg+O4eyEa52x6S6a362S5
69 | Tm5CNEr+fGYMAi6lfkRBjlfbwQo2xss1PeZYX0pR5RsuLUZVF3phCDdQbJ3r
70 | 7GH0RAgMZd/Ygqu6qLbaADYNFGAxi7gbwvcw7WtsMfx02wpXtLo+TqzOSIGp
71 | hSGW7FZ019DmAe3EEOxxQLnFbLVMVssTyvkBdKnV6sSJJGi5kHlXmr5W+x+b
72 | ofcW9cCE8wNejfDLPB7eQ230OTbGwZgMNr//BRcNmWHPdGKXa2cG8zv/7RHj
73 | JWO+HdfK2OWmzilRZuahN2Dyl0wz6HBiGESjswOw+85Z+3gs3Ka3ZwYL2706
74 | FsiQu9/TwTBnmIHf6GBAc48HgxoPBkzBa7wO5/41PSBjRO7/PY7Pk3Q5vxlx
75 | fCi+PfZ/Fcfny5sEK7nn5T2WQuI7A+4FS+ckTb9JRY/3nRG4XwfceHmhT7zm
76 | aofl1L+pkdG/WCMv1gmWyfHGNtbIF9d/X/VelpOeiPCwWCSrVTLWyP5h4+9h
77 | a3qbLq+w9UnolssRXf+z95IRXX1Evua9RAkoBdgdpxYRllrsN/QJb+qvwNpk
78 | tV7M1vhM5l/HRqz9R1jr69gRa7+ItceSFkH4TwAAAP//AwA79QzZ8hYAAA==
79 | http_version:
80 | recorded_at: Thu, 28 May 2015 09:47:52 GMT
81 | recorded_with: VCR 2.9.3
82 |
--------------------------------------------------------------------------------
/spec/fixtures/custom_fields.yml:
--------------------------------------------------------------------------------
1 | ---
2 | custom_fields_001:
3 | name: Database
4 | regexp: ""
5 | is_for_all: true
6 | is_filter: true
7 | type: IssueCustomField
8 | possible_values:
9 | - MySQL
10 | - PostgreSQL
11 | - Oracle
12 | id: 1
13 | is_required: false
14 | field_format: list
15 | default_value: ""
16 | editable: true
17 | position: 2
18 | custom_fields_002:
19 | name: Searchable field
20 | min_length: 1
21 | regexp: ""
22 | is_for_all: true
23 | is_filter: true
24 | type: IssueCustomField
25 | max_length: 100
26 | possible_values: ""
27 | id: 2
28 | is_required: false
29 | field_format: string
30 | searchable: true
31 | default_value: "Default string"
32 | editable: true
33 | position: 1
34 | custom_fields_003:
35 | name: Development status
36 | regexp: ""
37 | is_for_all: false
38 | is_filter: true
39 | type: ProjectCustomField
40 | possible_values:
41 | - Stable
42 | - Beta
43 | - Alpha
44 | - Planning
45 | id: 3
46 | is_required: false
47 | field_format: list
48 | default_value: ""
49 | editable: true
50 | position: 1
51 | custom_fields_004:
52 | name: Phone number
53 | regexp: ""
54 | is_for_all: false
55 | type: UserCustomField
56 | possible_values: ""
57 | id: 4
58 | is_required: false
59 | field_format: string
60 | default_value: ""
61 | editable: true
62 | position: 1
63 | custom_fields_005:
64 | name: Money
65 | regexp: ""
66 | is_for_all: false
67 | type: UserCustomField
68 | possible_values: ""
69 | id: 5
70 | is_required: false
71 | field_format: float
72 | default_value: ""
73 | editable: true
74 | position: 2
75 | custom_fields_006:
76 | name: Float field
77 | regexp: ""
78 | is_for_all: true
79 | type: IssueCustomField
80 | possible_values: ""
81 | id: 6
82 | is_required: false
83 | field_format: float
84 | default_value: ""
85 | editable: true
86 | position: 3
87 | custom_fields_007:
88 | name: Billable
89 | regexp: ""
90 | is_for_all: false
91 | is_filter: true
92 | type: TimeEntryActivityCustomField
93 | possible_values: ""
94 | id: 7
95 | is_required: false
96 | field_format: bool
97 | default_value: ""
98 | editable: true
99 | position: 1
100 | custom_fields_008:
101 | name: Custom date
102 | regexp: ""
103 | is_for_all: true
104 | is_filter: false
105 | type: IssueCustomField
106 | possible_values: ""
107 | id: 8
108 | is_required: false
109 | field_format: date
110 | default_value: ""
111 | editable: true
112 | position: 4
113 | custom_fields_009:
114 | name: Project 1 cf
115 | regexp: ""
116 | is_for_all: false
117 | is_filter: true
118 | type: IssueCustomField
119 | possible_values: ""
120 | id: 9
121 | is_required: false
122 | field_format: date
123 | default_value: ""
124 | editable: true
125 | position: 5
126 | custom_fields_010:
127 | name: Overtime
128 | regexp: ""
129 | is_for_all: false
130 | is_filter: false
131 | type: TimeEntryCustomField
132 | possible_values: ""
133 | id: 10
134 | is_required: false
135 | field_format: bool
136 | default_value: 0
137 | editable: true
138 | position: 1
139 | custom_fields_011:
140 | id: 11
141 | name: Binary
142 | type: CustomField
143 | possible_values:
144 | - !binary |
145 | SGXDqWzDp2prc2Tigqw2NTTDuQ==
146 | - Other value
147 | field_format: list
148 | custom_fields_012:
149 | id: 12
150 | name: Pivotal Project ID
151 | type: CustomField
152 | possible_values: ""
153 | field_format: string
154 | custom_fields_013:
155 | id: 13
156 | name: Pivotal Story ID
157 | type: CustomField
158 | possible_values: ""
159 | field_format: string
160 |
161 |
--------------------------------------------------------------------------------
/spec/fixtures/json/story_restarted.json:
--------------------------------------------------------------------------------
1 | {
2 | "kind": "story_update_activity",
3 | "guid": "1327280_21",
4 | "project_version": 21,
5 | "message": "Pedro started this feature",
6 | "highlight": "started",
7 | "changes": [
8 | {
9 | "kind": "label",
10 | "change_type": "update",
11 | "id": 11449356,
12 | "original_values": {
13 | "counts": {
14 | "number_of_zero_point_stories_by_state": {
15 | "accepted": 0,
16 | "started": 0,
17 | "finished": 0,
18 | "unstarted": 0,
19 | "planned": 0,
20 | "delivered": 0,
21 | "unscheduled": 0,
22 | "rejected": 0,
23 | "kind": "counts_by_story_state"
24 | },
25 | "sum_of_story_estimates_by_state": {
26 | "accepted": 1,
27 | "started": 0,
28 | "finished": 0,
29 | "unstarted": 0,
30 | "planned": 0,
31 | "delivered": 0,
32 | "unscheduled": 0,
33 | "rejected": 0,
34 | "kind": "counts_by_story_state"
35 | },
36 | "number_of_stories_by_state": {
37 | "accepted": 1,
38 | "started": 0,
39 | "finished": 0,
40 | "unstarted": 0,
41 | "planned": 0,
42 | "delivered": 0,
43 | "unscheduled": 0,
44 | "rejected": 0,
45 | "kind": "counts_by_story_state"
46 | },
47 | "kind": "story_counts"
48 | }
49 | },
50 | "new_values": {
51 | "counts": {
52 | "number_of_zero_point_stories_by_state": {
53 | "accepted": 0,
54 | "started": 0,
55 | "finished": 0,
56 | "unstarted": 0,
57 | "planned": 0,
58 | "delivered": 0,
59 | "unscheduled": 0,
60 | "rejected": 0,
61 | "kind": "counts_by_story_state"
62 | },
63 | "sum_of_story_estimates_by_state": {
64 | "accepted": 0,
65 | "started": 1,
66 | "finished": 0,
67 | "unstarted": 0,
68 | "planned": 0,
69 | "delivered": 0,
70 | "unscheduled": 0,
71 | "rejected": 0,
72 | "kind": "counts_by_story_state"
73 | },
74 | "number_of_stories_by_state": {
75 | "accepted": 0,
76 | "started": 1,
77 | "finished": 0,
78 | "unstarted": 0,
79 | "planned": 0,
80 | "delivered": 0,
81 | "unscheduled": 0,
82 | "rejected": 0,
83 | "kind": "counts_by_story_state"
84 | },
85 | "kind": "story_counts"
86 | }
87 | },
88 | "name": "niebieska"
89 | },
90 | {
91 | "kind": "story",
92 | "change_type": "update",
93 | "id": 92844256,
94 | "original_values": {
95 | "current_state": "accepted",
96 | "accepted_at": 1432020688000,
97 | "updated_at": 1432020689000
98 | },
99 | "new_values": {
100 | "current_state": "started",
101 | "accepted_at": null,
102 | "updated_at": 1432020710000
103 | },
104 | "name": "tolek lolek",
105 | "story_type": "feature"
106 | }
107 | ],
108 | "primary_resources": [
109 | {
110 | "kind": "story",
111 | "id": 92844256,
112 | "name": "tolek lolek",
113 | "story_type": "feature",
114 | "url": "https://www.pivotaltracker.com/story/show/92844256"
115 | }
116 | ],
117 | "project": {
118 | "kind": "project",
119 | "id": 1327280,
120 | "name": "ziomal"
121 | },
122 | "performed_by": {
123 | "kind": "person",
124 | "id": 1651216,
125 | "name": "Pedro",
126 | "initials": "PE"
127 | },
128 | "occurred_at": 1432020710000
129 | }
--------------------------------------------------------------------------------
/README.rdoc:
--------------------------------------------------------------------------------
1 | = Redmine Trackmine Plugin
2 |
3 | Redmine is an excellent multi-project issue tracking tool focussing on
4 | collaboration in the implementation and integration parts of software
5 | development. Pivotal Tracker, on the other hand, is a superb planning
6 | tool and extremely well suited for requirements capturing and customer
7 | feedback.
8 |
9 | The Trackmine plugin provides simple but effective bi-directional
10 | communication between Pivotal Tracker and Redmine by outsourcing the
11 | workflow between Pivotal's "Started" and "Finished" states to Redmine. The triggers for teleporting
12 | between the tools are starting a story in Pivotal and closing an issue
13 | in Redmine. The workflow in Redmine remains customizable and can be
14 | tailored to individual needs. {Step by step configuration tutorial}[http://piotrbrudny.com/post/120177000661/how-to-integrate-redmine-with-pivotal-tracker]
15 |
16 | [UPGRADED to work with Pivotal Tracker API v5 and Redmine 3]
17 |
18 |
19 | == Features
20 |
21 | * Starting a story in a Pivotal Tracker automatically creates a Redmine issue with status "Accepted".
22 | * Updating a story in a Pivotal Tracker updates the Redmine issue attributes (subject, description, status).
23 | * Closing a Redmine issue finishes the Pivotal Tracker story.
24 | * Mapping between Pivotal Tracker and Redmine attributes can be configured
25 |
26 | == Setup
27 |
28 | === Installation
29 |
30 | In Redmine app run:
31 |
32 | $ bin/plugin install https://github.com/capita/redmine_trackmine.git
33 |
34 | or clone it into /vendor/plugins/
35 |
36 | $ git clone git@github.com:capita/redmine_trackmine.git
37 |
38 | Install gems
39 |
40 | $ bundle install
41 |
42 | Run plugin migrations
43 |
44 | $ rake redmine:plugins:migrate
45 |
46 | === Configuration- Redmine side
47 |
48 | Make sure you have following custom fields for Redmine Issue:
49 | * 'Pivotal Project ID' (field_format: int, Trackers: Bug, Support, Feature) .
50 | * 'Pivotal Story ID' (field_format: int, Trackers: Bug, Support, Feature) .
51 |
52 | And there is IssueStatus 'Accepted'
53 |
54 | Add valid Pivotal Tracker credentials in [redmine_app]/config/trackmine.yml
55 |
56 |
57 | Syntax:
58 |
59 | [redmine_email]:
60 | email: [pivotal_tracker_email]
61 | password: [pivotal_tracker_password]
62 |
63 |
64 | super_user:
65 | # You can use an api token or email/password for the PT api.
66 | token: [pivotal_tracker_api_token]
67 |
68 | error_notification:
69 | recipient: [email_for_error_notifications]
70 | from: "[information to emails FROM field]"
71 |
72 | trackmine.yml
73 |
74 | foouser@example.net:
75 | token: 1234
76 |
77 | baruser@example.net:
78 | email: baruser2@fake.net
79 | password: 2222
80 |
81 | super_user:
82 | email: admin@net.org
83 | password: 1234
84 |
85 | error_notification:
86 | recipient: errors@examplet.net
87 | from: "Trackmine Notifications "
88 |
89 | Users mentioned in trackmine.yml should have administration rights in redmine.
90 | The user named 'super_user' should have access to all Pivotal Tracker projects you want to map to.
91 | It might be the Pivotal Tracker admin. Its credentials are used to handle Pivotal Tracker hooks.
92 |
93 | === Configuration- Pivotal Tracker side
94 |
95 | Add Web Hook Url pointing to your Redmine app. To do that:
96 |
97 | * On your project page choose 'Project -> Configure Integrations'
98 | * Find Activity Web Hook section
99 | * In 'Web Hook Url' put [redmine_app_url]/pivotal_activity.json
100 |
101 | Example:
102 |
103 | http://my-company-redmine-site.org/pivotal_activity.json
104 |
105 |
106 | == Usage
107 |
108 | === Mapping
109 |
110 | * As a Redmine administrator go to 'Administration -> Trackmine' section.
111 | * Use link 'Add mapping'
112 | * Select Redmine project and Pivotal project (or label)
113 |
114 | === Mapping Configuration
115 |
116 | You can configure:
117 |
118 | * Mapping between Pivotal story estimation points and Redmine estimated_hours
119 | Default:
120 | 1 point => 1 hour
121 | 2 points => 4 hours
122 | 3 points => 10 hours
123 |
124 |
125 | * Mapping between Pivotal story_types and Redmine trackers
126 | Default:
127 | 'feature' => 'Feature'
128 | 'bug' => 'Bug'
129 | 'chore' => 'Support'
130 |
131 | === Testing
132 |
133 | Trackmine has RSpec test coverage. Run specs with:
134 |
135 | rake redmine:plugins:test
136 |
137 | == Copyright
138 |
139 | Copyright (c) 2010-2015 Capita Unternehmensberatung GmbH. See LICENSE for details.
140 |
141 |
--------------------------------------------------------------------------------
/spec/fixtures/users.yml:
--------------------------------------------------------------------------------
1 | ---
2 | users_001:
3 | created_on: 2006-07-19 19:12:21 +02:00
4 | status: 1
5 | last_login_on: 2006-07-19 22:57:52 +02:00
6 | language: en
7 | # password = admin
8 | salt: 82090c953c4a0000a7db253b0691a6b4
9 | hashed_password: b5b6ff9543bf1387374cdfa27a54c96d236a7150
10 | updated_on: 2006-07-19 22:57:52 +02:00
11 | admin: true
12 | lastname: Admin
13 | firstname: Redmine
14 | id: 1
15 | auth_source_id:
16 | mail_notification: all
17 | login: admin
18 | type: User
19 | users_002:
20 | created_on: 2006-07-19 19:32:09 +02:00
21 | status: 1
22 | last_login_on: 2006-07-19 22:42:15 +02:00
23 | language: en
24 | # password = jsmith
25 | salt: 67eb4732624d5a7753dcea7ce0bb7d7d
26 | hashed_password: bfbe06043353a677d0215b26a5800d128d5413bc
27 | updated_on: 2006-07-19 22:42:15 +02:00
28 | admin: false
29 | lastname: Smith
30 | firstname: John
31 | id: 2
32 | auth_source_id:
33 | mail_notification: all
34 | login: jsmith
35 | type: User
36 | users_003:
37 | created_on: 2006-07-19 19:33:19 +02:00
38 | status: 1
39 | last_login_on:
40 | language: en
41 | # password = foo
42 | salt: 7599f9963ec07b5a3b55b354407120c0
43 | hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed
44 | updated_on: 2006-07-19 19:33:19 +02:00
45 | admin: false
46 | lastname: Lopper
47 | firstname: Dave
48 | id: 3
49 | auth_source_id:
50 | mail_notification: all
51 | login: dlopper
52 | type: User
53 | users_004:
54 | created_on: 2006-07-19 19:34:07 +02:00
55 | status: 1
56 | last_login_on:
57 | language: en
58 | # password = foo
59 | salt: 3126f764c3c5ac61cbfc103f25f934cf
60 | hashed_password: 9e4dd7eeb172c12a0691a6d9d3a269f7e9fe671b
61 | updated_on: 2006-07-19 19:34:07 +02:00
62 | admin: false
63 | lastname: Hill
64 | firstname: Robert
65 | id: 4
66 | auth_source_id:
67 | mail_notification: all
68 | login: rhill
69 | type: User
70 | users_005:
71 | id: 5
72 | created_on: 2006-07-19 19:33:19 +02:00
73 | # Locked
74 | status: 3
75 | last_login_on:
76 | language: en
77 | hashed_password: 1
78 | updated_on: 2006-07-19 19:33:19 +02:00
79 | admin: false
80 | lastname: Lopper2
81 | firstname: Dave2
82 | auth_source_id:
83 | mail_notification: all
84 | login: dlopper2
85 | type: User
86 | users_006:
87 | id: 6
88 | created_on: 2006-07-19 19:33:19 +02:00
89 | status: 0
90 | last_login_on:
91 | language: ''
92 | hashed_password: 1
93 | updated_on: 2006-07-19 19:33:19 +02:00
94 | admin: false
95 | lastname: Anonymous
96 | firstname: ''
97 | auth_source_id:
98 | mail_notification: only_my_events
99 | login: ''
100 | type: AnonymousUser
101 | users_007:
102 | # A user who does not belong to any project
103 | id: 7
104 | created_on: 2006-07-19 19:33:19 +02:00
105 | status: 1
106 | last_login_on:
107 | language: 'en'
108 | # password = foo
109 | salt: 7599f9963ec07b5a3b55b354407120c0
110 | hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed
111 | updated_on: 2006-07-19 19:33:19 +02:00
112 | admin: false
113 | lastname: One
114 | firstname: Some
115 | auth_source_id:
116 | mail_notification: only_my_events
117 | login: someone
118 | type: User
119 | users_008:
120 | id: 8
121 | created_on: 2006-07-19 19:33:19 +02:00
122 | status: 1
123 | last_login_on:
124 | language: 'it'
125 | # password = foo
126 | salt: 7599f9963ec07b5a3b55b354407120c0
127 | hashed_password: 8f659c8d7c072f189374edacfa90d6abbc26d8ed
128 | updated_on: 2006-07-19 19:33:19 +02:00
129 | admin: false
130 | lastname: Misc
131 | firstname: User
132 | auth_source_id:
133 | mail_notification: only_my_events
134 | login: miscuser8
135 | type: User
136 | users_009:
137 | id: 9
138 | created_on: 2006-07-19 19:33:19 +02:00
139 | status: 1
140 | last_login_on:
141 | language: 'it'
142 | hashed_password: 1
143 | updated_on: 2006-07-19 19:33:19 +02:00
144 | admin: false
145 | lastname: Misc
146 | firstname: User
147 | auth_source_id:
148 | mail_notification: only_my_events
149 | login: miscuser9
150 | type: User
151 | groups_010:
152 | id: 10
153 | lastname: A Team
154 | type: Group
155 | status: 1
156 | groups_011:
157 | id: 11
158 | lastname: B Team
159 | type: Group
160 | status: 1
161 | groups_non_member:
162 | id: 12
163 | lastname: Non member users
164 | type: GroupNonMember
165 | status: 1
166 | groups_anonymous:
167 | id: 13
168 | lastname: Anonymous users
169 | type: GroupAnonymous
170 | status: 1
171 |
172 |
--------------------------------------------------------------------------------
/spec/cassettes/finish_story.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://www.pivotaltracker.com/services/v3/tokens/active
6 | body:
7 | encoding: US-ASCII
8 | string: username=foobar%40gmail.com&password=secret&timeout=60
9 | headers:
10 | Accept:
11 | - "*/*; q=0.5, application/xml"
12 | Accept-Encoding:
13 | - gzip, deflate
14 | Content-Length:
15 | - '55'
16 | Content-Type:
17 | - application/x-www-form-urlencoded
18 | User-Agent:
19 | - Ruby
20 | response:
21 | status:
22 | code: 200
23 | message: OK
24 | headers:
25 | Content-Type:
26 | - application/xml; charset=utf-8
27 | Transfer-Encoding:
28 | - chunked
29 | Status:
30 | - 200 OK
31 | X-Ua-Compatible:
32 | - IE=Edge,chrome=1
33 | Etag:
34 | - '"2aca2abf73441eff33bb5c8599b6a03b"'
35 | Cache-Control:
36 | - max-age=0, private, must-revalidate
37 | Set-Cookie:
38 | - t_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWRmYWUwZTUxZTdmOTYxOTVhZGM0Y2Y4YjIxYTNjYTI1BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgMYqT78KOg1uYW5vX251bWkCRQM6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgeDcDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBU--a7ed1dba66217366553182275dbeeaecb65a9fb7;
39 | path=/; HttpOnly
40 | X-Request-Id:
41 | - c4daac0925bfa1d7e944ac9b571749fd
42 | X-Runtime:
43 | - '0.111316'
44 | Date:
45 | - Thu, 28 May 2015 09:47:53 GMT
46 | X-Rack-Cache:
47 | - invalidate, pass
48 | X-Powered-By:
49 | - Phusion Passenger 4.0.41
50 | Server:
51 | - nginx/1.6.0 + Phusion Passenger 4.0.41
52 | X-Tracker-Client-Pinger-Interval:
53 | - '12'
54 | body:
55 | encoding: UTF-8
56 | string: |
57 |
58 |
59 | b545bcaeafc773ced5b1a853fffd1fc9
60 | 838284
61 |
62 | http_version:
63 | recorded_at: Thu, 28 May 2015 09:47:54 GMT
64 | - request:
65 | method: get
66 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/stories/94184406
67 | body:
68 | encoding: US-ASCII
69 | string: ''
70 | headers:
71 | Accept:
72 | - "*/*; q=0.5, application/xml"
73 | Accept-Encoding:
74 | - gzip, deflate
75 | X-Trackertoken:
76 | - b545bcaeafc773ced5b1a853fffd1fc9
77 | Content-Type:
78 | - application/xml
79 | User-Agent:
80 | - Ruby
81 | response:
82 | status:
83 | code: 200
84 | message: OK
85 | headers:
86 | Content-Type:
87 | - application/xml; charset=utf-8
88 | Transfer-Encoding:
89 | - chunked
90 | Status:
91 | - 200 OK
92 | X-Ua-Compatible:
93 | - IE=Edge,chrome=1
94 | Cache-Control:
95 | - max-age=0, private, must-revalidate
96 | Set-Cookie:
97 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWU3ZDk5NjEzYmViZjAxNmY0NGEwNjZhNDQxMjg3ZGQwBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgNOPXr8KOg1uYW5vX251bWkB6zoNbmFub19kZW5pBjoNc3VibWljcm8iByNQOgtvZmZzZXRpADoJem9uZUkiCFVUQwY7AFRJIhBfY3NyZl90b2tlbgY7AEZJIjE2SURrcGlmYTlOUUdVbENWTFNqNTNTbUNUVjBKS28zM3FGd1hROFZxYWZRPQY7AEY%3D--87cd2da68923f5a2b7209959bf31ce17f9a6913f;
98 | path=/; HttpOnly
99 | X-Request-Id:
100 | - 7c66e557b09835d3855b6f1271d1bc1f
101 | X-Runtime:
102 | - '0.074891'
103 | Date:
104 | - Thu, 28 May 2015 09:47:54 GMT
105 | X-Rack-Cache:
106 | - miss
107 | X-Powered-By:
108 | - Phusion Passenger 4.0.41
109 | Server:
110 | - nginx/1.6.0 + Phusion Passenger 4.0.41
111 | X-Tracker-Client-Pinger-Interval:
112 | - '12'
113 | Content-Encoding:
114 | - gzip
115 | body:
116 | encoding: ASCII-8BIT
117 | string: !binary |-
118 | H4sIAAAAAAAAA3ySy27CMBBF93yFlTXFScojRMYsKnXdBayRiQcwJHZqO6TJ
119 | 19c2lEcrVcrCM3Pu1fg6ZPlVlegM2gglF1EyiiMEslBcyP0iWq/eX7JoSQfE
120 | WKU7OkCICI5sV8MiEtLCHnRE5+MkG4/jKcGCB6TW6giF3fxFk9d0lmYxwXck
121 | KIL9xvvSHTDbaCD4oeeRRpf0YG1tcozbth3V4qwsK61mxQn0qFDVRYHNQbX4
122 | vpPXeT0YKypm4ff2CcE/o8AVjdYg7cZYB9OdkMIcgBP83PckB1NoUVuXHD2y
123 | njPUo73SJ4FaxFWJaoWMFLBvXF0zt+cBFX1X+rHVfYeUUdtuQPCjj/eVrIKr
124 | oWTIMHnyUi9SR38kOBAe1fDZuO2Bb7Yd/QCuFcFPPQ+pVj4BtzpcV7u83ZjZ
125 | azDclS4piGgaJxMcuy9DySRPs3wyRevVm4vipglLNLXX/GuROItZnsT5ZH6x
126 | uGuCRcm2UBrq7zoMmQ1791gEX/supOsP+A0AAP//AwBvV9t2sAIAAA==
127 | http_version:
128 | recorded_at: Thu, 28 May 2015 09:47:54 GMT
129 | recorded_with: VCR 2.9.3
130 |
--------------------------------------------------------------------------------
/spec/cassettes/updating_story.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://www.pivotaltracker.com/services/v3/tokens/active
6 | body:
7 | encoding: US-ASCII
8 | string: username=foobar%40gmail.com&password=secret&timeout=60
9 | headers:
10 | Accept:
11 | - "*/*; q=0.5, application/xml"
12 | Accept-Encoding:
13 | - gzip, deflate
14 | Content-Length:
15 | - '55'
16 | Content-Type:
17 | - application/x-www-form-urlencoded
18 | User-Agent:
19 | - Ruby
20 | response:
21 | status:
22 | code: 200
23 | message: OK
24 | headers:
25 | Content-Type:
26 | - application/xml; charset=utf-8
27 | Transfer-Encoding:
28 | - chunked
29 | Status:
30 | - 200 OK
31 | X-Ua-Compatible:
32 | - IE=Edge,chrome=1
33 | Etag:
34 | - '"2aca2abf73441eff33bb5c8599b6a03b"'
35 | Cache-Control:
36 | - max-age=0, private, must-revalidate
37 | Set-Cookie:
38 | - t_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJThkOTE2MDIyNjkzODU0M2EyZDg0MGI4ZjEzN2Q3N2Y4BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgAF7bb8KOg1uYW5vX251bWkC7gE6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgdJQDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBU--d87ffeac0f19d54c583426be587b3b3d5f2ce869;
39 | path=/; HttpOnly
40 | X-Request-Id:
41 | - df52e7dcb79a6c6a8e71ee0d55e51d68
42 | X-Runtime:
43 | - '0.116613'
44 | Date:
45 | - Thu, 28 May 2015 09:47:54 GMT
46 | X-Rack-Cache:
47 | - invalidate, pass
48 | X-Powered-By:
49 | - Phusion Passenger 4.0.41
50 | Server:
51 | - nginx/1.6.0 + Phusion Passenger 4.0.41
52 | X-Tracker-Client-Pinger-Interval:
53 | - '12'
54 | body:
55 | encoding: UTF-8
56 | string: |
57 |
58 |
59 | b545bcaeafc773ced5b1a853fffd1fc9
60 | 838284
61 |
62 | http_version:
63 | recorded_at: Thu, 28 May 2015 09:47:55 GMT
64 | - request:
65 | method: get
66 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/stories/94184406
67 | body:
68 | encoding: US-ASCII
69 | string: ''
70 | headers:
71 | Accept:
72 | - "*/*; q=0.5, application/xml"
73 | Accept-Encoding:
74 | - gzip, deflate
75 | X-Trackertoken:
76 | - b545bcaeafc773ced5b1a853fffd1fc9
77 | Content-Type:
78 | - application/xml
79 | User-Agent:
80 | - Ruby
81 | response:
82 | status:
83 | code: 200
84 | message: OK
85 | headers:
86 | Content-Type:
87 | - application/xml; charset=utf-8
88 | Transfer-Encoding:
89 | - chunked
90 | Status:
91 | - 200 OK
92 | X-Ua-Compatible:
93 | - IE=Edge,chrome=1
94 | Cache-Control:
95 | - max-age=0, private, must-revalidate
96 | Set-Cookie:
97 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWY5MDQwZDU5MmVmZTRiMDhlYjA1MTZlYzQzMDlhNTE5BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgFzqfL8KOg1uYW5vX251bWkCWwI6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgdgMDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxaEg3M2VmZGo1K0IrZnNjOERzSjlSMlVEMnFTUzZPeVFpVGhhUXJyVjNnMD0GOwBG--e9b56f2f11a1d4ba710345466469ca61660065ee;
98 | path=/; HttpOnly
99 | X-Request-Id:
100 | - 98793c5509a55dc88b97ed531cf1cc38
101 | X-Runtime:
102 | - '0.059728'
103 | Date:
104 | - Thu, 28 May 2015 09:47:55 GMT
105 | X-Rack-Cache:
106 | - miss
107 | X-Powered-By:
108 | - Phusion Passenger 4.0.41
109 | Server:
110 | - nginx/1.6.0 + Phusion Passenger 4.0.41
111 | X-Tracker-Client-Pinger-Interval:
112 | - '12'
113 | Content-Encoding:
114 | - gzip
115 | body:
116 | encoding: ASCII-8BIT
117 | string: !binary |-
118 | H4sIAAAAAAAAAwIAAAD//3ySy27CMBBF93yFlTXFScojRMYsKnXdBayRiQcw
119 | JHZqO6TJ19c2lEcrVcrCM3Pu1fg6ZPlVlegM2gglF1EyiiMEslBcyP0iWq/e
120 | X7JoSQfEWKU7OkCICI5sV8MiEtLCHnRE5+MkG4/jKcGCB6TW6giF3fxFk9d0
121 | lmYxwXckKIL9xvvSHTDbaCD4oeeRRpf0YG1tcozbth3V4qwsK61mxQn0qFDV
122 | RYHNQbX4vpPXeT0YKypm4ff2CcE/o8AVjdYg7cZYB9OdkMIcgBP83PckB1No
123 | UVuXHD2ynjPUo73SJ4FaxFWJaoWMFLBvXF0zt+cBFX1X+rHVfYeUUdtuQPCj
124 | j/eVrIKroWTIMHnyUi9SR38kOBAe1fDZuO2Bb7Yd/QCuFcFPPQ+pVj4Btzpc
125 | V7u83ZjZazDclS4piGgaJxMcuy9DySRPs3wyRevVm4vipglLNLXX/GuROItZ
126 | nsT5ZH6xuGuCRcm2UBrq7zoMmQ1791gEX/supOsP+A0AAP//AwBvV9t2sAIA
127 | AA==
128 | http_version:
129 | recorded_at: Thu, 28 May 2015 09:47:56 GMT
130 | recorded_with: VCR 2.9.3
131 |
--------------------------------------------------------------------------------
/spec/cassettes/participant_email.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://www.pivotaltracker.com/services/v3/tokens/active
6 | body:
7 | encoding: US-ASCII
8 | string: username=foobar%40gmail.com&password=secret&timeout=60
9 | headers:
10 | Accept:
11 | - "*/*; q=0.5, application/xml"
12 | Accept-Encoding:
13 | - gzip, deflate
14 | Content-Length:
15 | - '55'
16 | Content-Type:
17 | - application/x-www-form-urlencoded
18 | User-Agent:
19 | - Ruby
20 | response:
21 | status:
22 | code: 200
23 | message: OK
24 | headers:
25 | Content-Type:
26 | - application/xml; charset=utf-8
27 | Transfer-Encoding:
28 | - chunked
29 | Status:
30 | - 200 OK
31 | X-Ua-Compatible:
32 | - IE=Edge,chrome=1
33 | Etag:
34 | - '"2aca2abf73441eff33bb5c8599b6a03b"'
35 | Cache-Control:
36 | - max-age=0, private, must-revalidate
37 | Set-Cookie:
38 | - t_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJTQ3NDlhNGQ2ZmU0N2VmY2I0MDQ2NmFkMTZiMGViMTM0BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgNgSD78KOg1uYW5vX251bWkC3QM6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgeYkDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBU--b0cee2909c5980b949bd8feca9953b1f847492f5;
39 | path=/; HttpOnly
40 | X-Request-Id:
41 | - bd361017ecc35193e7afbbef8d5c05ec
42 | X-Runtime:
43 | - '0.124677'
44 | Date:
45 | - Thu, 28 May 2015 09:47:49 GMT
46 | X-Rack-Cache:
47 | - invalidate, pass
48 | X-Powered-By:
49 | - Phusion Passenger 4.0.41
50 | Server:
51 | - nginx/1.6.0 + Phusion Passenger 4.0.41
52 | X-Tracker-Client-Pinger-Interval:
53 | - '12'
54 | body:
55 | encoding: UTF-8
56 | string: |
57 |
58 |
59 | b545bcaeafc773ced5b1a853fffd1fc9
60 | 838284
61 |
62 | http_version:
63 | recorded_at: Thu, 28 May 2015 09:47:50 GMT
64 | - request:
65 | method: get
66 | uri: https://www.pivotaltracker.com/services/v3/projects/1325832
67 | body:
68 | encoding: US-ASCII
69 | string: ''
70 | headers:
71 | Accept:
72 | - "*/*; q=0.5, application/xml"
73 | Accept-Encoding:
74 | - gzip, deflate
75 | X-Trackertoken:
76 | - b545bcaeafc773ced5b1a853fffd1fc9
77 | Content-Type:
78 | - application/xml
79 | User-Agent:
80 | - Ruby
81 | response:
82 | status:
83 | code: 200
84 | message: OK
85 | headers:
86 | Content-Type:
87 | - application/xml; charset=utf-8
88 | Transfer-Encoding:
89 | - chunked
90 | Status:
91 | - 200 OK
92 | X-Ua-Compatible:
93 | - IE=Edge,chrome=1
94 | Cache-Control:
95 | - max-age=0, private, must-revalidate
96 | Set-Cookie:
97 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWU5ZWYwNjMwOTFlZGU3NjlhZWJhY2EwMTdiZGMxYmNjBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgBHJHr8KOg1uYW5vX251bWkCgwE6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgc4cDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxdDJ6YTF2V21uNEloN3IybGVhRytSdWV5V2l6VUJJS0hWMW5ZdUxPamVpTT0GOwBG--2a64118a16e7640d4bd919c23eac16064510b777;
98 | path=/; HttpOnly
99 | X-Request-Id:
100 | - 5973b18dc0f505df424dea44a7622895
101 | X-Runtime:
102 | - '0.043785'
103 | Date:
104 | - Thu, 28 May 2015 09:47:50 GMT
105 | X-Rack-Cache:
106 | - miss
107 | X-Powered-By:
108 | - Phusion Passenger 4.0.41
109 | Server:
110 | - nginx/1.6.0 + Phusion Passenger 4.0.41
111 | X-Tracker-Client-Pinger-Interval:
112 | - '12'
113 | Content-Encoding:
114 | - gzip
115 | body:
116 | encoding: ASCII-8BIT
117 | string: !binary |-
118 | H4sIAAAAAAAAA4RUW0/bMBR+51dYec5w0g4oKJhtaHtDQxo8R45zmng4dmQ7
119 | 7frvd+ykTVuEkCrV+c537pfi4V+nyAask0bfJ/lllhDQwtRSN/fJ68uvL6vk
120 | gV0UvTV/QXh2QUgha5YvF1er5aKg+A6Q5h2wpx35w7teAXke2QWNeNTxYLlH
121 | H6UC3fiW+F0P94nUHhqwCcvR1Bkl6m0B3krnufVlzXfsyWj8K+gZHJi9QWOl
122 | E1wBy9I8XaTLgh6DgcSFMIP27IflGyCPMc2C7tHAWEvrfDnHMvr2soMp5Jp7
123 | CJ8JW2T5Fc2WdJmRLLuLP/L68ljQj23EnMRgLWCssxM9dBXY85rcFvQjarQD
124 | mlcKSs/dm5t0K2MUcJ0wbwco6DEjqmxAGSH9DuvUArbmO3aeN0DMmizJIR5X
125 | 0HPicdx7GcuzOcIDGJhSSy+5Kk+Y78DAHDMvzbqsjYa5JK70pnSt2bIcp+xz
126 | VrCleAXKMV53UqeVMk0qcG5SzFS8mcGnNfTK7DosPT6dbHQKvRTpGrgfLNQE
127 | Z7wehHephOtUA9SO1NKJwYXdSI2tcUtSC72xHscmdcCtaFMMsu+xedMQuRGI
128 | BHQx9ISS8MCQBscrqbD6+EKFBnTYCXQsDK6B9gWdMhiTwTHkwstNaBf3H0zf
129 | V5rfkPzmLlvdZdfj9Cl+qhkbz5UyWzTjuWhDBdw0Ie/xwO6HSknB1lw5nKLp
130 | Kwgw8LL1vnd72QwEcTU0ruS6LkVrLODTQgkOt4X7MKp7pc9owZQwXSd92Zn6
131 | oHYMBUoHYWtcK/v9+HNr+S4JCZ+IRwAhvFZXy9tVdrvaX67IxPY5o/csBKDj
132 | UrG+skOtd9+a8HWJ3nGhoiDaj5rxvj1Dbc186ybRNO6OPf9EZ+NCuEMk9NRn
133 | YXFv2e8tTkRB43vMgc45xjYefUdbuGl4QMfL+r4Iwe8sxitOD2f8PwAAAP//
134 | AwBMbtil+AUAAA==
135 | http_version:
136 | recorded_at: Thu, 28 May 2015 09:47:50 GMT
137 | - request:
138 | method: get
139 | uri: https://www.pivotaltracker.com/services/v3/projects/1325832/memberships
140 | body:
141 | encoding: US-ASCII
142 | string: ''
143 | headers:
144 | Accept:
145 | - "*/*; q=0.5, application/xml"
146 | Accept-Encoding:
147 | - gzip, deflate
148 | X-Trackertoken:
149 | - b545bcaeafc773ced5b1a853fffd1fc9
150 | Content-Type:
151 | - application/xml
152 | User-Agent:
153 | - Ruby
154 | response:
155 | status:
156 | code: 200
157 | message: OK
158 | headers:
159 | Content-Type:
160 | - application/xml; charset=utf-8
161 | Transfer-Encoding:
162 | - chunked
163 | Status:
164 | - 200 OK
165 | X-Ua-Compatible:
166 | - IE=Edge,chrome=1
167 | Cache-Control:
168 | - max-age=0, private, must-revalidate
169 | Set-Cookie:
170 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWNlY2U0ZDMzNjU0MzVjMTRkYzlmNWI5Yzc1YTdhN2Q4BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgMsnLb8HOgtvZmZzZXRpADoJem9uZUkiCFVUQwY7AFRJIhBfY3NyZl90b2tlbgY7AEZJIjFMZm1ZVjh5dmNIdmQxbTdvYW1nTVRsOG5RejNueXUrOURlNmJ4WWZjZkFNPQY7AEY%3D--5b3039948707980ee562be50c469c2f1dd3ad75d;
171 | path=/; HttpOnly
172 | X-Request-Id:
173 | - 4b8e5231cce0d667528cf7a5c68b991c
174 | X-Runtime:
175 | - '0.055731'
176 | Date:
177 | - Thu, 28 May 2015 09:47:50 GMT
178 | X-Rack-Cache:
179 | - miss
180 | X-Powered-By:
181 | - Phusion Passenger 4.0.41
182 | Server:
183 | - nginx/1.6.0 + Phusion Passenger 4.0.41
184 | X-Tracker-Client-Pinger-Interval:
185 | - '12'
186 | Content-Encoding:
187 | - gzip
188 | body:
189 | encoding: ASCII-8BIT
190 | string: !binary |-
191 | H4sIAAAAAAAAA0xQy27CMBC85yss38FAhBSkzdILvVWN1PYDTLwCV37JCZT8
192 | PSZulNx2dmZ2RgvHhzXsTrHT3tV8u95wRq71SrtLzX++31cVP2IBluw5ia46
193 | dKwfAtVcxigHjgVjC/IF00Ir3JeHanOoQKQ5L0Pye5dB0pCV2mA4x5tyw9vl
194 | hdattyAyMXqSzElL2JCKHsQ4T4R2utfSdNicUsgEcpRYZkH0hvDzz1EEMc7/
195 | faL/pbafDyrclrt9Ve7m0lOBj4F9SRsMsSa7lmVAhPkUiPlV6W8L1GHxBAAA
196 | //8DADPEdB9uAQAA
197 | http_version:
198 | recorded_at: Thu, 28 May 2015 09:47:51 GMT
199 | recorded_with: VCR 2.9.3
200 |
--------------------------------------------------------------------------------
/spec/cassettes/trackmine_activity.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://www.pivotaltracker.com/services/v3/tokens/active
6 | body:
7 | encoding: US-ASCII
8 | string: username=foobar%40gmail.com&password=secret&timeout=60
9 | headers:
10 | Accept:
11 | - "*/*; q=0.5, application/xml"
12 | Accept-Encoding:
13 | - gzip, deflate
14 | Content-Length:
15 | - '55'
16 | Content-Type:
17 | - application/x-www-form-urlencoded
18 | User-Agent:
19 | - Ruby
20 | response:
21 | status:
22 | code: 200
23 | message: OK
24 | headers:
25 | Content-Type:
26 | - application/xml; charset=utf-8
27 | Transfer-Encoding:
28 | - chunked
29 | Status:
30 | - 200 OK
31 | X-Ua-Compatible:
32 | - IE=Edge,chrome=1
33 | Etag:
34 | - '"2aca2abf73441eff33bb5c8599b6a03b"'
35 | Cache-Control:
36 | - max-age=0, private, must-revalidate
37 | Set-Cookie:
38 | - t_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJTkxMTlkZjhmZjRjNGQ5YjRmYWM1OGZjMjA3YzQ1MjdmBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgARXyL0KOg1uYW5vX251bWkC6wE6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgdJEDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBU--cf9558dc92bf97e3c9e34e2fcbdccdce52b7577f;
39 | path=/; HttpOnly
40 | X-Request-Id:
41 | - cdf60f89de718eac3c1430e9129c59d6
42 | X-Runtime:
43 | - '0.124102'
44 | Date:
45 | - Thu, 28 May 2015 09:47:28 GMT
46 | X-Rack-Cache:
47 | - invalidate, pass
48 | X-Powered-By:
49 | - Phusion Passenger 4.0.41
50 | Server:
51 | - nginx/1.6.0 + Phusion Passenger 4.0.41
52 | X-Tracker-Client-Pinger-Interval:
53 | - '12'
54 | body:
55 | encoding: UTF-8
56 | string: |
57 |
58 |
59 | b545bcaeafc773ced5b1a853fffd1fc9
60 | 838284
61 |
62 | http_version:
63 | recorded_at: Thu, 28 May 2015 09:47:29 GMT
64 | - request:
65 | method: get
66 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280
67 | body:
68 | encoding: US-ASCII
69 | string: ''
70 | headers:
71 | Accept:
72 | - "*/*; q=0.5, application/xml"
73 | Accept-Encoding:
74 | - gzip, deflate
75 | X-Trackertoken:
76 | - b545bcaeafc773ced5b1a853fffd1fc9
77 | Content-Type:
78 | - application/xml
79 | User-Agent:
80 | - Ruby
81 | response:
82 | status:
83 | code: 200
84 | message: OK
85 | headers:
86 | Content-Type:
87 | - application/xml; charset=utf-8
88 | Transfer-Encoding:
89 | - chunked
90 | Status:
91 | - 200 OK
92 | X-Ua-Compatible:
93 | - IE=Edge,chrome=1
94 | Cache-Control:
95 | - max-age=0, private, must-revalidate
96 | Set-Cookie:
97 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWEwNThkMzc4NGE5ZjcyNTQ2NWU5NThmYjM1NWMxM2YxBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgHqo2b0KOg1uYW5vX251bWkChwE6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgc5EDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxSU00TllqN3BQQTBrSDd1V01Uc0M5SVB0N2NneFlEWmdLY3ZhUWhHOUkxOD0GOwBG--49435869bab7edf32b25cafba6126671f83d06e2;
98 | path=/; HttpOnly
99 | X-Request-Id:
100 | - 0b7b9573b754e4d59dec8dba43d6aa13
101 | X-Runtime:
102 | - '0.152584'
103 | Date:
104 | - Thu, 28 May 2015 09:47:29 GMT
105 | X-Rack-Cache:
106 | - miss
107 | X-Powered-By:
108 | - Phusion Passenger 4.0.41
109 | Server:
110 | - nginx/1.6.0 + Phusion Passenger 4.0.41
111 | X-Tracker-Client-Pinger-Interval:
112 | - '12'
113 | Content-Encoding:
114 | - gzip
115 | body:
116 | encoding: ASCII-8BIT
117 | string: !binary |-
118 | H4sIAAAAAAAAA4RUS2/bMAy+91cYPmeV4zRoVrjqtmK7DethPQu0zdhaZMmQ
119 | 5GTprx+l2Hm06wYEiPjx45tm8fC7U8kWrZNG36fz6yxNUFemlrq5T59/fvuw
120 | Sh/4VdFb8wsrz6+SpJA1ny/y23yVFYzeAdLQIX+RpgNVsChEokcLnhwLhbrx
121 | beL3Pd6nUnts0KZ8TvavKNFuh7gRzoP1ooY9/240/RXsFRyYvSFnwlWgkGez
122 | +SyfLQp2DgYSVJUZtOdfLGwxeYy1FWxCA2MtrfPilMshtpcdjinX4DGIKc+z
123 | +ZJlS5bfJHl+l2X0S55/PhbsfR+xpmqwFinXUxA9dCXav/TkPWr0gxpKhcKD
124 | 27jRtjRGIeiUeztgwc4Z0WSLylTS76lPLdJoPtO4ocHErJNFcszHFew18Tzv
125 | ScfnNPUpwyMYmFJLL0GJC+YbMDAPlQuzFrXReGqJE94I15odn+e0RrE//2IF
126 | XwpKVI5riaVEt4GZA72ZOZKb2YvsoGAj40CmMUPl5Ta0A/z7071Nso93y8Xd
127 | YpyugkvL2FhQyuzIjYeq7Wi4bpzAWzyw+6FUsuJrUI6mNEpBMTgUrfe9m3Qn
128 | IKjLoXECdC2q1likp0WBjrYRfFiFyeh/tOCqMl0nvehMfTQ7hwKlw9B118p+
129 | Wi+wFvZpKPhCfQAIohOwvMny1c1qOgeR2ZMXoycWAdiBVLwv7VDr/acmSNcU
130 | nRY2KqL/aBnvxxPW1pxuyaga18nxp68U7LBw7pgJu4xZWPou+I+dRluw+D7U
131 | wE41xjGeydEXbTIdqMPletuEEPekptPIjrfxDwAAAP//AwDXq2nATQUAAA==
132 | http_version:
133 | recorded_at: Thu, 28 May 2015 09:47:30 GMT
134 | - request:
135 | method: get
136 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/stories/94184406
137 | body:
138 | encoding: US-ASCII
139 | string: ''
140 | headers:
141 | Accept:
142 | - "*/*; q=0.5, application/xml"
143 | Accept-Encoding:
144 | - gzip, deflate
145 | X-Trackertoken:
146 | - b545bcaeafc773ced5b1a853fffd1fc9
147 | Content-Type:
148 | - application/xml
149 | User-Agent:
150 | - Ruby
151 | response:
152 | status:
153 | code: 200
154 | message: OK
155 | headers:
156 | Content-Type:
157 | - application/xml; charset=utf-8
158 | Transfer-Encoding:
159 | - chunked
160 | Status:
161 | - 200 OK
162 | X-Ua-Compatible:
163 | - IE=Edge,chrome=1
164 | Cache-Control:
165 | - max-age=0, private, must-revalidate
166 | Set-Cookie:
167 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTVhYWZjYjQ0NjQ3MzQyNGYxY2RkNDAzZGM4ZTUzZDI0BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgGVK6r0KOg1uYW5vX251bWkiOg1uYW5vX2RlbmkGOg1zdWJtaWNybyIHApA6C29mZnNldGkAOgl6b25lSSIIVVRDBjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMWxmQ1d5dXJGdWNtUXd6Wk5ha3hHeVFxYmVYQU5iTzVYNjJEMHdUOVNuSU09BjsARg%3D%3D--84f2a23397829b6cba7c60502ee452cde2b3ce25;
168 | path=/; HttpOnly
169 | X-Request-Id:
170 | - 39bc3111246e044bb53de46f6c45cf61
171 | X-Runtime:
172 | - '0.074896'
173 | Date:
174 | - Thu, 28 May 2015 09:47:30 GMT
175 | X-Rack-Cache:
176 | - miss
177 | X-Powered-By:
178 | - Phusion Passenger 4.0.41
179 | Server:
180 | - nginx/1.6.0 + Phusion Passenger 4.0.41
181 | X-Tracker-Client-Pinger-Interval:
182 | - '12'
183 | Content-Encoding:
184 | - gzip
185 | body:
186 | encoding: ASCII-8BIT
187 | string: !binary |-
188 | H4sIAAAAAAAAAwIAAAD//3ySy27CMBBF93yFlTXFScojRMYsKnXdBayRiQcw
189 | JHZqO6TJ19c2lEcrVcrCM3Pu1fg6ZPlVlegM2gglF1EyiiMEslBcyP0iWq/e
190 | X7JoSQfEWKU7OkCICI5sV8MiEtLCHnRE5+MkG4/jKcGCB6TW6giF3fxFk9d0
191 | lmYxwXckKIL9xvvSHTDbaCD4oeeRRpf0YG1tcozbth3V4qwsK61mxQn0qFDV
192 | RYHNQbX4vpPXeT0YKypm4ff2CcE/o8AVjdYg7cZYB9OdkMIcgBP83PckB1No
193 | UVuXHD2ynjPUo73SJ4FaxFWJaoWMFLBvXF0zt+cBFX1X+rHVfYeUUdtuQPCj
194 | j/eVrIKroWTIMHnyUi9SR38kOBAe1fDZuO2Bb7Yd/QCuFcFPPQ+pVj4Btzpc
195 | V7u83ZjZazDclS4piGgaJxMcuy9DySRPs3wyRevVm4vipglLNLXX/GuROItZ
196 | nsT5ZH6xuGuCRcm2UBrq7zoMmQ1791gEX/supOsP+A0AAP//AwBvV9t2sAIA
197 | AA==
198 | http_version:
199 | recorded_at: Thu, 28 May 2015 09:47:31 GMT
200 | recorded_with: VCR 2.9.3
201 |
--------------------------------------------------------------------------------
/spec/fixtures/json/story_status_update.json:
--------------------------------------------------------------------------------
1 | {
2 | "kind": "story_update_activity",
3 | "guid": "1327280_11",
4 | "project_version": 11,
5 | "message": "Pedro finished this feature",
6 | "highlight": "finished",
7 | "changes": [
8 | {
9 | "kind": "label",
10 | "change_type": "update",
11 | "id": 11622596,
12 | "original_values": {
13 | "counts": {
14 | "number_of_zero_point_stories_by_state": {
15 | "accepted": 0,
16 | "started": 0,
17 | "finished": 0,
18 | "unstarted": 0,
19 | "planned": 0,
20 | "delivered": 0,
21 | "unscheduled": 0,
22 | "rejected": 0,
23 | "kind": "counts_by_story_state"
24 | },
25 | "sum_of_story_estimates_by_state": {
26 | "accepted": 0,
27 | "started": 1,
28 | "finished": 0,
29 | "unstarted": 0,
30 | "planned": 0,
31 | "delivered": 0,
32 | "unscheduled": 0,
33 | "rejected": 0,
34 | "kind": "counts_by_story_state"
35 | },
36 | "number_of_stories_by_state": {
37 | "accepted": 0,
38 | "started": 1,
39 | "finished": 0,
40 | "unstarted": 0,
41 | "planned": 0,
42 | "delivered": 0,
43 | "unscheduled": 0,
44 | "rejected": 0,
45 | "kind": "counts_by_story_state"
46 | },
47 | "kind": "story_counts"
48 | }
49 | },
50 | "new_values": {
51 | "counts": {
52 | "number_of_zero_point_stories_by_state": {
53 | "accepted": 0,
54 | "started": 0,
55 | "finished": 0,
56 | "unstarted": 0,
57 | "planned": 0,
58 | "delivered": 0,
59 | "unscheduled": 0,
60 | "rejected": 0,
61 | "kind": "counts_by_story_state"
62 | },
63 | "sum_of_story_estimates_by_state": {
64 | "accepted": 0,
65 | "started": 0,
66 | "finished": 1,
67 | "unstarted": 0,
68 | "planned": 0,
69 | "delivered": 0,
70 | "unscheduled": 0,
71 | "rejected": 0,
72 | "kind": "counts_by_story_state"
73 | },
74 | "number_of_stories_by_state": {
75 | "accepted": 0,
76 | "started": 0,
77 | "finished": 1,
78 | "unstarted": 0,
79 | "planned": 0,
80 | "delivered": 0,
81 | "unscheduled": 0,
82 | "rejected": 0,
83 | "kind": "counts_by_story_state"
84 | },
85 | "kind": "story_counts"
86 | }
87 | },
88 | "name": "sank"
89 | },
90 | {
91 | "kind": "label",
92 | "change_type": "update",
93 | "id": 11622598,
94 | "original_values": {
95 | "counts": {
96 | "number_of_zero_point_stories_by_state": {
97 | "accepted": 0,
98 | "started": 0,
99 | "finished": 0,
100 | "unstarted": 0,
101 | "planned": 0,
102 | "delivered": 0,
103 | "unscheduled": 0,
104 | "rejected": 0,
105 | "kind": "counts_by_story_state"
106 | },
107 | "sum_of_story_estimates_by_state": {
108 | "accepted": 0,
109 | "started": 1,
110 | "finished": 0,
111 | "unstarted": 0,
112 | "planned": 0,
113 | "delivered": 0,
114 | "unscheduled": 0,
115 | "rejected": 0,
116 | "kind": "counts_by_story_state"
117 | },
118 | "number_of_stories_by_state": {
119 | "accepted": 0,
120 | "started": 1,
121 | "finished": 0,
122 | "unstarted": 0,
123 | "planned": 0,
124 | "delivered": 0,
125 | "unscheduled": 0,
126 | "rejected": 0,
127 | "kind": "counts_by_story_state"
128 | },
129 | "kind": "story_counts"
130 | }
131 | },
132 | "new_values": {
133 | "counts": {
134 | "number_of_zero_point_stories_by_state": {
135 | "accepted": 0,
136 | "started": 0,
137 | "finished": 0,
138 | "unstarted": 0,
139 | "planned": 0,
140 | "delivered": 0,
141 | "unscheduled": 0,
142 | "rejected": 0,
143 | "kind": "counts_by_story_state"
144 | },
145 | "sum_of_story_estimates_by_state": {
146 | "accepted": 0,
147 | "started": 0,
148 | "finished": 1,
149 | "unstarted": 0,
150 | "planned": 0,
151 | "delivered": 0,
152 | "unscheduled": 0,
153 | "rejected": 0,
154 | "kind": "counts_by_story_state"
155 | },
156 | "number_of_stories_by_state": {
157 | "accepted": 0,
158 | "started": 0,
159 | "finished": 1,
160 | "unstarted": 0,
161 | "planned": 0,
162 | "delivered": 0,
163 | "unscheduled": 0,
164 | "rejected": 0,
165 | "kind": "counts_by_story_state"
166 | },
167 | "kind": "story_counts"
168 | }
169 | },
170 | "name": "snieg"
171 | },
172 | {
173 | "kind": "label",
174 | "change_type": "update",
175 | "id": 11622600,
176 | "original_values": {
177 | "counts": {
178 | "number_of_zero_point_stories_by_state": {
179 | "accepted": 0,
180 | "started": 0,
181 | "finished": 0,
182 | "unstarted": 0,
183 | "planned": 0,
184 | "delivered": 0,
185 | "unscheduled": 0,
186 | "rejected": 0,
187 | "kind": "counts_by_story_state"
188 | },
189 | "sum_of_story_estimates_by_state": {
190 | "accepted": 0,
191 | "started": 1,
192 | "finished": 0,
193 | "unstarted": 0,
194 | "planned": 0,
195 | "delivered": 0,
196 | "unscheduled": 0,
197 | "rejected": 0,
198 | "kind": "counts_by_story_state"
199 | },
200 | "number_of_stories_by_state": {
201 | "accepted": 0,
202 | "started": 1,
203 | "finished": 0,
204 | "unstarted": 0,
205 | "planned": 0,
206 | "delivered": 0,
207 | "unscheduled": 0,
208 | "rejected": 0,
209 | "kind": "counts_by_story_state"
210 | },
211 | "kind": "story_counts"
212 | }
213 | },
214 | "new_values": {
215 | "counts": {
216 | "number_of_zero_point_stories_by_state": {
217 | "accepted": 0,
218 | "started": 0,
219 | "finished": 0,
220 | "unstarted": 0,
221 | "planned": 0,
222 | "delivered": 0,
223 | "unscheduled": 0,
224 | "rejected": 0,
225 | "kind": "counts_by_story_state"
226 | },
227 | "sum_of_story_estimates_by_state": {
228 | "accepted": 0,
229 | "started": 0,
230 | "finished": 1,
231 | "unstarted": 0,
232 | "planned": 0,
233 | "delivered": 0,
234 | "unscheduled": 0,
235 | "rejected": 0,
236 | "kind": "counts_by_story_state"
237 | },
238 | "number_of_stories_by_state": {
239 | "accepted": 0,
240 | "started": 0,
241 | "finished": 1,
242 | "unstarted": 0,
243 | "planned": 0,
244 | "delivered": 0,
245 | "unscheduled": 0,
246 | "rejected": 0,
247 | "kind": "counts_by_story_state"
248 | },
249 | "kind": "story_counts"
250 | }
251 | },
252 | "name": "zima"
253 | },
254 | {
255 | "kind": "story",
256 | "change_type": "update",
257 | "id": 94184406,
258 | "original_values": {
259 | "current_state": "started",
260 | "updated_at": 1431099420000
261 | },
262 | "new_values": {
263 | "current_state": "finished",
264 | "updated_at": 1431099477000
265 | },
266 | "name": "jazda na sankach w parach",
267 | "story_type": "feature"
268 | }
269 | ],
270 | "primary_resources": [
271 | {
272 | "kind": "story",
273 | "id": 94184406,
274 | "name": "jazda na sankach w parach",
275 | "story_type": "feature",
276 | "url": "https://www.pivotaltracker.com/story/show/94184406"
277 | }
278 | ],
279 | "project": {
280 | "kind": "project",
281 | "id": 1327280,
282 | "name": "ziomal"
283 | },
284 | "performed_by": {
285 | "kind": "person",
286 | "id": 1651216,
287 | "name": "Pedro",
288 | "initials": "PE"
289 | },
290 | "occurred_at": 1431099477000
--------------------------------------------------------------------------------
/spec/fixtures/json/story_started.json:
--------------------------------------------------------------------------------
1 | {
2 | "kind": "story_update_activity",
3 | "guid": "1327280_8",
4 | "project_version": 8,
5 | "message": "Pedro started this feature",
6 | "highlight": "started",
7 | "changes": [
8 | {
9 | "kind": "label",
10 | "change_type": "update",
11 | "id": 11622596,
12 | "original_values": {
13 | "counts": {
14 | "number_of_zero_point_stories_by_state": {
15 | "accepted": 0,
16 | "started": 0,
17 | "finished": 0,
18 | "unstarted": 0,
19 | "planned": 0,
20 | "delivered": 0,
21 | "unscheduled": 0,
22 | "rejected": 0,
23 | "kind": "counts_by_story_state"
24 | },
25 | "sum_of_story_estimates_by_state": {
26 | "accepted": 0,
27 | "started": 0,
28 | "finished": 0,
29 | "unstarted": 0,
30 | "planned": 0,
31 | "delivered": 0,
32 | "unscheduled": 1,
33 | "rejected": 0,
34 | "kind": "counts_by_story_state"
35 | },
36 | "number_of_stories_by_state": {
37 | "accepted": 0,
38 | "started": 0,
39 | "finished": 0,
40 | "unstarted": 0,
41 | "planned": 0,
42 | "delivered": 0,
43 | "unscheduled": 1,
44 | "rejected": 0,
45 | "kind": "counts_by_story_state"
46 | },
47 | "kind": "story_counts"
48 | }
49 | },
50 | "new_values": {
51 | "counts": {
52 | "number_of_zero_point_stories_by_state": {
53 | "accepted": 0,
54 | "started": 0,
55 | "finished": 0,
56 | "unstarted": 0,
57 | "planned": 0,
58 | "delivered": 0,
59 | "unscheduled": 0,
60 | "rejected": 0,
61 | "kind": "counts_by_story_state"
62 | },
63 | "sum_of_story_estimates_by_state": {
64 | "accepted": 0,
65 | "started": 1,
66 | "finished": 0,
67 | "unstarted": 0,
68 | "planned": 0,
69 | "delivered": 0,
70 | "unscheduled": 0,
71 | "rejected": 0,
72 | "kind": "counts_by_story_state"
73 | },
74 | "number_of_stories_by_state": {
75 | "accepted": 0,
76 | "started": 1,
77 | "finished": 0,
78 | "unstarted": 0,
79 | "planned": 0,
80 | "delivered": 0,
81 | "unscheduled": 0,
82 | "rejected": 0,
83 | "kind": "counts_by_story_state"
84 | },
85 | "kind": "story_counts"
86 | }
87 | },
88 | "name": "sank"
89 | },
90 | {
91 | "kind": "label",
92 | "change_type": "update",
93 | "id": 11622598,
94 | "original_values": {
95 | "counts": {
96 | "number_of_zero_point_stories_by_state": {
97 | "accepted": 0,
98 | "started": 0,
99 | "finished": 0,
100 | "unstarted": 0,
101 | "planned": 0,
102 | "delivered": 0,
103 | "unscheduled": 0,
104 | "rejected": 0,
105 | "kind": "counts_by_story_state"
106 | },
107 | "sum_of_story_estimates_by_state": {
108 | "accepted": 0,
109 | "started": 0,
110 | "finished": 0,
111 | "unstarted": 0,
112 | "planned": 0,
113 | "delivered": 0,
114 | "unscheduled": 1,
115 | "rejected": 0,
116 | "kind": "counts_by_story_state"
117 | },
118 | "number_of_stories_by_state": {
119 | "accepted": 0,
120 | "started": 0,
121 | "finished": 0,
122 | "unstarted": 0,
123 | "planned": 0,
124 | "delivered": 0,
125 | "unscheduled": 1,
126 | "rejected": 0,
127 | "kind": "counts_by_story_state"
128 | },
129 | "kind": "story_counts"
130 | }
131 | },
132 | "new_values": {
133 | "counts": {
134 | "number_of_zero_point_stories_by_state": {
135 | "accepted": 0,
136 | "started": 0,
137 | "finished": 0,
138 | "unstarted": 0,
139 | "planned": 0,
140 | "delivered": 0,
141 | "unscheduled": 0,
142 | "rejected": 0,
143 | "kind": "counts_by_story_state"
144 | },
145 | "sum_of_story_estimates_by_state": {
146 | "accepted": 0,
147 | "started": 1,
148 | "finished": 0,
149 | "unstarted": 0,
150 | "planned": 0,
151 | "delivered": 0,
152 | "unscheduled": 0,
153 | "rejected": 0,
154 | "kind": "counts_by_story_state"
155 | },
156 | "number_of_stories_by_state": {
157 | "accepted": 0,
158 | "started": 1,
159 | "finished": 0,
160 | "unstarted": 0,
161 | "planned": 0,
162 | "delivered": 0,
163 | "unscheduled": 0,
164 | "rejected": 0,
165 | "kind": "counts_by_story_state"
166 | },
167 | "kind": "story_counts"
168 | }
169 | },
170 | "name": "snieg"
171 | },
172 | {
173 | "kind": "label",
174 | "change_type": "update",
175 | "id": 11622600,
176 | "original_values": {
177 | "counts": {
178 | "number_of_zero_point_stories_by_state": {
179 | "accepted": 0,
180 | "started": 0,
181 | "finished": 0,
182 | "unstarted": 0,
183 | "planned": 0,
184 | "delivered": 0,
185 | "unscheduled": 0,
186 | "rejected": 0,
187 | "kind": "counts_by_story_state"
188 | },
189 | "sum_of_story_estimates_by_state": {
190 | "accepted": 0,
191 | "started": 0,
192 | "finished": 0,
193 | "unstarted": 0,
194 | "planned": 0,
195 | "delivered": 0,
196 | "unscheduled": 1,
197 | "rejected": 0,
198 | "kind": "counts_by_story_state"
199 | },
200 | "number_of_stories_by_state": {
201 | "accepted": 0,
202 | "started": 0,
203 | "finished": 0,
204 | "unstarted": 0,
205 | "planned": 0,
206 | "delivered": 0,
207 | "unscheduled": 1,
208 | "rejected": 0,
209 | "kind": "counts_by_story_state"
210 | },
211 | "kind": "story_counts"
212 | }
213 | },
214 | "new_values": {
215 | "counts": {
216 | "number_of_zero_point_stories_by_state": {
217 | "accepted": 0,
218 | "started": 0,
219 | "finished": 0,
220 | "unstarted": 0,
221 | "planned": 0,
222 | "delivered": 0,
223 | "unscheduled": 0,
224 | "rejected": 0,
225 | "kind": "counts_by_story_state"
226 | },
227 | "sum_of_story_estimates_by_state": {
228 | "accepted": 0,
229 | "started": 1,
230 | "finished": 0,
231 | "unstarted": 0,
232 | "planned": 0,
233 | "delivered": 0,
234 | "unscheduled": 0,
235 | "rejected": 0,
236 | "kind": "counts_by_story_state"
237 | },
238 | "number_of_stories_by_state": {
239 | "accepted": 0,
240 | "started": 1,
241 | "finished": 0,
242 | "unstarted": 0,
243 | "planned": 0,
244 | "delivered": 0,
245 | "unscheduled": 0,
246 | "rejected": 0,
247 | "kind": "counts_by_story_state"
248 | },
249 | "kind": "story_counts"
250 | }
251 | },
252 | "name": "zima"
253 | },
254 | {
255 | "kind": "story",
256 | "change_type": "update",
257 | "id": 94184406,
258 | "original_values": {
259 | "current_state": "unscheduled",
260 | "owned_by_id": null,
261 | "owner_ids": [
262 |
263 | ],
264 | "updated_at": 1431098936000
265 | },
266 | "new_values": {
267 | "current_state": "started",
268 | "owned_by_id": 1651216,
269 | "owner_ids": [
270 | 1651216
271 | ],
272 | "updated_at": 1431098967000
273 | },
274 | "name": "jazda na sankach",
275 | "story_type": "feature"
276 | }
277 | ],
278 | "primary_resources": [
279 | {
280 | "kind": "story",
281 | "id": 94184406,
282 | "name": "jazda na sankach",
283 | "story_type": "feature",
284 | "url": "https://www.pivotaltracker.com/story/show/94184406"
285 | }
286 | ],
287 | "project": {
288 | "kind": "project",
289 | "id": 1327280,
290 | "name": "ziomal"
291 | },
292 | "performed_by": {
293 | "kind": "person",
294 | "id": 1651216,
295 | "name": "Pedro",
296 | "initials": "PE"
297 | },
298 | "occurred_at": 1431098967000
299 | }
--------------------------------------------------------------------------------
/spec/cassettes/issue_creator.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://www.pivotaltracker.com/services/v3/tokens/active
6 | body:
7 | encoding: US-ASCII
8 | string: username=foobar%40gmail.com&password=secret&timeout=60
9 | headers:
10 | Accept:
11 | - "*/*; q=0.5, application/xml"
12 | Accept-Encoding:
13 | - gzip, deflate
14 | Content-Length:
15 | - '55'
16 | Content-Type:
17 | - application/x-www-form-urlencoded
18 | User-Agent:
19 | - Ruby
20 | response:
21 | status:
22 | code: 200
23 | message: OK
24 | headers:
25 | Content-Type:
26 | - application/xml; charset=utf-8
27 | Transfer-Encoding:
28 | - chunked
29 | Status:
30 | - 200 OK
31 | X-Ua-Compatible:
32 | - IE=Edge,chrome=1
33 | Etag:
34 | - '"2aca2abf73441eff33bb5c8599b6a03b"'
35 | Cache-Control:
36 | - max-age=0, private, must-revalidate
37 | Set-Cookie:
38 | - t_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJTVlMzBhN2ZlOTI5NzcwMzJlMjg1NDUzNjA4MzQwNmZkBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgEvw%2Bb0KOg1uYW5vX251bWkcOg1uYW5vX2RlbmkGOg1zdWJtaWNybyIHAjA6C29mZnNldGkAOgl6b25lSSIIVVRDBjsAVA%3D%3D--6ce0a4774f0175f092d741642ca5c36153d702a6;
39 | path=/; HttpOnly
40 | X-Request-Id:
41 | - 5b65ff86d7ea2faf9adca467ffd578a5
42 | X-Runtime:
43 | - '0.120306'
44 | Date:
45 | - Thu, 28 May 2015 09:47:31 GMT
46 | X-Rack-Cache:
47 | - invalidate, pass
48 | X-Powered-By:
49 | - Phusion Passenger 4.0.41
50 | Server:
51 | - nginx/1.6.0 + Phusion Passenger 4.0.41
52 | X-Tracker-Client-Pinger-Interval:
53 | - '12'
54 | body:
55 | encoding: UTF-8
56 | string: |
57 |
58 |
59 | b545bcaeafc773ced5b1a853fffd1fc9
60 | 838284
61 |
62 | http_version:
63 | recorded_at: Thu, 28 May 2015 09:47:32 GMT
64 | - request:
65 | method: get
66 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280
67 | body:
68 | encoding: US-ASCII
69 | string: ''
70 | headers:
71 | Accept:
72 | - "*/*; q=0.5, application/xml"
73 | Accept-Encoding:
74 | - gzip, deflate
75 | X-Trackertoken:
76 | - b545bcaeafc773ced5b1a853fffd1fc9
77 | Content-Type:
78 | - application/xml
79 | User-Agent:
80 | - Ruby
81 | response:
82 | status:
83 | code: 200
84 | message: OK
85 | headers:
86 | Content-Type:
87 | - application/xml; charset=utf-8
88 | Transfer-Encoding:
89 | - chunked
90 | Status:
91 | - 200 OK
92 | X-Ua-Compatible:
93 | - IE=Edge,chrome=1
94 | Cache-Control:
95 | - max-age=0, private, must-revalidate
96 | Set-Cookie:
97 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWE3NWM1OTk5ZDZkMzVmZDFkMjEwNzBhYjA1ZDcwNWE0BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgBhuCr4KOg1uYW5vX251bWkC0AM6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgeXYDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxVklYNmdKR29KM09BaUV3NFVkTWhPYW1SaU90dzF1bEhJL1RaVk02Y0xRRT0GOwBG--75477a5b294d13f13736a05594beb173aed85d3c;
98 | path=/; HttpOnly
99 | X-Request-Id:
100 | - 2d68b8ab3ff4f4b2888710ed76566314
101 | X-Runtime:
102 | - '0.049506'
103 | Date:
104 | - Thu, 28 May 2015 09:47:32 GMT
105 | X-Rack-Cache:
106 | - miss
107 | X-Powered-By:
108 | - Phusion Passenger 4.0.41
109 | Server:
110 | - nginx/1.6.0 + Phusion Passenger 4.0.41
111 | X-Tracker-Client-Pinger-Interval:
112 | - '12'
113 | Content-Encoding:
114 | - gzip
115 | body:
116 | encoding: ASCII-8BIT
117 | string: !binary |-
118 | H4sIAAAAAAAAAwIAAAD//4RUS2/bMAy+91cYPmeV4zRoVrjqtmK7DethPQu0
119 | zdhaZMmQ5GTprx+l2Hm06wYEiPjx45tm8fC7U8kWrZNG36fz6yxNUFemlrq5
120 | T59/fvuwSh/4VdFb8wsrz6+SpJA1ny/y23yVFYzeAdLQIX+RpgNVsChEokcL
121 | nhwLhbrxbeL3Pd6nUnts0KZ8TvavKNFuh7gRzoP1ooY9/240/RXsFRyYvSFn
122 | wlWgkGez+SyfLQp2DgYSVJUZtOdfLGwxeYy1FWxCA2MtrfPilMshtpcdjinX
123 | 4DGIKc+z+ZJlS5bfJHl+l2X0S55/PhbsfR+xpmqwFinXUxA9dCXav/TkPWr0
124 | gxpKhcKD27jRtjRGIeiUeztgwc4Z0WSLylTS76lPLdJoPtO4ocHErJNFcszH
125 | Few18TzvScfnNPUpwyMYmFJLL0GJC+YbMDAPlQuzFrXReGqJE94I15odn+e0
126 | RrE//2IFXwpKVI5riaVEt4GZA72ZOZKb2YvsoGAj40CmMUPl5Ta0A/z7071N
127 | so93y8XdYpyugkvL2FhQyuzIjYeq7Wi4bpzAWzyw+6FUsuJrUI6mNEpBMTgU
128 | rfe9m3QnIKjLoXECdC2q1likp0WBjrYRfFiFyeh/tOCqMl0nvehMfTQ7hwKl
129 | w9B118p+Wi+wFvZpKPhCfQAIohOwvMny1c1qOgeR2ZMXoycWAdiBVLwv7VDr
130 | /acmSNcUnRY2KqL/aBnvxxPW1pxuyaga18nxp68U7LBw7pgJu4xZWPou+I+d
131 | Rluw+D7UwE41xjGeydEXbTIdqMPletuEEPekptPIjrfxDwAAAP//AwDXq2nA
132 | TQUAAA==
133 | http_version:
134 | recorded_at: Thu, 28 May 2015 09:47:33 GMT
135 | - request:
136 | method: get
137 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/stories/94184406
138 | body:
139 | encoding: US-ASCII
140 | string: ''
141 | headers:
142 | Accept:
143 | - "*/*; q=0.5, application/xml"
144 | Accept-Encoding:
145 | - gzip, deflate
146 | X-Trackertoken:
147 | - b545bcaeafc773ced5b1a853fffd1fc9
148 | Content-Type:
149 | - application/xml
150 | User-Agent:
151 | - Ruby
152 | response:
153 | status:
154 | code: 200
155 | message: OK
156 | headers:
157 | Content-Type:
158 | - application/xml; charset=utf-8
159 | Transfer-Encoding:
160 | - chunked
161 | Status:
162 | - 200 OK
163 | X-Ua-Compatible:
164 | - IE=Edge,chrome=1
165 | Cache-Control:
166 | - max-age=0, private, must-revalidate
167 | Set-Cookie:
168 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTcyMTQyMDI4MGQyZjQyZGQ5NmM3NjEzOTg1OTZhOGRmBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgGE8Gb4KOg1uYW5vX251bWkCuAI6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgdpYDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxN2JuSEZLTXVWbDhjZ01WTmUxaE1nVkl4V3lmVzB2ODlSLzU3c2U0TWFEaz0GOwBG--1af22d30a4633ccaa6d8421c7a724edde7dccc9e;
169 | path=/; HttpOnly
170 | X-Request-Id:
171 | - 94ca736c0f14ef4e0e7c8747cdfad7fd
172 | X-Runtime:
173 | - '0.065170'
174 | Date:
175 | - Thu, 28 May 2015 09:47:33 GMT
176 | X-Rack-Cache:
177 | - miss
178 | X-Powered-By:
179 | - Phusion Passenger 4.0.41
180 | Server:
181 | - nginx/1.6.0 + Phusion Passenger 4.0.41
182 | X-Tracker-Client-Pinger-Interval:
183 | - '12'
184 | Content-Encoding:
185 | - gzip
186 | body:
187 | encoding: ASCII-8BIT
188 | string: !binary |-
189 | H4sIAAAAAAAAAwIAAAD//3ySy27CMBBF93yFlTXFScojRMYsKnXdBayRiQcw
190 | JHZqO6TJ19c2lEcrVcrCM3Pu1fg6ZPlVlegM2gglF1EyiiMEslBcyP0iWq/e
191 | X7JoSQfEWKU7OkCICI5sV8MiEtLCHnRE5+MkG4/jKcGCB6TW6giF3fxFk9d0
192 | lmYxwXckKIL9xvvSHTDbaCD4oeeRRpf0YG1tcozbth3V4qwsK61mxQn0qFDV
193 | RYHNQbX4vpPXeT0YKypm4ff2CcE/o8AVjdYg7cZYB9OdkMIcgBP83PckB1No
194 | UVuXHD2ynjPUo73SJ4FaxFWJaoWMFLBvXF0zt+cBFX1X+rHVfYeUUdtuQPCj
195 | j/eVrIKroWTIMHnyUi9SR38kOBAe1fDZuO2Bb7Yd/QCuFcFPPQ+pVj4Btzpc
196 | V7u83ZjZazDclS4piGgaJxMcuy9DySRPs3wyRevVm4vipglLNLXX/GuROItZ
197 | nsT5ZH6xuGuCRcm2UBrq7zoMmQ1791gEX/supOsP+A0AAP//AwBvV9t2sAIA
198 | AA==
199 | http_version:
200 | recorded_at: Thu, 28 May 2015 09:47:34 GMT
201 | - request:
202 | method: get
203 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/stories/94184406/notes
204 | body:
205 | encoding: US-ASCII
206 | string: ''
207 | headers:
208 | Accept:
209 | - "*/*; q=0.5, application/xml"
210 | Accept-Encoding:
211 | - gzip, deflate
212 | X-Trackertoken:
213 | - b545bcaeafc773ced5b1a853fffd1fc9
214 | Content-Type:
215 | - application/xml
216 | User-Agent:
217 | - Ruby
218 | response:
219 | status:
220 | code: 200
221 | message: OK
222 | headers:
223 | Content-Type:
224 | - application/xml; charset=utf-8
225 | Transfer-Encoding:
226 | - chunked
227 | Status:
228 | - 200 OK
229 | X-Ua-Compatible:
230 | - IE=Edge,chrome=1
231 | Cache-Control:
232 | - max-age=0, private, must-revalidate
233 | Set-Cookie:
234 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTE2M2FmMmQ4NTA4YWM0ZTI2MDgyZGU1ZjIyM2NlM2VlBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgMWhML4KOg1uYW5vX251bWkClQE6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgdAUDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxS2trajNJMk04elNacEZHOXhOS2hYbW5acVNtMHFDQ2oyeG1nV2VHUUxZWT0GOwBG--94aecbc773b702832f19a373792aae04e73e3726;
235 | path=/; HttpOnly
236 | X-Request-Id:
237 | - b7414806172d6ab80c453be3f31b0fb7
238 | X-Runtime:
239 | - '0.041954'
240 | Date:
241 | - Thu, 28 May 2015 09:47:35 GMT
242 | X-Rack-Cache:
243 | - miss
244 | X-Powered-By:
245 | - Phusion Passenger 4.0.41
246 | Server:
247 | - nginx/1.6.0 + Phusion Passenger 4.0.41
248 | X-Tracker-Client-Pinger-Interval:
249 | - '12'
250 | Content-Encoding:
251 | - gzip
252 | body:
253 | encoding: ASCII-8BIT
254 | string: !binary |-
255 | H4sIAAAAAAAAA7Kxr8jNUShLLSrOzM+zVTLUM1BSSM1Lzk/JzEu3VQoNcdO1
256 | ULK347LJyy9JLVYoqSxItVVKLCpKrFTSt+MCAAAA//8DAPeRVfM9AAAA
257 | http_version:
258 | recorded_at: Thu, 28 May 2015 09:47:36 GMT
259 | recorded_with: VCR 2.9.3
260 |
--------------------------------------------------------------------------------
/spec/cassettes/restarting_story.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://www.pivotaltracker.com/services/v3/tokens/active
6 | body:
7 | encoding: US-ASCII
8 | string: username=foobar%40gmail.com&password=secret&timeout=60
9 | headers:
10 | Accept:
11 | - "*/*; q=0.5, application/xml"
12 | Accept-Encoding:
13 | - gzip, deflate
14 | Content-Length:
15 | - '55'
16 | Content-Type:
17 | - application/x-www-form-urlencoded
18 | User-Agent:
19 | - Ruby
20 | response:
21 | status:
22 | code: 200
23 | message: OK
24 | headers:
25 | Content-Type:
26 | - application/xml; charset=utf-8
27 | Transfer-Encoding:
28 | - chunked
29 | Status:
30 | - 200 OK
31 | X-Ua-Compatible:
32 | - IE=Edge,chrome=1
33 | Etag:
34 | - '"2aca2abf73441eff33bb5c8599b6a03b"'
35 | Cache-Control:
36 | - max-age=0, private, must-revalidate
37 | Set-Cookie:
38 | - t_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJTQ1NGZlODQyODUwYTQwNzRjMmRiNWE0ZTgxMTk5MmRjBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgOl6mL8KOg1uYW5vX251bWkCIwM6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgeAMDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBU--d62f62c4321c8efd59aeab89b696aa34a2af5867;
39 | path=/; HttpOnly
40 | X-Request-Id:
41 | - 8364ff82affe35560ad3efa12c14fefd
42 | X-Runtime:
43 | - '0.120550'
44 | Date:
45 | - Thu, 28 May 2015 09:47:57 GMT
46 | X-Rack-Cache:
47 | - invalidate, pass
48 | X-Powered-By:
49 | - Phusion Passenger 4.0.41
50 | Server:
51 | - nginx/1.6.0 + Phusion Passenger 4.0.41
52 | X-Tracker-Client-Pinger-Interval:
53 | - '12'
54 | body:
55 | encoding: UTF-8
56 | string: |
57 |
58 |
59 | b545bcaeafc773ced5b1a853fffd1fc9
60 | 838284
61 |
62 | http_version:
63 | recorded_at: Thu, 28 May 2015 09:47:58 GMT
64 | - request:
65 | method: get
66 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/memberships
67 | body:
68 | encoding: US-ASCII
69 | string: ''
70 | headers:
71 | Accept:
72 | - "*/*; q=0.5, application/xml"
73 | Accept-Encoding:
74 | - gzip, deflate
75 | X-Trackertoken:
76 | - b545bcaeafc773ced5b1a853fffd1fc9
77 | Content-Type:
78 | - application/xml
79 | User-Agent:
80 | - Ruby
81 | response:
82 | status:
83 | code: 200
84 | message: OK
85 | headers:
86 | Content-Type:
87 | - application/xml; charset=utf-8
88 | Transfer-Encoding:
89 | - chunked
90 | Status:
91 | - 200 OK
92 | X-Ua-Compatible:
93 | - IE=Edge,chrome=1
94 | Cache-Control:
95 | - max-age=0, private, must-revalidate
96 | Set-Cookie:
97 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWU4M2M4OWMzNTM1NWJiYmY3MTE0NmQ2NTMxNTkxY2FkBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgF%2F4p78KOg1uYW5vX251bWkCGQE6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgcoEDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxWDZpTk1NR3JrTkdLelRaYThyQk9CRll5dkt0dklkYk9jMDZXL2lnRWw4ND0GOwBG--1fc426d1629f831698d291a9887d7485da64ea91;
98 | path=/; HttpOnly
99 | X-Request-Id:
100 | - 54bcdc593fe63f9fab85ab19e782d200
101 | X-Runtime:
102 | - '0.049570'
103 | Date:
104 | - Thu, 28 May 2015 09:47:58 GMT
105 | X-Rack-Cache:
106 | - miss
107 | X-Powered-By:
108 | - Phusion Passenger 4.0.41
109 | Server:
110 | - nginx/1.6.0 + Phusion Passenger 4.0.41
111 | X-Tracker-Client-Pinger-Interval:
112 | - '12'
113 | Content-Encoding:
114 | - gzip
115 | body:
116 | encoding: ASCII-8BIT
117 | string: !binary |-
118 | H4sIAAAAAAAAAwIAAAD//0xQu27DMAzc/RWC9kaOk6IeaKZLuyZD+wGKRSQs
119 | 9ILsJnW/vopdw954vDvegXD4cVbcKHUcfCO3m1IK8m0w7C+N/Px4f6rlAQtw
120 | 5M5ZdOXYiX6I1Eidkh4kFkKsyAfMCzb4vC+rel+DyvO0jNkf/ASyhpxmi/Gc
121 | vo0fXi8PtGmDAzURoyfLvHaEJzIpgBrnmWDPPWvb4ekth8xgilLrLEjBEh7v
122 | nhKocf7vk8IXtf1y0OB2V71UdbmUngv8cnDarhuAiosf1PKf/KwV6rD4AwAA
123 | //8DAHDPkbBjAQAA
124 | http_version:
125 | recorded_at: Thu, 28 May 2015 09:47:59 GMT
126 | - request:
127 | method: post
128 | uri: https://www.pivotaltracker.com/services/v3/tokens/active
129 | body:
130 | encoding: US-ASCII
131 | string: username=foobar%40gmail.com&password=secret&timeout=60
132 | headers:
133 | Accept:
134 | - "*/*; q=0.5, application/xml"
135 | Accept-Encoding:
136 | - gzip, deflate
137 | Content-Length:
138 | - '55'
139 | Content-Type:
140 | - application/x-www-form-urlencoded
141 | User-Agent:
142 | - Ruby
143 | response:
144 | status:
145 | code: 200
146 | message: OK
147 | headers:
148 | Content-Type:
149 | - application/xml; charset=utf-8
150 | Transfer-Encoding:
151 | - chunked
152 | Status:
153 | - 200 OK
154 | X-Ua-Compatible:
155 | - IE=Edge,chrome=1
156 | Etag:
157 | - '"2aca2abf73441eff33bb5c8599b6a03b"'
158 | Cache-Control:
159 | - max-age=0, private, must-revalidate
160 | Set-Cookie:
161 | - t_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWRmMjgzODY4YzRkMTNiZDkzZWFkODU2YTViNTM2ZjVjBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgButtr8KOg1uYW5vX251bWkCFwI6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgdTUDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBU--d998dc6034eb0ae3593e17d2a2a4cf580bb97bdf;
162 | path=/; HttpOnly
163 | X-Request-Id:
164 | - c27a1de69e56911f53ca46e743b948b8
165 | X-Runtime:
166 | - '0.123150'
167 | Date:
168 | - Thu, 28 May 2015 09:47:59 GMT
169 | X-Rack-Cache:
170 | - invalidate, pass
171 | X-Powered-By:
172 | - Phusion Passenger 4.0.41
173 | Server:
174 | - nginx/1.6.0 + Phusion Passenger 4.0.41
175 | X-Tracker-Client-Pinger-Interval:
176 | - '12'
177 | body:
178 | encoding: UTF-8
179 | string: |
180 |
181 |
182 | b545bcaeafc773ced5b1a853fffd1fc9
183 | 838284
184 |
185 | http_version:
186 | recorded_at: Thu, 28 May 2015 09:48:00 GMT
187 | - request:
188 | method: get
189 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/stories/92844256
190 | body:
191 | encoding: US-ASCII
192 | string: ''
193 | headers:
194 | Accept:
195 | - "*/*; q=0.5, application/xml"
196 | Accept-Encoding:
197 | - gzip, deflate
198 | X-Trackertoken:
199 | - b545bcaeafc773ced5b1a853fffd1fc9
200 | Content-Type:
201 | - application/xml
202 | User-Agent:
203 | - Ruby
204 | response:
205 | status:
206 | code: 200
207 | message: OK
208 | headers:
209 | Content-Type:
210 | - application/xml; charset=utf-8
211 | Transfer-Encoding:
212 | - chunked
213 | Status:
214 | - 200 OK
215 | X-Ua-Compatible:
216 | - IE=Edge,chrome=1
217 | Cache-Control:
218 | - max-age=0, private, must-revalidate
219 | Set-Cookie:
220 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWM0ZDQ0OThkYjA5MWMxYzA4MDIzYWQzMTEwNjU4ZGM5BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgI%2B9BsAKOg1uYW5vX251bWkCggI6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgdkIDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxWDRQaVpZYjdCcWpxb2FPbEZsSzYwWHllTiswcU1JbDFCY3A5a0lVOGF4VT0GOwBG--7f6ecd1c00c604b20dba09c60951763a6a12cccd;
221 | path=/; HttpOnly
222 | X-Request-Id:
223 | - 0112f6aea4b5ef3db4cf17153a0d1f78
224 | X-Runtime:
225 | - '0.058097'
226 | Date:
227 | - Thu, 28 May 2015 09:48:00 GMT
228 | X-Rack-Cache:
229 | - miss
230 | X-Powered-By:
231 | - Phusion Passenger 4.0.41
232 | Server:
233 | - nginx/1.6.0 + Phusion Passenger 4.0.41
234 | X-Tracker-Client-Pinger-Interval:
235 | - '12'
236 | Content-Encoding:
237 | - gzip
238 | body:
239 | encoding: ASCII-8BIT
240 | string: !binary |-
241 | H4sIAAAAAAAAAwIAAAD//3yRy27CMBBF93yFlX1xEhIekTGLSl13AevIxAOY
242 | JHZqO6T062sbyqOVurE0d869mhmT1WfboBNoI5RcRsk4jhDISnEh98tos357
243 | mUcrOiLGKn2mI4SI4MieO1hGQlrYg47oIp1nWZpPCRY8IJ1WR6hs+RdNJuks
244 | nccE35HgCPGlz6U7YLbXQPCD5pFeN/RgbWcKjIdhGHfipCxrrGZVDXpcqfbi
245 | wOagBnyfyfu8H4wVLbPwe/qE4J9W4Kpea5C2NNbBdCekMAfgBD/rnuRgKi06
246 | 6y5HoVHoS6i2FqhllQC0Y0cJiAdlcK1WuJUeHT5BshaoVQ3UqPEvwUHxLQ0f
247 | vZsLeLk903fgWhH8pHlIDfIJuNVhEe0u6drMXlfmrnQ3gIimcZLjOMNpjJJp
248 | kWdFlqHN+tUtefOEIfrOe/6JyHE6Q/GiyCfFJL5E3D0homFbaAyVArYCTM0I
249 | viqj6w/T0TcAAAD//wMAn+5QTIQCAAA=
250 | http_version:
251 | recorded_at: Thu, 28 May 2015 09:48:01 GMT
252 | - request:
253 | method: put
254 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/stories/92844256
255 | body:
256 | encoding: UTF-8
257 | string: |
258 |
259 |
260 | tolek lolek
261 | elo ziomki macie fajne domki w zimie
262 | feature
263 | 1
264 | finished
265 | Pedro
266 | Pedro
267 | niebieska
268 | 1327280
269 | 2015-04-20T16:54:44+00:00
270 |
271 | headers:
272 | Accept:
273 | - "*/*; q=0.5, application/xml"
274 | Accept-Encoding:
275 | - gzip, deflate
276 | X-Trackertoken:
277 | - b545bcaeafc773ced5b1a853fffd1fc9
278 | Content-Type:
279 | - application/xml
280 | Content-Length:
281 | - '417'
282 | User-Agent:
283 | - Ruby
284 | response:
285 | status:
286 | code: 200
287 | message: OK
288 | headers:
289 | Content-Type:
290 | - application/xml; charset=utf-8
291 | Transfer-Encoding:
292 | - chunked
293 | Status:
294 | - 200 OK
295 | X-Ua-Compatible:
296 | - IE=Edge,chrome=1
297 | Etag:
298 | - '"2d16160707383764f5c482483ad97cc9"'
299 | Cache-Control:
300 | - max-age=0, private, must-revalidate
301 | Set-Cookie:
302 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJThiM2YyZDkxZTliMzFlODUwZWFmNjFkOGMyMGI0ZTZmBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgO5rFcAKOg1uYW5vX251bWkBpjoNbmFub19kZW5pBjoNc3VibWljcm8iBxZgOgtvZmZzZXRpADoJem9uZUkiCFVUQwY7AFRJIhBfY3NyZl90b2tlbgY7AEZJIjFXeWNtSmpWbFJuUnQ2ZzZ5ZWhXNm9kOUJUdW5XNFlhd3hkSTNjSjVxdGtzPQY7AEY%3D--9862b2f80a258212743cc49f8ac7d9b6be8013b4;
303 | path=/; HttpOnly
304 | X-Request-Id:
305 | - 5db582d677c63b9e97ffa8f35cabc6ab
306 | X-Runtime:
307 | - '0.179818'
308 | Date:
309 | - Thu, 28 May 2015 09:48:01 GMT
310 | X-Rack-Cache:
311 | - invalidate, pass
312 | X-Powered-By:
313 | - Phusion Passenger 4.0.41
314 | Server:
315 | - nginx/1.6.0 + Phusion Passenger 4.0.41
316 | X-Tracker-Client-Pinger-Interval:
317 | - '12'
318 | body:
319 | encoding: UTF-8
320 | string: |
321 |
322 |
323 | 92844256
324 | 1327280
325 | feature
326 | https://www.pivotaltracker.com/story/show/92844256
327 | 1
328 | finished
329 | elo ziomki macie fajne domki w zimie
330 | tolek lolek
331 | Pedro
332 | Pedro
333 | 2015/04/20 16:54:44 UTC
334 | 2015/05/27 09:53:30 UTC
335 | niebieska
336 |
337 | http_version:
338 | recorded_at: Thu, 28 May 2015 09:48:02 GMT
339 | recorded_with: VCR 2.9.3
340 |
--------------------------------------------------------------------------------
/spec/cassettes/pivotal_project.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://www.pivotaltracker.com/services/v3/tokens/active
6 | body:
7 | encoding: US-ASCII
8 | string: username=foobar%40gmail.com&password=secret&timeout=60
9 | headers:
10 | Accept:
11 | - "*/*; q=0.5, application/xml"
12 | Accept-Encoding:
13 | - gzip, deflate
14 | Content-Length:
15 | - '55'
16 | Content-Type:
17 | - application/x-www-form-urlencoded
18 | User-Agent:
19 | - Ruby
20 | response:
21 | status:
22 | code: 200
23 | message: OK
24 | headers:
25 | Content-Type:
26 | - application/xml; charset=utf-8
27 | Transfer-Encoding:
28 | - chunked
29 | Status:
30 | - 200 OK
31 | X-Ua-Compatible:
32 | - IE=Edge,chrome=1
33 | Etag:
34 | - '"2aca2abf73441eff33bb5c8599b6a03b"'
35 | Cache-Control:
36 | - max-age=0, private, must-revalidate
37 | Set-Cookie:
38 | - t_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWUxYzkwMzJhZWJkMDQzY2QwODU1N2M5MmE2MDc0MmIyBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgIQh3b4KOg1uYW5vX251bWkC%2FgE6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgZROgtvZmZzZXRpADoJem9uZUkiCFVUQwY7AFQ%3D--51a0c5441a874401478866fe9ff13e930b741366;
39 | path=/; HttpOnly
40 | X-Request-Id:
41 | - 1d633f68f48590a6bd056290af844462
42 | X-Runtime:
43 | - '0.121398'
44 | Date:
45 | - Thu, 28 May 2015 09:47:45 GMT
46 | X-Rack-Cache:
47 | - invalidate, pass
48 | X-Powered-By:
49 | - Phusion Passenger 4.0.41
50 | Server:
51 | - nginx/1.6.0 + Phusion Passenger 4.0.41
52 | X-Tracker-Client-Pinger-Interval:
53 | - '12'
54 | body:
55 | encoding: UTF-8
56 | string: |
57 |
58 |
59 | b545bcaeafc773ced5b1a853fffd1fc9
60 | 838284
61 |
62 | http_version:
63 | recorded_at: Thu, 28 May 2015 09:47:46 GMT
64 | - request:
65 | method: get
66 | uri: https://www.pivotaltracker.com/services/v3/projects/1325832
67 | body:
68 | encoding: US-ASCII
69 | string: ''
70 | headers:
71 | Accept:
72 | - "*/*; q=0.5, application/xml"
73 | Accept-Encoding:
74 | - gzip, deflate
75 | X-Trackertoken:
76 | - b545bcaeafc773ced5b1a853fffd1fc9
77 | Content-Type:
78 | - application/xml
79 | User-Agent:
80 | - Ruby
81 | response:
82 | status:
83 | code: 200
84 | message: OK
85 | headers:
86 | Content-Type:
87 | - application/xml; charset=utf-8
88 | Transfer-Encoding:
89 | - chunked
90 | Status:
91 | - 200 OK
92 | X-Ua-Compatible:
93 | - IE=Edge,chrome=1
94 | Cache-Control:
95 | - max-age=0, private, must-revalidate
96 | Set-Cookie:
97 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTQ5MmRmZTg4Y2NiMGEwODI3NmY2MzJkZDA5ZDNjMjljBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgD%2BT7L4KOg1uYW5vX251bWlROg1uYW5vX2RlbmkGOg1zdWJtaWNybyIHB2A6C29mZnNldGkAOgl6b25lSSIIVVRDBjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMW1YeER0QUlxVlBaUXlJY2FPSkE5S3dQQUlXVGsrWHdlMysxYS91TUd2RlU9BjsARg%3D%3D--2fb68dc0951b437d5324c6a76adbe8235110e4f9;
98 | path=/; HttpOnly
99 | X-Request-Id:
100 | - bc6a97c2b2b3804adb9a735098057e71
101 | X-Runtime:
102 | - '0.113725'
103 | Date:
104 | - Thu, 28 May 2015 09:47:46 GMT
105 | X-Rack-Cache:
106 | - miss
107 | X-Powered-By:
108 | - Phusion Passenger 4.0.41
109 | Server:
110 | - nginx/1.6.0 + Phusion Passenger 4.0.41
111 | X-Tracker-Client-Pinger-Interval:
112 | - '12'
113 | Content-Encoding:
114 | - gzip
115 | body:
116 | encoding: ASCII-8BIT
117 | string: !binary |-
118 | H4sIAAAAAAAAAwIAAAD//4RUW0/bMBR+51dYec5w0g4oKJhtaHtDQxo8R45z
119 | mng4dmQ77frvd+ykTVuEkCrV+c537pfi4V+nyAask0bfJ/lllhDQwtRSN/fJ
120 | 68uvL6vkgV0UvTV/QXh2QUgha5YvF1er5aKg+A6Q5h2wpx35w7teAXke2QWN
121 | eNTxYLlHH6UC3fiW+F0P94nUHhqwCcvR1Bkl6m0B3krnufVlzXfsyWj8K+gZ
122 | HJi9QWOlE1wBy9I8XaTLgh6DgcSFMIP27IflGyCPMc2C7tHAWEvrfDnHMvr2
123 | soMp5Jp7CJ8JW2T5Fc2WdJmRLLuLP/L68ljQj23EnMRgLWCssxM9dBXY85rc
124 | FvQjarQDmlcKSs/dm5t0K2MUcJ0wbwco6DEjqmxAGSH9DuvUArbmO3aeN0DM
125 | mizJIR5X0HPicdx7GcuzOcIDGJhSSy+5Kk+Y78DAHDMvzbqsjYa5JK70pnSt
126 | 2bIcp+xzVrCleAXKMV53UqeVMk0qcG5SzFS8mcGnNfTK7DosPT6dbHQKvRTp
127 | GrgfLNQEZ7wehHephOtUA9SO1NKJwYXdSI2tcUtSC72xHscmdcCtaFMMsu+x
128 | edMQuRGIBHQx9ISS8MCQBscrqbD6+EKFBnTYCXQsDK6B9gWdMhiTwTHkwstN
129 | aBf3H0zfV5rfkPzmLlvdZdfj9Cl+qhkbz5UyWzTjuWhDBdw0Ie/xwO6HSknB
130 | 1lw5nKLpKwgw8LL1vnd72QwEcTU0ruS6LkVrLODTQgkOt4X7MKp7pc9owZQw
131 | XSd92Zn6oHYMBUoHYWtcK/v9+HNr+S4JCZ+IRwAhvFZXy9tVdrvaX67IxPY5
132 | o/csBKDjUrG+skOtd9+a8HWJ3nGhoiDaj5rxvj1Dbc186ybRNO6OPf9EZ+NC
133 | uEMk9NRnYXFv2e8tTkRB43vMgc45xjYefUdbuGl4QMfL+r4Iwe8sxitOD2f8
134 | PwAAAP//AwBMbtil+AUAAA==
135 | http_version:
136 | recorded_at: Thu, 28 May 2015 09:47:47 GMT
137 | - request:
138 | method: get
139 | uri: https://www.pivotaltracker.com/services/v3/projects/1325832/stories
140 | body:
141 | encoding: US-ASCII
142 | string: ''
143 | headers:
144 | Accept:
145 | - "*/*; q=0.5, application/xml"
146 | Accept-Encoding:
147 | - gzip, deflate
148 | X-Trackertoken:
149 | - b545bcaeafc773ced5b1a853fffd1fc9
150 | Content-Type:
151 | - application/xml
152 | User-Agent:
153 | - Ruby
154 | response:
155 | status:
156 | code: 200
157 | message: OK
158 | headers:
159 | Content-Type:
160 | - application/xml; charset=utf-8
161 | Transfer-Encoding:
162 | - chunked
163 | Status:
164 | - 200 OK
165 | X-Ua-Compatible:
166 | - IE=Edge,chrome=1
167 | Cache-Control:
168 | - max-age=0, private, must-revalidate
169 | Set-Cookie:
170 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTBiZDcyODIzMTI2MTM3NGE2YTYyOTg3MmQ4OWY0ODg5BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgDcD%2FL4KOg1uYW5vX251bWkCngE6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgdBQDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxYktEamZoM3Q0MGx2ZG5vdUk0QlkzdTZOb2RPS0h1K1o5TTA4Q0NvNlp2QT0GOwBG--70b829be8745e791b48a969593b6954d437554e1;
171 | path=/; HttpOnly
172 | X-Request-Id:
173 | - 8f37853feee0bd0d358e9c1bb62c0c97
174 | X-Runtime:
175 | - '0.196941'
176 | Date:
177 | - Thu, 28 May 2015 09:47:47 GMT
178 | X-Rack-Cache:
179 | - miss
180 | X-Powered-By:
181 | - Phusion Passenger 4.0.41
182 | Server:
183 | - nginx/1.6.0 + Phusion Passenger 4.0.41
184 | X-Tracker-Client-Pinger-Interval:
185 | - '12'
186 | Content-Encoding:
187 | - gzip
188 | body:
189 | encoding: ASCII-8BIT
190 | string: !binary |-
191 | H4sIAAAAAAAAAwIAAAD//+xbXW/bNhR9768g/LIXL7LzZTtwXHQdBnTDsAJp
192 | 170FtETHXCRRI6m47q/f4YcsO6lqO6ZTpwgQILJESlfU4eU5914OX3/OUnLH
193 | pOIiv2x1jzotwvJYJDy/uWx9/PDbz/3W69GrodJCcqaInhfsskWlpPMWiUWZ
194 | 68vW2aBFtNA0tYejV4TY5nNzhGOe+F481+yGydZocNzr9gdnp8OIJ75RIcW/
195 | LNbXDxt3T47P+ifHw6hu4vvYh1wbi0bxVEg2jJbOuGeXMh1NtS7URRTNZrOj
196 | gt8ZQ7Wk8S2TR7HIXJ9ITcUsqu0y/dwd4lJKlutrpalmIxrHrNAsGUar513b
197 | hKlY8kJjKEefGMkZS8gxyWg85TnGTjFNymIYLTdzHXOasdEV02VBEnbHUlFk
198 | eCY+xB2XIjfHw8i2cc0l+69kCmZcj+ej9yyRYhitnPOmSwabk2uq/QdI8FPz
199 | jLVGx53uWdQ5iU46pNO5sH/k44e3eK1FH/+ssjC9vnGT06jbI93eRefsotNz
200 | N6n7+JtUw/ZNU7r3TFnq5G+TC30Pgu4CQGYuVT++jrn+8Rle+rzGnAWnZp/1
201 | 6NOU6p8UEaUk4zK5wWeaCEn0lC2+3ethZFvagbUdaamBuWr0/a/6srFnu0Gr
202 | eixeKarfCV/fvLq55EFuDzeaZUtvPDykWQa7dp9lV1NRpgkZM2LQohQfp4xM
203 | pMjwMbXiCbNfMWd6JuRtm8y4npIxVTwm5outnYqZwKSV8I4v0w9wS+mYpWqU
204 | sCIVc+eU/KnH4LIfzvtP4OfKcP4fltXIhJ/lGTzg/TUMC1J1yXunx64Ub5KM
205 | 5wQLUIVkogoWc5qSEuCzzz0iWE5imhPnni2oJ1wqTajtbBsmXGIFTecEJ0yD
206 | X39pw51pkjLj3LCoy3mBlQBXCqoUJkRy1DgBHthk5pUWJBU3PH+ZDPVksOM/
207 | jB4/D847hzoPjGXr50E32Dx4L0VSxhrwxeqLKQcWheM4LcGXiOY6ZW2wowXD
208 | apNC8hjnrv74uD2Q/UTK2Qy3sc99QXVIVMM9huL2Yb37OSxbj+pw3n1rF1ti
209 | daVJhUpSTIUGvX9h/xX92N3jBtSdgbEJy9Zj8ySYx30sNrMy1bwAI/Cu04FU
210 | EZonUEzylogchBxO23ANCfok5z86gk8jiN9VKf1Qv3qWsDuCA2q6wAheUXX7
211 | 586NCIYwLAqQYk+rFWMk5eDLYlKBVnk56AHqMOxQW2bjnPL0BbM1I8A4FgVi
212 | gjtR3YOVfOcbSb5wVLcRthUHHksxUxjuJVlYUEgvE4rzuO12FkgmBum4jgjo
213 | j80TtvGyIRDbO1hxZixbTxWegMb+SW9rHrCArQerkXBvfn/zz8vyb0LGfvmv
214 | gNkuFR3zlGuMTh0/QLsAYe4lT2uj1TZ4XTkXuxAad2EiOu6/pLniVnH7BRM2
215 | EIlEBJSI/agLB/NMw+C9gxWkxrL1M/k7kn6eFUJqsiD9SzET5WLtb6/+Rjgy
216 | fVl+lmb5ziS/d7Ay1Vi2HrFPwJbukXyTBfJx6jjlsZGhhFYkqW3VqdEBNE0X
217 | wjVhGkQfUsAFGg3jsgEXtRcmBfpyfiD5Vpu13VCvBmFSBytZextJ1u+KZprU
218 | 8UAs2dX3QEZI7idsfWhAXS0vaAysmPFoB0HrwSrV3kZKNRzvf4shJTy2qRjQ
219 | xYJIfjPVqPyROZNeiVKSI2IChsjzhMdI3MCLopwGocAcyUjNMmU6O7A21b6s
220 | hmuWPPkdR4oGz9cogkGJxuTZob93cXry6LKYRXEN7nLq7rJ/9PcPVvUay3Zn
221 | HglLOWo6NqniagzUNFMPyTJxV0tiW4zyA3lsr1SDudr+wQozY9nuYJvwnKvp
222 | TlizPhjOlBdl6tLiXqTDTe4vuvJkHCA4ogIKp3GJiHeQqtL+imharRVCbanc
223 | qKi02R2J7EE2zoRwVExTFKEiT4cQMUqDZlOWu4COlTqu8uGZi517YbVdMhT9
224 | g1UpxrLdnVGZbww1BAszlIuZQliWQSOj0iyRqLC0MhpgUiKnKf8CcGU4i2Bi
225 | G+Ial1xjW2hZZYe9yHbpYde4GciNRBDFbSJD1WFSa3oTv6QIQXGcfR6Cvd/A
226 | BENiOKB2CVlW319RLqsOcAtcNiIHGmHCb1AGSpRIpQXupESoxwSsAU0qTRU+
227 | vPkeMmTBl8p1MLFvs4ujGxwsxTeWrXd068LhWwDqL9SqOHgghs1SpFf9L0+y
228 | UiFuUckiRXlTuzQDonvViMYvohSxEZ/NiqF6OhC7z1rE74PSIPGYQUCRgKwW
229 | oyrUZiFjWQ3X8F7tXY60HErBE6hKs9zx/A5VNUI+E872VUe27RaWQUBCH7bc
230 | yVj2pM7qEd4FcTOE5lDvnHDE7ahMVgqsbVJkym1tT0XxnsEa2b9AJsVuWHuw
231 | 16ySk1MW32ITUBj/E1AXhORUg29sotpiCWxE1TuzY1Oa3S+O0FO77Yfc4MyM
232 | 7qeo46lXqTgoTgJy78CeaqO8QUBa1YipTyYEYQOipjyzHGfcxPVlYtIJbhsl
233 | VKXbT7xQkDQzO41dsUHxI4PQbBlW2Mml4hKbGUX+Ve8VpERoed9RXSIEkmp2
234 | oc1AiUEykCu3u1z5Fxd2xLZw7wns99rnplhPHPayKXbQ6Ryo/HGWrWcU67LR
235 | m/v+/wEAAP//7F3BTttQEPwVfwCUEEIlLpXaqpV6bi89GuKEqCmJYkDK33dm
236 | 9z3HCTUO8tpsLF9LEc/yeHdnd3bep8rv9AdGbVssmf9NZpRISK8loIEbhJoJ
237 | 9MMEE1rk62W6TbLNBiwmdIT4K+FDP4GSAuvr/61Wd8I9w1SBF+20qNWTuYHg
238 | fgBawEThSRa90doBUeeUWUJRnECznJVGUFwgHKBYZ8SBF25Y3VpWLXoyH1D8
239 | ycYzstFiJgoH6CG00Q1BggIQ4e8uk+qYgVK3gnvQapQnObONfE6LZMDtqCK5
240 | TlxjkXyrm4XyKlCdwfFA5DCKvlukXvJ8sniiTmYt5cjYiwQsD4TO104t/7ZW
241 | 0s3o0m3hx5N1GuqEhwmaZM9oH1CSW8sLdPcpNC3c51yJvZEEufwPpm/iRIR/
242 | +ZD8umd6VgJRGgXGcFi9o18Ndv6J+Aeg7UU7R0E9oBkOWkCzYVvcNnHzZJ2i
243 | uZLGqJMJvVM2mWgJKf/WyBiRpTNtgSwm3OvVQ07DiYK7nHKr/cDS4cwgghry
244 | FrtWKL6FV/Q1JhlZzNuSbw/YwsyS3+yjh2GdFIMtO7V13RW18HjCOzEkFpZj
245 | Oz1Zm2O7L9grSZbp0wPH9KdMA6ZZOl0S8Wr8eOggCBPBycEaSfyNt5vV4bW4
246 | pQY8WX1Ce19qkC/msAJbi/QF+Q5Ccemay+hmT8N12pCMWik8LR72IuFjN/Hg
247 | uhmN3bICnqwedl20g6uLdNRM6pg5Xz1iS6NwlxtQVva7BcrcVus8mXeUwXmQ
248 | np4DqA5AZVhi2VLAcdeK5UoKuN/poCbkiO6GJFPZeWPbY4GMqul0AOABAN2W
249 | bOOjSjbD3IkUGcZRsvC4TGGz8XGUTNNt9JpCJQ0tqXQW8D+XHFxFRl61GAkY
250 | QmOvBrHlhlxpRTI0NrSpgSYcbdH7AdPQgwyfXqPO75XbGo8nq8++htTia0kL
251 | qJu7Rd8WqBLhB/Y41C+Yi2sNoJmzbVzWHnIuETdJykavcDAWlMdJ04DfvdsS
252 | bka8AcGjo6qerB6/hnG2OSLjZhJC8Sx9hsAJ5voD4g4RZ9jptS0tr46SXXtB
253 | XJw7yHjh5W74AMCXd77wIhYEFkNuYzlq4LnabB5j9fKZV1fMIAa9xUU1rBiR
254 | g1kJgobIFJRLSRf4OUZZkOkhfPUieulDNpnvX7llIzxZfZbsQoD9eb3GJnj+
255 | uAUbmcsgHxPROO6fpXeyGY6FdJGXcORPfOEqCSxNQVOCvnKOfl9wfouwHOAn
256 | EWvilmTwZPXwMyQZjYq09YoOleE+CM2f/ajP5KKWeYZATiff6GvUJOJN3PIC
257 | nqwecm6qNG45Bcgh2G3BRFcrsWC+PL+mPOqkVy53OpAWEOiWJ0zc8IS9pSfI
258 | 5HZGycGCJYjZ0S7Z0Ji3iH3qpsauSfBYQ04OARHXmsHZAPk7wwWDvdocbwGj
259 | hlTClstO3IxJXpvwwgY6ok7UBQPcZGeuirlO3NIQnqw+KZ93kZWr7piTG2QK
260 | hPFGjvDF9cPjRzcq4iPFD6nRbOPaLe3gyZzA7bteElnINouZR4qxWopBnN6a
261 | SLKL0R2cTIUGt3SnRtd6Tlu4uaUc10dRjneNbuHiQVZ04shxS2ELui2Lu2VP
262 | ZhAa4PhcTXit5e3gthUbT+YkplWlUBm77iGLs9XpJp3BSBRL/L1o1xnhzC0z
263 | 4F3lrePsHwAAAP//7J3dagIxEIXvfYp9g/amgiAFLyr0btEn8CewgV1Saq19
264 | fM9MsibrTxt1aJOld6I3Kx4nyWTO+cbh5f7Fnl25XQIagxTbI1E5t9fpCtoL
265 | gd1dwpI9BTylcwoolSGSpFNSMNWEaBhi/eIdtDi4ln3qRTGbz9nbOvkwzb/I
266 | cOWQKj/aPlki9evSOsmGwAZwgYpuxBCVvEGbg2hHvZCWXSDtF+Lo09t900RN
267 | TnP6KI7n/KdbfvXFAC076Un9jJaXFVyqkrGqAIUNvV9v3bem7Dy0OPo+jk9S
268 | i4L3DZJjIcPOuUA+CnSm2LBcVCCw+MQbD7Rleh+4VwrTxtSkpex3/tvn4D/8
269 | QT4yftSh4F5f1o9KT+bXSnntTCkJO/Ar52RNPSuNa4M/iPArtYBJQSGwRers
270 | w09+dgxDr7fgN4wfuh8N+PIh7uTmhijOkVkJELEz75z/gfbA6wtE2INaoRW+
271 | x+1bnVSZv6PHOOZvzFZHQFhH0bDIaTMNz7RYGwpF7wMJWnMils0RzFhc11ab
272 | VGmz0JBYh1xAQ8CZA8RV6LIySBhAF8lNI8Ic1Q5AHOoWJ/u5rN6MleQHcdSb
273 | Xt1VpwS3wbIN8jg+7C/VqSli+ZaEcIC8EDBc12ZH6x2NmLiQnwVybtsh/OA6
274 | NtuV8FCs7AutNs+DPQAAAP//AwCPuqWQ55UAAA==
275 | http_version:
276 | recorded_at: Thu, 28 May 2015 09:47:48 GMT
277 | recorded_with: VCR 2.9.3
278 |
--------------------------------------------------------------------------------
/spec/cassettes/issues_creator.yml:
--------------------------------------------------------------------------------
1 | ---
2 | http_interactions:
3 | - request:
4 | method: post
5 | uri: https://www.pivotaltracker.com/services/v3/tokens/active
6 | body:
7 | encoding: US-ASCII
8 | string: username=foobar%40gmail.com&password=secret&timeout=60
9 | headers:
10 | Accept:
11 | - "*/*; q=0.5, application/xml"
12 | Accept-Encoding:
13 | - gzip, deflate
14 | Content-Length:
15 | - '55'
16 | Content-Type:
17 | - application/x-www-form-urlencoded
18 | User-Agent:
19 | - Ruby
20 | response:
21 | status:
22 | code: 200
23 | message: OK
24 | headers:
25 | Content-Type:
26 | - application/xml; charset=utf-8
27 | Transfer-Encoding:
28 | - chunked
29 | Status:
30 | - 200 OK
31 | X-Ua-Compatible:
32 | - IE=Edge,chrome=1
33 | Etag:
34 | - '"2aca2abf73441eff33bb5c8599b6a03b"'
35 | Cache-Control:
36 | - max-age=0, private, must-revalidate
37 | Set-Cookie:
38 | - t_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWFkMjRjYzRiN2M2OWI2Njg5ZDhjMGE3NmZmNDJjM2UzBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgLb%2FQL4KOg1uYW5vX251bWkCswM6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgeUcDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBU--b48c3dc1ad62501e4218916805ff139ad72aa8b2;
39 | path=/; HttpOnly
40 | X-Request-Id:
41 | - f58e40a0acaf98ff68e2cbcc272fdb9d
42 | X-Runtime:
43 | - '0.116360'
44 | Date:
45 | - Thu, 28 May 2015 09:47:36 GMT
46 | X-Rack-Cache:
47 | - invalidate, pass
48 | X-Powered-By:
49 | - Phusion Passenger 4.0.41
50 | Server:
51 | - nginx/1.6.0 + Phusion Passenger 4.0.41
52 | X-Tracker-Client-Pinger-Interval:
53 | - '12'
54 | body:
55 | encoding: UTF-8
56 | string: |
57 |
58 |
59 | b545bcaeafc773ced5b1a853fffd1fc9
60 | 838284
61 |
62 | http_version:
63 | recorded_at: Thu, 28 May 2015 09:47:37 GMT
64 | - request:
65 | method: get
66 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280
67 | body:
68 | encoding: US-ASCII
69 | string: ''
70 | headers:
71 | Accept:
72 | - "*/*; q=0.5, application/xml"
73 | Accept-Encoding:
74 | - gzip, deflate
75 | X-Trackertoken:
76 | - b545bcaeafc773ced5b1a853fffd1fc9
77 | Content-Type:
78 | - application/xml
79 | User-Agent:
80 | - Ruby
81 | response:
82 | status:
83 | code: 200
84 | message: OK
85 | headers:
86 | Content-Type:
87 | - application/xml; charset=utf-8
88 | Transfer-Encoding:
89 | - chunked
90 | Status:
91 | - 200 OK
92 | X-Ua-Compatible:
93 | - IE=Edge,chrome=1
94 | Cache-Control:
95 | - max-age=0, private, must-revalidate
96 | Set-Cookie:
97 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTE3ZmU5ZGVhOGIxMjI3MTY0MzdmNzAwOGE1MzU0MTFlBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgJ9AUL4KOg1uYW5vX251bWkCwwI6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgdwcDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxVUcwV0lXRHZRa1NCaVdBMzl5TUVWTDVyUVpTUjJ5L3paYUljSjhzaVoxTT0GOwBG--553f206d4c82266dc939a8f77b8facd988966979;
98 | path=/; HttpOnly
99 | X-Request-Id:
100 | - 1ef6a9033afd16fbbc77c724ee628fc8
101 | X-Runtime:
102 | - '0.045315'
103 | Date:
104 | - Thu, 28 May 2015 09:47:37 GMT
105 | X-Rack-Cache:
106 | - miss
107 | X-Powered-By:
108 | - Phusion Passenger 4.0.41
109 | Server:
110 | - nginx/1.6.0 + Phusion Passenger 4.0.41
111 | X-Tracker-Client-Pinger-Interval:
112 | - '12'
113 | Content-Encoding:
114 | - gzip
115 | body:
116 | encoding: ASCII-8BIT
117 | string: !binary |-
118 | H4sIAAAAAAAAAwIAAAD//4RUS2/bMAy+91cYPmeV4zRoVrjqtmK7DethPQu0
119 | zdhaZMmQ5GTprx+l2Hm06wYEiPjx45tm8fC7U8kWrZNG36fz6yxNUFemlrq5
120 | T59/fvuwSh/4VdFb8wsrz6+SpJA1ny/y23yVFYzeAdLQIX+RpgNVsChEokcL
121 | nhwLhbrxbeL3Pd6nUnts0KZ8TvavKNFuh7gRzoP1ooY9/240/RXsFRyYvSFn
122 | wlWgkGez+SyfLQp2DgYSVJUZtOdfLGwxeYy1FWxCA2MtrfPilMshtpcdjinX
123 | 4DGIKc+z+ZJlS5bfJHl+l2X0S55/PhbsfR+xpmqwFinXUxA9dCXav/TkPWr0
124 | gxpKhcKD27jRtjRGIeiUeztgwc4Z0WSLylTS76lPLdJoPtO4ocHErJNFcszH
125 | Few18TzvScfnNPUpwyMYmFJLL0GJC+YbMDAPlQuzFrXReGqJE94I15odn+e0
126 | RrE//2IFXwpKVI5riaVEt4GZA72ZOZKb2YvsoGAj40CmMUPl5Ta0A/z7071N
127 | so93y8XdYpyugkvL2FhQyuzIjYeq7Wi4bpzAWzyw+6FUsuJrUI6mNEpBMTgU
128 | rfe9m3QnIKjLoXECdC2q1likp0WBjrYRfFiFyeh/tOCqMl0nvehMfTQ7hwKl
129 | w9B118p+Wi+wFvZpKPhCfQAIohOwvMny1c1qOgeR2ZMXoycWAdiBVLwv7VDr
130 | /acmSNcUnRY2KqL/aBnvxxPW1pxuyaga18nxp68U7LBw7pgJu4xZWPou+I+d
131 | Rluw+D7UwE41xjGeydEXbTIdqMPletuEEPekptPIjrfxDwAAAP//AwDXq2nA
132 | TQUAAA==
133 | http_version:
134 | recorded_at: Thu, 28 May 2015 09:47:37 GMT
135 | - request:
136 | method: get
137 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/stories/94184406
138 | body:
139 | encoding: US-ASCII
140 | string: ''
141 | headers:
142 | Accept:
143 | - "*/*; q=0.5, application/xml"
144 | Accept-Encoding:
145 | - gzip, deflate
146 | X-Trackertoken:
147 | - b545bcaeafc773ced5b1a853fffd1fc9
148 | Content-Type:
149 | - application/xml
150 | User-Agent:
151 | - Ruby
152 | response:
153 | status:
154 | code: 200
155 | message: OK
156 | headers:
157 | Content-Type:
158 | - application/xml; charset=utf-8
159 | Transfer-Encoding:
160 | - chunked
161 | Status:
162 | - 200 OK
163 | X-Ua-Compatible:
164 | - IE=Edge,chrome=1
165 | Cache-Control:
166 | - max-age=0, private, must-revalidate
167 | Set-Cookie:
168 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWJjMGIyOTYxZmQ4YTVkYzdjMWI0ZmY5OWY2M2UzZmE0BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgKEXXr4KOg1uYW5vX251bWkCyAE6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgdFYDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxRi9Pa2tCK0lvcGd4dklXVFRrNDZKRGRJR3VLZVhxMUNzZDBGeUJOVGtybz0GOwBG--a0f12da7802c2cb3335d2da51db121409aaf6e26;
169 | path=/; HttpOnly
170 | X-Request-Id:
171 | - bd5fe652c1b94d8c9d291f817b3dd20e
172 | X-Runtime:
173 | - '0.081793'
174 | Date:
175 | - Thu, 28 May 2015 09:47:37 GMT
176 | X-Rack-Cache:
177 | - miss
178 | X-Powered-By:
179 | - Phusion Passenger 4.0.41
180 | Server:
181 | - nginx/1.6.0 + Phusion Passenger 4.0.41
182 | X-Tracker-Client-Pinger-Interval:
183 | - '12'
184 | Content-Encoding:
185 | - gzip
186 | body:
187 | encoding: ASCII-8BIT
188 | string: !binary |-
189 | H4sIAAAAAAAAAwIAAAD//3ySy27CMBBF93yFlTXFScojRMYsKnXdBayRiQcw
190 | JHZqO6TJ19c2lEcrVcrCM3Pu1fg6ZPlVlegM2gglF1EyiiMEslBcyP0iWq/e
191 | X7JoSQfEWKU7OkCICI5sV8MiEtLCHnRE5+MkG4/jKcGCB6TW6giF3fxFk9d0
192 | lmYxwXckKIL9xvvSHTDbaCD4oeeRRpf0YG1tcozbth3V4qwsK61mxQn0qFDV
193 | RYHNQbX4vpPXeT0YKypm4ff2CcE/o8AVjdYg7cZYB9OdkMIcgBP83PckB1No
194 | UVuXHD2ynjPUo73SJ4FaxFWJaoWMFLBvXF0zt+cBFX1X+rHVfYeUUdtuQPCj
195 | j/eVrIKroWTIMHnyUi9SR38kOBAe1fDZuO2Bb7Yd/QCuFcFPPQ+pVj4Btzpc
196 | V7u83ZjZazDclS4piGgaJxMcuy9DySRPs3wyRevVm4vipglLNLXX/GuROItZ
197 | nsT5ZH6xuGuCRcm2UBrq7zoMmQ1791gEX/supOsP+A0AAP//AwBvV9t2sAIA
198 | AA==
199 | http_version:
200 | recorded_at: Thu, 28 May 2015 09:47:38 GMT
201 | - request:
202 | method: get
203 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280
204 | body:
205 | encoding: US-ASCII
206 | string: ''
207 | headers:
208 | Accept:
209 | - "*/*; q=0.5, application/xml"
210 | Accept-Encoding:
211 | - gzip, deflate
212 | X-Trackertoken:
213 | - b545bcaeafc773ced5b1a853fffd1fc9
214 | Content-Type:
215 | - application/xml
216 | User-Agent:
217 | - Ruby
218 | response:
219 | status:
220 | code: 200
221 | message: OK
222 | headers:
223 | Content-Type:
224 | - application/xml; charset=utf-8
225 | Transfer-Encoding:
226 | - chunked
227 | Status:
228 | - 200 OK
229 | X-Ua-Compatible:
230 | - IE=Edge,chrome=1
231 | Cache-Control:
232 | - max-age=0, private, must-revalidate
233 | Set-Cookie:
234 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTFhZTRlYTJlYjE0Mzc1MTNmYzlkNjUzZDJhYjYxMjU5BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgFptcb4KOg1uYW5vX251bWkCDQM6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgd4EDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxVVZsOHhYTXhXeXdSUkdsaElEaW94STRISFR0ZUhmM2xPNVpvTkUwMExWWT0GOwBG--a673b61634a02cc3a56610966803372682277242;
235 | path=/; HttpOnly
236 | X-Request-Id:
237 | - b1942a716eaca43dd8a979f709fcca2b
238 | X-Runtime:
239 | - '0.045435'
240 | Date:
241 | - Thu, 28 May 2015 09:47:39 GMT
242 | X-Rack-Cache:
243 | - miss
244 | X-Powered-By:
245 | - Phusion Passenger 4.0.41
246 | Server:
247 | - nginx/1.6.0 + Phusion Passenger 4.0.41
248 | X-Tracker-Client-Pinger-Interval:
249 | - '12'
250 | Content-Encoding:
251 | - gzip
252 | body:
253 | encoding: ASCII-8BIT
254 | string: !binary |-
255 | H4sIAAAAAAAAAwIAAAD//4RUS2/bMAy+91cYPmeV4zRoVrjqtmK7DethPQu0
256 | zdhaZMmQ5GTprx+l2Hm06wYEiPjx45tm8fC7U8kWrZNG36fz6yxNUFemlrq5
257 | T59/fvuwSh/4VdFb8wsrz6+SpJA1ny/y23yVFYzeAdLQIX+RpgNVsChEokcL
258 | nhwLhbrxbeL3Pd6nUnts0KZ8TvavKNFuh7gRzoP1ooY9/240/RXsFRyYvSFn
259 | wlWgkGez+SyfLQp2DgYSVJUZtOdfLGwxeYy1FWxCA2MtrfPilMshtpcdjinX
260 | 4DGIKc+z+ZJlS5bfJHl+l2X0S55/PhbsfR+xpmqwFinXUxA9dCXav/TkPWr0
261 | gxpKhcKD27jRtjRGIeiUeztgwc4Z0WSLylTS76lPLdJoPtO4ocHErJNFcszH
262 | Few18TzvScfnNPUpwyMYmFJLL0GJC+YbMDAPlQuzFrXReGqJE94I15odn+e0
263 | RrE//2IFXwpKVI5riaVEt4GZA72ZOZKb2YvsoGAj40CmMUPl5Ta0A/z7071N
264 | so93y8XdYpyugkvL2FhQyuzIjYeq7Wi4bpzAWzyw+6FUsuJrUI6mNEpBMTgU
265 | rfe9m3QnIKjLoXECdC2q1likp0WBjrYRfFiFyeh/tOCqMl0nvehMfTQ7hwKl
266 | w9B118p+Wi+wFvZpKPhCfQAIohOwvMny1c1qOgeR2ZMXoycWAdiBVLwv7VDr
267 | /acmSNcUnRY2KqL/aBnvxxPW1pxuyaga18nxp68U7LBw7pgJu4xZWPou+I+d
268 | Rluw+D7UwE41xjGeydEXbTIdqMPletuEEPekptPIjrfxDwAAAP//AwDXq2nA
269 | TQUAAA==
270 | http_version:
271 | recorded_at: Thu, 28 May 2015 09:47:40 GMT
272 | - request:
273 | method: get
274 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/memberships
275 | body:
276 | encoding: US-ASCII
277 | string: ''
278 | headers:
279 | Accept:
280 | - "*/*; q=0.5, application/xml"
281 | Accept-Encoding:
282 | - gzip, deflate
283 | X-Trackertoken:
284 | - b545bcaeafc773ced5b1a853fffd1fc9
285 | Content-Type:
286 | - application/xml
287 | User-Agent:
288 | - Ruby
289 | response:
290 | status:
291 | code: 200
292 | message: OK
293 | headers:
294 | Content-Type:
295 | - application/xml; charset=utf-8
296 | Transfer-Encoding:
297 | - chunked
298 | Status:
299 | - 200 OK
300 | X-Ua-Compatible:
301 | - IE=Edge,chrome=1
302 | Cache-Control:
303 | - max-age=0, private, must-revalidate
304 | Set-Cookie:
305 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWJiMDkzMzk3NTIwMmZmYmFiZWRmMGY2NmJiYTM1ODliBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgJwLgL4KOg1uYW5vX251bWkCPgI6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgdXQDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxZEhoV2UzaURvdFIzTFdLV2NsSjRLUTc3WURKL3h1ZWpuMGtJdVJvN2ZZUT0GOwBG--0381d32eed6f2bc7bfc5e58aab576336bd567ec4;
306 | path=/; HttpOnly
307 | X-Request-Id:
308 | - 60f9285f776afaf2efe37f46c8d84ca0
309 | X-Runtime:
310 | - '0.061025'
311 | Date:
312 | - Thu, 28 May 2015 09:47:40 GMT
313 | X-Rack-Cache:
314 | - miss
315 | X-Powered-By:
316 | - Phusion Passenger 4.0.41
317 | Server:
318 | - nginx/1.6.0 + Phusion Passenger 4.0.41
319 | X-Tracker-Client-Pinger-Interval:
320 | - '12'
321 | Content-Encoding:
322 | - gzip
323 | body:
324 | encoding: ASCII-8BIT
325 | string: !binary |-
326 | H4sIAAAAAAAAAwIAAAD//0xQu27DMAzc/RWC9kaOk6IeaKZLuyZD+wGKRSQs
327 | 9ILsJnW/vopdw954vDvegXD4cVbcKHUcfCO3m1IK8m0w7C+N/Px4f6rlAQtw
328 | 5M5ZdOXYiX6I1Eidkh4kFkKsyAfMCzb4vC+rel+DyvO0jNkf/ASyhpxmi/Gc
329 | vo0fXi8PtGmDAzURoyfLvHaEJzIpgBrnmWDPPWvb4ekth8xgilLrLEjBEh7v
330 | nhKocf7vk8IXtf1y0OB2V71UdbmUngv8cnDarhuAiosf1PKf/KwV6rD4AwAA
331 | //8DAHDPkbBjAQAA
332 | http_version:
333 | recorded_at: Thu, 28 May 2015 09:47:40 GMT
334 | - request:
335 | method: get
336 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/stories/94184406/notes
337 | body:
338 | encoding: US-ASCII
339 | string: ''
340 | headers:
341 | Accept:
342 | - "*/*; q=0.5, application/xml"
343 | Accept-Encoding:
344 | - gzip, deflate
345 | X-Trackertoken:
346 | - b545bcaeafc773ced5b1a853fffd1fc9
347 | Content-Type:
348 | - application/xml
349 | User-Agent:
350 | - Ruby
351 | response:
352 | status:
353 | code: 200
354 | message: OK
355 | headers:
356 | Content-Type:
357 | - application/xml; charset=utf-8
358 | Transfer-Encoding:
359 | - chunked
360 | Status:
361 | - 200 OK
362 | X-Ua-Compatible:
363 | - IE=Edge,chrome=1
364 | Cache-Control:
365 | - max-age=0, private, must-revalidate
366 | Set-Cookie:
367 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTk0OTk4Y2M4MDc5MGRjMTUyZmNlODE0NzkxMDZkMmM1BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgBMoj74KOg1uYW5vX251bWkCHAM6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgd5YDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxZm4rbUZNRFRCWUVjWE9xZ0poT1NYbGNBa0N4OWVFRlBkOFVkM3B5dXppZz0GOwBG--19b09618dbbb41c7f1807447ec76d33645f9f190;
368 | path=/; HttpOnly
369 | X-Request-Id:
370 | - ebdf3b2349e5239d68682c8f4b1dc96f
371 | X-Runtime:
372 | - '0.043605'
373 | Date:
374 | - Thu, 28 May 2015 09:47:41 GMT
375 | X-Rack-Cache:
376 | - miss
377 | X-Powered-By:
378 | - Phusion Passenger 4.0.41
379 | Server:
380 | - nginx/1.6.0 + Phusion Passenger 4.0.41
381 | X-Tracker-Client-Pinger-Interval:
382 | - '12'
383 | Content-Encoding:
384 | - gzip
385 | body:
386 | encoding: ASCII-8BIT
387 | string: !binary |-
388 | H4sIAAAAAAAAA7Kxr8jNUShLLSrOzM+zVTLUM1BSSM1Lzk/JzEu3VQoNcdO1
389 | ULK347LJyy9JLVYoqSxItVVKLCpKrFTSt+MCAAAA//8DAPeRVfM9AAAA
390 | http_version:
391 | recorded_at: Thu, 28 May 2015 09:47:41 GMT
392 | - request:
393 | method: get
394 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280
395 | body:
396 | encoding: US-ASCII
397 | string: ''
398 | headers:
399 | Accept:
400 | - "*/*; q=0.5, application/xml"
401 | Accept-Encoding:
402 | - gzip, deflate
403 | X-Trackertoken:
404 | - b545bcaeafc773ced5b1a853fffd1fc9
405 | Content-Type:
406 | - application/xml
407 | User-Agent:
408 | - Ruby
409 | response:
410 | status:
411 | code: 200
412 | message: OK
413 | headers:
414 | Content-Type:
415 | - application/xml; charset=utf-8
416 | Transfer-Encoding:
417 | - chunked
418 | Status:
419 | - 200 OK
420 | X-Ua-Compatible:
421 | - IE=Edge,chrome=1
422 | Cache-Control:
423 | - max-age=0, private, must-revalidate
424 | Set-Cookie:
425 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJWE5N2Q4YmRkMDQxOTJjNTBkMzY5NjA3NDlhMjA5ODVkBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgK6jnb4KOg1uYW5vX251bWkC2gI6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgZzOgtvZmZzZXRpADoJem9uZUkiCFVUQwY7AFRJIhBfY3NyZl90b2tlbgY7AEZJIjFwdFB4SXJiRTdlanJGYnJQdXMrVGdOYUlHcFBCam1XZGdLaHBpRVRIUUI0PQY7AEY%3D--4bf494df7675f8de9bcd69624bbb4c9a7f796d85;
426 | path=/; HttpOnly
427 | X-Request-Id:
428 | - c10274b779d0ec2a4e0866312495bc34
429 | X-Runtime:
430 | - '0.040416'
431 | Date:
432 | - Thu, 28 May 2015 09:47:41 GMT
433 | X-Rack-Cache:
434 | - miss
435 | X-Powered-By:
436 | - Phusion Passenger 4.0.41
437 | Server:
438 | - nginx/1.6.0 + Phusion Passenger 4.0.41
439 | X-Tracker-Client-Pinger-Interval:
440 | - '12'
441 | Content-Encoding:
442 | - gzip
443 | body:
444 | encoding: ASCII-8BIT
445 | string: !binary |-
446 | H4sIAAAAAAAAA4RUS2/bMAy+91cYPmeV4zRoVrjqtmK7DethPQu0zdhaZMmQ
447 | 5GTprx+l2Hm06wYEiPjx45tm8fC7U8kWrZNG36fz6yxNUFemlrq5T59/fvuw
448 | Sh/4VdFb8wsrz6+SpJA1ny/y23yVFYzeAdLQIX+RpgNVsChEokcLnhwLhbrx
449 | beL3Pd6nUnts0KZ8TvavKNFuh7gRzoP1ooY9/240/RXsFRyYvSFnwlWgkGez
450 | +SyfLQp2DgYSVJUZtOdfLGwxeYy1FWxCA2MtrfPilMshtpcdjinX4DGIKc+z
451 | +ZJlS5bfJHl+l2X0S55/PhbsfR+xpmqwFinXUxA9dCXav/TkPWr0gxpKhcKD
452 | 27jRtjRGIeiUeztgwc4Z0WSLylTS76lPLdJoPtO4ocHErJNFcszHFew18Tzv
453 | ScfnNPUpwyMYmFJLL0GJC+YbMDAPlQuzFrXReGqJE94I15odn+e0RrE//2IF
454 | XwpKVI5riaVEt4GZA72ZOZKb2YvsoGAj40CmMUPl5Ta0A/z7071Nso93y8Xd
455 | YpyugkvL2FhQyuzIjYeq7Wi4bpzAWzyw+6FUsuJrUI6mNEpBMTgUrfe9m3Qn
456 | IKjLoXECdC2q1likp0WBjrYRfFiFyeh/tOCqMl0nvehMfTQ7hwKlw9B118p+
457 | Wi+wFvZpKPhCfQAIohOwvMny1c1qOgeR2ZMXoycWAdiBVLwv7VDr/acmSNcU
458 | nRY2KqL/aBnvxxPW1pxuyaga18nxp68U7LBw7pgJu4xZWPou+I+dRluw+D7U
459 | wE41xjGeydEXbTIdqMPletuEEPekptPIjrfxDwAAAP//AwDXq2nATQUAAA==
460 | http_version:
461 | recorded_at: Thu, 28 May 2015 09:47:42 GMT
462 | - request:
463 | method: get
464 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/memberships
465 | body:
466 | encoding: US-ASCII
467 | string: ''
468 | headers:
469 | Accept:
470 | - "*/*; q=0.5, application/xml"
471 | Accept-Encoding:
472 | - gzip, deflate
473 | X-Trackertoken:
474 | - b545bcaeafc773ced5b1a853fffd1fc9
475 | Content-Type:
476 | - application/xml
477 | User-Agent:
478 | - Ruby
479 | response:
480 | status:
481 | code: 200
482 | message: OK
483 | headers:
484 | Content-Type:
485 | - application/xml; charset=utf-8
486 | Transfer-Encoding:
487 | - chunked
488 | Status:
489 | - 200 OK
490 | X-Ua-Compatible:
491 | - IE=Edge,chrome=1
492 | Cache-Control:
493 | - max-age=0, private, must-revalidate
494 | Set-Cookie:
495 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTczYjc5NjY3NjhhOWRmMjMyMjlkMDNiYzBkZGFhODYzBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgFLbq74KOg1uYW5vX251bWkCXwM6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgeGMDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxMkd5ZENSSExSNkxtZUUvSXlrcGVkZmF3MHExMWFPZU9lbUx5YlA4c1U4RT0GOwBG--38356172ce14b72f533c1df03d0b8e81f4a79e06;
496 | path=/; HttpOnly
497 | X-Request-Id:
498 | - 036bc3a68117b751df2ce2d02f2d6fbd
499 | X-Runtime:
500 | - '0.058892'
501 | Date:
502 | - Thu, 28 May 2015 09:47:42 GMT
503 | X-Rack-Cache:
504 | - miss
505 | X-Powered-By:
506 | - Phusion Passenger 4.0.41
507 | Server:
508 | - nginx/1.6.0 + Phusion Passenger 4.0.41
509 | X-Tracker-Client-Pinger-Interval:
510 | - '12'
511 | Content-Encoding:
512 | - gzip
513 | body:
514 | encoding: ASCII-8BIT
515 | string: !binary |-
516 | H4sIAAAAAAAAAwIAAAD//0xQu27DMAzc/RWC9kaOk6IeaKZLuyZD+wGKRSQs
517 | 9ILsJnW/vopdw954vDvegXD4cVbcKHUcfCO3m1IK8m0w7C+N/Px4f6rlAQtw
518 | 5M5ZdOXYiX6I1Eidkh4kFkKsyAfMCzb4vC+rel+DyvO0jNkf/ASyhpxmi/Gc
519 | vo0fXi8PtGmDAzURoyfLvHaEJzIpgBrnmWDPPWvb4ekth8xgilLrLEjBEh7v
520 | nhKocf7vk8IXtf1y0OB2V71UdbmUngv8cnDarhuAiosf1PKf/KwV6rD4AwAA
521 | //8DAHDPkbBjAQAA
522 | http_version:
523 | recorded_at: Thu, 28 May 2015 09:47:43 GMT
524 | - request:
525 | method: get
526 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280
527 | body:
528 | encoding: US-ASCII
529 | string: ''
530 | headers:
531 | Accept:
532 | - "*/*; q=0.5, application/xml"
533 | Accept-Encoding:
534 | - gzip, deflate
535 | X-Trackertoken:
536 | - b545bcaeafc773ced5b1a853fffd1fc9
537 | Content-Type:
538 | - application/xml
539 | User-Agent:
540 | - Ruby
541 | response:
542 | status:
543 | code: 200
544 | message: OK
545 | headers:
546 | Content-Type:
547 | - application/xml; charset=utf-8
548 | Transfer-Encoding:
549 | - chunked
550 | Status:
551 | - 200 OK
552 | X-Ua-Compatible:
553 | - IE=Edge,chrome=1
554 | Cache-Control:
555 | - max-age=0, private, must-revalidate
556 | Set-Cookie:
557 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTBlNmZkOGE5Y2M3ZTNjNjM2M2M2N2YxMDA1MDI0NWQyBjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgLWmvL4KOg1uYW5vX251bWkByToNbmFub19kZW5pBjoNc3VibWljcm8iByAQOgtvZmZzZXRpADoJem9uZUkiCFVUQwY7AFRJIhBfY3NyZl90b2tlbgY7AEZJIjE5UFllWHNTMk0zb2hvSVo2QlplSGl0bXdQL3VnZWlFc1BYQ1QwdnZOQllnPQY7AEY%3D--476fdc692bf5ef3742e33bfb6487e7212a93a8f2;
558 | path=/; HttpOnly
559 | X-Request-Id:
560 | - af0e96de8ce8ac0761b2d5087dc099fc
561 | X-Runtime:
562 | - '0.043550'
563 | Date:
564 | - Thu, 28 May 2015 09:47:43 GMT
565 | X-Rack-Cache:
566 | - miss
567 | X-Powered-By:
568 | - Phusion Passenger 4.0.41
569 | Server:
570 | - nginx/1.6.0 + Phusion Passenger 4.0.41
571 | X-Tracker-Client-Pinger-Interval:
572 | - '12'
573 | Content-Encoding:
574 | - gzip
575 | body:
576 | encoding: ASCII-8BIT
577 | string: !binary |-
578 | H4sIAAAAAAAAAwIAAAD//4RUS2/bMAy+91cYPmeV4zRoVrjqtmK7DethPQu0
579 | zdhaZMmQ5GTprx+l2Hm06wYEiPjx45tm8fC7U8kWrZNG36fz6yxNUFemlrq5
580 | T59/fvuwSh/4VdFb8wsrz6+SpJA1ny/y23yVFYzeAdLQIX+RpgNVsChEokcL
581 | nhwLhbrxbeL3Pd6nUnts0KZ8TvavKNFuh7gRzoP1ooY9/240/RXsFRyYvSFn
582 | wlWgkGez+SyfLQp2DgYSVJUZtOdfLGwxeYy1FWxCA2MtrfPilMshtpcdjinX
583 | 4DGIKc+z+ZJlS5bfJHl+l2X0S55/PhbsfR+xpmqwFinXUxA9dCXav/TkPWr0
584 | gxpKhcKD27jRtjRGIeiUeztgwc4Z0WSLylTS76lPLdJoPtO4ocHErJNFcszH
585 | Few18TzvScfnNPUpwyMYmFJLL0GJC+YbMDAPlQuzFrXReGqJE94I15odn+e0
586 | RrE//2IFXwpKVI5riaVEt4GZA72ZOZKb2YvsoGAj40CmMUPl5Ta0A/z7071N
587 | so93y8XdYpyugkvL2FhQyuzIjYeq7Wi4bpzAWzyw+6FUsuJrUI6mNEpBMTgU
588 | rfe9m3QnIKjLoXECdC2q1likp0WBjrYRfFiFyeh/tOCqMl0nvehMfTQ7hwKl
589 | w9B118p+Wi+wFvZpKPhCfQAIohOwvMny1c1qOgeR2ZMXoycWAdiBVLwv7VDr
590 | /acmSNcUnRY2KqL/aBnvxxPW1pxuyaga18nxp68U7LBw7pgJu4xZWPou+I+d
591 | Rluw+D7UwE41xjGeydEXbTIdqMPletuEEPekptPIjrfxDwAAAP//AwDXq2nA
592 | TQUAAA==
593 | http_version:
594 | recorded_at: Thu, 28 May 2015 09:47:44 GMT
595 | - request:
596 | method: get
597 | uri: https://www.pivotaltracker.com/services/v3/projects/1327280/memberships
598 | body:
599 | encoding: US-ASCII
600 | string: ''
601 | headers:
602 | Accept:
603 | - "*/*; q=0.5, application/xml"
604 | Accept-Encoding:
605 | - gzip, deflate
606 | X-Trackertoken:
607 | - b545bcaeafc773ced5b1a853fffd1fc9
608 | Content-Type:
609 | - application/xml
610 | User-Agent:
611 | - Ruby
612 | response:
613 | status:
614 | code: 200
615 | message: OK
616 | headers:
617 | Content-Type:
618 | - application/xml; charset=utf-8
619 | Transfer-Encoding:
620 | - chunked
621 | Status:
622 | - 200 OK
623 | X-Ua-Compatible:
624 | - IE=Edge,chrome=1
625 | Cache-Control:
626 | - max-age=0, private, must-revalidate
627 | Set-Cookie:
628 | - t_session=BAh7CEkiD3Nlc3Npb25faWQGOgZFVEkiJTc1NjAzZmRkYzZjYzczOGIyOWE3NmJiODZlYzMzY2Y4BjsAVEkiD2V4cGlyZXNfYXQGOwBGSXU6CVRpbWUNidQcgOvzyr4KOg1uYW5vX251bWkCSAE6DW5hbm9fZGVuaQY6DXN1Ym1pY3JvIgcygDoLb2Zmc2V0aQA6CXpvbmVJIghVVEMGOwBUSSIQX2NzcmZfdG9rZW4GOwBGSSIxbDM3aWJqVGdsUHdYYUVDWlVqK1hacGpyeGpwSWEwQkZiUHdYOVdDdC9Raz0GOwBG--3f8c4073c3a9f3a2f67951f9e6ba8163c9935285;
629 | path=/; HttpOnly
630 | X-Request-Id:
631 | - c9b1e9efbbd2d958e3770f6afd3f550f
632 | X-Runtime:
633 | - '0.049405'
634 | Date:
635 | - Thu, 28 May 2015 09:47:44 GMT
636 | X-Rack-Cache:
637 | - miss
638 | X-Powered-By:
639 | - Phusion Passenger 4.0.41
640 | Server:
641 | - nginx/1.6.0 + Phusion Passenger 4.0.41
642 | X-Tracker-Client-Pinger-Interval:
643 | - '12'
644 | Content-Encoding:
645 | - gzip
646 | body:
647 | encoding: ASCII-8BIT
648 | string: !binary |-
649 | H4sIAAAAAAAAA0xQu27DMAzc/RWC9kaOk6IeaKZLuyZD+wGKRSQs9ILsJnW/
650 | vopdw954vDvegXD4cVbcKHUcfCO3m1IK8m0w7C+N/Px4f6rlAQtw5M5ZdOXY
651 | iX6I1Eidkh4kFkKsyAfMCzb4vC+rel+DyvO0jNkf/ASyhpxmi/Gcvo0fXi8P
652 | tGmDAzURoyfLvHaEJzIpgBrnmWDPPWvb4ekth8xgilLrLEjBEh7vnhKocf7v
653 | k8IXtf1y0OB2V71UdbmUngv8cnDarhuAiosf1PKf/KwV6rD4AwAA//8DAHDP
654 | kbBjAQAA
655 | http_version:
656 | recorded_at: Thu, 28 May 2015 09:47:45 GMT
657 | recorded_with: VCR 2.9.3
658 |
--------------------------------------------------------------------------------