Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist
View 1 hello.md

Deployer thing

Super cheapo Capistrano replacement. Inspired by github.com/cyx/tell.
This is more of a proof-of-concept than production-grade code... be sure you scrutinize it before you use it.

Contents:

  • deploy.yml (the config file)
  • deploy.rb (the deployer itself)

Usage

./deploy.rb production    # Deploys to production servers

Example output

$ ./deploy.rb production

server1.myapp.com$ git pull
  ...done.

server1.myapp.com$ rake cdn:propogate
  Sending new assets to Akamai...
  done.

server1.myapp.com$ thin restart
  Restarting thin.

server2.myapp.com$ git pull
  ...
  ...
  ...etc
View 1 hello.md
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
# This is the config file describing the servers.
#
# This describes a cluster that looks like this:
#
# - 3 production servers (server1.myapp.com ... server3.myapp.com)
# - 1 development server (dev.myapp.com)
# - 1 test server (test.myapp.com)
#
# With this setup, you can:
#
# ./deploy.rb production # Deploys to server1 to server3.myapp.com
# ./deploy.rb test # Deploys to test.myapp.com
#
production.1: &production
host: server1.myapp.com
deploy:
- "git pull"
- "rake cdn:propogate"
- "sudo thin restart"
 
# Notice how these take advantage of YAML's inheritance
production.2:
<<: *production
host: server2.myapp.com
 
production.3:
<<: *production
host: server2.myapp.com
 
development: &dev
host: dev.myapp.com
deploy:
- "git pull"
- "touch tmp/restart.txt"
 
test:
<<: *dev
host: test.myapp.com
identity: id_rsa.pub
login: rsc
# ^-- not supported, but support for these can easily be added in as
# an exercise to the reader.
View 1 hello.md
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#!/usr/bin/env ruby
 
# The deployer class.
#
# Basic usage:
#
# d = Deployer.new yaml_filename
# d.run!('production') # deploys to servers matching production*
#
class Deployer
include Process
 
def initialize(file='deploy.yml')
require 'yaml'
@data = YAML::load_file(file)
end
 
# Deploys to given hosts matching /to/.
def run!(to, options={})
select(to).each do |(key, data)|
host = data['host'] || key
fork?(options[:fork]) {
data['deploy'].each { |cmd| tell host, cmd }
}
end
 
wait if options[:fork]
end
 
# Forks if the given parameter is truthy; else, runs as is.
def fork?(fork_it)
fork_it ? fork { yield } : yield
end
 
# Tells a server `host` to do a command `cmd`.
def tell(host, cmd)
log host, cmd
system "ssh #{host} -- #{cmd}"
end
 
# Logs something to stdout.
def log(host, cmd)
c1 = "\033[0;30m"
c2 = "\033[0m"
puts "\n#{c1}%s$#{c2} %s" % [ host, cmd ]
end
 
# Returns servers matching the spec given in `to`.
def select(to)
@data.select { |(key, data)| key.match(/^#{to}/) }
end
end
 
if $0 == __FILE__
if ARGV.size < 0
$stderr << "Usage: $0 <to>\n"
exit
end
 
Deployer.new.run! ARGV[0]
 
# Yes if you've noticed: you can add `, :fork => true` to the end of
# the previous line to do the deployments in parallel.
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.