class GitPivotalTrackerIntegration::Util::Story

Utilities for dealing with +PivotalTracker::Story+s

Constants

CANDIDATE_STATES
CONTENT_WIDTH
LABEL_DESCRIPTION
LABEL_TITLE
LABEL_WIDTH

Public Class Methods

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/git-pivotal-tracker-integration/util/story.rb, line 33
def self.pretty_print(story)
  print_label LABEL_TITLE
  print_value story.name

  description = story.description
  if !description.nil? && !description.empty?
    print_label 'Description'
    print_value description
  end

  story.comments.sort_by{ |comment| comment.updated_at }.each_with_index do |comment, index|
    print_label "Note #{index + 1}"
    print_value comment.text
  end

  puts
end
select_release(project, filter = 'b', limit = 10) click to toggle source
# File lib/git-pivotal-tracker-integration/util/story.rb, line 89
def self.select_release(project, filter = 'b', limit = 10)
  if filter =~ /[[:digit:]]/
    story = project.story filter.to_i
    if story.story_type != "release"
      $LOG.fatal("Specified story##{filter} is not a valid release story")
      puts "Specified story##{filter} is not a valid release story"
      abort 'FAIL'
    end
  else
    story = find_release_story project, filter, limit
  end

  story
end
select_story(project, filter = nil, limit = 5) click to toggle source

Selects a Pivotal Tracker story by doing the following steps:

@param [PivotalTracker::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/git-pivotal-tracker-integration/util/story.rb, line 62
def self.select_story(project, filter = nil, limit = 5)
  story = nil

  if filter =~ /[[:digit:]]/
    story = project.story filter.to_i
  else
    # story type from (feature, bug, chore)
    # state from (rejected unstarted unscheduled)
    # if story type is "feature", then retrieve only estimated ones.
    criteria = " state:unstarted,rejected,unscheduled,planned"

    if %w(feature bug chore).include?(filter)
      criteria << " type:#{filter}"
      criteria << " -estimate:-1" if filter == "feature"
    else
      criteria << " type:feature,bug,chore"
    end

    candidates  = project.stories(filter: criteria, limit: limit)
    #limit is not working as expected. Need to find the reason. For now handle via ruby
    candidates  = candidates[0...5]
    story       = choose_story(candidates) unless candidates.empty?
  end

  story
end

Private Class Methods

choose_story(candidates, type = nil) click to toggle source
# File lib/git-pivotal-tracker-integration/util/story.rb, line 124
def self.choose_story(candidates, type = nil)
  choose do |menu|
    puts "\nUnestimated features can not be started.\n\n" if type != "release"

    menu.prompt = 'Choose a story to start: '

    candidates.each do |story|
      name = type ? story.name : '%-7s %s' % [story.story_type.upcase, story.name]
      menu.choice(name) { story }
    end
    menu.choice('Quit') do
      say "Thank you for using v2gpti"
      exit 0
    end
  end
end
create_new_release(project, next_release_number) click to toggle source
# File lib/git-pivotal-tracker-integration/util/story.rb, line 209
def self.create_new_release (project, next_release_number)
  project.create_story(:story_type => 'release', :current_state => 'unstarted', :name => next_release_number)
end
find_release_story(project, type, limit) click to toggle source

story type is release with story name starting with “v”/“b” or story labels includes story name. state from (rejected unstarted unscheduled) sort stories based on version (version number part of the story name) and pick the latest one.

# File lib/git-pivotal-tracker-integration/util/story.rb, line 144
def self.find_release_story(project, type, limit)
  release_type = (type == "b") ? "build" : "version"

  criteria =  "type:release"
  criteria << " state:unstarted,rejected,planned"
  criteria << " name:/#{type}*/"    #story name starts with  b or v

  candidates = project.stories(filter: criteria, limit: limit)

  candidates = candidates.select do |story|
    labels = story.labels.map(&:name)
    !labels.include?(story.name)
  end

  unless candidates.empty?
    story = choose_story(candidates, "release")
  else
    puts "There are no available release stories."
    last_release = last_release_story(project, type)

    if last_release
      puts " The last #{release_type} release was #{last_release.name}."
      if release_type == "version"
        next_release_number = ask("To create a new #{release_type}, enter a name for the new release story:")
      else
        next_release_number = set_next_release_number(last_release, release_type)
      end
    else
      next_release_number = ask("To create a new #{release_type}, enter a name for the new release story:")
    end

    puts "New #{release_type} release number is: #{next_release_number}"
    story = self.create_new_release(project, next_release_number)
  end

  story
end
last_release_story(project, type) click to toggle source

sort stories based on version (version number part of the story name) and pick the latest one.

# File lib/git-pivotal-tracker-integration/util/story.rb, line 183
def self.last_release_story (project, type)

  candidates = project.stories filter: "type:release name:/#{type}*/"
  candidates = candidates.select do |story|
    labels = story.labels.map(&:name)
    labels.include?(story.name)
  end
  candidates.sort! { |x,y| Gem::Version.new(y.name[1 .. -1]) <=> Gem::Version.new(x.name[1 .. -1]) }

  candidates.first
end
print_label(label) click to toggle source
print_value(value) click to toggle source
set_next_release_number(last_release, release_type) click to toggle source
# File lib/git-pivotal-tracker-integration/util/story.rb, line 195
def self.set_next_release_number(last_release, release_type)
  case release_type
  when "build"
    # just increment the last number
    last_release.name.next
  when "version"
    version_split           = last_release.name.split(/\./)
    last_incremented_number = version_split.last.next
    version_split.pop
    version_split.push(last_incremented_number)
    version_split.join(".")
  end
end