pivotal-tracker-fox 0.5.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +17 -0
  5. data/Gemfile.lock +57 -0
  6. data/LICENSE +20 -0
  7. data/README.rdoc +82 -0
  8. data/Rakefile +46 -0
  9. data/VERSION +1 -0
  10. data/lib/pivotal-tracker.rb +40 -0
  11. data/lib/pivotal-tracker/activity.rb +45 -0
  12. data/lib/pivotal-tracker/attachment.rb +16 -0
  13. data/lib/pivotal-tracker/client.rb +81 -0
  14. data/lib/pivotal-tracker/extensions.rb +11 -0
  15. data/lib/pivotal-tracker/iteration.rb +40 -0
  16. data/lib/pivotal-tracker/membership.rb +20 -0
  17. data/lib/pivotal-tracker/note.rb +58 -0
  18. data/lib/pivotal-tracker/project.rb +94 -0
  19. data/lib/pivotal-tracker/proxy.rb +64 -0
  20. data/lib/pivotal-tracker/story.rb +157 -0
  21. data/lib/pivotal-tracker/task.rb +71 -0
  22. data/lib/pivotal-tracker/validation.rb +69 -0
  23. data/lib/pivotal_tracker.rb +2 -0
  24. data/pivotal-tracker.gemspec +131 -0
  25. data/spec/fixtures/activity.xml +177 -0
  26. data/spec/fixtures/bugs.xml +279 -0
  27. data/spec/fixtures/created_note.xml +14 -0
  28. data/spec/fixtures/created_story.xml +14 -0
  29. data/spec/fixtures/features.xml +293 -0
  30. data/spec/fixtures/iterations_all.xml +243 -0
  31. data/spec/fixtures/iterations_backlog.xml +166 -0
  32. data/spec/fixtures/iterations_current.xml +48 -0
  33. data/spec/fixtures/iterations_current_backlog.xml +211 -0
  34. data/spec/fixtures/iterations_done.xml +34 -0
  35. data/spec/fixtures/memberships.xml +42 -0
  36. data/spec/fixtures/notes.xml +33 -0
  37. data/spec/fixtures/project.xml +53 -0
  38. data/spec/fixtures/project_activity.xml +177 -0
  39. data/spec/fixtures/projects.xml +107 -0
  40. data/spec/fixtures/stale_fish.yml +167 -0
  41. data/spec/fixtures/stories.xml +293 -0
  42. data/spec/fixtures/story-4459994.xml +37 -0
  43. data/spec/fixtures/story-4460038.xml +46 -0
  44. data/spec/fixtures/story-4460598.xml +32 -0
  45. data/spec/fixtures/story-4473735.xml +48 -0
  46. data/spec/fixtures/tasks.xml +24 -0
  47. data/spec/fixtures/update_tasks.xml +8 -0
  48. data/spec/pivotal-tracker/activity_spec.rb +32 -0
  49. data/spec/pivotal-tracker/attachment_spec.rb +62 -0
  50. data/spec/pivotal-tracker/client_spec.rb +148 -0
  51. data/spec/pivotal-tracker/iteration_spec.rb +76 -0
  52. data/spec/pivotal-tracker/membership_spec.rb +20 -0
  53. data/spec/pivotal-tracker/note_spec.rb +61 -0
  54. data/spec/pivotal-tracker/project_spec.rb +98 -0
  55. data/spec/pivotal-tracker/story_spec.rb +247 -0
  56. data/spec/pivotal-tracker/task_spec.rb +33 -0
  57. data/spec/spec.opts +1 -0
  58. data/spec/spec_helper.rb +46 -0
  59. data/spec/support/stale_fish_fixtures.rb +71 -0
  60. metadata +287 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 80d343bd4d40b36df622edb5fe15fa98b76ec0fd
