capistrano_deploy_lock 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +14 -1
- data/lib/capistrano/deploy_lock.rb +24 -2
- data/lib/capistrano/recipes/deploy_lock.rb +44 -28
- data/lib/capistrano_deploy_lock/version.rb +1 -1
- metadata +5 -13
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NWVmOTJlNzg5NjYzZTY0NzJiOGViMzBiZDFhYzk0ODhmYjQ0OTE5OA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MDEzMjM3MDBmMTU1ZjBhZTI3OGM3YTlhNjNhMGZmNGEzNTU1MzVlMQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NjMyYTFhN2U5OTE2MjI1MDlmYjg2NzYyN2NkODhiNzM4Y2M1MDA5YmYzYmU5
|
10
|
+
MGJmYzQ0MmQ1MWRlODFhOTA3MWUzYmE4YjE0NDQ3NTQ4ZDgwYjg4ZTU3MGMx
|
11
|
+
YjE5YTdiZjI1ZTk2YmQwODQwOWM3YTExN2MyODA1ZTk1MmRjMzY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ODgzNjA2NzlhMGIwZTllOTYyN2NmNzg0ZWM5Y2IxNzEyZjIyNmU5YjJjYjNm
|
14
|
+
MWMyNGU2NTM1YWJiZTE1YmJmMzk4ZDBlYjE2MjBmYWZiMTEyOTUyNGIyN2Mz
|
15
|
+
Nzc5NmQwZGMzZDdjZjE2NzI5OWVkOThkYzIzNWIzMDJmZDMwOWM=
|
data/README.md
CHANGED
@@ -48,7 +48,6 @@ The following task will be run after deploy:
|
|
48
48
|
* Removes any default deploy locks. If you set a custom lock, it will not be removed at this step.
|
49
49
|
* You can remove a custom deploy lock by running `cap deploy:unlock` by itself, or by chaining `deploy:unlock:force` at the end of the command.
|
50
50
|
|
51
|
-
|
52
51
|
## Tasks
|
53
52
|
|
54
53
|
### `deploy:with_lock`
|
@@ -102,6 +101,20 @@ The lock file will be created at `#{shared_path}/capistrano.lock.yml` by default
|
|
102
101
|
set :deploy_lockfile, "path/to/deploy/lock/file"
|
103
102
|
|
104
103
|
|
104
|
+
## MOTD script
|
105
|
+
|
106
|
+
If you install the gem on your server, you can use the `cap_deploy_lock_msg` script to display the lock status when you login via SSH.
|
107
|
+
|
108
|
+
Usage:
|
109
|
+
|
110
|
+
cap_deploy_lock_msg <application_name> <stage> <path/to/lock_file.yml>
|
111
|
+
|
112
|
+
If you are using `update-motd` on Ubuntu, create `/etc/update-motd.d/10-deploy-lock` with the following:
|
113
|
+
|
114
|
+
#!/bin/sh
|
115
|
+
/usr/local/bin/cap_deploy_lock_msg application stage /var/www/apps/application/shared/capistrano.lock.yml
|
116
|
+
|
117
|
+
|
105
118
|
## Thanks
|
106
119
|
|
107
120
|
Special thanks to [David Bock](https://github.com/bokmann), who wrote the [deploy_lock.rb](https://github.com/bokmann/dunce-cap/blob/master/recipes/deploy_lock.rb)
|
@@ -30,9 +30,31 @@ module Capistrano
|
|
30
30
|
if deploy_lock[:expire_at]
|
31
31
|
if defined?(Capistrano::DateHelper)
|
32
32
|
expires_in = Capistrano::DateHelper.distance_of_time_in_words_to_now deploy_lock[:expire_at].localtime
|
33
|
-
message << "\
|
33
|
+
message << "\nLock expires in #{expires_in}"
|
34
34
|
else
|
35
|
-
message << "\
|
35
|
+
message << "\nLock expires at #{deploy_lock[:expire_at].localtime.strftime("%H:%M:%S")}"
|
36
|
+
end
|
37
|
+
else
|
38
|
+
message << "\nLock must be manually removed with: cap #{stage} deploy:unlock"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.expired_message(application, stage, deploy_lock)
|
43
|
+
message = "#{application} (#{stage}) was locked"
|
44
|
+
if defined?(Capistrano::DateHelper)
|
45
|
+
locked_ago = Capistrano::DateHelper.distance_of_time_in_words_to_now deploy_lock[:created_at].localtime
|
46
|
+
message << " #{locked_ago} ago"
|
47
|
+
else
|
48
|
+
message << " at #{deploy_lock[:created_at].localtime}"
|
49
|
+
end
|
50
|
+
message << " by '#{deploy_lock[:username]}'\nMessage: #{deploy_lock[:message]}"
|
51
|
+
|
52
|
+
if deploy_lock[:expire_at]
|
53
|
+
if defined?(Capistrano::DateHelper)
|
54
|
+
expires_in = Capistrano::DateHelper.distance_of_time_in_words_to_now deploy_lock[:expire_at].localtime
|
55
|
+
message << "\nLock expired #{expires_in} ago, unlocking..."
|
56
|
+
else
|
57
|
+
message << "\nLock expired at #{deploy_lock[:expire_at].localtime.strftime("%H:%M:%S")}"
|
36
58
|
end
|
37
59
|
else
|
38
60
|
message << "\nLock must be manually removed with: cap #{stage} deploy:unlock"
|
@@ -1,11 +1,11 @@
|
|
1
1
|
Capistrano::Configuration.instance(:must_exist).load do
|
2
|
-
before "deploy",
|
3
|
-
before "deploy",
|
4
|
-
before "deploy",
|
5
|
-
after "deploy", "deploy:unlock"
|
2
|
+
before "deploy:update_code", "deploy:check_lock"
|
3
|
+
before "deploy:update_code", "deploy:refresh_lock"
|
4
|
+
before "deploy:update_code", "deploy:create_lock"
|
5
|
+
after "deploy:create_symlink", "deploy:unlock"
|
6
6
|
|
7
|
-
# Default lock expiry of
|
8
|
-
_cset :default_lock_expiry, (
|
7
|
+
# Default lock expiry of 10 minutes (in case deploy crashes or is interrupted)
|
8
|
+
_cset :default_lock_expiry, (10 * 60)
|
9
9
|
_cset(:deploy_lockfile) { "#{shared_path}/capistrano.lock.yml" }
|
10
10
|
|
11
11
|
# Show lock message as bright red
|
@@ -14,6 +14,9 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
14
14
|
namespace :deploy do
|
15
15
|
# Fetch the deploy lock unless already cached
|
16
16
|
def fetch_deploy_lock
|
17
|
+
# Return if we know that the deploy lock has just been removed
|
18
|
+
return if self[:deploy_lock_removed]
|
19
|
+
|
17
20
|
if self[:deploy_lock].nil?
|
18
21
|
lock_file = capture("[ -e #{deploy_lockfile} ] && cat #{deploy_lockfile} || true").strip
|
19
22
|
if lock_file != ""
|
@@ -28,6 +31,12 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
28
31
|
put deploy_lock.to_yaml, deploy_lockfile, :mode => 0777
|
29
32
|
end
|
30
33
|
|
34
|
+
def remove_deploy_lock
|
35
|
+
run "rm -f #{deploy_lockfile}"
|
36
|
+
self[:deploy_lock] = nil
|
37
|
+
self[:deploy_lock_removed] = true
|
38
|
+
end
|
39
|
+
|
31
40
|
desc "Deploy with a custom deploy lock"
|
32
41
|
task :with_lock do
|
33
42
|
lock
|
@@ -37,6 +46,7 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
37
46
|
desc "Set deploy lock with a custom lock message and expiry time"
|
38
47
|
task :lock do
|
39
48
|
set :lock_message, Capistrano::CLI.ui.ask("Lock Message: ")
|
49
|
+
set :custom_deploy_lock, true
|
40
50
|
|
41
51
|
while self[:lock_expiry].nil?
|
42
52
|
expiry_str = Capistrano::CLI.ui.ask("Expire lock at? (optional): ")
|
@@ -60,13 +70,12 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
60
70
|
end
|
61
71
|
|
62
72
|
create_lock
|
63
|
-
set :custom_deploy_lock, true
|
64
73
|
end
|
65
74
|
|
66
75
|
desc "Creates a lock file, so that futher deploys will be prevented"
|
67
76
|
task :create_lock do
|
68
|
-
if self[:
|
69
|
-
logger.info '
|
77
|
+
if self[:deploy_lock]
|
78
|
+
logger.info 'Deploy lock already created.'
|
70
79
|
next
|
71
80
|
end
|
72
81
|
|
@@ -77,13 +86,16 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
77
86
|
set :lock_expiry, (Time.now + default_lock_expiry).utc
|
78
87
|
end
|
79
88
|
|
80
|
-
|
89
|
+
deploy_lock_data = {
|
81
90
|
:created_at => Time.now.utc,
|
82
91
|
:username => ENV['USER'],
|
83
92
|
:expire_at => self[:lock_expiry],
|
84
|
-
:message => self[:lock_message]
|
93
|
+
:message => self[:lock_message],
|
94
|
+
:custom => !!self[:custom_deploy_lock]
|
85
95
|
}
|
86
|
-
write_deploy_lock(
|
96
|
+
write_deploy_lock(deploy_lock_data)
|
97
|
+
|
98
|
+
self[:deploy_lock] = deploy_lock_data
|
87
99
|
end
|
88
100
|
|
89
101
|
namespace :unlock do
|
@@ -93,37 +105,40 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
93
105
|
if self[:custom_deploy_lock]
|
94
106
|
logger.info 'Not removing custom deploy lock.'
|
95
107
|
else
|
96
|
-
|
108
|
+
remove_deploy_lock
|
97
109
|
end
|
98
110
|
end
|
99
111
|
|
100
112
|
task :force do
|
101
|
-
|
113
|
+
remove_deploy_lock
|
102
114
|
end
|
103
115
|
end
|
104
116
|
|
105
117
|
desc "Checks for a deploy lock. If present, deploy is aborted and message is displayed. Any expired locks are deleted."
|
106
118
|
task :check_lock do
|
107
119
|
# Don't check the lock if we just created it
|
108
|
-
next if self[:
|
120
|
+
next if self[:deploy_lock]
|
109
121
|
|
110
122
|
fetch_deploy_lock
|
111
123
|
# Return if no lock
|
112
124
|
next unless self[:deploy_lock]
|
113
125
|
|
114
126
|
if deploy_lock[:expire_at] && deploy_lock[:expire_at] < Time.now
|
115
|
-
logger.info
|
116
|
-
|
127
|
+
logger.info Capistrano::DeployLock.expired_message(application, stage, deploy_lock)
|
128
|
+
remove_deploy_lock
|
117
129
|
next
|
118
130
|
end
|
119
131
|
|
132
|
+
# Check if lock is a custom lock
|
133
|
+
self[:custom_deploy_lock] = deploy_lock[:custom]
|
134
|
+
|
120
135
|
# Unexpired lock is present, so display the lock message
|
121
136
|
logger.important Capistrano::DeployLock.message(application, stage, deploy_lock)
|
122
137
|
|
123
|
-
# Don't raise exception if current user owns the lock.
|
124
|
-
# Just sleep so they have a chance to Ctrl-C
|
125
|
-
if deploy_lock[:username] == ENV['USER']
|
126
|
-
|
138
|
+
# Don't raise exception if current user owns the lock, and lock has an expiry time.
|
139
|
+
# Just sleep for a few seconds so they have a chance to cancel the deploy with Ctrl-C
|
140
|
+
if deploy_lock[:expire_at] && deploy_lock[:username] == ENV['USER']
|
141
|
+
5.downto(1) do |i|
|
127
142
|
Kernel.print "\rDeploy lock was created by you (#{ENV['USER']}). Continuing deploy in #{i}..."
|
128
143
|
sleep 1
|
129
144
|
end
|
@@ -135,22 +150,23 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
135
150
|
|
136
151
|
desc "Refreshes an existing deploy lock's expiry time, if it is less than the default time"
|
137
152
|
task :refresh_lock do
|
138
|
-
# Don't refresh custom locks
|
139
|
-
next if self[:custom_deploy_lock]
|
140
|
-
|
141
153
|
fetch_deploy_lock
|
142
154
|
next unless self[:deploy_lock]
|
143
155
|
|
144
|
-
#
|
156
|
+
# Don't refresh custom locks
|
157
|
+
if deploy_lock[:custom]
|
158
|
+
logger.info 'Not refreshing custom deploy lock.'
|
159
|
+
next
|
160
|
+
end
|
161
|
+
|
162
|
+
# Refresh lock expiry time if it's going to expire
|
145
163
|
if deploy_lock[:expire_at] && deploy_lock[:expire_at] < (Time.now + default_lock_expiry)
|
146
164
|
logger.info "Resetting lock expiry to default..."
|
165
|
+
deploy_lock[:username] = ENV['USER']
|
147
166
|
deploy_lock[:expire_at] = (Time.now + default_lock_expiry).utc
|
148
167
|
|
149
168
|
write_deploy_lock(deploy_lock)
|
150
169
|
end
|
151
|
-
|
152
|
-
# Set the deploy_lock_created flag so that the lock isn't automatically removed after deploy
|
153
|
-
set :custom_deploy_lock, true
|
154
170
|
end
|
155
171
|
end
|
156
172
|
end
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capistrano_deploy_lock
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Nathan Broadbent
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2013-09-12 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
13
|
description: Lock a server during deploy, to prevent people from deploying at the
|
15
14
|
same time.
|
@@ -35,32 +34,25 @@ files:
|
|
35
34
|
homepage: https://github.com/ndbroadbent/capistrano_deploy_lock
|
36
35
|
licenses:
|
37
36
|
- MIT
|
37
|
+
metadata: {}
|
38
38
|
post_install_message:
|
39
39
|
rdoc_options: []
|
40
40
|
require_paths:
|
41
41
|
- lib
|
42
42
|
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
-
none: false
|
44
43
|
requirements:
|
45
44
|
- - ! '>='
|
46
45
|
- !ruby/object:Gem::Version
|
47
46
|
version: '0'
|
48
|
-
segments:
|
49
|
-
- 0
|
50
|
-
hash: -2094697491794115315
|
51
47
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
-
none: false
|
53
48
|
requirements:
|
54
49
|
- - ! '>='
|
55
50
|
- !ruby/object:Gem::Version
|
56
51
|
version: '0'
|
57
|
-
segments:
|
58
|
-
- 0
|
59
|
-
hash: -2094697491794115315
|
60
52
|
requirements: []
|
61
53
|
rubyforge_project:
|
62
|
-
rubygems_version:
|
54
|
+
rubygems_version: 2.0.5
|
63
55
|
signing_key:
|
64
|
-
specification_version:
|
56
|
+
specification_version: 4
|
65
57
|
summary: Capistrano Deploy Lock
|
66
58
|
test_files: []
|