recap 1.1.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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