Skip to content

Instantly share code, notes, and snippets.

@taktran
Created September 11, 2012 11:09
Show Gist options
  • Save taktran/3697640 to your computer and use it in GitHub Desktop.
Save taktran/3697640 to your computer and use it in GitHub Desktop.
Ship it! rake task. Some details about the rationale here: http://blog.pebblecode.com/post/32263926012/ship-it
# Ship it! rake task
#
# Merge branch (master by default) to deployment branch, and deploy to server.
#
# Prerequisite:
#
# * Declare all deployment branches in `ALL_DEPLOYMENT_BRANCHES`
# * Declare deploy only branches in `DEPLOY_ONLY_BRANCHES` (ie, does not merge master)
# * Modify `Deploy.command` function as necessary
#
# Usage:
#
# # To initalise local branch and push to origin
# bundle exec rake shipit:init[deployment-branch]
#
# # Setup heroku if required
# bundle exec rake deploy:init:heroku[name]
#
# # Do work on `master`, and commit
# # Merge `master` to `deployment-branch`, and deploy with:
# bundle exec rake shipit[deployment-branch]
#
# # Do work on `some-branch`, and commit
# # Merge `some-branch` to `deployment-branch`, and deploy with:
# bundle exec rake shipit:branch[some-branch,deployment-branch]
#
# Notes:
#
# * Merge conflicts may occur, which the rake tasks don't currently
# handle. You need to exercise your git-foo in these cases.
#
require 'fileutils'
ALL_DEPLOYMENT_BRANCHES = ["staging"]
DEPLOY_ONLY_BRANCHES = []
module Deploy
# Remember to download the [heroku toolbelt first](https://toolbelt.heroku.com/)
def self.init_heroku(name)
Rake.sh "heroku create #{name}"
end
def self.command(branch)
# For capitrano - Assume that capistrano task is the same name as the branch
# "bundle exec cap #{branch} deploy"
# For heroku - Assume heroku is setup
"git push heroku #{branch}:master"
end
def self.branch!(branch)
Rake.sh self.command(branch)
end
end
module Git
def self.create_branch!(branch, &next_command)
Rake.sh "git checkout -b #{branch}", &next_command
end
# Since Git 1.7.0
def self.push_new_branch_to_origin!(branch, &next_command)
Rake.sh "git push -u origin #{branch}", &next_command
end
def self.checkout!(branch, &next_command)
Rake.sh "git checkout #{branch}", &next_command
end
def self.merge!(branch, &next_command)
Rake.sh "git merge #{branch}", &next_command
end
def self.push_origin!(local_branch, remote_branch)
Rake.sh "git push origin #{local_branch}:#{remote_branch}"
end
# Merge `from_branch` and push to remote server, and checkout `from_branch` at the end.
def self.merge_branch!(from_branch, to_branch)
run_push_origin = Proc.new do |ok, resp|
if ok
self.push_origin!(to_branch, to_branch)
self.checkout!(from_branch)
else
abort(resp.to_s)
end
end
run_merge = Proc.new do |ok, resp|
if ok
self.merge!(from_branch, &run_push_origin)
else
abort(resp.to_s)
end
end
# Checkout -> merge -> push origin
self.checkout! to_branch, &run_merge
end
end
desc "Merge master to branch, and push to origin server."
task "merge_master_and_push_to", [:branch] do |t, args|
Git.merge_branch!("master", args.branch)
end
desc "Deploy branch to server."
task :deploy, [:branch] do |t, args|
Deploy.branch!(args.branch)
end
namespace "deploy" do
desc "Initialise heroku"
task "init:heroku", [:name] do |t, args|
Deploy.init_heroku(args.name)
end
end
desc "Ship it! Merge master and push branch to origin (if not in `DEPLOY_ONLY_BRANCHES`), then deploy to the server."
task "shipit", [:branch] do |t, args|
if ALL_DEPLOYMENT_BRANCHES.include? args.branch
unless DEPLOY_ONLY_BRANCHES.include? args.branch
Rake::Task["merge_master_and_push_to"].invoke(args.branch)
end
Rake::Task["deploy"].invoke(args.branch)
else
puts "Invalid deployment branch: #{args.branch}"
puts "Available deployment branches are: #{ALL_DEPLOYMENT_BRANCHES.to_s}"
end
end
namespace "shipit" do
desc "Initialise shipit with local branch, and push branch to origin server."
task "init", [:branch] do |t, args|
branch = args.branch
run_push_origin = Proc.new do |ok, resp|
if ok
Git.push_new_branch_to_origin!(branch)
else
abort(resp.to_s)
end
end
# Create local branch -> push to branch to origin
Git.create_branch!(branch, &run_push_origin)
end
desc "Merge branch to deployment branch, push to remote server, and deploy."
task :branch, [:from_branch, :deploy_branch] do |t, args|
from_branch = args.from_branch
deploy_branch = args.deploy_branch
if ALL_DEPLOYMENT_BRANCHES.include? deploy_branch
Git.merge_branch!(from_branch, deploy_branch)
Rake::Task["deploy"].invoke(deploy_branch)
else
puts "Invalid deployment branch: #{args.branch}"
puts "Available deployment branches are: #{ALL_DEPLOYMENT_BRANCHES.to_s}"
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment