recap 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 93a885c11e132676dc0f220d5eb9cbd50508e861
4
- data.tar.gz: fb685ee8cded3a4771b985ea60c2d0823c5d1fbd
3
+ metadata.gz: 001ac16e3f6040b7229222dfabd8c945be2bb1b2
4
+ data.tar.gz: f07c98d248d99f45b774f57711c9769f5d32d2bb
5
5
  SHA512:
6
- metadata.gz: 512cd41ee586903a52d2d65f6c298ece8a0329906ed2b28e20503af8797198098da12d5c5df5172432c85ddeda906b79ced0368d63cbcf47843e69f81fe41342
7
- data.tar.gz: 3d1358e405a2fe2815f2d9280e10b9a344bb8009e235222d83ebb392e13ba5a62d659a18697e896623ab6ef02263aaf9d3e21cf57aed9f1451a5ac5e2e1e0374
6
+ metadata.gz: 8a47f44dcf16f289d474e456a9e6a1fc512e829fe9af591bc653e7b7b50261721d74e702cf4592a8293ffc434474313e90f2a82d031dc548a083aa45017bbf1f
7
+ data.tar.gz: eeb0c99b00c97f82c194b7fda771c6d44382e18ea41fc9114c712366e29dbb7b59ffb0d6bcfe63023566baa358b4a69ecff5bec83f2a66b27b5508bcc60d2a83
@@ -10,7 +10,7 @@ module Recap::Support::CapistranoExtensions
10
10
  end
11
11
 
12
12
  def as_app_once(command, pwd = deploy_to)
13
- sudo "su - #{application_user} -c 'cd #{pwd} && #{command}'", once: true
13
+ sudo "su - #{application_user} -c 'cd #{pwd} && #{command}'", :once => true
14
14
  end
15
15
 
16
16
  # Put a string into a file as the application user
@@ -87,5 +87,31 @@ module Recap::Support::CapistranoExtensions
87
87
  force_full_deploy || changed_files.detect {|p| p[0, path.length] == path}
88
88
  end
89
89
 
90
+ def claim_lock(message)
91
+ begin
92
+ sudo "[ ! -e #{deploy_lock_file} ] && echo '#{message}' > #{deploy_lock_file}"
93
+ rescue Exception => e
94
+ abort %{
95
+ Failed to claim lock: " + capture("cat #{deploy_lock_file}"
96
+
97
+ If you think this lock no longer applies, clear it using the `deploy:unlock` task
98
+ and try again.
99
+ }
100
+ end
101
+ end
102
+
103
+ def release_lock
104
+ sudo "rm -rf #{deploy_lock_file}"
105
+ end
106
+
107
+ def transaction_with_lock(message)
108
+ on_rollback { release_lock }
109
+ transaction do
110
+ claim_lock(message)
111
+ yield
112
+ release_lock
113
+ end
114
+ end
115
+
90
116
  Capistrano::Configuration.send :include, self
91
117
  end
@@ -52,6 +52,13 @@ module Recap::Tasks::Deploy
52
52
  # Force a complete deploy, even if no trigger files have changed
53
53
  set(:force_full_deploy, false)
54
54
 
55
+ # A lock file is used to ensure deployments don't overlap
56
+ set(:deploy_lock_file) { "#{deploy_to}/.recap-lock"}
57
+
58
+ # The lock file is set to include a message that can be displayed
59
+ # if claiming the lock fails
60
+ set(:deploy_lock_message) { "Deployment in progress (started #{Time.now.to_s})" }
61
+
55
62
  # To authenticate with github or other git servers, it is easier (and cleaner) to forward the
56
63
  # deploying user's ssh key than manage keys on deployment servers.
57
64
  ssh_options[:forward_agent] = true
@@ -87,7 +94,7 @@ module Recap::Tasks::Deploy
87
94
  # tags the release and restarts the application.
88
95
  desc "Deploy the latest application code"
89
96
  task :default do
90
- transaction do
97
+ transaction_with_lock deploy_lock_message do
91
98
  top.env.set
92
99
  update_code
93
100
  tag
@@ -148,5 +155,18 @@ module Recap::Tasks::Deploy
148
155
  task :destroy do
149
156
  sudo "rm -rf #{deploy_to}"
