v2gpti 1.1.9 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/bin/git-deliver +1 -1
  3. data/bin/git-finish +1 -1
  4. data/bin/git-newbug +1 -1
  5. data/bin/git-newfeature +1 -1
  6. data/bin/git-qa +1 -1
  7. data/bin/git-release +1 -1
  8. data/bin/git-report +1 -1
  9. data/bin/git-start +1 -1
  10. data/bin/git-uat +1 -1
  11. data/config_template +16 -0
  12. data/lib/git-pivotal-tracker-integration/command/base.rb +235 -322
  13. data/lib/git-pivotal-tracker-integration/command/configuration.rb +183 -109
  14. data/lib/git-pivotal-tracker-integration/command/deliver.rb +145 -200
  15. data/lib/git-pivotal-tracker-integration/command/finish.rb +70 -63
  16. data/lib/git-pivotal-tracker-integration/command/newbug.rb +36 -39
  17. data/lib/git-pivotal-tracker-integration/command/newfeature.rb +43 -42
  18. data/lib/git-pivotal-tracker-integration/command/release.rb +171 -203
  19. data/lib/git-pivotal-tracker-integration/command/report.rb +33 -36
  20. data/lib/git-pivotal-tracker-integration/command/start.rb +74 -78
  21. data/lib/git-pivotal-tracker-integration/util/git.rb +202 -204
  22. data/lib/git-pivotal-tracker-integration/util/shell.rb +19 -16
  23. data/lib/git-pivotal-tracker-integration/util/story.rb +155 -177
  24. data/lib/git-pivotal-tracker-integration/version-update/gradle.rb +44 -40
  25. data/lib/git-pivotal-tracker-integration.rb +44 -0
  26. data/spec/git-pivotal-tracker-integration/command/configuration_spec.rb +1 -2
  27. data/spec/git-pivotal-tracker-integration/command/finish_spec.rb +1 -1
  28. data/spec/git-pivotal-tracker-integration/command/release_spec.rb +1 -1
  29. data/spec/git-pivotal-tracker-integration/command/start_spec.rb +1 -1
  30. data/spec/git-pivotal-tracker-integration/util/story_spec.rb +21 -32
  31. data/tracker_api/lib/tracker_api/client.rb +241 -0
  32. data/tracker_api/lib/tracker_api/endpoints/activity.rb +38 -0
  33. data/tracker_api/lib/tracker_api/endpoints/comments.rb +27 -0
  34. data/tracker_api/lib/tracker_api/endpoints/epic.rb +17 -0
  35. data/tracker_api/lib/tracker_api/endpoints/epics.rb +20 -0
  36. data/tracker_api/lib/tracker_api/endpoints/file_attachment.rb +18 -0
  37. data/tracker_api/lib/tracker_api/endpoints/iterations.rb +20 -0
  38. data/tracker_api/lib/tracker_api/endpoints/me.rb +17 -0
  39. data/tracker_api/lib/tracker_api/endpoints/memberships.rb +20 -0
  40. data/tracker_api/lib/tracker_api/endpoints/notifications.rb +20 -0
  41. data/tracker_api/lib/tracker_api/endpoints/project.rb +17 -0
  42. data/tracker_api/lib/tracker_api/endpoints/projects.rb +18 -0
  43. data/tracker_api/lib/tracker_api/endpoints/stories.rb +20 -0
  44. data/tracker_api/lib/tracker_api/endpoints/story.rb +37 -0
  45. data/tracker_api/lib/tracker_api/endpoints/tasks.rb +20 -0
  46. data/tracker_api/lib/tracker_api/error.rb +18 -0
  47. data/tracker_api/lib/tracker_api/logger.rb +31 -0
  48. data/tracker_api/lib/tracker_api/resources/account.rb +18 -0
  49. data/tracker_api/lib/tracker_api/resources/activity.rb +24 -0
  50. data/tracker_api/lib/tracker_api/resources/base.rb +71 -0
  51. data/tracker_api/lib/tracker_api/resources/change.rb +15 -0
  52. data/tracker_api/lib/tracker_api/resources/comment.rb +20 -0
  53. data/tracker_api/lib/tracker_api/resources/epic.rb +17 -0
  54. data/tracker_api/lib/tracker_api/resources/file_attachment.rb +23 -0
  55. data/tracker_api/lib/tracker_api/resources/iteration.rb +24 -0
  56. data/tracker_api/lib/tracker_api/resources/label.rb +14 -0
  57. data/tracker_api/lib/tracker_api/resources/me.rb +21 -0
  58. data/tracker_api/lib/tracker_api/resources/membership_summary.rb +15 -0
  59. data/tracker_api/lib/tracker_api/resources/notification.rb +26 -0
  60. data/tracker_api/lib/tracker_api/resources/person.rb +14 -0
  61. data/tracker_api/lib/tracker_api/resources/primary_resource.rb +13 -0
  62. data/tracker_api/lib/tracker_api/resources/project.rb +131 -0
  63. data/tracker_api/lib/tracker_api/resources/project_membership.rb +16 -0
  64. data/tracker_api/lib/tracker_api/resources/story.rb +102 -0
  65. data/tracker_api/lib/tracker_api/resources/task.rb +16 -0
  66. data/tracker_api/lib/tracker_api/resources/time_zone.rb +13 -0
  67. data/tracker_api/lib/tracker_api/version.rb +3 -0
  68. data/tracker_api/lib/tracker_api.rb +60 -0
  69. metadata +202 -53
  70. data/lib/git-pivotal-tracker-integration/command/command.rb +0 -20
  71. data/lib/git-pivotal-tracker-integration/util/util.rb +0 -20
  72. data/lib/git-pivotal-tracker-integration/version-update/version_update.rb +0 -20
  73. data/lib/git_pivotal_tracker_integration.rb +0 -18
@@ -0,0 +1,20 @@
1
+ module TrackerApi
2
+ module Endpoints
3
+ class Tasks
4
+ attr_accessor :client
5
+
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def get(project_id, story_id, params={})
11
+ data = client.paginate("/projects/#{project_id}/stories/#{story_id}/tasks", params: params)
12
+ raise TrackerApi::Errors::UnexpectedData, 'Array of tasks expected' unless data.is_a? Array
13
+
14
+ data.map do |task|
15
+ Resources::Task.new({ story_id: story_id }.merge(task))
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module TrackerApi
2
+ class Error < StandardError
3
+ attr_reader :wrapped_exception, :response
4
+
5
+ def initialize(wrapped_exception)
6
+ @wrapped_exception = wrapped_exception
7
+ @response = wrapped_exception.response
8
+ message = if wrapped_exception.is_a?(Faraday::Error::ParsingError)
9
+ wrapped_exception.message
10
+ elsif wrapped_exception.is_a?(Faraday::Error::ClientError)
11
+ wrapped_exception.response.inspect
12
+ else
13
+ wrapped_exception.instance_variable_get(:@wrapped_exception).inspect
14
+ end
15
+ super(message)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ module TrackerApi
2
+ class Logger < Faraday::Response::Middleware
3
+ extend Forwardable
4
+
5
+ def initialize(app, logger = nil)
6
+ super(app)
7
+ @logger = logger || ::Logger.new(STDOUT)
8
+ end
9
+
10
+ def_delegators :@logger, :debug, :info, :warn, :error, :fatal
11
+
12
+ def call(env)
13
+ info("#{env[:method]} => #{env[:url].to_s}")
14
+ debug('request') { dump_headers env[:request_headers] }
15
+ debug('request.body') { env[:body] }
16
+ super
17
+ end
18
+
19
+ def on_complete(env)
20
+ info("#{env[:status]} <= #{env[:url].to_s}")
21
+ debug('response') { dump_headers env[:response_headers] }
22
+ debug('response.body') { env[:body] }
23
+ end
24
+
25
+ private
26
+
27
+ def dump_headers(headers)
28
+ headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,18 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Account
4
+ include Virtus.model
5
+
6
+ attribute :id, Integer
7
+ attribute :created_at, DateTime
8
+ attribute :status, String
9
+ attribute :kind, String
10
+ attribute :name, String
11
+ attribute :updated_at, DateTime
12
+ attribute :url, String
13
+ attribute :plan, String
14
+ attribute :days_left, Integer
15
+ attribute :over_the_limit, Boolean
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Activity
4
+ include Virtus.model
5
+
6
+ attribute :client
7
+
8
+ attribute :kind, String
9
+ attribute :guid, String
10
+ attribute :project_version, Integer
11
+ attribute :message, String
12
+ attribute :highlight, String
13
+ attribute :changes, Array[TrackerApi::Resources::Change]
14
+ attribute :primary_resources, Array[TrackerApi::Resources::PrimaryResource]
15
+ attribute :project, TrackerApi::Resources::Project
16
+ attribute :performed_by, TrackerApi::Resources::Person
17
+ attribute :occurred_at, DateTime
18
+
19
+ def project=(data)
20
+ super.client = client
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,71 @@
1
+ require 'virtus'
2
+ require 'active_support/concern'
3
+ require 'active_model'
4
+
5
+ module TrackerApi
6
+ module Resources
7
+ module Base
8
+ extend ActiveSupport::Concern
9
+
10
+ include ActiveModel::Model
11
+ include ActiveModel::Dirty
12
+
13
+ included do
14
+ include Virtus.model
15
+ include OverrideAttributes
16
+
17
+ attribute :id, Integer
18
+
19
+ def initialize(attrs)
20
+ super
21
+
22
+ # always reset dirty tracking on initialize
23
+ clear_changes_information
24
+ end
25
+
26
+ private
27
+
28
+ # @return [Hash] key value pairs for just the changed attributes with their new values.
29
+ def just_changes
30
+ # @see changes in ActiveModel::Dirty in active_model/dirty.rb
31
+ # { attr => [original value, new value] }
32
+ changes.inject({}) do |h, (k, v)|
33
+ h[k] = v[1]; h;
34
+ end
35
+ end
36
+ end
37
+
38
+ module OverrideAttributes
39
+ extend ActiveSupport::Concern
40
+
41
+ module ClassMethods
42
+ def attribute(name, type, options = {})
43
+ define_attribute_methods name
44
+
45
+ attribute = super
46
+ create_writer_with_dirty_tracking(name)
47
+ attribute
48
+ end
49
+
50
+ private
51
+
52
+ def create_writer_with_dirty_tracking(name)
53
+ method_str = <<-RUBY
54
+ def #{name}=(value)
55
+ prev_value = #{name}
56
+ new_value = value
57
+ if prev_value != new_value
58
+ #{name}_will_change!
59
+ new_value = super(value)
60
+ end
61
+ new_value
62
+ end
63
+ RUBY
64
+
65
+ class_eval method_str, __FILE__, __LINE__ + 1
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,15 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Change
4
+ include Virtus.model
5
+
6
+ attribute :change_type, String
7
+ attribute :id, Integer
8
+ attribute :kind, String
9
+ attribute :name, String
10
+ attribute :new_values, Hash
11
+ attribute :original_values, Hash
12
+ attribute :story_type, String
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Comment
4
+ include Virtus.model
5
+
6
+ attribute :id, Integer
7
+ attribute :story_id, Integer
8
+ attribute :epic_id, Integer
9
+ attribute :text, String
10
+ attribute :person_id, Integer
11
+ attribute :created_at, DateTime
12
+ attribute :updated_at, DateTime
13
+ attribute :file_attachment_ids, Array[Integer]
14
+ attribute :google_attachment_ids, Array[Integer]
15
+ attribute :commit_identifier, String
16
+ attribute :commit_type, String
17
+ attribute :kind, String
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Epic
4
+ include Virtus.model
5
+
6
+ attribute :id, Integer
7
+ attribute :created_at, DateTime
8
+ attribute :description, String
9
+ attribute :kind, String
10
+ attribute :label, TrackerApi::Resources::Label
11
+ attribute :name, String
12
+ attribute :project_id, Integer
13
+ attribute :updated_at, DateTime
14
+ attribute :url, String
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class FileAttachment
4
+ include Virtus.model
5
+
6
+ attribute :id, Integer
7
+ attribute :filename, String
8
+ attribute :created_at, DateTime
9
+ attribute :uploader_id, Integer
10
+ attribute :thumbnailable, Boolean
11
+ attribute :height, Integer
12
+ attribute :width, Integer
13
+ attribute :size, Integer
14
+ attribute :download_url, String
15
+ attribute :content_type, String
16
+ attribute :uploaded, Boolean
17
+ attribute :big_url, String
18
+ attribute :thumbnail_url, String
19
+ attribute :kind, String
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Iteration
4
+ include Virtus.model
5
+
6
+ attribute :client
7
+
8
+ attribute :finish, DateTime
9
+ attribute :kind, String
10
+ attribute :length, Integer
11
+ attribute :number, Integer
12
+ attribute :planned, Boolean
13
+ attribute :project_id, Integer
14
+ attribute :start, DateTime
15
+ attribute :stories, [TrackerApi::Resources::Story]
16
+ attribute :story_ids, [Integer]
17
+ attribute :team_strength, Float
18
+
19
+ def stories=(data)
20
+ super.each { |s| s.client = client }
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Label
4
+ include Virtus.model
5
+
6
+ attribute :id, Integer
7
+ attribute :created_at, DateTime
8
+ attribute :kind, String
9
+ attribute :name, String
10
+ attribute :project_id, Integer
11
+ attribute :updated_at, DateTime
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Me
4
+ include Virtus.model
5
+
6
+ attribute :id, Integer
7
+ attribute :name, String
8
+ attribute :initials, String
9
+ attribute :username, String
10
+ attribute :time_zone, TrackerApi::Resources::TimeZone
11
+ attribute :api_token, String
12
+ attribute :has_google_identity, Boolean
13
+ attribute :project_ids, Array[Integer]
14
+ attribute :projects, [TrackerApi::Resources::MembershipSummary]
15
+ attribute :workspace_ids, Array[Integer]
16
+ attribute :email, String
17
+ attribute :receives_in_app_notifications, Boolean
18
+ attribute :kind, String
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class MembershipSummary
4
+ include Virtus.model
5
+
6
+ attribute :id, Integer
7
+ attribute :kind, String
8
+ attribute :last_viewed_at, DateTime
9
+ attribute :project_color, String
10
+ attribute :project_id, Integer
11
+ attribute :project_name, String
12
+ attribute :role, String
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Notification
4
+ include Virtus.model
5
+
6
+ attribute :client
7
+
8
+ attribute :id, Integer
9
+ attribute :message, String
10
+ attribute :kind, String
11
+ attribute :project, TrackerApi::Resources::Project
12
+ attribute :story, TrackerApi::Resources::Story
13
+ attribute :performer, TrackerApi::Resources::Person
14
+ attribute :created_at, DateTime
15
+ attribute :updated_at, DateTime
16
+
17
+ def project=(data)
18
+ super.client = client
19
+ end
20
+
21
+ def story=(data)
22
+ super.client = client
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,14 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Person
4
+ include Virtus.model
5
+
6
+ attribute :kind, String
7
+ attribute :id, Integer
8
+ attribute :name, String
9
+ attribute :email, String
10
+ attribute :initials, String
11
+ attribute :username, String
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class PrimaryResource
4
+ include Virtus.model
5
+
6
+ attribute :id, Integer
7
+ attribute :kind, String
8
+ attribute :name, String
9
+ attribute :story_type, String
10
+ attribute :url, String
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,131 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Project
4
+ include Virtus.model
5
+
6
+ attribute :client
7
+
8
+ attribute :account, TrackerApi::Resources::Account
9
+ attribute :account_id, Integer
10
+ attribute :atom_enabled, Boolean
11
+ attribute :bugs_and_chores_are_estimatable, Boolean
12
+ attribute :created_at, DateTime
13
+ attribute :current_iteration_number, Integer
14
+ attribute :current_velocity, Integer
15
+ attribute :description, String
16
+ attribute :enable_following, Boolean
17
+ attribute :enable_incoming_emails, Boolean
18
+ attribute :enable_planned_mode, Boolean
19
+ attribute :enable_tasks, Boolean
20
+ attribute :epic_ids, Array[Integer]
21
+ attribute :epics, Array[TrackerApi::Resources::Epic]
22
+ attribute :has_google_domain, Boolean
23
+ attribute :id, Integer
24
+ attribute :initial_velocity, Integer
25
+ attribute :iteration_length, Integer
26
+ attribute :kind, String
27
+ attribute :label_ids, Array[Integer]
28
+ attribute :labels, Array[TrackerApi::Resources::Label]
29
+ attribute :name, String
30
+ attribute :number_of_done_iterations_to_show, Integer
31
+ attribute :point_scale, String
32
+ attribute :point_scale_is_custom, Boolean
33
+ attribute :profile_content, String
34
+ attribute :public, Boolean
35
+ attribute :start_date, DateTime
36
+ attribute :start_time, DateTime
37
+ attribute :time_zone, TrackerApi::Resources::TimeZone
38
+ attribute :updated_at, DateTime
39
+ attribute :velocity_averaged_over, Integer
40
+ attribute :version, Integer
41
+ attribute :week_start_day, String
42
+
43
+ # @return [String] comma separated list of labels
44
+ def label_list
45
+ @label_list ||= labels.collect(&:name).join(',')
46
+ end
47
+
48
+ # @param [Hash] params
49
+ # @return [Array[Epic]] epics associated with this project
50
+ def epics(params={})
51
+ raise ArgumentError, 'Expected @epics to be an Array' unless @epics.is_a? Array
52
+ return @epics unless @epics.empty?
53
+
54
+ @epics = Endpoints::Epics.new(client).get(id, params)
55
+ end
56
+
57
+ # @param [Hash] params
58
+ # @option params [String] :scope Restricts the state of iterations to return.
59
+ # If not specified, it defaults to all iterations including done.
60
+ # Valid enumeration values: done, current, backlog, current_backlog.
61
+ # @option params [Integer] :number The iteration to retrieve, starting at 1
62
+ # @option params [Integer] :offset The offset of first iteration to return, relative to the
63
+ # set of iterations specified by 'scope', with zero being the first iteration in the scope.
64
+ # @option params [Integer] :limit The number of iterations to return relative to the offset.
65
+ # @return [Array[Iteration]] iterations associated with this project
66
+ def iterations(params = {})
67
+ if params.include?(:number)
68
+ number = params[:number].to_i
69
+ raise ArgumentError, ':number must be > 0' unless number > 0
70
+
71
+ params = params.merge(auto_paginate: false, limit: 1)
72
+ params.delete(:number)
73
+
74
+ offset = number - 1
75
+ params[:offset] = offset if offset > 0
76
+ end
77
+
78
+ Endpoints::Iterations.new(client).get(id, params)
79
+ end
80
+
81
+ # @param [Hash] params
82
+ # @option params [String] :with_label A label name which all returned stories must match.
83
+ # @option params [String] :with_state A story's current_state which all returned stories must match.
84
+ # Valid enumeration values: accepted, delivered, finished, started, rejected, unstarted, unscheduled
85
+ # @option params [String] :filter This parameter supplies a search string;
86
+ # only stories that match the search criteria are returned.
87
+ # Cannot be used together with any other parameters except limit and offset.
88
+ # ex) state:started requester:OWK label:"jedi stuff" keyword
89
+ # @option params [Integer] :offset With the first story in your priority list as 0,
90
+ # the index of the first story you want returned.
91
+ # @option params [Integer] :limit The number of stories you want returned.
92
+ # @return [Array[Story]] stories associated with this project
93
+ def stories(params = {})
94
+ Endpoints::Stories.new(client).get(id, params)
95
+ end
96
+
97
+ # @param [Hash] params
98
+ # @return [Array[ProjectMembership]] memberships of this project
99
+ def memberships(params = {})
100
+ Endpoints::Memberships.new(client).get(id, params)
101
+ end
102
+
103
+ # Provides a list of all the activity performed on a project.
104
+ #
105
+ # @param [Hash] params
106
+ # @return [Array[Activity]]
107
+ def activity(params = {})
108
+ Endpoints::Activity.new(client).get_project(id, params)
109
+ end
110
+
111
+ # @param [Fixnum] story_id id of story to get
112
+ # @return [Story] story with given id
113
+ def story(story_id)
114
+ Endpoints::Story.new(client).get(id, story_id)
115
+ end
116
+
117
+ # @param [Hash] params attributes to create the story with
118
+ # @return [Story] newly created Story
119
+ def create_story(params)
120
+ Endpoints::Story.new(client).create(id, params)
121
+ end
122
+
123
+ # @file_name [String] name of the file to be uploaded. Full path to be specified
124
+ # @content_type [String] content type of the file.
125
+ # @return [FileAttachment] newly created FileAttachment.
126
+ def add_attachment(file_name, content_type)
127
+ Endpoints::FileAttachment.new(client).create(id, file_name, content_type)
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,16 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class ProjectMembership
4
+ include Virtus.model
5
+
6
+ attribute :id, Integer
7
+ attribute :person_id, Integer
8
+ attribute :project_id, Integer
9
+ attribute :role, String
10
+ attribute :project_color, String
11
+ attribute :wants_comment_notification_emails, Boolean
12
+ attribute :kind, String
13
+ attribute :person, TrackerApi::Resources::Person
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,102 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Story
4
+ include TrackerApi::Resources::Base
5
+
6
+ attribute :client
7
+
8
+ attribute :accepted_at, DateTime
9
+ attribute :comment_ids, Array[Integer]
10
+ attribute :comments, Array[TrackerApi::Resources::Comment]
11
+ attribute :created_at, DateTime
12
+ attribute :current_state, String # (accepted, delivered, finished, started, rejected, planned, unstarted, unscheduled)
13
+ attribute :deadline, DateTime
14
+ attribute :description, String
15
+ attribute :estimate, Float
16
+ attribute :external_id, String
17
+ attribute :follower_ids, Array[Integer]
18
+ attribute :integration_id, Integer
19
+ attribute :kind, String
20
+ attribute :label_ids, Array[Integer]
21
+ attribute :labels, Array[TrackerApi::Resources::Label]
22
+ attribute :name, String
23
+ attribute :owned_by_id, Integer # deprecated!
24
+ attribute :owner_ids, Array[Integer]
25
+ attribute :owners, Array[TrackerApi::Resources::Person]
26
+ attribute :planned_iteration_number, Integer
27
+ attribute :project_id, Integer
28
+ attribute :requested_by_id, Integer
29
+ attribute :story_type, String # (feature, bug, chore, release)
30
+ attribute :task_ids, Array[Integer]
31
+ attribute :tasks, Array[TrackerApi::Resources::Task]
32
+ attribute :updated_at, DateTime
33
+ attribute :url, String
34
+ attribute :before_id, Integer
35
+ attribute :after_id, Integer
36
+
37
+ # @return [String] Comma separated list of labels.
38
+ def label_list
39
+ @label_list ||= labels.collect(&:name).join(',')
40
+ end
41
+
42
+ # Provides a list of all the activity performed on the story.
43
+ #
44
+ # @param [Hash] params
45
+ # @return [Array[Activity]]
46
+ def activity(params = {})
47
+ Endpoints::Activity.new(client).get_story(project_id, id, params)
48
+ end
49
+
50
+ # Provides a list of all the comments on the story.
51
+ #
52
+ # @param [Hash] params
53
+ # @return [Array[Comment]]
54
+ def comments(params = {})
55
+ if @comments.any?
56
+ @comments
57
+ else
58
+ @comments = Endpoints::Comments.new(client).get(project_id, id, params)
59
+ end
60
+ end
61
+
62
+ # @param [Hash] params
63
+ # @return [Array[Task]]
64
+ def tasks(params = {})
65
+ if @tasks.any?
66
+ @tasks
67
+ else
68
+ @tasks = Endpoints::Tasks.new(client).get(project_id, id, params)
69
+ end
70
+ end
71
+
72
+ # Save changes to an existing Story.
73
+ def save
74
+ raise ArgumentError, 'Can not update a story with an unknown project_id.' if project_id.nil?
75
+
76
+ Endpoints::Story.new(client).update(self, just_changes)
77
+
78
+ changes_applied
79
+ end
80
+
81
+ # update labels.This method can also be used to remove labels.
82
+ def add_labels(*new_labels)
83
+ raise ArgumentError, 'Can not update a story with an unknown project_id.' if project_id.nil?
84
+ raise ArgumentError, 'Provide at lease one label name' if new_labels.empty?
85
+
86
+ Endpoints::Story.new(client).update(self, {:labels => new_labels.map{|l| {:name => l.to_s}}})
87
+
88
+ changes_applied
89
+ end
90
+
91
+ # Add an existing attachment to the story
92
+ def add_comment_with_attachment(text, file_attachment)
93
+ raise ArgumentError, 'Can not update a story with an unknown project_id.' if project_id.nil?
94
+
95
+ comment = {:text => text, :file_attachments => [file_attachment.attributes]}
96
+ Endpoints::Comments.new(client).create_with_attachment(project_id, id, text, file_attachment)
97
+
98
+ changes_applied
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,16 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class Task
4
+ include Virtus.model
5
+
6
+ attribute :id, Integer
7
+ attribute :story_id, Integer
8
+ attribute :description, String
9
+ attribute :complete, Boolean
10
+ attribute :position, Integer
11
+ attribute :created_at, DateTime
12
+ attribute :updated_at, DateTime
13
+ attribute :kind, String
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ module TrackerApi
2
+ module Resources
3
+ class TimeZone
4
+ include Virtus.value_object
5
+
6
+ values do
7
+ attribute :offset, String
8
+ attribute :olson_name, String
9
+ attribute :kind, String
10
+ end
11
+ end
12
+ end
13
+ end