Skip to content

Instantly share code, notes, and snippets.

@oc
Created January 13, 2012 10:19
Show Gist options
  • Save oc/1605409 to your computer and use it in GitHub Desktop.
Save oc/1605409 to your computer and use it in GitHub Desktop.
Rakefile deployhelper example
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/lib')
require 'rubygems'
require 'bundler'
Bundler.setup
require 'thor'
require 'cucumber/rake/task'
require 'rspec/core/rake_task'
require 'label_generator/version'
require 'net/http'
require 'net/ssh'
require 'net/scp'
Bundler.require(:default, :development)
class ReleaseHelper < Bundler::GemHelper
include Rake::DSL
# override
def self.install_tasks(opts = nil)
dir = caller.find{|c| /Rakefile:/}[/^(.*?)\/Rakefile:/, 1]
self.new(dir, opts && opts[:name]).install
end
# override
def initialize(base, name = nil)
Bundler.ui = Bundler::UI::Shell.new(Thor::Shell::Color.new)
@base = base
end
# override
def install
desc "Create tag #{version_tag} and build and push #{name}-#{version}.war to Repo"
task :release do
release_war
end
desc "Build #{name}-#{version}.war"
task :war do
build_war
end
end
def release_war
guard_clean
guard_already_tagged
build_war
tag_version do
git_push
deploy_nexus
end
end
# override
def version; LabelGenerator::VERSION; end
# override
def name; LabelGenerator::NAME; end
def repo_url; 'http://bring.ewok.no/nexus/content/repositories/releases'; end
def repo_name; 'bring.releases'; end
# See issue: #668 if warble fails...
# http://github.com/carlhuda/bundler/issuesearch?state=closed&q=w0t#issue/668
def build_war
Bundler.ui.info "Building war..."
system("warble")
end
def deploy_nexus
Bundler.ui.info "Uploading war to Nexus..."
system("mvn deploy:deploy-file -DgroupId=no.bring.booking -DartifactId=#{name} -Dversion=#{version} -Dpackaging=war -Dfile=#{war_path} -Durl=#{repo_url} -DrepositoryId=#{repo_name}")
end
def cuke(env)
system("rake cucumber --tags @online --tags @#{env}")
end
def war_path
"#{name}-#{version}.war"
end
end
ReleaseHelper.install_tasks
class DeployHelper < Bundler::GemHelper
# override
def self.install_tasks(opts = nil)
dir = caller.find{|c| /Rakefile:/}[/^(.*?)\/Rakefile:/, 1]
self.new(dir, opts && opts[:name]).install
end
# override
def initialize(base, name = nil)
Bundler.ui = Bundler::UI::Shell.new(Thor::Shell::Color.new)
@base = base
end
# override
def install
[:qa, :production].each do |env|
namespace env do
desc "Setup #{env.to_s}"
task :setup do
self.__send__("setup", env.to_s)
end
desc "Deploy #{name} (#{version}) to #{env.to_s}"
task :deploy => :war do
self.__send__("deploy", env.to_s)
end
desc "Upload #{name} (#{version}) to #{env.to_s}"
task :upload => :war do
self.__send__("upload", env.to_s)
end
desc "Restart #{name} (#{version}) to #{env.to_s}"
task :restart do
self.__send__("restart", env.to_s)
end
desc "Check #{name} (#{version}) to #{env.to_s}"
task :verify do
self.__send__("verify", env.to_s)
end
desc "Rollback #{name} (#{version}) to #{env.to_s} - WARNING - Not implemented"
task :rollback do
self.__send__("rollback", env.to_s)
end
end
end
end
# override
def version
LabelGenerator::VERSION
end
# override
def name
LabelGenerator::NAME
end
def timestamp
@timestamp ||= Time.now.strftime("%Y%m%d%H%M")
end
def war_path
"#{name}-#{version}.war"
end
###
###
###
def configuration
{
'production' => {
:hosts => %w[lochee.os.ergo.no dunbar.os.ergo.no],
:user => 'bring',
:prefix => '/u01/bring',
:verify_url => "http://beta.bring.no/#{name}/version"
},
'qa' => {
:hosts => %w[beta.qa.bring.no],
:user => 'bring',
:prefix => '/bring',
:verify_url => "http://beta.qa.bring.no/#{name}/version"
}
}
end
def setup(environment)
configuration[environment][:hosts].each do |host|
Bundler.ui.info "Setting up #{environment}: #{host}"
setup_host(environment, host, configuration[environment][:user], configuration[environment][:prefix])
end
Bundler.ui.confirm "Setup done!"
end
def setup_host(environment, host, user, prefix)
Net::SSH.start(host, user) do |ssh|
ssh.exec!("mkdir -p #{prefix}/{apps,logs}/#{name}")
ssh.exec!("mkdir -p #{prefix}/{conf,bin}")
end
Net::SCP.start(host, user) do |scp|
scp.upload!("config/#{environment}/#{name}.sh" ,"#{prefix}/bin/")
end
end
def deploy(environment)
upload(environment)
restart(environment)
Bundler.ui.info "Waiting 20 seconds for webapps to come back up..."
sleep 20
verify(environment)
end
def upload(environment)
configuration[environment][:hosts].each do |host|
upload_host(host, configuration[environment][:user], configuration[environment][:prefix])
end
end
def upload_host(host, user, prefix)
Net::SSH.start(host, user) do |ssh|
Bundler.ui.info "Marking previous release on #{host}..."
ssh.exec!("touch #{prefix}/apps/#{name}/#{name}.war")
ssh.exec!("mv #{prefix}/apps/#{name}/#{name}.war #{prefix}/apps/#{name}/#{name}.war.previous")
end
Net::SCP.start(host, user) do |scp|
Bundler.ui.info "Uploading #{war_path} to #{host}..."
scp.upload!(war_path ,"#{prefix}/apps/#{name}")
end
Net::SSH.start(host, user) do |ssh|
Bundler.ui.info "Symlinking new release..."
ssh.exec("ln -sf #{prefix}/apps/#{name}/#{war_path} #{prefix}/apps/#{name}/#{name}.war")
end
end
def restart(environment)
configuration[environment][:hosts].each do |host|
restart_host(host, configuration[environment][:user], configuration[environment][:prefix])
end
end
def restart_host(host, user, prefix)
Net::SSH.start(host, user) do |ssh|
stop(ssh, host, prefix)
clear_working_folder(ssh, host, prefix)
start(ssh, host, prefix)
end
end
def clear_working_folder(ssh, host, prefix)
backup_name = "#{prefix}/deployments/#{name}.#{timestamp}"
Bundler.ui.info "Renaming working folder to #{backup_name} on #{host}..."
ssh.exec!("mv #{prefix}/deployments/#{name} #{backup_name}")
end
def stop(ssh, host, prefix)
Bundler.ui.info "Stopping service on #{host}..."
ssh.exec!("sh #{prefix}/bin/#{name}.sh stop")
end
def start(ssh, host, prefix)
Bundler.ui.info "Starting service on #{host}..."
ssh.exec!("sh #{prefix}/bin/#{name}.sh start")
end
def verify(environment)
running_version = Net::HTTP.get(URI.parse(configuration[environment][:verify_url]))
if(running_version == version)
Bundler.ui.confirm "Deployment OK!"
else
Bundler.ui.error "Deployment failed. Expected new running version to be #{version}, but it is #{running_version}"
end
end
def rollback(environment)
Bundler.ui.warn "Not implemented. Perform manual rollback."
end
end
DeployHelper.install_tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment