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
@@ -1,37 +1,86 @@
1
- module Scorer
1
+ # PROPERTIES
2
+ # id int
3
+ # — Database id of the comment. This field is read only. This field is always returned.
4
+ #
5
+ # story_id int
6
+ # — The id of the story to which the comment is attached (will be absent if comment attached to an epic. This field is read only.
7
+ #
8
+ # epic_id int
9
+ # — The id of the epic to which the comment is attached (will be absent if comment attached to a story. This field is read only.
10
+ #
11
+ # text string[20000]
12
+ # — Content of the comment. This field is writable only on create.
13
+ #
14
+ # person_id int
15
+ # — The id of the comment creator. This field is writable only on create. In API responses, this attribute may be person_id or person.
16
+ #
17
+ # created_at datetime
18
+ # — Creation time. This field is read only.
19
+ #
20
+ # updated_at datetime
21
+ # — Updated time. (Comments are updated by removing one of their attachments.) This field is read only.
22
+ #
23
+ # file_attachment_ids List[int]
24
+ # — IDs of any file attachments associated with the comment. This field is writable only on create. This field is excluded by default. In API responses, this attribute may be file_attachment_ids or file_attachments.
25
+ #
26
+ # google_attachment_ids List[int]
27
+ # — IDs of any google attachments associated with the comment. This field is writable only on create. This field is excluded by default. In API responses, this attribute may be google_attachment_ids or google_attachments.
28
+ #
29
+ # commit_identifier string[255]
30
+ # — Commit Id on the remote source control system for the comment. Present only on comments that were created by a POST to the source commits API endpoint. This field is writable only on create. (Note that this attribute does not indicate an association to another resource.)
31
+ #
32
+ # commit_type string[255]
33
+ # — String identifying the type of remote source control system if Pivotal Tracker can determine it. Present only on comments that were created by a POST to the source commits API endpoint. This field is writable only on create.
34
+ #
35
+ # kind string
36
+ # — The type of this object: comment. This field is read only.
37
+
38
+ module PivotalAPI
2
39
  class Comment < Base
3
40
 
4
- attr_accessor :project_id, :story_id, :id, :text, :author, :created_at, :updated_at, :file_attachments
41
+ attr_accessor :project_id, :story_id, :epic_id, :id, :text, :person,
42
+ :created_at, :updated_at, :file_attachments,
43
+ :google_attachment_ids, :commit_identifier, :commit_type,
44
+ :kind
5
45
 
6
46
  def self.fields
7
- ["person(#{Scorer::Person.fields.join(',')})", 'text', 'updated_at', 'id',
8
- 'created_at', 'story_id', 'file_attachments']
47
+ ["person(#{Person.fields.join(',')})", 'text', 'updated_at', 'id',
48
+ 'created_at', 'story_id', 'file_attachments', 'google_attachment_ids',
49
+ 'commit_identifier', 'commit_type', 'kind']
50
+ end
51
+
52
+ def self.from_json(json)
53
+ parse_json_comment(json)
54
+ end
55
+
56
+ def self.parse_json_comment(comment)
57
+ person = Person.from_json(comment[:person]) if comment[:person]
58
+ person = Person.unkown if person.nil?
59
+ new({
60
+ id: comment[:id].to_i,
61
+ text: comment[:text],
62
+ person: person,
63
+ created_at: DateTime.parse(comment[:created_at].to_s),
64
+ updated_at: DateTime.parse(comment[:updated_at].to_s),
65
+ file_attachments: FileAttachments.from_json(comment[:file_attachments]),
66
+ commit_identifier: comment[:commit_identifier],
67
+ google_attachment_ids: comment[:google_attachment_ids],
68
+ commit_type: comment[:commit_type],
69
+ kind: comment[:kind]
70
+ })
9
71
  end
10
72
 
