pivotal-tracker-api 0.2.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +8 -2
  3. data/Gemfile.lock +65 -47
  4. data/README.md +7 -7
  5. data/VERSION +1 -1
  6. data/lib/pivotal-tracker-api.rb +10 -2
  7. data/lib/pivotal-tracker-api/activity.rb +52 -18
  8. data/lib/pivotal-tracker-api/analytics.rb +23 -0
  9. data/lib/pivotal-tracker-api/base.rb +14 -2
  10. data/lib/pivotal-tracker-api/client.rb +43 -21
  11. data/lib/pivotal-tracker-api/comment.rb +76 -27
  12. data/lib/pivotal-tracker-api/core_ext/string.rb +3 -0
  13. data/lib/pivotal-tracker-api/cycle_time_details.rb +43 -0
  14. data/lib/pivotal-tracker-api/file_attachment.rb +56 -0
  15. data/lib/pivotal-tracker-api/iteration.rb +73 -11
  16. data/lib/pivotal-tracker-api/label.rb +32 -0
  17. data/lib/pivotal-tracker-api/me.rb +16 -0
  18. data/lib/pivotal-tracker-api/person.rb +13 -9
  19. data/lib/pivotal-tracker-api/project.rb +76 -23
  20. data/lib/pivotal-tracker-api/service.rb +202 -0
  21. data/lib/pivotal-tracker-api/story.rb +173 -132
  22. data/lib/pivotal-tracker-api/story_transition.rb +81 -0
  23. data/lib/pivotal-tracker-api/string_extensions.rb +61 -0
  24. data/lib/pivotal-tracker-api/task.rb +56 -12
  25. data/pivotal-tracker-api.gemspec +28 -15
  26. data/test/helper.rb +1 -0
  27. data/test/test_activity.rb +79 -0
  28. data/test/test_analytics.rb +38 -0
  29. data/test/test_cycle_time_details.rb +69 -0
  30. data/test/test_iteration.rb +182 -0
  31. data/test/test_label.rb +29 -0
  32. data/test/test_me.rb +52 -0
  33. data/test/test_service.rb +67 -0
  34. data/test/test_story.rb +557 -0
  35. data/test/test_story_transition.rb +80 -0
  36. data/test/test_string_extensions.rb +37 -0
  37. metadata +29 -27
  38. data/lib/pivotal-tracker-api/attachment.rb +0 -28
  39. data/lib/pivotal-tracker-api/pivotal_service.rb +0 -141
  40. data/test/test_pivotal-tracker-api.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab585f160402f79d123587706e8c51fb779657aa
4
- data.tar.gz: 1181ea8f46993d016907a5ed13bebf7432720d79
3
+ metadata.gz: cbfb334bb577e14833146540ec08e68f8dc26cca
4
+ data.tar.gz: dc59ed6076a4899c0b09458865c99aee9982d381
5
5
  SHA512:
6
- metadata.gz: 497c21fe94dbdc3a2bc0700c027e75801056d41991adb6b132341c6b771ede50f5bdec4ec1270bf50673fb70a7b1c1e25219f7a795f98b93803abc613f9cae21
7
- data.tar.gz: 611c2875df73319dc0b02590b6a33660bbe6dbd5543913751aa76c814adaf85b140ab1834d1331d5fe3e539db1af82b37093b556ae31b1e3ffbdccd33f3b4c7c
6
+ metadata.gz: 4b689d03586d7eed80ffb25444b47192adb4a5371c65b79710971805331f178d10bb092207f3800ecacf93b1fc006ae9ce67034636f2941bb78c7282b826b672
7
+ data.tar.gz: 9f959cc0af6ce48c3acde9785a10ad268bad1b82c3ee1376cf428b0f91636152bc6f99d14e8ce2c22f951b117004b06d38a8e93397063a113988c02e306aac60
data/Gemfile CHANGED
@@ -3,13 +3,19 @@ source 'http://rubygems.org'
3
3
  # Example:
4
4
  # gem 'activesupport', '>= 2.3.5'
5
5
  gem 'rest-client', '~> 1.7'
6
+ gem 'business_time', '~> 0.7.6'
6
7
 
7
8
  # Add dependencies to develop your gem here.
8
9
  # Include everything needed to run rake, tests, features, etc.
9
10
  group :development do
10
- gem 'shoulda', '>= 0'
11
11
  gem 'rdoc', '~> 3.12'
12
12
  gem 'bundler', '~> 1.0'
13
- gem 'jeweler', '~> 1.8.7'
13
+ gem 'jeweler', '~> 2.1'
14
+ end
15
+
16
+ group :test do
17
+ gem 'shoulda'
18
+ gem "mocha"
19
+ gem 'test-unit'
14
20
  gem 'simplecov'
15
21
  end
@@ -1,83 +1,101 @@
1
1
  GEM
2
2
  remote: http://rubygems.org/
3
3
  specs:
4
- activesupport (4.0.0)
5
- i18n (~> 0.6, >= 0.6.4)
6
- minitest (~> 4.2)
7
- multi_json (~> 1.3)
8
- thread_safe (~> 0.1)
9
- tzinfo (~> 0.3.37)
10
- addressable (2.3.5)
11
- atomic (1.1.14)
4
+ activesupport (5.0.0.1)
5
+ concurrent-ruby (~> 1.0, >= 1.0.2)
6
+ i18n (~> 0.7)
7
+ minitest (~> 5.1)
8
+ tzinfo (~> 1.1)
9
+ addressable (2.4.0)
12
10
  builder (3.2.2)
13
- faraday (0.8.8)
14
- multipart-post (~> 1.2.0)
15
- git (1.2.6)
16
- github_api (0.10.1)
17
- addressable
18
- faraday (~> 0.8.1)
19
- hashie (>= 1.2)
20
- multi_json (~> 1.4)
21
- nokogiri (~> 1.5.2)
22
- oauth2
23
- hashie (2.0.5)
24
- highline (1.6.20)
25
- httpauth (0.2.0)
26
- i18n (0.6.5)
27
- jeweler (1.8.8)
11
+ business_time (0.7.6)
12
+ activesupport (>= 3.1.0)
13
+ tzinfo
14
+ concurrent-ruby (1.0.2)
15
+ descendants_tracker (0.0.4)
16
+ thread_safe (~> 0.3, >= 0.3.1)
17
+ faraday (0.9.2)
18
+ multipart-post (>= 1.2, < 3)
19
+ git (1.3.0)
20
+ github_api (0.14.5)
21
+ addressable (~> 2.4.0)
22
+ descendants_tracker (~> 0.0.4)
23
+ faraday (~> 0.8, < 0.10)
24
+ hashie (>= 3.4)
25
+ oauth2 (~> 1.0)
26
+ hashie (3.4.4)
27
+ highline (1.7.8)
28
+ i18n (0.7.0)
29
+ jeweler (2.1.1)
28
30
  builder
29
- bundler (~> 1.0)
31
+ bundler (>= 1.0)
30
32
  git (>= 1.2.5)
31
- github_api (= 0.10.1)
33
+ github_api
32
34
  highline (>= 1.6.15)
33
- nokogiri (= 1.5.10)
35
+ nokogiri (>= 1.5.10)
34
36
  rake
35
37
  rdoc
36
- json (1.8.1)
37
- jwt (0.1.8)
38
- multi_json (>= 1.5)
38
+ semver
39
+ json (1.8.3)
40
+ jwt (1.5.4)
41
+ metaclass (0.0.4)
39
42
  mime-types (2.4.3)
40
- minitest (4.7.5)
41
- multi_json (1.8.2)
43
+ mini_portile2 (2.1.0)
44
+ minitest (5.9.0)
45
+ mocha (1.1.0)
46
+ metaclass (~> 0.0.1)
47
+ multi_json (1.12.1)
42
48
  multi_xml (0.5.5)
