v2gpti 1.1.9 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/git-deliver +1 -1
- data/bin/git-finish +1 -1
- data/bin/git-newbug +1 -1
- data/bin/git-newfeature +1 -1
- data/bin/git-qa +1 -1
- data/bin/git-release +1 -1
- data/bin/git-report +1 -1
- data/bin/git-start +1 -1
- data/bin/git-uat +1 -1
- data/config_template +16 -0
- data/lib/git-pivotal-tracker-integration/command/base.rb +235 -322
- data/lib/git-pivotal-tracker-integration/command/configuration.rb +183 -109
- data/lib/git-pivotal-tracker-integration/command/deliver.rb +145 -200
- data/lib/git-pivotal-tracker-integration/command/finish.rb +70 -63
- data/lib/git-pivotal-tracker-integration/command/newbug.rb +36 -39
- data/lib/git-pivotal-tracker-integration/command/newfeature.rb +43 -42
- data/lib/git-pivotal-tracker-integration/command/release.rb +171 -203
- data/lib/git-pivotal-tracker-integration/command/report.rb +33 -36
- data/lib/git-pivotal-tracker-integration/command/start.rb +74 -78
- data/lib/git-pivotal-tracker-integration/util/git.rb +202 -204
- data/lib/git-pivotal-tracker-integration/util/shell.rb +19 -16
- data/lib/git-pivotal-tracker-integration/util/story.rb +155 -177
- data/lib/git-pivotal-tracker-integration/version-update/gradle.rb +44 -40
- data/lib/git-pivotal-tracker-integration.rb +44 -0
- data/spec/git-pivotal-tracker-integration/command/configuration_spec.rb +1 -2
- data/spec/git-pivotal-tracker-integration/command/finish_spec.rb +1 -1
- data/spec/git-pivotal-tracker-integration/command/release_spec.rb +1 -1
- data/spec/git-pivotal-tracker-integration/command/start_spec.rb +1 -1
- data/spec/git-pivotal-tracker-integration/util/story_spec.rb +21 -32
- data/tracker_api/lib/tracker_api/client.rb +241 -0
- data/tracker_api/lib/tracker_api/endpoints/activity.rb +38 -0
- data/tracker_api/lib/tracker_api/endpoints/comments.rb +27 -0
- data/tracker_api/lib/tracker_api/endpoints/epic.rb +17 -0
- data/tracker_api/lib/tracker_api/endpoints/epics.rb +20 -0
- data/tracker_api/lib/tracker_api/endpoints/file_attachment.rb +18 -0
- data/tracker_api/lib/tracker_api/endpoints/iterations.rb +20 -0
- data/tracker_api/lib/tracker_api/endpoints/me.rb +17 -0
- data/tracker_api/lib/tracker_api/endpoints/memberships.rb +20 -0
- data/tracker_api/lib/tracker_api/endpoints/notifications.rb +20 -0
- data/tracker_api/lib/tracker_api/endpoints/project.rb +17 -0
- data/tracker_api/lib/tracker_api/endpoints/projects.rb +18 -0
- data/tracker_api/lib/tracker_api/endpoints/stories.rb +20 -0
- data/tracker_api/lib/tracker_api/endpoints/story.rb +37 -0
- data/tracker_api/lib/tracker_api/endpoints/tasks.rb +20 -0
- data/tracker_api/lib/tracker_api/error.rb +18 -0
- data/tracker_api/lib/tracker_api/logger.rb +31 -0
- data/tracker_api/lib/tracker_api/resources/account.rb +18 -0
- data/tracker_api/lib/tracker_api/resources/activity.rb +24 -0
- data/tracker_api/lib/tracker_api/resources/base.rb +71 -0
- data/tracker_api/lib/tracker_api/resources/change.rb +15 -0
- data/tracker_api/lib/tracker_api/resources/comment.rb +20 -0
- data/tracker_api/lib/tracker_api/resources/epic.rb +17 -0
- data/tracker_api/lib/tracker_api/resources/file_attachment.rb +23 -0
- data/tracker_api/lib/tracker_api/resources/iteration.rb +24 -0
- data/tracker_api/lib/tracker_api/resources/label.rb +14 -0
- data/tracker_api/lib/tracker_api/resources/me.rb +21 -0
- data/tracker_api/lib/tracker_api/resources/membership_summary.rb +15 -0
- data/tracker_api/lib/tracker_api/resources/notification.rb +26 -0
- data/tracker_api/lib/tracker_api/resources/person.rb +14 -0
- data/tracker_api/lib/tracker_api/resources/primary_resource.rb +13 -0
- data/tracker_api/lib/tracker_api/resources/project.rb +131 -0
- data/tracker_api/lib/tracker_api/resources/project_membership.rb +16 -0
- data/tracker_api/lib/tracker_api/resources/story.rb +102 -0
- data/tracker_api/lib/tracker_api/resources/task.rb +16 -0
- data/tracker_api/lib/tracker_api/resources/time_zone.rb +13 -0
- data/tracker_api/lib/tracker_api/version.rb +3 -0
- data/tracker_api/lib/tracker_api.rb +60 -0
- metadata +202 -53
- data/lib/git-pivotal-tracker-integration/command/command.rb +0 -20
- data/lib/git-pivotal-tracker-integration/util/util.rb +0 -20
- data/lib/git-pivotal-tracker-integration/version-update/version_update.rb +0 -20
- data/lib/git_pivotal_tracker_integration.rb +0 -18
@@ -13,361 +13,274 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
#
|
25
|
-
#
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
16
|
+
module GitPivotalTrackerIntegration
|
17
|
+
module Command
|
18
|
+
|
19
|
+
# An abstract base class for all commands
|
20
|
+
# @abstract Subclass and override {#run} to implement command functionality
|
21
|
+
class Base
|
22
|
+
|
23
|
+
# Common initialization functionality for all command classes. This
|
24
|
+
# enforces that:
|
25
|
+
# * the command is being run within a valid Git repository
|
26
|
+
# * the user has specified their Pivotal Tracker API token
|
27
|
+
# * all communication with Pivotal Tracker will be protected with SSL
|
28
|
+
# * the user has configured the project id for this repository
|
29
|
+
def initialize
|
30
|
+
self.start_logging
|
31
|
+
self.check_version
|
32
|
+
|
33
|
+
git_global_push_default = (Util::Shell.exec "git config --global push.default", false).chomp
|
34
|
+
if git_global_push_default != "simple"
|
35
|
+
puts "git config --global push.default simple"
|
36
|
+
puts Util::Shell.exec "git config --global push.default simple"
|
37
|
+
end
|
38
|
+
|
39
|
+
@repository_root = Util::Git.repository_root
|
40
|
+
@toggl = Toggl.new
|
41
|
+
@configuration = Command::Configuration.new
|
42
|
+
|
43
|
+
@configuration.check_for_config_file
|
44
|
+
@configuration.check_for_config_contents
|
45
|
+
|
46
|
+
@client = TrackerApi::Client.new(:token => @configuration.api_token)
|
47
|
+
@platform = @configuration.platform_name
|
48
|
+
|
49
|
+
current_project_id = @configuration.project_id.to_i
|
50
|
+
@project = @client.project current_project_id
|
51
|
+
my_projects = @client.projects
|
52
|
+
|
53
|
+
unless my_projects && my_projects.map(&:id).include?(current_project_id)
|
54
|
+
project_manager_name = @configuration.pconfig["project"]["project-manager"]
|
55
|
+
project_manager_email = @configuration.pconfig["project"]["project-manager-email"]
|
56
|
+
project_name = @configuration.pconfig["project"]["project-name"]
|
57
|
+
abort "This project requires access to the Pivotal Tracker project [#{project_name} - #{current_project_id}]. Please speak with project manager [#{project_manager_name} - #{project_manager_email}] and ask him to add you to the project in Pivotal Tracker."
|
58
|
+
end
|
59
|
+
end
|
50
60
|
|
51
|
-
|
52
|
-
|
61
|
+
def finish_toggle(configuration, time_spent)
|
62
|
+
current_story = @configuration.story(@project)
|
63
|
+
|
64
|
+
# If a story gets rejected and the developer works on it, then we need to check if the task is already created or not.
|
65
|
+
params = parameters(configuration, time_spent)
|
66
|
+
if params[:tid].nil?
|
67
|
+
begin
|
68
|
+
@toggl.create_task(parameters(configuration, time_spent))
|
69
|
+
rescue TogglException => te
|
70
|
+
puts ""
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#If for some reason time entry cannot be done, then catch exception and continue.
|
75
|
+
begin
|
76
|
+
@toggl.create_time_entry(parameters(configuration, time_spent))
|
77
|
+
rescue TogglException => te
|
78
|
+
puts "Unable to log the time."
|
79
|
+
end
|
80
|
+
end
|
53
81
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
current_project_id = @configuration.project_id.to_i
|
58
|
-
project_manager_name = @configuration.pconfig["project"]["project-manager"]
|
59
|
-
project_manager_email = @configuration.pconfig["project"]["project-manager-email"]
|
60
|
-
project_name = @configuration.pconfig["project"]["project-name"]
|
61
|
-
abort "This project requires access to the Pivotal Tracker project [#{project_name} - #{current_project_id}]. Please speak with project manager [#{project_manager_name} - #{project_manager_email}] and ask him to add you to the project in Pivotal Tracker." unless my_all_projects_ids.include?(current_project_id)
|
62
|
-
end
|
82
|
+
def start_logging
|
83
|
+
$LOG = Logger.new("#{logger_filename}", 'weekly')
|
84
|
+
end
|
63
85
|
|
64
|
-
|
65
|
-
|
86
|
+
def logger_filename
|
87
|
+
return "#{Dir.home}/.v2gpti_local.log"
|
88
|
+
end
|
66
89
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
90
|
+
def check_version
|
91
|
+
gem_latest_version = (Util::Shell.exec "gem list v2gpti --remote")[/\(.*?\)/].delete "()"
|
92
|
+
gem_installed_version = Gem.loaded_specs["v2gpti"].version.version
|
93
|
+
if (gem_installed_version == gem_latest_version)
|
94
|
+
$LOG.info("v2gpti verison #{gem_installed_version} is up to date.")
|
95
|
+
else
|
96
|
+
$LOG.fatal("Out of date")
|
97
|
+
if OS.windows?
|
98
|
+
abort "\n\nYou are using v2gpti version #{gem_installed_version}, but the current version is #{gem_latest_version}.\nPlease update your gem with the following command.\n\n gem update v2gpti\n\n"
|
99
|
+
else
|
100
|
+
abort "\n\nYou are using v2gpti version #{gem_installed_version}, but the current version is #{gem_latest_version}.\nPlease update your gem with the following command.\n\n sudo gem update v2gpti\n\n"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
rescue StandardError => se
|
73
104
|
puts ""
|
74
105
|
end
|
75
|
-
end
|
76
106
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def start_logging
|
86
|
-
$LOG = Logger.new("#{logger_filename}", 'weekly')
|
87
|
-
end
|
107
|
+
# The main entry point to the command's execution
|
108
|
+
# @abstract Override this method to implement command functionality
|
109
|
+
def run
|
110
|
+
raise NotImplementedError
|
111
|
+
end
|
88
112
|
|
89
|
-
|
90
|
-
|
91
|
-
|
113
|
+
# Toggl keys
|
114
|
+
# name : The name of the task (string, required, unique in project)
|
115
|
+
# pid : project ID for the task (integer, required)
|
116
|
+
# wid : workspace ID, where the task will be saved (integer, project's workspace id is used when not supplied)
|
117
|
+
# uid : user ID, to whom the task is assigned to (integer, not required)
|
118
|
+
# estimated_seconds : estimated duration of task in seconds (integer, not required)
|
119
|
+
# active : whether the task is done or not (boolean, by default true)
|
120
|
+
# at : timestamp that is sent in the response for PUT, indicates the time task was last updated
|
121
|
+
# -- Additional fields --
|
122
|
+
# done_seconds : duration (in seconds) of all the time entries registered for this task
|
123
|
+
# uname : full name of the person to whom the task is assigned to
|
124
|
+
TIMER_TOKENS = {
|
125
|
+
"m" => (60),
|
126
|
+
"h" => (60 * 60),
|
127
|
+
"d" => (60 * 60 * 8) # a work day is 8 hours
|
128
|
+
}
|
129
|
+
def parameters(configuration, time_spent)
|
130
|
+
current_story = configuration.story(@project)
|
131
|
+
params = Hash.new
|
132
|
+
params[:name] = "#{current_story.id}" + " - " + "#{current_story.name}"
|
133
|
+
params[:estimated_seconds] = estimated_seconds current_story
|
134
|
+
params[:pid] = configuration.toggl_project_id
|
135
|
+
params[:uid] = @toggl.me["id"]
|
136
|
+
params[:tags] = [current_story.story_type]
|
137
|
+
params[:active] = false
|
138
|
+
params[:description] = "#{current_story.id}" + " commit:" + "#{(Util::Shell.exec "git rev-parse HEAD").chomp[0..6]}"
|
139
|
+
params[:created_with] = "v2gpti"
|
140
|
+
params[:duration] = seconds_spent(time_spent)
|
141
|
+
params[:start] = (Time.now - params[:duration]).iso8601
|
142
|
+
task = @toggl.get_project_task_with_name(configuration.toggl_project_id, "#{current_story.id}")
|
143
|
+
if !task.nil?
|
144
|
+
params[:tid] = task['id']
|
145
|
+
end
|
146
|
+
params
|
147
|
+
end
|
148
|
+
def seconds_spent(time_spent)
|
149
|
+
seconds = 0
|
150
|
+
time_spent.scan(/(\d+)(\w)/).each do |amount, measure|
|
151
|
+
seconds += amount.to_i * TIMER_TOKENS[measure]
|
152
|
+
end
|
153
|
+
seconds
|
154
|
+
end
|
155
|
+
def estimated_seconds(story)
|
156
|
+
estimate = story.estimate
|
157
|
+
seconds = 0
|
158
|
+
case estimate
|
159
|
+
when 0
|
160
|
+
estimate = 15 * 60
|
161
|
+
when 1
|
162
|
+
estimate = 1.25 * 60 * 60
|
163
|
+
when 2
|
164
|
+
estimate = 3 * 60 * 60
|
165
|
+
when 3
|
166
|
+
estimate = 8 * 60 * 60
|
167
|
+
else
|
168
|
+
estimate = -1 * 60 * 60
|
169
|
+
end
|
170
|
+
estimate
|
171
|
+
end
|
92
172
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
else
|
103
|
-
abort "\n\nYou are using v2gpti version #{gem_installed_version}, but the current version is #{gem_latest_version}.\nPlease update your gem with the following command.\n\n sudo gem update v2gpti\n\n"
|
104
|
-
end
|
105
|
-
end
|
106
|
-
rescue StandardError => se
|
107
|
-
puts ""
|
108
|
-
end
|
173
|
+
def create_story(args)
|
174
|
+
story_types = {"f" => "feature", "b" => "bug", "c" => "chore"}
|
175
|
+
new_story_type = nil
|
176
|
+
new_story_title = nil
|
177
|
+
new_story_estimate = -1
|
178
|
+
args.each do |arg|
|
179
|
+
new_story_type = story_types[arg[-1]] if arg.include? '-n'
|
180
|
+
new_story_title = arg if arg[0] != "-"
|
181
|
+
end
|
109
182
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
end
|
183
|
+
while new_story_type.nil?
|
184
|
+
nst = ask("Please enter f for feature, b for bug, or c for chore")
|
185
|
+
new_story_type = story_types[nst]
|
186
|
+
end
|
115
187
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
# wid : workspace ID, where the task will be saved (integer, project's workspace id is used when not supplied)
|
120
|
-
# uid : user ID, to whom the task is assigned to (integer, not required)
|
121
|
-
# estimated_seconds : estimated duration of task in seconds (integer, not required)
|
122
|
-
# active : whether the task is done or not (boolean, by default true)
|
123
|
-
# at : timestamp that is sent in the response for PUT, indicates the time task was last updated
|
124
|
-
# -- Additional fields --
|
125
|
-
# done_seconds : duration (in seconds) of all the time entries registered for this task
|
126
|
-
# uname : full name of the person to whom the task is assigned to
|
127
|
-
TIMER_TOKENS = {
|
128
|
-
"m" => (60),
|
129
|
-
"h" => (60 * 60),
|
130
|
-
"d" => (60 * 60 * 8) # a work day is 8 hours
|
131
|
-
}
|
132
|
-
def parameters(configuration, time_spent)
|
133
|
-
current_story = configuration.story(@project)
|
134
|
-
params = Hash.new
|
135
|
-
params[:name] = "#{current_story.id}" + " - " + "#{current_story.name}"
|
136
|
-
params[:estimated_seconds] = estimated_seconds current_story
|
137
|
-
params[:pid] = configuration.toggl_project_id
|
138
|
-
params[:uid] = @toggl.me["id"]
|
139
|
-
params[:tags] = [current_story.story_type]
|
140
|
-
params[:active] = false
|
141
|
-
params[:description] = "#{current_story.id}" + " commit:" + "#{(GitPivotalTrackerIntegration::Util::Shell.exec "git rev-parse HEAD").chomp[0..6]}"
|
142
|
-
params[:created_with] = "v2gpti"
|
143
|
-
params[:duration] = seconds_spent(time_spent)
|
144
|
-
params[:start] = (Time.now - params[:duration]).iso8601
|
145
|
-
task = @toggl.get_project_task_with_name(configuration.toggl_project_id, "#{current_story.id}")
|
146
|
-
if !task.nil?
|
147
|
-
params[:tid] = task['id']
|
148
|
-
end
|
149
|
-
params
|
150
|
-
end
|
151
|
-
def seconds_spent(time_spent)
|
152
|
-
seconds = 0
|
153
|
-
time_spent.scan(/(\d+)(\w)/).each do |amount, measure|
|
154
|
-
seconds += amount.to_i * TIMER_TOKENS[measure]
|
155
|
-
end
|
156
|
-
seconds
|
157
|
-
end
|
158
|
-
def estimated_seconds(story)
|
159
|
-
estimate = story.estimate
|
160
|
-
seconds = 0
|
161
|
-
case estimate
|
162
|
-
when 0
|
163
|
-
estimate = 15 * 60
|
164
|
-
when 1
|
165
|
-
estimate = 1.25 * 60 * 60
|
166
|
-
when 2
|
167
|
-
estimate = 3 * 60 * 60
|
168
|
-
when 3
|
169
|
-
estimate = 8 * 60 * 60
|
170
|
-
else
|
171
|
-
estimate = -1 * 60 * 60
|
172
|
-
end
|
173
|
-
estimate
|
174
|
-
end
|
188
|
+
while (new_story_title.nil? || new_story_title.empty?)
|
189
|
+
new_story_title = ask("Please enter the title for this #{new_story_type}.")
|
190
|
+
end
|
175
191
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
new_story_title = nil
|
180
|
-
new_story_estimate = -1
|
181
|
-
args.each do |arg|
|
182
|
-
new_story_type = story_types[arg[-1]] if arg.include? '-n'
|
183
|
-
new_story_title = arg if arg[0] != "-"
|
184
|
-
end
|
192
|
+
if (new_story_type == "feature" && (new_story_estimate < 0 || new_story_estimate > 3))
|
193
|
+
new_story_estimate = estimate_story
|
194
|
+
end
|
185
195
|
|
186
|
-
|
187
|
-
|
188
|
-
new_story_type = story_types[nst]
|
189
|
-
end
|
196
|
+
attrs = {:story_type => new_story_type, :current_state => 'unstarted', :name => new_story_title}
|
197
|
+
attrs[:estimate] = new_story_estimate if new_story_type == "feature"
|
190
198
|
|
191
|
-
|
192
|
-
new_story_title = ask("Please enter the title for this #{new_story_type}.")
|
193
|
-
end
|
199
|
+
@project.create_story(attrs)
|
194
200
|
|
195
|
-
while (new_story_type == "feature" && (new_story_estimate < 0 || new_story_estimate > 3))
|
196
|
-
nse = ask("Please enter an estimate for this #{new_story_type}. (0,1,2,3)")
|
197
|
-
if !nse.empty?
|
198
|
-
new_story_estimate = nse.to_i
|
199
201
|
end
|
200
|
-
end
|
201
202
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
new_story.current_state = "unstarted"
|
206
|
-
new_story.name = new_story_title
|
207
|
-
if new_story_type == "feature"
|
208
|
-
new_story.estimate = new_story_estimate
|
209
|
-
end
|
203
|
+
def create_icebox_bug_story(args)
|
204
|
+
create_story_with_type_state("bug", "unscheduled", args)
|
205
|
+
end
|
210
206
|
|
211
|
-
|
207
|
+
def create_backlog_bug_story(args)
|
208
|
+
create_story_with_type_state("bug", "unstarted", args)
|
209
|
+
end
|
212
210
|
|
213
|
-
|
211
|
+
def create_icebox_feature_story(args)
|
212
|
+
create_story_with_type_state("feature", "unscheduled", args)
|
213
|
+
end
|
214
214
|
|
215
|
-
|
216
|
-
|
217
|
-
args.each do |arg|
|
218
|
-
new_bug_story_title = arg if arg[0] != "-"
|
215
|
+
def create_backlog_feature_story(args)
|
216
|
+
create_story_with_type_state("feature", "unstarted", args)
|
219
217
|
end
|
220
|
-
while (new_bug_story_title.nil? || new_bug_story_title.empty?)
|
221
|
-
new_bug_story_title = ask("Please enter the title for this bug story")
|
222
|
-
end
|
223
|
-
icebox_stories = Array.new
|
224
|
-
@project.stories.all.collect{|story| icebox_stories.push story if story.current_state == "unscheduled"}
|
225
|
-
new_bug_story = PivotalTracker::Story.new
|
226
|
-
new_bug_story.project_id = @project.id
|
227
|
-
new_bug_story.story_type = "bug"
|
228
|
-
new_bug_story.current_state = "unscheduled"
|
229
|
-
new_bug_story.name = new_bug_story_title
|
230
|
-
|
231
|
-
if args.any?{|arg| arg.include?("-tl") } && !(icebox_stories.empty? || icebox_stories.nil?)
|
232
|
-
icebox_first_story = icebox_stories.first
|
233
|
-
(new_bug_story.create).move(:before, icebox_first_story)
|
234
|
-
elsif args.any?{|arg| arg.include?("-bl")} && !(icebox_stories.empty? || icebox_stories.nil?)
|
235
|
-
icebox_last_story = icebox_stories.last
|
236
|
-
(new_bug_story.create).move(:after, icebox_last_story)
|
237
|
-
else
|
238
|
-
new_bug_story.create
|
239
|
-
end
|
240
|
-
end
|
241
218
|
|
242
|
-
|
243
|
-
new_bug_story_title = nil
|
244
|
-
args.each do |arg|
|
245
|
-
new_bug_story_title = arg if arg[0] != "-"
|
246
|
-
end
|
247
|
-
while (new_bug_story_title.nil? || new_bug_story_title.empty?)
|
248
|
-
new_bug_story_title = ask("Please enter the title for this bug story")
|
249
|
-
end
|
250
|
-
backlog_stories = Array.new
|
251
|
-
@project.stories.all.collect{|story| backlog_stories.push story if story.current_state == "unstarted" && story.story_type != "release"}
|
252
|
-
new_bug_story = PivotalTracker::Story.new
|
253
|
-
new_bug_story.project_id = @project.id
|
254
|
-
new_bug_story.story_type = "bug"
|
255
|
-
new_bug_story.current_state = "unstarted"
|
256
|
-
new_bug_story.name = new_bug_story_title
|
257
|
-
if args.any?{|arg| arg.include?("-tl")} && !(backlog_stories.empty? || backlog_stories.nil?)
|
258
|
-
backlog_first_story = backlog_stories.first
|
259
|
-
(new_bug_story.create).move(:before, backlog_first_story)
|
260
|
-
elsif args.any?{|arg| arg.include?("-bl")} && !(backlog_stories.empty? || backlog_stories.nil?)
|
261
|
-
backlog_last_story = backlog_stories.last
|
262
|
-
(new_bug_story.create).move(:after, backlog_last_story)
|
263
|
-
else
|
264
|
-
new_bug_story.create
|
265
|
-
end
|
266
|
-
end
|
219
|
+
private
|
267
220
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
args.each do |arg|
|
272
|
-
new_feature_story_title = arg if arg[0] != "-"
|
273
|
-
end
|
274
|
-
while (new_feature_story_title.nil? || new_feature_story_title.empty?)
|
275
|
-
new_feature_story_title = ask("\nPlease enter the title for this feature story")
|
221
|
+
def pwd
|
222
|
+
command = OS.windows? ? 'echo %cd%': 'pwd'
|
223
|
+
Util::Shell.exec(command).chop
|
276
224
|
end
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
args.each do |arg|
|
286
|
-
new_feature_story_points = arg[2] if arg[0] == "-" && arg[1].downcase == "p"
|
287
|
-
end
|
288
|
-
while (new_feature_story_points.nil? || new_feature_story_points.empty?)
|
289
|
-
new_feature_story_points = ask("\nPlease enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n")
|
290
|
-
end
|
291
|
-
while (!["0","1","2","3","n"].include?(new_feature_story_points.downcase))
|
292
|
-
new_feature_story_points = ask("\nInvalid entry...Please enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n")
|
225
|
+
|
226
|
+
def estimate_story
|
227
|
+
estimate = ask("Please enter the estimate points(0/1/2/3) for this story.") do |q|
|
228
|
+
q.in = ["0", "1", "2", "3"]
|
229
|
+
q.responses[:not_in_range] = "Invalid entry...Please enter the estimate points(0/1/2/3) for this story."
|
230
|
+
end
|
231
|
+
estimate.to_i
|
293
232
|
end
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
233
|
+
|
234
|
+
def estimate_story_optional
|
235
|
+
estimate = ask("Please enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n") do |q|
|
236
|
+
q.in = ["0", "1", "2", "3", "n"]
|
237
|
+
q.responses[:not_in_range] = "Invalid entry...Please enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n"
|
238
|
+
end
|
239
|
+
if estimate == "n"
|
240
|
+
estimate = nil
|
241
|
+
else
|
242
|
+
estimate.to_i
|
243
|
+
end
|
298
244
|
end
|
299
245
|
|
246
|
+
def create_story_with_type_state(type, state, args)
|
247
|
+
story_title = nil
|
248
|
+
story_points = nil
|
300
249
|
|
301
|
-
|
302
|
-
icebox_first_story = icebox_stories.first
|
303
|
-
(new_feature_story.create).move(:before, icebox_first_story)
|
304
|
-
elsif args.any?{|arg| arg.include?("-bl")} && !(icebox_stories.empty? || icebox_stories.nil?)
|
305
|
-
icebox_last_story = icebox_stories.last
|
306
|
-
(new_feature_story.create).move(:after, icebox_last_story)
|
307
|
-
else
|
308
|
-
new_feature_story.create
|
309
|
-
end
|
310
|
-
end
|
250
|
+
args.each {|arg| story_title = arg if arg[0] != "-" }
|
311
251
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
args.each do |arg|
|
316
|
-
new_feature_story_title = arg if arg[0] != "-"
|
317
|
-
end
|
318
|
-
while (new_feature_story_title.nil? || new_feature_story_title.empty?)
|
319
|
-
new_feature_story_title = ask("\nPlease enter the title for this feature story")
|
320
|
-
end
|
321
|
-
backlog_stories = Array.new
|
322
|
-
@project.stories.all.collect{|story| backlog_stories.push story if story.current_state == "unstarted" && story.story_type != "release"}
|
323
|
-
new_feature_story = PivotalTracker::Story.new
|
324
|
-
new_feature_story.project_id = @project.id
|
325
|
-
new_feature_story.story_type = "feature"
|
326
|
-
new_feature_story.current_state = "unstarted"
|
327
|
-
new_feature_story.name = new_feature_story_title
|
328
|
-
|
329
|
-
args.each do |arg|
|
330
|
-
new_feature_story_points = arg[2] if arg[0] == "-" && arg[1].downcase == "p"
|
331
|
-
end
|
332
|
-
while (new_feature_story_points.nil? || new_feature_story_points.empty?)
|
333
|
-
new_feature_story_points = ask("\nPlease enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n")
|
334
|
-
end
|
335
|
-
while (!["0","1","2","3","n"].include?(new_feature_story_points.downcase))
|
336
|
-
new_feature_story_points = ask("\nInvalid entry...Please enter the estimate points(0/1/2/3) for this feature story.\nIf you don't want to estimate then enter n")
|
337
|
-
end
|
338
|
-
if new_feature_story_points.downcase == "n"
|
339
|
-
new_feature_story.estimate = -1
|
340
|
-
else
|
341
|
-
new_feature_story.estimate = new_feature_story_points
|
342
|
-
end
|
252
|
+
while (story_title.nil? || story_title.empty?)
|
253
|
+
story_title = ask("Please enter the title for the story")
|
254
|
+
end
|
343
255
|
|
344
|
-
|
345
|
-
backlog_first_story = backlog_stories.first
|
346
|
-
(new_feature_story.create).move(:before, backlog_first_story)
|
347
|
-
elsif args.any?{|arg| arg.include?("-bl")} && !(backlog_stories.empty? || backlog_stories.nil?)
|
348
|
-
backlog_last_story = backlog_stories.last
|
349
|
-
(new_feature_story.create).move(:after, backlog_last_story)
|
350
|
-
else
|
351
|
-
new_feature_story.create
|
352
|
-
end
|
353
|
-
end
|
256
|
+
story_params = {:story_type => type, :current_state => state, :name => story_title}
|
354
257
|
|
355
|
-
|
258
|
+
# if it is a feature, get the estimate for the story.
|
259
|
+
# if it is not provided in the command line, ask for it
|
260
|
+
if type == "feature" #set the story points if it is feature story
|
261
|
+
args.each do |arg|
|
262
|
+
story_points = arg[2] if arg[0] == "-" && arg[1].downcase == "p"
|
263
|
+
end
|
264
|
+
story_points = estimate_story_optional if story_points.nil? || story_points.empty?
|
265
|
+
story_params[:estimate] = story_points unless story_points.nil?
|
266
|
+
end
|
356
267
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
268
|
+
story = @project.create_story(story_params)
|
269
|
+
|
270
|
+
#move the story
|
271
|
+
stories = @project.stories(:with_state => state, :fields => 'name')
|
272
|
+
|
273
|
+
if args.any?{|arg| arg.include?("-tl") } && !(stories.empty? || stories.nil?)
|
274
|
+
story.before_id = stories.first.id
|
275
|
+
elsif args.any?{|arg| arg.include?("-bl")} && !(stories.empty? || stories.nil?)
|
276
|
+
story.after_id = stories.last.id
|
277
|
+
end
|
278
|
+
|
279
|
+
story.save
|
280
|
+
story
|
281
|
+
end
|
361
282
|
|
362
|
-
def estimate_story(story)
|
363
|
-
story_points = nil
|
364
|
-
while (story_points.nil? || story_points.empty?)
|
365
|
-
story_points = ask("\nPlease enter the estimate points(0/1/2/3) for this story.")
|
366
|
-
end
|
367
|
-
while (!["0","1","2","3"].include?(story_points))
|
368
|
-
story_points = ask("\nInvalid entry...Please enter the estimate points(0/1/2/3) for this story.")
|
369
283
|
end
|
370
|
-
story.update(:estimate => story_points)
|
371
|
-
end
|
372
284
|
|
285
|
+
end
|
373
286
|
end
|