11
- def self.parse_json_comments(json_comments, story)
12
- comments = Array.new
13
- json_comments.each do |comment|
14
- person = Scorer::Person.parse_json_person(comment[:person]) if comment[:person]
15
- person = Scorer::Person.parse_json_person({
16
- id: '0',
17
- name: 'Unkown',
18
- initials: 'Unkown',
19
- username: 'Unkown',
20
- email: 'Unkown'
21
- }) if person.nil?
22
- file_attachments = []
23
- file_attachments = Scorer::Attachment.parse_attachments(comment[:file_attachments]) if comment[:file_attachments]
24
- comments << new({
25
- id: comment[:id].to_i,
26
- text: comment[:text],
27
- author: person,
28
- created_at: DateTime.parse(comment[:created_at].to_s).to_s,
29
- updated_at: DateTime.parse(comment[:updated_at].to_s).to_s,
30
- file_attachments: file_attachments
31
- })
32
- end
73
+ end
74
+
75
+ class Comments < Comment
76
+ def self.from_json(json)
77
+ parse_json_comments(json) if json.is_a?(Array)
78
+ end
79
+
80
+ def self.parse_json_comments(json_comments)
81
+ comments = []
82
+ json_comments.each { |comment| comments << parse_json_comment(comment) }
33
83
  comments
34
84
  end
35
-
36
85
  end
37
86
  end
@@ -0,0 +1,3 @@
1
+ class String
2
+ include PivotalAPI::Extensions::String::QueryParams
3
+ end
@@ -0,0 +1,43 @@
1
+ # PROPERTIES
2
+ # total_cycle_time int
3
+ # — The total amount of time, in milliseconds, between when the story was first started to when it was last accepted. In the case where a story has not been accepted, it is the time between when the story was first started to the current time. If the story has not been started, this property is not returned. This field is read only.
4
+ #
5
+ # started_time int
6
+ # — The total amount of time, in milliseconds, that the story was in the started state. This field is read only.
7
+ #
8
+ # started_count int
9
+ # — The number of times that the story has been in the started state. This field is read only.
10
+ #
11
+ # finished_time int
12
+ # — The total amount of time, in milliseconds, that the story was in the finished state. This field is read only.
13
+ #
14
+ # finished_count int
15
+ # — The number of times that the story has been in the finished state. This field is read only.
16
+ #
17
+ # delivered_time int
18
+ # — The total amount of time, in milliseconds, that the story was in the delivered state. This field is read only.
19
+ #
20
+ # delivered_count int
21
+ # — The number of times that the story has been in the delivered state. This field is read only.
22
+ #
23
+ # rejected_time int
24
+ # — The total amount of time, in milliseconds, that the story was in the rejected state. This field is read only.
25
+ #
26
+ # rejected_count int
27
+ # — The number of times that the story has been in the rejected state. This field is read only.
28
+ #
29
+ # story_id int
30
+ # — The id of the associated story. This field is read only.
31
+ #
32
+ # kind string
33
+ # — The type of this object: cycle_time_details. This field is read only.
34
+
35
+ module PivotalAPI
36
+ class CycleTimeDetails < Base
37
+
38
+ attr_accessor :total_cycle_time, :started_time, :started_count, :finished_time,
39
+ :finished_count, :delivered_time, :delivered_count, :rejected_time,
40
+ :rejected_count, :story_id, :kind
41
+
42
+ end
43
+ end
@@ -0,0 +1,56 @@
1
+ # PROPERTIES
2
+ # id int
3
+ # — Database id of the file_attachment. This field is read only. This field is always returned.
4
+ #
5
+ # filename string[255]
6
+ # — The file's name. This field is read only.
7
+ #
8
+ # created_at datetime
9
+ # — Creation time. This field is read only.
10
+ #
11
+ # uploader_id int
12
+ # — The id of the person who uploaded the file. This field is read only. In API responses, this attribute may be uploader_id or uploader.
13
+ #
14
+ # thumbnailable boolean
15
+ # — Flag indicating whether Tracker knows how to make a thumbnail image from the attachment. This field is read only.
16
+ #
17
+ # height int
18
+ # — If the attachment is thumbnailable the height of it in pixels. This field is read only.
19
+ #
20
+ # width int
21
+ # — If the attachment is thumbnailable the width of it in pixels. This field is read only.
22
+ #
23
+ # size int
24
+ # — The size of the attachment in bytes. This field is read only.
25
+ #
26
+ # download_url string
27
+ # — The URL for the original attachment on S3. This field is read only.
28
+ #
29
+ # content_type string[255]
30
+ # — The MIME type of the attachment. This field is read only.
31
+ #
32
+ # uploaded boolean
33
+ # — Flag indicating whether the attachment has been moved to S3. This field is read only.
34
+ #
35
+ # big_url string
36
+ # — URL to larger-size thumbnail version if attachment is an image. This field is read only.
37
+ #
38
+ # thumbnail_url string
39
+ # — URL to small-size thumbnail version if attachment is an image. This field is read only.
40
+ #
41
+ # kind string
42
+ # — The type of this object: file_attachment. This field is read only.
43
+
44
+ module PivotalAPI
45
+ class FileAttachment < Base
46
+
47
+ attr_accessor :filename, :id, :created_at, :uploaded_by, :big_url,
48
+ :width, :height, :download_url, :thumbnail_url, :size,
49
+ :content_type, :kind, :uploader_id, :thumbnailable,
50
+ :uploaded
51
+
52
+ end
53
+
54
+ class FileAttachments < FileAttachment
55
+ end
56
+ end
@@ -1,12 +1,67 @@
1
- module Scorer
1
+ # PROPERTIES
2
+ # number int
3
+ # — Iteration number starting from 1 for the first iteration in the project. This field is read only. This field is always returned.
4
+ #
5
+ # project_id int
6
+ # — id of the project. This field is read only.
7
+ #
8
+ # length int
9
+ # — Iteration length in weeks.
10
+ #
11
+ # team_strength float
12
+ # — Iteration team strength, 1.0 is full-strength.
13
+ #
14
+ # story_ids List[int]
15
+ # — Array of stories contained in the iteration. This field is read only. By default this will be included in responses as an array of nested structures, using the key stories. In API responses, this attribute may be story_ids or stories.
16
+ #
17
+ # start datetime
18
+ # — Iteration start time. This field is read only.
19
+ #
20
+ # finish datetime
21
+ # — Iteration finish time. This field is read only.
22
+ #
23
+ # velocity float
24
+ # — The averaged number of points completed over a number of previous iterations, as determined by the project's velocity_averaged_over attribute. This field is read only. This field is excluded by default.
25
+ #
26
+ # points int
27
+ # — The number of points in the iteration. This field is read only. This field is excluded by default.
28
+ #
29
+ # effective_points float
30
+ # — The number of points in the iteration normalized by iteration length and team strength. This field is read only. This field is excluded by default.
31
+ #
32
+ # accepted daily_history_container
33
+ # — The daily summary of stories accepted in this iteration. This field is read only. This field is excluded by default.
34
+ #
35
+ # created daily_history_container
36
+ # — The number of stories created in this iteration by type. This field is read only. This field is excluded by default.
37
+ #
38
+ # analytics analytics
39
+ # — Analytics data for this iteration. This field is read only. This field is excluded by default.
40
+ #
41
+ # kind string
42
+ # — The type of this object: iteration. This field is read only.
43
+
44
+ module PivotalAPI
2
45
  class Iteration < Base
3
46
 
4
- attr_accessor :project_id, :length, :planned, :stories, :story_ids, :number, :team_strength, :finish, :kind, :start
47
+ attr_accessor :project_id, :length, :stories, :story_ids, :number, :team_strength,
48
+ :finish, :kind, :start, :velocity, :points, :effective_points, :analytics
49
+
50
+ def self.fields
51
+ ['velocity', 'points', 'effective_points', 'analytics', "stories(#{Story.fields.join(',')})", 'team_strength',
52
+ 'project_id', 'length', 'start', 'finish']
53
+ end
54
+
55
+ def self.from_json(json)
56
+ parse_json_iteration(json)
57
+ end
58
+
59
+ protected
5
60
 