150
157
  end
158
+
159
+ # As well as locking during each deployment, locks can manually be set with `deploy:lock`. To
160
+ # use a custom lock message, do `DEPLOY_LOCK_MESSAGE="My message" cap deploy:lock`. Locking
161
+ # prevents deployments, but not other tasks.
162
+ task :lock do
163
+ claim_lock ENV['DEPLOY_LOCK_MESSAGE'] || "Manually locked at #{Time.now}"
164
+ end
165
+
166
+ # To unlock a manually set lock, or a lock that has been left behind in error, the `deploy:unlock`
167
+ # task can be used.
168
+ task :unlock do
169
+ release_lock
170
+ end
151
171
  end
152
172
  end
data/lib/recap/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Recap
2
- VERSION = '1.1.3'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -161,6 +161,7 @@ describe Recap::Tasks::Deploy do
161
161
 
162
162
  describe 'deploy' do
163
163
  it 'runs env:set, deploy:update_code, deploy:tag and then deploy:restart tasks' do
164
+ namespace.stubs(:transaction_with_lock).yields
164
165
  env = stub('env')
165
166
  config.stubs(:env).returns(env)
166
167
  env.expects('set')
@@ -170,20 +171,20 @@ describe Recap::Tasks::Deploy do
170
171
  config.find_and_execute_task('deploy')
171
172
  end
172
173
 
173
- it 'calls deploy:update_code task within a transaction' do
174
- namespace.stubs(:transaction)
174
+ it 'calls deploy:update_code task within a locked transaction' do
175
+ namespace.stubs(:transaction_with_lock)
175
176
  namespace.expects(:update_code).never
176
177
  config.find_and_execute_task('deploy')
177
178
  end
178
179
 
179
- it 'calls deploy:tag task within a transaction' do
180
- namespace.stubs(:transaction)
180
+ it 'calls deploy:tag task within a locked transaction' do
181
+ namespace.stubs(:transaction_with_lock)
181
182
  namespace.expects(:tag).never
182
183
  config.find_and_execute_task('deploy')
183
184
  end
184
185
 
185
186
  it 'calls restart outside the transaction' do
186
- namespace.stubs(:transaction)
187
+ namespace.stubs(:transaction_with_lock)
187
188
  namespace.expects(:restart)
188
189
  config.find_and_execute_task('deploy')
189
190
  end
@@ -242,6 +243,28 @@ describe Recap::Tasks::Deploy do
242
243
  end
243
244
  end
244
245
 
246
+ describe 'deploy:lock' do
247
+ it 'locks deployments with the message DEPLOY_LOCK_MESSAGE if available' do
248
+ ENV.stubs("[]").with("DEPLOY_LOCK_MESSAGE").returns("custom-message")
249
+ namespace.expects(:claim_lock).with("custom-message")
250
+ namespace.find_and_execute_task('deploy:lock')
251
+ end
252
+
253
+ it 'locks deployments with a default message if no message provided' do
254
+ now = Time.now
255
+ Time.stubs(:now).returns(now)
256
+ namespace.expects(:claim_lock).with("Manually locked at #{Time.now}")
257
+ namespace.find_and_execute_task('deploy:lock')
258
+ end
259
+ end
260
+
261
+ describe 'deploy:unlock' do
262
+ it 'removes any existing locks' do
263
+ namespace.expects(:release_lock)
264
+ namespace.find_and_execute_task('deploy:unlock')
265
+ end
266
+ end
267
+
245
268
  describe 'deploy:restart' do
246
269
  it 'does nothing (but can be overidden by other recipes)' do
247
270
  namespace.expects(:run).never
@@ -258,4 +281,4 @@ describe Recap::Tasks::Deploy do
258
281
  end
259
282
  end
260
283
  end
261
- end
284
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: recap
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Ward
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-04 00:00:00.000000000 Z
11
+ date: 2013-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capistrano
@@ -223,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
223
223
  version: '0'
224
224
  requirements: []
225
225
  rubyforge_project:
226
- rubygems_version: 2.0.2
226
+ rubygems_version: 2.0.3
227
227
  signing_key:
228
228
  specification_version: 4
229
229
  summary: GIT based deployment recipes for Capistrano