class GithubPivotalFlow::Story
Constants
- CANDIDATE_STATES
- CONTENT_WIDTH
- LABEL_DESCRIPTION
- LABEL_ID
- LABEL_TITLE
- LABEL_WIDTH
Attributes
branch_name[RW]
pivotal_story[RW]
project[RW]
root_branch_name[RW]
Public Class Methods
new(project, pivotal_story, options = {})
click to toggle source
@param [Project] project the Project
for this repo @param [PivotalTracker::Story] pivotal_story
the Pivotal tracker story to wrap
# File lib/github_pivotal_flow/story.rb, line 52 def initialize(project, pivotal_story, options = {}) raise "Invalid PivotalTracker::Story" if pivotal_story.nil? @project = project @pivotal_story = pivotal_story @branch_name = options.delete(:branch_name) @branch_suffix = @branch_name.split('-').last if @branch_name @branch_suffix ||= nil end
pretty_print(story)
click to toggle source
Print a human readable version of a story. This pretty prints the title, description, and notes for the story.
@param [PivotalTracker::Story] story the story to pretty print @return [void]
# File lib/github_pivotal_flow/story.rb, line 11 def self.pretty_print(story) print_label LABEL_ID print_value story.id print_label LABEL_TITLE print_value story.name description = story.description if !description.nil? && !description.empty? print_label 'Description' print_value description end PivotalTracker::Note.all(story).sort_by { |note| note.noted_at }.each_with_index do |note, index| print_label "Note #{index + 1}" print_value note.text end puts end
select_story(project, filter = nil, limit = 5)
click to toggle source
Selects a Pivotal Tracker story by doing the following steps:
@param [Project] project the project to select stories from @param [String, nil] filter a filter for selecting the story to start. This
filter can be either: * a story id: selects the story represented by the id * a story type (feature, bug, chore): offers the user a selection of stories of the given type * +nil+: offers the user a selection of stories of all types
@param [Fixnum] limit The number maximum number of stories the user can choose from @return [PivotalTracker::Story] The Pivotal Tracker story selected by the user
# File lib/github_pivotal_flow/story.rb, line 41 def self.select_story(project, filter = nil, limit = 5) if filter =~ /[[:digit:]]/ story = project.stories.find filter.to_i else story = find_story project, filter, limit end self.new(project, story) end
Private Class Methods
find_story(project, type, limit)
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 245 def self.find_story(project, type, limit) criteria = { :current_state => CANDIDATE_STATES, :limit => limit } if type criteria[:story_type] = type else criteria[:story_type] = ['feature', 'bug'] end candidates = project.stories.all criteria if candidates.length == 1 story = candidates[0] else story = choose do |menu| menu.prompt = 'Choose story to start: ' candidates.each do |story| name = type ? story.name : '%-7s %s' % [story.story_type.upcase, story.name] menu.choice(name) { story } end end puts end story end
print_label(label)
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 227 def self.print_label(label) print "%#{LABEL_WIDTH}s" % ["#{label}: "] end
print_value(value)
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 231 def self.print_value(value) if value.blank? puts '' else value.to_s.scan(/\S.{0,#{CONTENT_WIDTH - 2}}\S(?=\s|$)|\S+/).each_with_index do |line, index| if index == 0 puts line else puts "%#{LABEL_WIDTH}s%s" % ['', line] end end end end
Public Instance Methods
branch_name_from(branch_prefix, story_id, branch_name)
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 157 def branch_name_from(branch_prefix, story_id, branch_name) if story_type == 'release' # For release branches the format is release/5.0 "#{Git.get_config(KEY_RELEASE_PREFIX, :inherited)}#{branch_name}" else n = "#{branch_prefix}" n << "#{branch_name}" unless branch_name.blank? n end end
branch_suffix()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 153 def branch_suffix @branch_suffix ||= ask("Enter branch name (#{branch_name_from(branch_prefix, id, "<branch-name>")}): ") end
can_merge?()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 205 def can_merge? Git.clean_working_tree? end
cleanup!()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 141 def cleanup! Git.delete_remote_branch(branch_name) end
create_branch!(options = {})
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 84 def create_branch!(options = {}) Git.checkout(root_branch_name) root_origin = Git.get_remote remote_branch_name = [root_origin, root_branch_name].join('/') print "Creating branch for story with branch name #{branch_name} from #{remote_branch_name}... " Git.pull_remote Git.create_branch(branch_name, remote_branch_name, track: true) Git.checkout(branch_name) Git.set_config('root-branch', root_branch_name, :branch) Git.set_config('root-remote', root_origin, :branch) end
delete_branch!()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 135 def delete_branch! print "Deleting #{branch_name}... " Git.delete_branch(branch_name) puts 'OK' end
development_branch_name()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 183 def development_branch_name Git.get_config(KEY_DEVELOPMENT_BRANCH, :inherited) end
labels()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 187 def labels return [] if pivotal_story.labels.blank? pivotal_story.labels.split(',').collect(&:strip) end
mark_started!()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 75 def mark_started! print 'Starting story on Pivotal Tracker... ' self.update( current_state: 'started', owned_by: Git.get_config(KEY_USER_NAME, :inherited).strip ) puts 'OK' end
master_branch_name()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 179 def master_branch_name Git.get_config(KEY_MASTER_BRANCH, :inherited) end
merge_release!(commit_message = nil, options = {})
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 108 def merge_release!(commit_message = nil, options = {}) commit_message ||= "Release #{escape_quotes(name)}" commit_message << "\n\n[#{options[:no_complete] ? '' : 'Completes '}##{id}] " print "Merging #{branch_name} to #{master_branch_name}... " Git.checkout(master_branch_name) Git.pull_remote(master_branch_name) if trivial_merge?(master_branch_name) Git.merge(branch_name, commit_message: commit_message, ff: true) else Git.merge(branch_name, commit_message: commit_message, no_ff: true) end print "Merging #{branch_name} to #{development_branch_name}... " Git.checkout(development_branch_name) Git.pull_remote(development_branch_name) if trivial_merge?(development_branch_name) Git.merge(branch_name, commit_message: commit_message, ff: true) else Git.merge(branch_name, commit_message: commit_message, no_ff: true) end Git.checkout(master_branch_name) Git.tag(name, annotated: true, message: "Release #{escape_quotes(name)}") Git.push(master_branch_name, development_branch_name) Git.push_tags self.delete_branch! self.cleanup! end
merge_to_root!(commit_message = nil, options = {})
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 96 def merge_to_root!(commit_message = nil, options = {}) commit_message = "Merge #{branch_name} to #{root_branch_name}" if commit_message.blank? commit_message << "\n\n[#{options[:no_complete] ? '' : 'Completes '}##{id}] " print "Merging #{branch_name} to #{root_branch_name}... " Git.checkout(root_branch_name) Git.pull_remote(root_branch_name) Git.merge(branch_name, commit_message: commit_message, no_ff: true) Git.push(root_branch_name) self.delete_branch! self.cleanup! end
method_missing(m, *args, &block)
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 201 def method_missing(m, *args, &block) return @pivotal_story.send(m, *args, &block) end
params_for_pull_request()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 192 def params_for_pull_request { base: root_branch_name, head: branch_name, title: name, body: description, } end
release?()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 61 def release? story_type == 'release' end
request_estimation!()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 69 def request_estimation! self.update( estimate: ask('Story is not yet estimated. Please estimate difficulty: ') ) end
trivial_merge?(to_branch = nil)
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 209 def trivial_merge?(to_branch = nil) to_branch ||= root_branch_name root_tip = Shell.exec "git rev-parse #{to_branch}" common_ancestor = Shell.exec "git merge-base #{to_branch} #{branch_name}" if root_tip != common_ancestor return false end return true end
unestimated?()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 65 def unestimated? estimate == -1 end
Private Instance Methods
branch_prefix()
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 275 def branch_prefix case story_type when 'feature' prefix = Git.get_config(KEY_FEATURE_PREFIX, :inherited) when 'bug' prefix = labels.include?('hotfix') ? Git.get_config(KEY_HOTFIX_PREFIX, :inherited) : Git.get_config(KEY_FEATURE_PREFIX, :inherited) when 'release' prefix = Git.get_config(KEY_RELEASE_PREFIX, :inherited) else prefix = 'misc/' end prefix = "#{prefix.strip}/" unless prefix.strip[-1,1] == '/' return prefix.strip end
escape_quotes(string)
click to toggle source
# File lib/github_pivotal_flow/story.rb, line 290 def escape_quotes(string) string.gsub('"', '\"') end