6
- def self.parse_json_iteration(json_iteration, include_done)
61
+ def self.parse_json_iteration(json_iteration)
7
62
  new({
8
63
  project_id: json_iteration[:project_id].to_i,
9
- stories: parse_stories(json_iteration[:stories], json_iteration[:project_id].to_i, include_done),
64
+ stories: Stories.from_json(json_iteration[:stories]),
10
65
  story_ids: json_iteration[:story_ids],
11
66
  number: json_iteration[:number],
12
67
  team_strength: json_iteration[:team_strength],
@@ -16,14 +71,21 @@ module Scorer
16
71
  })
17
72
  end
18
73
 
74
+ end
75
+
76
+ class Iterations < Iteration
77
+
78
+ def self.from_json(json)
79
+ parse_json_iterations(json)
80
+ end
81
+
19
82
  protected
20
-
21
- def self.parse_stories(stories, project_id, include_done)
22
- story_ids = Array.new
23
- stories.each { |story| story_ids << story[:id].to_i if !story[:id].nil? }
24
- project = PivotalService.one_project(project_id)
25
- PivotalService.stories(project, true, story_ids, Scorer::Story.fields, include_done)
83
+
84
+ def self.parse_json_iterations(json_iterations)
85
+ iterations = []
86
+ json_iterations.each { |iteration| iterations << parse_json_iteration(iteration) }
87
+ iterations
26
88
  end
27
-
89
+
28
90
  end
29
91
  end
@@ -0,0 +1,32 @@
1
+ # PROPERTIES
2
+ # id int
3
+ # — Database id of the label. This field is read only. This field is always returned.
4
+ #
5
+ # project_id int
6
+ # — id of the project. This field is read only.
7
+ #
8
+ # name string[255]
9
+ # Required — The label's name.
10
+ #
11
+ # created_at datetime
12
+ # — Creation time. This field is read only.
13
+ #
14
+ # updated_at datetime
15
+ # — Time of last update. This field is read only.
16
+ #
17
+ # counts story_counts
18
+ # — Summary of numbers of stories and points contained. This field is read only. This field is excluded by default.
19
+ #
20
+ # kind string
21
+ # — The type of this object: label. This field is read only.
22
+
23
+ module PivotalAPI
24
+ class Label < Base
25
+
26
+ attr_accessor :id, :project_id, :name, :created_at, :updated_at, :counts, :kind
27
+
28
+ end
29
+
30
+ class Labels < Label
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ module PivotalAPI
2
+ class Me < Person
3
+
4
+ attr_accessor :api_token, :updated_at, :created_at, :has_google_identity,
5
+ :projects, :receives_in_app_notifications, :time_zone
6
+
7
+ def self.retrieve(username, password)
8
+ Service.me(username, password)
9
+ end
10
+
11
+ def projects
12
+ Projects.retrieve()
13
+ end
14
+
15
+ end
16
+ end
@@ -1,21 +1,25 @@
1
- module Scorer
1
+ module PivotalAPI
2
2
  class Person < Base
3
3
 
4
- attr_accessor :name, :id, :initials, :email, :username
4
+ attr_accessor :name, :id, :initials, :email, :username, :kind
5
5
 
6
6
  def self.fields
7
- ['name', 'id', 'initials', 'email', 'username']
7
+ ['name', 'id', 'initials', 'email', 'username', 'kind']
8
8
  end
9
9
 
10
- def self.parse_json_person(json_person)
10
+ def self.unknown
11
11
  new({
12
- id: json_person[:id].to_i,
13
- name: json_person[:name],
14
- initials: json_person[:initals],
15
- email: json_person[:email],
16
- username: json_person[:username]
12
+ id: '0',
13
+ name: 'Unkown',
14
+ initials: 'Unkown',
15
+ username: 'Unkown',
16
+ email: 'Unkown',
17
+ kind: 'person'
17
18
  })