43
- multipart-post (1.2.0)
49
+ multipart-post (2.0.0)
44
50
  netrc (0.8.0)
45
- nokogiri (1.5.10)
46
- oauth2 (0.9.2)
47
- faraday (~> 0.8)
48
- httpauth (~> 0.2)
49
- jwt (~> 0.1.4)
50
- multi_json (~> 1.0)
51
+ nokogiri (1.6.8)
52
+ mini_portile2 (~> 2.1.0)
53
+ pkg-config (~> 1.1.7)
54
+ oauth2 (1.2.0)
55
+ faraday (>= 0.8, < 0.10)
56
+ jwt (~> 1.0)
57
+ multi_json (~> 1.3)
51
58
  multi_xml (~> 0.5)
52
- rack (~> 1.2)
53
- rack (1.5.2)
54
- rake (10.1.0)
59
+ rack (>= 1.2, < 3)
60
+ pkg-config (1.1.7)
61
+ power_assert (0.3.0)
62
+ rack (2.0.1)
63
+ rake (11.2.2)
55
64
  rdoc (3.12.2)
56
65
  json (~> 1.4)
57
66
  rest-client (1.7.2)
58
67
  mime-types (>= 1.16, < 3.0)
59
68
  netrc (~> 0.7)
69
+ semver (1.0.1)
60
70
  shoulda (3.5.0)
61
71
  shoulda-context (~> 1.0, >= 1.0.1)
62
72
  shoulda-matchers (>= 1.4.1, < 3.0)
63
- shoulda-context (1.1.5)
64
- shoulda-matchers (2.4.0)
73
+ shoulda-context (1.2.1)
74
+ shoulda-matchers (2.8.0)
65
75
  activesupport (>= 3.0.0)
66
76
  simplecov (0.7.1)
67
77
  multi_json (~> 1.0)
68
78
  simplecov-html (~> 0.7.1)
69
79
  simplecov-html (0.7.1)
70
- thread_safe (0.1.3)
71
- atomic
72
- tzinfo (0.3.38)
80
+ test-unit (3.2.1)
81
+ power_assert
82
+ thread_safe (0.3.5)
83
+ tzinfo (1.2.2)
84
+ thread_safe (~> 0.1)
73
85
 
74
86
  PLATFORMS
75
87
  ruby
76
88
 
77
89
  DEPENDENCIES
78
90
  bundler (~> 1.0)
79
- jeweler (~> 1.8.7)
91
+ business_time (~> 0.7.6)
92
+ jeweler (~> 2.1)
93
+ mocha
80
94
  rdoc (~> 3.12)
81
95
  rest-client (~> 1.7)
82
96
  shoulda
83
97
  simplecov
98
+ test-unit
99
+
100
+ BUNDLED WITH
101
+ 1.12.5
data/README.md CHANGED
@@ -10,7 +10,7 @@ A Pivotal Tracker API gem that can be used to interface with the Pivotal Tracker
10
10
  def set_token
11
11
  # This will set the @token in the Client class. Class caching must be enabled for the token to persist.
12
12
  # config.cache_classes = true
13
- PivotalService.set_token(your_token_here)
13
+ PivotalAPI::Service.set_token(your_token_here)
14
14
  end
15
15
  ```
16
16
 
@@ -21,7 +21,7 @@ def get_user_token
21
21
  pass = params[:pass]
22
22
  # This will set the @token in the Client class. Class caching must be enabled for the token to persist.
23
23
  # config.cache_classes = true
24
- token = Scorer::Client.token(email, pass)
24
+ token = PivotalAPI::Client.token(email, pass)
25
25
  # do something with the token
26
26
  end
27
27
  ```
@@ -29,14 +29,14 @@ end
29
29
  ```ruby
30
30
  # Get all of the users Projects
31
31
  def projects
32
- @projects = PivotalService.all_projects(Scorer::Project.fields)
32
+ @projects = PivotalAPI::Service.all_projects(PivotalAPI::Project.fields)
33
33
  end
34
34
  ```