4
+ data.tar.gz: 8fa41a04e8520910f816cb30d70e77c52e36f87a
5
+ SHA512:
6
+ metadata.gz: 09742ce0b199d6439c49868dad497285ec1c3d5d3d14b0c8ca463bad5b10efb2cb29bc667bddf3d2f6bd3f0391416056a8124cfa097ddc48a5619a5965ac2367
7
+ data.tar.gz: bf9455c9183e487da98d2770e7f989550c6eea875ee85abdfe49c65149e2ba835e0f2c126774a6484cac3c77794b91217e4dd568e8bf20ffdf916abca36b3488
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'http://rubygems.org'
2
+
3
+ group :runtime do
4
+ gem 'rest-client', '~> 1.6.0'
5
+ gem 'nokogiri-happymapper', '>= 0.5.4', :require => 'happymapper'
6
+ gem 'builder'
7
+ gem 'nokogiri', '>= 1.5.5'
8
+ gem 'crack'
9
+ end
10
+
11
+ group :test do
12
+ gem 'rspec'
13
+ gem 'rake'
14
+ gem 'jeweler'
15
+ gem 'stale_fish', '~> 1.3.2'
16
+ gem 'autotest'
17
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,57 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ ZenTest (4.8.2)
5
+ activesupport (3.2.9)
6
+ i18n (~> 0.6)
7
+ multi_json (~> 1.0)
8
+ autotest (4.4.6)
9
+ ZenTest (>= 4.4.1)
10
+ builder (3.1.4)
11
+ crack (0.3.1)
12
+ diff-lcs (1.1.3)
13
+ fakeweb (1.3.0)
14
+ git (1.2.5)
15
+ i18n (0.6.1)
16
+ jeweler (1.8.4)
17
+ bundler (~> 1.0)
18
+ git (>= 1.2.5)
19
+ rake
20
+ rdoc
21
+ json (1.7.5)
22
+ mime-types (1.19)
23
+ multi_json (1.3.7)
24
+ nokogiri (1.5.5)
25
+ nokogiri-happymapper (0.5.6)
26
+ nokogiri (~> 1.5)
27
+ rake (10.0.2)
28
+ rdoc (3.12)
29
+ json (~> 1.4)
30
+ rest-client (1.6.7)
31
+ mime-types (>= 1.16)
32
+ rspec (2.12.0)
33
+ rspec-core (~> 2.12.0)
34
+ rspec-expectations (~> 2.12.0)
35
+ rspec-mocks (~> 2.12.0)
36
+ rspec-core (2.12.0)
37
+ rspec-expectations (2.12.0)
38
+ diff-lcs (~> 1.1.3)
39
+ rspec-mocks (2.12.0)
40
+ stale_fish (1.3.2)
41
+ activesupport
42
+ fakeweb
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ autotest
49
+ builder
50
+ crack
51
+ jeweler
52
+ nokogiri (>= 1.5.5)
53
+ nokogiri-happymapper (>= 0.5.4)
54
+ rake
55
+ rest-client (~> 1.6.0)
56
+ rspec
57
+ stale_fish (~> 1.3.2)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Justin Smestad
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.
data/README.rdoc ADDED
@@ -0,0 +1,82 @@
1
+ = pivotal-tracker.rb
2
+
3
+ Ruby wrapper for Pivotal Tracker API, no frameworks required. Simply Ruby.
4
+
5
+ {<img src="https://secure.travis-ci.org/jsmestad/pivotal-tracker.png" />}[http://travis-ci.org/jsmestad/pivotal-tracker]
6
+ {<img src="https://badge.fury.io/rb/pivotal-tracker.png" alt="Gem Version" />}[http://rubygems.org/gems/pivotal-tracker]
7
+
8
+ == Features
9
+
10
+ * Compatible with Pivotal Tracker API version 3
11
+ * ActiveRecord-style Wrapper API
12
+ * Support for SSL protected repositories
13
+
14
+ == Overview
15
+
16
+ PivotalTracker::Client.token('myusername@email.com', 'secretpassword') # Automatically fetch API Token
17
+ PivotalTracker::Client.token = 'jkfduisj97823974j2kl24899234' # Manually set API Token
18
+
19
+ @projects = PivotalTracker::Project.all # return all projects
20
+ @a_project = PivotalTracker::Project.find(84739) # find project with a given ID
21
+
22
+ @a_project.stories.all # return all stories for "a_project"
23
+ @a_project.stories.all(:label => 'overdue', :story_type => ['bug', 'chore']) # return all stories that match the passed filters
24
+ @a_project.stories.find(847762630) # find story with a given ID
25
+
26
+ @a_project.stories.create(:name => 'My Story', :story_type => 'feature') # create a story for this project
27
+
28
+ # all tracker defined filters are allowed, as well as :limit & :offset for pagination
29
+
30
+ # The below pattern below is planned to be added to the final release:
31
+
32
+ @a_project.stories << PivotalTracker::Story.new(84739, :name => 'Ur Story') # same as earlier story creation, useful for copying/cloning from proj
33
+
34
+
35
+ @story = @a_project.stories.find(847762630)
36
+ @story.notes.all # return all notes (comments) for a story
37
+ @story.notes.create(:text => 'A new comment', :noted_at => '06/29/2010 05:00 EST') # add a new note
38
+
39
+
40
+ @story.attachments # return an array of all attachment items (data only, not the files)
41
+ @story.upload_attachment(file_path) # add a file attachment to @story that can be found at file_path
42
+
43
+
44
+ # All 4 examples below return a PivotalTracker::Story from the new project, with the same story ID
45
+
46
+ @story.move_to_project(123456) # move @story to the project with ID 123456
47
+ @story.move_to_project('123456') # same as above
48
+ @story.move_to_project(@project) # move @story to @project
49
+ @story.move_to_project(@another_story) # move @story into the same project as @another_story
50
+
51
+
52
+ # Connect to custom API endpoint
53
+ PivotalTracker::Client.tracker_host = 'www.my-pivotal-tracker.com'
54
+
55
+ The API is based on the following this gist: http://gist.github.com/283120
56
+
57
+ == Getting Started
58
+
59
+ * Installing:
60
+
61
+ $ gem install pivotal-tracker
62
+
63
+ * Contributing (requires Bundler >= 0.9.7):
64
+
65
+ $ git clone git://github.com/jsmestad/pivotal-tracker
66
+ $ cd pivotal-tracker
67
+ $ bundle install
68
+ $ bundle exec rake
69
+
70
+ == Additional Information
71
+
72
+ * Wiki: http://wiki.github.com/jsmestad/pivotal-tracker
73
+ * Documentation: http://rdoc.info/projects/jsmestad/pivotal-tracker
74
+ * Pivotal API v3 Docs: http://www.pivotaltracker.com/help/api?version=v3
75
+
76
+ == Contributors along the way
77
+
78
+ * Justin Smestad (http://github.com/jsmestad)
79
+ * Josh Nichols (http://github.com/technicalpickles)
80
+ * Terence Lee (http://github.com/hone)
81
+ * Jon Mischo (http://github.com/supertaz)
82
+ * Gabor Ratky (http://github.com/rgabo)
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ begin
9
+ require 'jeweler'
10
+ Jeweler::Tasks.new do |gem|
11
+ gem.name = "pivotal-tracker"
12
+ gem.summary = %Q{Ruby wrapper for the Pivotal Tracker API}
13
+ gem.email = "justin.smestad@gmail.com"
14
+ gem.homepage = "http://github.com/jsmestad/pivotal-tracker"
15
+ gem.authors = ["Justin Smestad", "Josh Nichols", "Terence Lee"]
16
+
17
+ gem.add_dependency 'rest-client', '~> 1.6.0'
18
+ gem.add_dependency 'happymapper', '>= 0.3.2'
19
+ gem.add_dependency 'builder'
20
+ gem.add_dependency 'nokogiri', '>= 1.4.3'
21
+
22
+ gem.add_development_dependency 'rspec'
23
+ gem.add_development_dependency 'bundler', '~> 1.0.12'
24
+ gem.add_development_dependency 'jeweler'
25
+ gem.add_development_dependency 'stale_fish', '~> 1.3.0'
26
+ end
27
+ Jeweler::GemcutterTasks.new
28
+ rescue LoadError
29
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
30
+ end
31
+
32
+ require 'rspec/core'
33
+ require 'rspec/core/rake_task'
34
+ RSpec::Core::RakeTask.new(:spec)
35
+
36
+ task :default => :spec
37
+
38
+ begin
39
+ require 'yard'
40
+ YARD::Rake::YardocTask.new
41
+ rescue LoadError
42
+ task :yardoc do
43
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
44
+ end
45
+ end
46
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.5.11
@@ -0,0 +1,40 @@
1
+ require 'cgi'
2
+ require 'rest_client'
3
+ require 'happymapper'
4
+ require 'nokogiri'
5
+
6
+
7
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'validation')
8
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'extensions')
9
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'proxy')
10
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'client')
11
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'project')
12
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'attachment')
13
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'story')
14
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'task')
15
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'membership')
16
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'activity')
17
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'iteration')
18
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker', 'note')
19
+
20
+ module PivotalTracker
21
+
22
+ # define error types
23
+ class ProjectNotSpecified < StandardError; end
24
+
25
+ def self.encode_options(options)
26
+ options_strings = options.inject({}) do |m, (k,v)|
27
+ if [:limit, :offset].include?(k.to_sym)
28
+ m.update k => v
29
+ elsif k.to_sym == :search
30
+ m.update :filter => v
31
+ else
32
+ filter_query = %{#{k}:#{[v].flatten.join(",")}}
33
+ m.update :filter => (m[:filter] ? "#{m[:filter]} #{filter_query}" : filter_query)
34
+ end
35
+ end.map {|k,v| "#{k}=#{CGI.escape(v.to_s)}"}
36
+
37
+ %{?#{options_strings.join("&")}} unless options_strings.empty?
38
+ end
39
+
40
+ end
@@ -0,0 +1,45 @@
1
+ module PivotalTracker
2
+ class Activity
3
+ include HappyMapper
4
+ class << self
5
+ def all(project=nil, options={})
6
+ params = self.encode_options(options)
7
+ if project
8
+ parse(Client.connection["/projects/#{project.id}/activities#{params}"].get)
9
+ else
10
+ parse(Client.connection["/activities#{params}"].get)
11
+ end
12
+ end
13
+
14
+ protected
15
+
16
+ def encode_options(options)
17
+ return nil if !options.is_a?(Hash) || options.empty?
18
+
19
+ options_string = []
20
+ options_string << "limit=#{options.delete(:limit)}" if options[:limit]
21
+ options_string << "newer_than_version=#{options.delete(:newer_than_version)}" if options[:newer_than_version]
22
+
23
+ if options[:occurred_since]
24
+ options_string << "occurred_since_date=\"#{options[:occurred_since].utc}\""
25
+ elsif options[:occurred_since_date]
26
+ options_string << "occurred_since_date=#{URI.escape options[:occurred_since_date].strftime("%Y/%m/%d %H:%M:%S %Z")}"
27
+ end
28
+
29
+ return "?#{options_string.join('&')}"
30
+ end
31
+
32
+ end
33
+
34
+ element :id, Integer
35
+ element :version, Integer
36
+ element :event_type, String
37
+ element :occurred_at, DateTime
38
+ element :author, String
39
+ element :project_id, Integer
40
+ element :description, String
41
+
42
+ has_many :stories, Story
43
+
44
+ end
45
+ end
@@ -0,0 +1,16 @@
1
+ module PivotalTracker
2
+ class Attachment
3
+ include HappyMapper
4
+
5
+ tag 'attachment'
6
+
7
+ element :id, Integer
8
+ element :filename, String
9
+ element :description, String
10
+ element :uploaded_by, String
11
+ element :uploaded_at, DateTime
12
+ element :url, String
13
+ element :status, String
14
+
15
+ end
16
+ end
@@ -0,0 +1,81 @@
1
+ module PivotalTracker
2
+
3
+ class Client
4
+
5
+ class NoToken < StandardError; end
6
+
7
+ class << self
8
+ attr_writer :use_ssl, :token, :tracker_host
9
+
10
+ def use_ssl
11
+ @use_ssl || false
12
+ end
13
+
14
+ def token(username, password, method='post')
15
+ response = if method == 'post'
16
+ RestClient.post api_ssl_url + '/tokens/active', :username => username, :password => password
17
+ else
18
+ RestClient.get "#{api_ssl_url(username, password)}/tokens/active"
19
+ end
20
+ @token= Nokogiri::XML(response.body).search('guid').inner_html
21
+ end
22
+
23
+ # this is your connection for the entire module
24
+ def connection(options={})
25
+ raise NoToken if @token.to_s.empty?
26
+
27
+ @connections ||= {}
28
+
29
+ cached_connection? && !protocol_changed? ? cached_connection : new_connection
30
+ end
31
+
32
+ def clear_connections
33
+ @connections = nil
34
+ end
35
+
36
+ def tracker_host
37
+ @tracker_host ||= "www.pivotaltracker.com"
38
+ end
39
+
40
+ def api_ssl_url(user=nil, password=nil)
41
+ user_password = (user && password) ? "#{user}:#{password}@" : ''
42
+ "https://#{user_password}#{tracker_host}#{api_path}"
43
+ end
44
+
45
+ def api_url
46
+ "http://#{tracker_host}#{api_path}"
47
+ end
48
+
49
+ protected
50
+
51
+ def protocol
52
+ use_ssl ? 'https' : 'http'
53
+ end
54
+
55
+ def cached_connection?
56
+ !@connections[@token].nil?
57
+ end
58
+
59
+ def cached_connection
60
+ @connections[@token]
61
+ end
62
+
63
+ def new_connection
64
+ @connections[@token] = RestClient::Resource.new("#{use_ssl ? api_ssl_url : api_url}", :headers => {'X-TrackerToken' => @token, 'Content-Type' => 'application/xml'})
65
+ end
66
+
67
+ def protocol_changed?
68
+ cached_connection? ? (cached_connection_protocol != protocol) : false
69
+ end
70
+
71
+ def cached_connection_protocol
72
+ cached_connection.url.match(/^(.*):\/\//).captures.first
73
+ end
74
+
75
+ def api_path
76
+ '/services/v3'
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,11 @@
1
+ # Happymapper patch for RestClient API Change (response => response.body)
2
+
3
+ module HappyMapper
4
+ module ClassMethods
5
+ alias_method :orig_parse, :parse
6
+ def parse(xml, options={})
7
+ xml = xml.to_s if xml.is_a?(RestClient::Response)
8
+ orig_parse(xml, options)
9
+ end
10
+ end
11
+ end