18
19
  end
19
20
 
20
21
  end
22
+
23
+ class People < Person
24
+ end
21
25
  end
@@ -1,4 +1,4 @@
1
- module Scorer
1
+ module PivotalAPI
2
2
  class Project < Base
3
3
 
4
4
  attr_accessor :updated_at, :bugs_and_chores_are_estimatable, :enable_planned_mode, :public, :story_ids, :name,
@@ -11,16 +11,18 @@ module Scorer
11
11
  class << self
12
12
 
13
13
  def fields
14
- ['description', 'labels', 'name']
14
+ ['description', 'labels', 'name', 'current_velocity', 'velocity_averaged_over']
15
15
  end
16
16
 
17
- def parse_json_projects(json_projects)
18
- projects = Array.new
19
- json_projects.each do |project|
20
- projects << parse_json_project(project)
21
- end
22
- projects
17
+ def from_json(json)
18
+ parse_json_project(json)
23
19
  end
20
+
21
+ def retrieve(project_id)
22
+ Service.project(project_id: project_id, fields: Project.fields)
23
+ end
24
+
25
+ protected
24
26
 
25
27
  def parse_json_project(project)
26
28
  new({
@@ -28,28 +30,79 @@ module Scorer
28
30
  name: project[:name],
29
31
  week_start_day: project[:week_start_day],
30
32
  point_scale: project[:point_scale],
31
- labels: parse_labels(project[:labels]),
33
+ labels: PivotalAPI::Label.from_json(project[:labels]),
32
34
  iteration_length: project[:iteration_length],
33
35
  current_velocity: project[:current_velocity]
34
36
  })
35
37
  end
36
-
37
- def parse_labels(labels)
38
- parsed_labels = ''
39
- labels.each do |label|
40
- parsed_labels = parsed_labels + "#{label[:name]},"
41
- end
42
- parsed_labels
43
- end
38
+
44
39
  end
45
-
46
- def initialize(attributes={})
47
- update_attributes(attributes)
40
+
41
+ def activity(opts={})
42
+ opts[:project_id] = id
43
+
44
+ Service.activity(opts)
48
45
  end
49
-
50
- def get_labels
51
- self.labels.split(',')
46
+
47
+ def story(opts={})
48
+ opts[:project_id] = id
49
+ opts[:parameters] = {} unless opts[:parameters]
50
+ opts[:parameters][:fields] = Story.fields
51
+
52
+ Service.story(opts)
53
+ end
54
+
55
+ def stories(opts={})
56
+ opts[:project_id] = id
57
+ opts[:parameters] = {} unless opts[:parameters]
58
+ opts[:parameters][:fields] = Story.fields
59
+
60
+ Service.stories(opts)
61
+ end
62
+
63
+ def iterations(opts={})
64
+ opts[:project_id] = id
65
+ opts[:parameters] = {} unless opts[:parameters]
66
+ opts[:fields] = Iteration.fields if opts[:fields].nil?
67
+
68
+ Service.iterations(opts)
69
+ end
70
+
71
+ def current_iteration
72
+ iterations.first
73
+ end
74
+
75
+ def previous_iteration
76
+ iterations(scope: 'done').first
77
+ end
78
+
79
+ def next_iteration
80
+ iterations(scope: 'backlog').first
52
81
  end
53
82
 
54
83
  end
84
+
85
+ class Projects < Project
86
+
87
+ class << self
88
+
89
+ def retrieve()
90
+ Service.projects(fields: Project.fields)
91
+ end
92
+
93
+ def from_json(json)
94
+ parse_json_projects(json)
95
+ end
96
+
97
+ protected
98
+
99
+ def parse_json_projects(json_projects)
100
+ projects = Array.new
101
+ json_projects.each { |project| projects << parse_json_project(project) }
102
+ projects
103
+ end
104
+
105
+ end
106
+
107
+ end
55
108
  end