class BBFlow::PullRequester

Constants

Public Class Methods

add_pull_request_to_cards(pull_request) click to toggle source

@param [Sawyer::Resource] pull_request

# File lib/bb_flow/pull_requester.rb, line 79
def add_pull_request_to_cards(pull_request)
  puts 'Adding the pull request to the trello cards...'

  cards.reject { |card| card.attachments.map(&:url).include?(pull_request.html_url) }.each do |card|
    # Note that this title is formatted in a special way that makes Trello recognize it as
    # a GitHub PR instead of a regular attachment.
    title = "#{pull_request.head.repo.name} ##{pull_request.number} #{pull_request.title}"
    card.add_attachment(pull_request.html_url, title)
  end
end
create!() click to toggle source

@return [void]

# File lib/bb_flow/pull_requester.rb, line 11
def create!
  ensure_has_remote!
  ensure_pushed!

  existing_pull_request = Github.find_pull_request

  if existing_pull_request
    Printer.success("A pull request for this branch already exists.\n#{existing_pull_request.html_url}")
  else
    response = Github.create_pull_request(title, Misc.edit(body_template) + ADVERTISEMENT)

    unless reviewers.empty?
      Github.add_reviewers_to_pull_request(response.number, reviewers.map(&:first))
    end

    unless labels.empty?
      Github.add_labels_to_pull_request(response.number, labels)
    end

    unless cards.empty?
      add_pull_request_to_cards(response)

      if Options.get(:base_branch) == Options.default(:base_branch) ||
         Printer.simple_question("You're going to merge into a non-default branch. Would you still like me to move the #{Misc.pluralize('card', cards.size)}?")
        move_cards_to_done_list
      end
    end

    Printer.success('The pull request has been created, sir.')
    Misc.open_url(response.html_url)
  end
rescue Octokit::Error => exception
  Printer.error(exception.message)
end
ensure_has_remote!() click to toggle source

@return [void]

# File lib/bb_flow/pull_requester.rb, line 47
def ensure_has_remote!
  unless Github.has_branch?
    question = "The branch isn't pushed yet. Would you like me to push it for you?"

    if Printer.simple_question(question)
      Misc.execute("git push --set-upstream #{Github.remote_name} #{Misc.git.current_branch}")
    else
      puts "Sorry, you should push your local branch to remote before creating a pull request."
      puts 'Exiting...'
      exit
    end
  end
end
ensure_pushed!() click to toggle source

@return [void]

# File lib/bb_flow/pull_requester.rb, line 62
def ensure_pushed!
  unless Github.pushed?
    question = "Your local branch is ahead of '#{Github.remote_branch}' by #{Github.unpushed_commits_number} commits. Would you like me to push it?"

    if Printer.simple_question(question)
      Misc.execute("git push --set-upstream #{Github.remote_name} #{Misc.git.current_branch}")
    end
  end
end
move_cards_to_done_list() click to toggle source

@return [void]

# File lib/bb_flow/pull_requester.rb, line 73
def move_cards_to_done_list
  puts "Moving cards to the „#{Trello.done_list.name}“ list..."
  cards.each { |card| card.move_to_list(Trello.done_list) }
end

Private Class Methods

body_template() click to toggle source

@return [String]

# File lib/bb_flow/pull_requester.rb, line 102
def body_template
  card_links = cards.map { |card| %Q(<a href="#{card.url}"><img src="https://github.trello.services/images/trello-icon.png" width="12" height="12"> #{card.name}</a>) }

  body_parts = []

  unless card_links.empty?
    body_parts << card_links.join("\n")
  end

  body_parts << '###### Changes'
  body_parts << commit_messages.map { |message| "  * #{message.lines.first.strip}" }.join("\n")

  unless Github.other_branch_committers.empty?
    logins = Github.other_branch_committers.map { |login| "@#{login}" }.join(", ")
    body_parts << "CC: #{logins}"
  end

  body_parts.join("\n\n")
end
cards() click to toggle source
# File lib/bb_flow/pull_requester.rb, line 150
        def cards
  return [] if Trello.cards.blank?

  Printer.select_items(
    Trello.cards,
    'Which cards does it implement?',
    formatter: Trello.method(:format_card),
    preselected: Trello.cards.map { |card| commit_messages.any? { |message| message.include?(card.short_url) } }
  )
end
commit_messages() click to toggle source
# File lib/bb_flow/pull_requester.rb, line 162
        def commit_messages
  Github.commits_info.reject { |info| info.parents.size > 1 }.map { |info| info.commit.message }
end
guessed_labels(labels) click to toggle source

@param [Array<String>] labels

@return [Array<String>]

# File lib/bb_flow/pull_requester.rb, line 169
def guessed_labels(labels)
  specialized_predicates = {
    'bugfix'      => -> { Trello.labels.include?('bug') },
    'refactoring' => -> { Github.changed_files.size > 50 || commit_messages.map(&:downcase).any? { |message| message.include?('refactor') } },
    'specs'       => -> { Github.changed_files.present? && Github.changed_files.all? { |file| file.start_with?('spec/') && file.end_with?('_spec.rb') } },
    'wip'         => -> { %w(wip skip-ci).any?(&commit_messages.last.downcase.method(:include?)) },
    'ui'          => -> { Github.changed_files.present? && Github.changed_files.all? { |file| file.start_with?('app/assets/stylesheets/') } }
  }.tap { |hash| hash.default = ->() { false } }

  labels.select { |label| Misc.git.current_branch.include?(label) || Trello.labels.include?(label) || specialized_predicates[label].call }
end
labels() click to toggle source
# File lib/bb_flow/pull_requester.rb, line 137
        def labels
  labels = Github.labels.sort_by(&:downcase)
  downcased = labels.map(&:downcase)

  Printer.select_items(
    labels,
    'Which labels do you want to add to this pull request?',
    formatter: ->(label) { label },
    preselected: downcased.map(&guessed_labels(downcased).method(:include?))
  )
end
reviewers() click to toggle source
# File lib/bb_flow/pull_requester.rb, line 123
        def reviewers
  previous_reviewers = Persistent::Store.get(:local).transaction(true) { |store| store['previous_reviewers'] } || []

  reviewers = Printer.select_items(
    Github.collaborators,
    'Who will be reviewing the pull request?',
    formatter: proc { |login, name| [login, name] },
    preselected: Github.collaborators.map { |user| previous_reviewers.include?(user) }
  )

  Persistent::Store.get(:local).transaction { |store| store['previous_reviewers'] = reviewers }
end
title() click to toggle source

@return [String]

# File lib/bb_flow/pull_requester.rb, line 93
def title
  if cards.size == 1
    cards.first.name
  else
    Printer.ask('Title:')
  end
end