class Shipit::Cli::Work

Attributes

client[R]
global_options[R]
issue_id[R]

Public Class Methods

new(issue_id, global_options) click to toggle source

@param issue_id [Integer] The issue GitLab IID @param target_branch [String] “master”, “develop”… @param global_options [Hash] A hash of options

- dry_run : If true will not perform the commands
- client : an instance of the GitLab client
# File lib/shipit/cli/work.rb, line 13
def initialize(issue_id, global_options)
  @issue_id       = issue_id
  @global_options = global_options
  @client = global_options.fetch(:client)
end

Public Instance Methods

dry_run?() click to toggle source

@return [Boolean]

# File lib/shipit/cli/work.rb, line 43
def dry_run?
  global_options["dry_run"] == true
end
perform(target_branch) click to toggle source
  1. Get issue : docs.gitlab.com/ee/api/issues.html#single-issue

  2. Validate issue properties

  3. Create branch : docs.gitlab.com/ee/api/branches.html#create-repository-branch

  4. First commit : docs.gitlab.com/ee/api/commits.html#create-a-commit-with-multiple-files-and-actions

  5. New merge request : docs.gitlab.com/ee/api/merge_requests.html#create-mr

# File lib/shipit/cli/work.rb, line 24
def perform(target_branch)
  # 1. Load issue
  issue = fetch_remote_issue(issue_id).to_hash
  # 2. Validate issue
  validate_issue(issue)
  # 3. Add additional issue attributes
  enhanced_issue = enhance_issue(issue, target_branch)
  # 4. Create remote branch & checkout
  create_source_branch(enhanced_issue)
  # 5. Create merge request
  create_merge_request(enhanced_issue)
  # 6. Motivation!
  puts ""
  Shipit::Cli.ascii
rescue => e
  exit_now! e
end

Private Instance Methods

create_merge_request(issue) click to toggle source
# File lib/shipit/cli/work.rb, line 65
def create_merge_request(issue)
  return if dry_run?
  opts = issue.slice("source_branch", "target_branch", "assignee_id", "labels", "milestone_id", "remove_source_branch")
  client.create_merge_request(project_path,
                              issue["merge_request_title"],
                              opts)
rescue Gitlab::Error => e
  exit_now! "There was a problem creating your merge request on the GitLab server. Please do it manually.\nError : #{e.message}"
end
create_source_branch(issue) click to toggle source
# File lib/shipit/cli/work.rb, line 56
def create_source_branch(issue)
  commands = Shipit::Cli::Git.run(command: :new,
                                  branch: issue["source_branch"],
                                  message: issue["first_commit_message"],
                                  target_branch: issue["target_branch"],
                                  dry_run: global_options["dry_run"])
  raise "There was an error creating your working branch.\nPROTIP: Review the previous trace and fix the errors before retrying." if !dry_run? && commands.any? { |c| c == false }
end
define_source_branch_name() click to toggle source

Branch names are constructed like so : {label}-{assignee initials}-{issue id}-{issue title}

@return [String]

# File lib/shipit/cli/work.rb, line 113
def define_source_branch_name
  [first_label, assignee_initials, @id, issue_title].compact.join("-")
end
enhance_issue(issue, target_branch) click to toggle source
# File lib/shipit/cli/work.rb, line 85
def enhance_issue(issue, target_branch)
  # 1. Build properties
  issue_id = issue["iid"]
  labels = issue["labels"].join(", ")
  assignee = issue["assignees"].first
  sane_title = issue["title"].gsub(/[^0-9A-Za-z ,.]/, '').strip
  assignee_initials = assignee["name"].split.map(&:first).join.downcase.gsub(/[^a-z]/, '').strip
  assignee_id = assignee["id"]
  issue_title = sane_title.parameterize[0..20]
  first_commit_message = "[#{labels}] Fixes ##{issue_id} - #{sane_title}"
  mr_title = "[WIP] [#{labels}] ##{issue_id} - #{sane_title}"

  # 2. Add to issue properties
  issue["source_branch"] = [issue["labels"].first.gsub(/\s+/, ""), assignee_initials, issue_id, issue_title].compact.join("-")
  issue["first_commit_message"] = first_commit_message
  issue["target_branch"] = target_branch
  issue["merge_request_title"] = mr_title
  issue["assignee_id"] = assignee_id
  issue["milestone_id"] = issue["milestone"]["id"]
  issue["remove_source_branch"] = true
  issue["labels"] = labels
  issue
end
fetch_remote_issue(id) click to toggle source

@param id [Integer] The issue IID to fetch from GitLab

# File lib/shipit/cli/work.rb, line 50
def fetch_remote_issue(id)
  client.issue(project_path, id)
rescue Gitlab::Error::NotFound => e
  exit_now! "Issue #{id} not found for project #{project_name} on the remote GitLab server."
end
project_git_url() click to toggle source

@return [String]

# File lib/shipit/cli/work.rb, line 118
def project_git_url
  @project_git_url ||= `git config --local remote.origin.url`.chomp
end
project_name() click to toggle source

@return [String]

# File lib/shipit/cli/work.rb, line 123
def project_name
  @project_name ||= project_git_url.split("/").last.gsub(".git", "")
end
project_namespace() click to toggle source

@return [String]

# File lib/shipit/cli/work.rb, line 128
def project_namespace
  @project_namespace ||= project_git_url.split(":").last.split("/").first
end
project_path() click to toggle source

@return [String]

# File lib/shipit/cli/work.rb, line 133
def project_path
  @project_path ||= [project_namespace, project_name].join("/")
end
validate_issue(issue) click to toggle source

@param issue [Hash] A hash of properties @return true if issue if valid

# File lib/shipit/cli/work.rb, line 77
def validate_issue(issue)
  errors = []
  errors << "Assignee missing" if issue["assignees"].empty? # returns an array of assignees (Array of hash)
  errors << "Milestone missing" if issue["milestone"].to_s.empty? # returns a hash with the milestone properties
  errors << "Labels missing" if issue["labels"].empty? # returns an array of strings
  exit_now!("Invalid remote GitLab issue. Please fix the following warnings : #{errors.join(", ")}") if errors.any?
end