35
35
 
36
36
  ```ruby
37
37
  # Get only 1 of the users Projects
38
38
  def project
39
- @project = PivotalService.one_project(params[:project_id], Scorer::Project.fields)
39
+ @project = PivotalAPI::Service.one_project(params[:project_id], PivotalAPI::Project.fields)
40
40
  end
41
41
  ```
42
42
 
@@ -45,7 +45,7 @@ end
45
45
  def stories_by_label
46
46
  project_label = params[:project_label]
47
47
  @project_label = CGI.escape(project_label) if project_label
48
- @stories = PivotalService.all_stories(@project_label, @project, Scorer::Story.fields) if @project_label
48
+ @stories = PivotalAPI::Service.all_stories(@project_label, @project, PivotalAPI::Story.fields) if @project_label
49
49
  end
50
50
  ```
51
51
 
@@ -53,12 +53,12 @@ end
53
53
  # Get an Iteration and it's Stories
54
54
  def get_iteration
55
55
  @project_id = params[:project_id]
56
- @iteration = PivotalService.iterations(@project_id, 'current')
56
+ @iteration = PivotalAPI::Service.iterations(@project_id, 'current')
57
57
  @stories = @iteration.stories
58
58
  end
59
59
  ```
60
60
 
61
- For additional infomation on how to interface with this gem and use it to communicate with the Pivotal Tracker API v5 see the [PivotalService](https://github.com/atljeremy/pivotal-tracker-api/blob/master/lib/pivotal-tracker-api/pivotal_service.rb) class.
61
+ For additional infomation on how to interface with this gem and use it to communicate with the Pivotal Tracker API v5 see the [PivotalAPI::Service](https://github.com/atljeremy/pivotal-tracker-api/blob/master/lib/pivotal-tracker-api/pivotal_service.rb) class.
62
62
 
63
63
  ### Contributing to pivotal-tracker-api
64
64
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 1.0.0
@@ -1,13 +1,21 @@
1
1
  require 'rest_client'
2
+ require 'business_time'
2
3
 
4
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'string_extensions')
5
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'core_ext', 'string')
3
6
  require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'base')
4
7
  require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'client')
8
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'cycle_time_details')
9
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'label')
10
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'analytics')
11
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'story_transition')
5
12
  require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'project')
6
- require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'attachment')
13
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'file_attachment')
7
14
  require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'story')
8
15
  require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'task')
9
16
  require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'activity')
10
17
  require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'iteration')
11
18
  require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'comment')
12
19
  require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'person')
13
- require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'pivotal_service')
20
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'me')
21
+ require File.join(File.dirname(__FILE__), 'pivotal-tracker-api', 'service')
@@ -1,31 +1,65 @@
1
- module Scorer
1
+ # PROPERTIES
2
+ # guid string
3
+ # — Project id and version of the activity. This field is read only. This field is always returned.
4
+ #
5
+ # project_version int
6
+ # — The version of the activity. This field is read only. This field is always returned.
7
+ #
8
+ # message string
9
+ # — Description of the activity. This field is read only.
10
+ #
11
+ # highlight string
12
+ # — Boldface portion of the message. This field is read only.
13
+ #
14
+ # changes List[object]
15
+ # — The set of changes. This field is read only.
16
+ #
17
+ # primary_resources List[object]
18
+ # — The primary resource(s) affected by this command. This field is read only.
19
+ #
20
+ # project_id int
21
+ # — id of the project. This field is read only. By default this will be included in responses as a nested structure, using the key project.
22
+ #
23
+ # performed_by_id int
24
+ # — id of the person who performed this change. This field is read only. By default this will be included in responses as a nested structure, using the key performed_by.
25
+ #
26
+ # occurred_at datetime
27
+ # — Time of the activity. This field is read only.
28
+ #
29
+ # kind string
30
+ # — Thevalue of 'kind' will reflect the specific type of activity that an activity resource represents. The value will be a string that ends in '_activity' and which starts with a name based on the change which occurred. This field is read only.
31
+
32
+ module PivotalAPI
2
33
  class Activity < Base
