-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
97 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,59 +1,79 @@ | ||
Capistrano::Configuration.instance.load do | ||
|
||
set :lockfile, "cap.lock" | ||
require 'capistrano' | ||
|
||
module Capistrano | ||
module Caplock | ||
|
||
# Returns Boolean indicating the result of +filetest+ on +full_path+ on the server, evaluated by shell on | ||
# the server (usually bash or something roughly compatible). | ||
def remote_filetest_passes?(filetest, full_path) | ||
'true' == capture("if [ #{filetest} #{full_path} ]; then echo 'true'; fi").strip | ||
end | ||
# Returns Boolean indicating the result of +filetest+ on +full_path+ on the server, evaluated by shell on | ||
# the server (usually bash or something roughly compatible). | ||
def remote_filetest_passes?(filetest, full_path) | ||
'true' == capture("if [ #{filetest} #{full_path} ]; then echo 'true'; fi").strip | ||
end | ||
|
||
# Checks if a symlink exists on the remote machine. | ||
def remote_symlink_exists?(full_path) | ||
remote_filetest_passes?('-L', full_path) | ||
end | ||
# Checks if a symlink exists on the remote machine. | ||
def remote_symlink_exists?(full_path) | ||
remote_filetest_passes?('-L', full_path) | ||
end | ||
|
||
# Returns Boolean value indicating whether file exists on server | ||
def remote_file_exists?(full_path) | ||
remote_filetest_passes?('-e', full_path) | ||
end | ||
# Returns Boolean value indicating whether file exists on server | ||
def remote_file_exists?(full_path) | ||
remote_filetest_passes?('-e', full_path) | ||
end | ||
|
||
# Returns Boolean value indicating whether the file at +full_path+ matches +content+. Checks if file | ||
# is equivalent to content by checking whether or not the MD5 of the remote content is the same as the | ||
# MD5 of the String in +content+. | ||
def remote_file_content_same_as?(full_path, content) | ||
Digest::MD5.hexdigest(content) == capture("md5sum #{full_path} | awk '{ print $1 }'").strip | ||
end | ||
# Returns Boolean value indicating whether the file at +full_path+ matches +content+. Checks if file | ||
# is equivalent to content by checking whether or not the MD5 of the remote content is the same as the | ||
# MD5 of the String in +content+. | ||
def remote_file_content_same_as?(full_path, content) | ||
Digest::MD5.hexdigest(content) == capture("md5sum #{full_path} | awk '{ print $1 }'").strip | ||
end | ||
|
||
# Returns Boolean indicating whether the remote file is present and has the same contents as | ||
# the String in +content+. | ||
def remote_file_differs?(full_path, content) | ||
!remote_file_exists?(full_path) || remote_file_exists?(full_path) && !remote_file_content_same_as?(full_path, content) | ||
end | ||
|
||
namespace :lock do | ||
desc "check lock" | ||
task :check, :roles => :app do | ||
if remote_file_exists?("#{deploy_to}/#{lockfile}") | ||
abort "\n\n\n\e[0;31m A Deployment is already in progress\n Remove #{deploy_to}/#{lockfile} to unlock \e[0m\n\n\n" | ||
end | ||
# Returns Boolean indicating whether the remote file is present and has the same contents as | ||
# the String in +content+. | ||
def remote_file_differs?(full_path, content) | ||
!remote_file_exists?(full_path) || remote_file_exists?(full_path) && !remote_file_content_same_as?(full_path, content) | ||
end | ||
|
||
desc "create lock" | ||
task :create, :roles => :app do | ||
timestamp = Time.now.strftime("%m/%d/%Y %H:%M:%S %Z") | ||
lock_message = "Deploy started at #{timestamp} in progress" | ||
put lock_message, "#{deploy_to}/#{lockfile}", :mode => 0644 | ||
def self.load_into(configuration) | ||
configuration.load do | ||
set :lockfile, "cap.lock" | ||
|
||
namespace :lock do | ||
desc "check lock" | ||
task :check, :roles => :app do | ||
if caplock.remote_file_exists?("#{deploy_to}/#{lockfile}") | ||
abort "\n\n\n\e[0;31m A Deployment is already in progress\n Remove #{deploy_to}/#{lockfile} to unlock \e[0m\n\n\n" | ||
end | ||
end | ||
|
||
desc "create lock" | ||
task :create, :roles => :app do | ||
timestamp = Time.now.strftime("%m/%d/%Y %H:%M:%S %Z") | ||
lock_message = "Deploy started at #{timestamp} in progress" | ||
put lock_message, "#{deploy_to}/#{lockfile}", :mode => 0644 | ||
end | ||
|
||
desc "release lock" | ||
task :release, :roles => :app do | ||
run "rm -f #{deploy_to}/#{lockfile}" | ||
end | ||
end | ||
|
||
# Deployment | ||
before "deploy", "lock:check" | ||
after "lock:check", "lock:create" | ||
after "deploy", "lock:release" | ||
|
||
# Rollback | ||
before "deploy:rollback", "lock:check" | ||
after "deploy:rollback", "lock:release" | ||
|
||
end | ||
end | ||
|
||
desc "release lock" | ||
task :release, :roles => :app do | ||
run "rm -f #{deploy_to}/#{lockfile}" | ||
end | ||
Capistrano.plugin :caplock, Caplock | ||
|
||
end | ||
|
||
before "deploy", "lock:check" | ||
after "lock:check", "lock:create" | ||
after "deploy", "lock:release" | ||
end | ||
|
||
if Capistrano::Configuration.instance | ||
Capistrano::Caplock.load_into(Capistrano::Configuration.instance) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,35 @@ | ||
require 'helper' | ||
|
||
class TestCaplock < Test::Unit::TestCase | ||
should "probably rename this file and start testing for real" do | ||
flunk "hey buddy, you should probably rename this file and start testing for real" | ||
def setup | ||
@config = Capistrano::Configuration.new | ||
Capistrano::Caplock.load_into(@config) | ||
@config.set :deploy_to, "/tmp" | ||
@config.role :app, "localhost" | ||
end | ||
|
||
should "use default lockfile name 'cap.lock'" do | ||
assert_equal @config.lockfile, 'cap.lock' | ||
end | ||
|
||
should "set lockfile name to 'test.lock'" do | ||
@config.set :lockfile, 'test.lock' | ||
assert_equal @config.lockfile, 'test.lock' | ||
end | ||
|
||
should "create lock" do | ||
assert_nil @config.lock.create | ||
assert File.exists?("/tmp/cap.lock") | ||
end | ||
|
||
should "remove lock" do | ||
assert_nil @config.lock.create | ||
assert_nil @config.lock.release | ||
assert !File.exists?("/tmp/cap.lock") | ||
end | ||
|
||
should "check for lock and pass" do | ||
assert_nil @config.lock.release | ||
assert_nil @config.lock.check | ||
end | ||
end |