Module: Capistrano::Caplock

Defined in:
lib/caplock.rb

Defined Under Namespace

Classes: LockedDeployError

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.load_into(configuration) ⇒ Object



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
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/caplock.rb', line 37

def self.load_into(configuration)
  configuration.load do
    set :lockfile, "cap.lock"

    # internal
    set :keep_lock, false

    namespace :lock do
      desc "check lock"
      task :check, :roles => :app do
        if caplock.remote_file_exists?("#{deploy_to}/#{lockfile}")
          keep_lock = true
          raise LockedDeployError, "\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
        on_rollback { find_and_execute_task("lock:release") }
      end

      desc "release lock"
      task :release, :roles => :app do
         run "rm -f #{deploy_to}/#{lockfile}" unless keep_lock
      end
    end

    # Deployment
    before "deploy:update_code", "lock:check"
    after "lock:check", "lock:create"
    after "deploy", "lock:release"

    # Rollback
    before "deploy:rollback", "lock:check"
    after "deploy:rollback", "lock:release"
    
  end
end

Instance Method Details

#remote_file_content_same_as?(full_path, content) ⇒ Boolean

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.

Returns:

  • (Boolean)


27
28
29
# File 'lib/caplock.rb', line 27

def remote_file_content_same_as?(full_path, content)
  Digest::MD5.hexdigest(content) == top.capture("md5sum #{full_path} | awk '{ print $1 }'").strip
end

#remote_file_differs?(full_path, content) ⇒ Boolean

Returns Boolean indicating whether the remote file is present and has the same contents as the String in content.

Returns:

  • (Boolean)


33
34
35
# File 'lib/caplock.rb', line 33

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

#remote_file_exists?(full_path) ⇒ Boolean

Returns Boolean value indicating whether file exists on server

Returns:

  • (Boolean)


20
21
22
# File 'lib/caplock.rb', line 20

def remote_file_exists?(full_path)
  remote_filetest_passes?('-e', full_path)
end

#remote_filetest_passes?(filetest, full_path) ⇒ Boolean

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).

Returns:

  • (Boolean)


10
11
12
# File 'lib/caplock.rb', line 10

def remote_filetest_passes?(filetest, full_path)
  'true' ==  top.capture("if [ #{filetest} #{full_path} ]; then echo 'true'; fi").strip
end

Checks if a symlink exists on the remote machine.

Returns:

  • (Boolean)


15
16
17
# File 'lib/caplock.rb', line 15

def remote_symlink_exists?(full_path)
  remote_filetest_passes?('-L', full_path)
end