v2gpti 1.1.9 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|