3
34
 
4
- attr_accessor :project_id, :occurred_at, :highlight, :primary_resources, :changes, :guid, :kind, :performed_by_id,
35
+ attr_accessor :project_id, :occurred_at, :highlight, :primary_resources,
36
+ :changes, :guid, :kind, :performed_by_id,
5
37
  :performed_by, :message, :project_version
6
38
 
7
- def self.parse_json_activity(json_activity, project_id)
39
+ def self.from_json(json)
40
+ parse_json_activity(json) if json.is_a?(Array)
41
+ end
42
+
43
+ protected
44
+
45
+ def self.parse_json_activity(json_activity)
46
+ parsed_activity = []
8
47
  json_activity.each do |activity|
9
- new({
10
- project_id: project_id,
11
- occurred_at: activity[:stories],
12
- highlight: activity[:number],
13
- primary_resources: activity[:team_strength],
14
- changes: activity[:finish],
15
- guid: activity[:kind],
16
- kind: activity[:start],
48
+ parsed_activity << new({
49
+ project_id: activity[:project_id].to_i,
50
+ occurred_at: DateTime.parse(activity[:occurred_at].to_s),
51
+ highlight: activity[:highlight],
52
+ primary_resources: activity[:primary_resources],
53
+ changes: activity[:changes],
54
+ guid: activity[:guid],
55
+ kind: activity[:kind],
17
56
  performed_by_id: activity[:performed_by_id],
18
- performed_by: parse_person(activity[:performed_by]),
57
+ performed_by: Person.from_json(activity[:performed_by]),
19
58
  message: activity[:message],
20
59
  project_version: activity[:project_version]
21
60
  })
22
61
  end
23
- end
24
-
25
- protected
26
-
27
- def self.parse_person(json_person)
28
- Scorer::Person.parse_json_person(json_person)
62
+ parsed_activity
29
63
  end
30
64
 
31
65
  end
@@ -0,0 +1,23 @@
1
+ # PROPERTIES
2
+ # stories_accepted int
3
+ # — Number of stories accepted during this iteration. This field is read only.
4
+ #
5
+ # bugs_created int
6
+ # — Number of new bugs created. This field is read only.
7
+ #
8
+ # cycle_time int
9
+ # — Median cycle time in milliseconds for contained stories. This field is read only.
10
+ #
11
+ # rejection_rate float
12
+ # — Percentage of accepted bugs and features in the iteration that have ever been rejected. This field is read only.
13
+ #
14
+ # kind string
15
+ # — The type of this object: analytics. This field is read only.
16
+
17
+ module PivotalAPI
18
+ class Analytics < Base
19
+
20
+ attr_accessor :stories_accepted, :bugs_created, :cycle_time, :rejection_rate, :kind
21
+
22
+ end
23
+ end
@@ -1,9 +1,21 @@
1
- module Scorer
1
+ module PivotalAPI
2
2
  class Base
3
3
 
4
4
  def initialize(attributes={})
5
5
  update_attributes(attributes)
6
6
  end
7
+
8
+ def self.from_json(json)
9
+ object = nil
10
+ if json.is_a?(Array)
11
+ vals = []
12
+ json.each { |val| vals << new(val) }
13
+ object = vals
14
+ else
15
+ object = new(json)
16
+ end
17
+ object
18
+ end
7
19
 
8
20
  def to_json
9
21
  hash = {}
@@ -21,7 +33,7 @@ module Scorer
21
33
  attrs.each do |key, value|
22
34
  # self.send("#{key}=", value.is_a?(Array) ? value.join(',') : value )
23
35
  self.send("#{key}=", value)
24
- end
36
+ end if attrs
25
37
  end
26
38
 
27
39
  end
@@ -1,12 +1,11 @@
1
- module Scorer
1
+ module PivotalAPI
2
2
  class Client
3
3
 
4
4
  class NoToken < StandardError; end
5
5
 
6
6
  class << self
7
7
 
8
- attr_writer :token, :ssl_enabled
9
- attr_reader :api_host, :api_projects_path
8
+ attr_writer :token, :username, :password
10
9
 
11
10
  def get(path)
12
11
  begin
@@ -17,6 +16,20 @@ module Scorer
17
16
  set_response_headers(connection["#{api_version}#{path}"].get)
18
17
  end
19
18
  end
19
+
20
+ def ssl_get(path)
21
+ raise ArgumentError.new("missing required fields :username and :password. " \
22
+ "Set these using PivotalAPI::Client.username = USERNAME " \
23
+ "and PivotalAPI::Client.password = PASSWORD.") unless @username && @password
24
+ begin
25
+ puts "ssl_connection: #{ssl_connection}"
26
+ set_response_headers(ssl_connection["#{api_version}#{path}"].get)
27
+ rescue
28
+ puts "Encountered Error in ssl_get: #{$!}"
29
+ clear_connections
30
+ set_response_headers(ssl_connection["#{api_version}#{path}"].get)
31
+ end
32
+ end
20
33
 
21
34
  def get_with_caching(path)
22
35
  begin
@@ -37,32 +50,29 @@ module Scorer
37
50
  @connections ||= {}
38
51
  cached_connection? ? cached_connection : new_connection
39
52
  end
53
+
54
+ def ssl_connection
55
+ raise NoToken if @username.to_s.empty?
56
+ @connections ||= {}
57
+ cached_ssl_connection? ? cached_ssl_connection : new_ssl_connection
58
+ end
40
59
 
41
60
  def clear_connections
42
61
  @connections = nil
43
62
  end
44
63
 
45
- def ssl_enabled
46
- @ssl_enabled || true
47
- end
48
-
49
- def token(username, password)
50
- response = RestClient.get("#{api_ssl_host(username, password)}#{api_version}/me")
51
- json = JSON.parse(response, {:symbolize_names => true})
52
- @token = json[:api_token]
53
- end
54
-
55
- def api_ssl_host(user=nil, password=nil)
56
- user_password = (user && password) ? "#{user}:#{CGI.escape(password)}@" : ''
57
- "https://#{user_password}www.pivotaltracker.com"
64
+ def api_ssl_host
65
+ "https://#{@username}:#{CGI.escape(@password)}@www.pivotaltracker.com"
58
66
  end
59
67
 
60
68
  def api_host
61
- @api_host ||= 'http://www.pivotaltracker.com'
69
+ @api_host ||= 'https://www.pivotaltracker.com'
62
70
  end
63
-
64
- def api_projects_path
65
- @api_projects_path ||= "#{ssl_enabled ? api_ssl_host : api_host}#{api_version}/projects"
71
+
72
+ def token=(val)
73
+ @username = nil
74
+ @password = nil
75
+ @token = val
66
76
  end
67
77
 
68
78
  protected
@@ -87,7 +97,19 @@ module Scorer
87
97
  end
88
98
 
89
99
  def new_connection
90
- @connections[@token] = RestClient::Resource.new("#{ssl_enabled ? api_ssl_host : api_host}", :headers => {'X-TrackerToken' => @token, 'Content-Type' => 'application/json'})
100
+ @connections[@token] = RestClient::Resource.new(api_host, :headers => {'X-TrackerToken' => @token, 'Content-Type' => 'application/json'})
101
+ end
102
+
103
+ def cached_ssl_connection?
104
+ !@connections[@username].nil?
105
+ end
106
+
107
+ def cached_ssl_connection
108
+ @connections[@username]
109
+ end
110
+
111
+ def new_ssl_connection
112
+ @connections[@username] = RestClient::Resource.new(api_ssl_host, :headers => {'Content-Type' => 'application/json'})
91
113
  end
92
114
 
93
115
  end