capistrano-deploy-lock 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7d4652733e283c12103ecd2b697180b3ff456779
4
+ data.tar.gz: f95004d72cf11976f3239df1479cb6e41d11cb5f
5
+ SHA512:
6
+ metadata.gz: e493cdfeb9e74fcc287ffc3dfda4036bee1849eec3f3040fba4809cdf4bf9f5cb2b9e62a9c9a72cec3dceb45354edb4adff5d728dec7f6d487acc845cf9cb4b5
7
+ data.tar.gz: ff6eeb61f098a5b7eb1a89becd4ecfc024e53a203520e10e03371b8fd7ababc43f03c6f6fcc2ff4973eabda2f720d7f44c9fb81fd9b6daaacfa48ff9a40c2060
@@ -0,0 +1 @@
1
+ nbproject/
@@ -0,0 +1,2 @@
1
+ # Cap Deploy Lock Change log
2
+
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Maruf Hasan Bulbul
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ # Cap Deploy Lock 1.0.0
2
+
3
+ Deploy Lock feature for Capistrano 3.x
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'capistrano-deploy-lock', '~> 1.0'
10
+ gem 'capistrano'
11
+
12
+ And then execute:
13
+
14
+ $ bundle install
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install capistrano-deploy-lock
19
+
20
+ ## Usage
21
+
22
+ Require in `Capfile` to use the default task:
23
+
24
+ ```ruby
25
+ require 'capistrano/deploy-lock'
26
+ ```
27
+
28
+ ## Contributing
29
+
30
+ 1. Fork it
31
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
32
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
33
+ 4. Push to the branch (`git push origin my-new-feature`)
34
+ 5. Create new Pull Request
35
+
36
+ ## Credits
37
+
38
+ cap-deploy-lock is maintained by [Maruf Hasan Bulbul](http://www.mhbweb.com).
39
+
40
+ ## License
41
+
42
+ © 2016 Maruf Hasan Bulbul. It is free software and may be redistributed under the terms specified in the LICENSE file.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,22 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "capistrano-deploy-lock"
7
+ spec.version = "1.0.0"
8
+ spec.authors = ["Maruf Hasan Bulbul"]
9
+ spec.email = ["mhb.cse@gmail.com"]
10
+ spec.summary = %q{Deploy lock feature for Capistrano 3.x}
11
+ spec.description = %q{Lock deploy when one deployment is running.}
12
+ spec.homepage = "https://github.com/maruf-freelancer/capistrano-deploy-lock"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_dependency 'capistrano', '~> 3.4'
20
+
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ end
File without changes
@@ -0,0 +1 @@
1
+ load File.expand_path('../tasks/deploy-lock.rake', __FILE__)
@@ -0,0 +1,215 @@
1
+ set :deploy_lock_file, -> { File.join(shared_path, "deploy-lock.yml") }
2
+ set :deploy_lock_roles, -> { :app }
3
+ set :deploy_lock_rack_env, -> { fetch(:rails_env) == "development" ? "development" : "deployment" }
4
+ set :default_lock_expiry, (15 * 60)
5
+ set :deploy_lock, false
6
+ set :lock_message, nil
7
+ set :lock_expiry, nil
8
+
9
+ namespace :deploy do
10
+
11
+ desc "Deploy with a custom deploy lock"
12
+ task :with_lock do
13
+ on roles(fetch(:deploy_lock_roles)) do
14
+ with rails_env: fetch(:deploy_lock_rack_env) do
15
+ invoke 'deploy:lock'
16
+ invoke 'deploy'
17
+ end
18
+ end
19
+ end
20
+
21
+ desc "Set deploy lock with a custom lock message and expiry time"
22
+ task :lock do
23
+ on roles(fetch(:deploy_lock_roles)) do
24
+ with rails_env: fetch(:deploy_lock_rack_env) do
25
+ set :custom_deploy_lock, true
26
+ set :lock_message, ask('lock message', '', echo: true)
27
+ puts "Lock message: #{fetch(:lock_message)}"
28
+
29
+ while fetch(:lock_expiry).nil?
30
+ set :expire_after, ask('minutes of expiry', 'optional', echo: true)
31
+ expire_after = fetch(:expire_after)
32
+
33
+ if expire_after == "optional"
34
+ # Never expire an explicit lock if no time given
35
+ set :lock_expiry, false
36
+ puts colorize("Lock will never expire automatically.", color: 33)
37
+ else
38
+ unless expire_after.to_i == 0
39
+ set :lock_expiry, (Time.now + expire_after.to_i * 60).utc
40
+ puts colorize("Expire after #{fetch(:expire_after)} minutes", color: 33)
41
+ else
42
+ puts colorize("'#{expire_after}' is not valid input. Please try again.")
43
+ end
44
+ end
45
+ end
46
+
47
+ invoke 'deploy:create_lock'
48
+ end
49
+ end
50
+ end
51
+
52
+ desc "Creates a lock file, so that futher deploys will be prevented"
53
+ task :create_lock do
54
+ on roles(fetch(:deploy_lock_roles)) do
55
+ with rails_env: fetch(:deploy_lock_rack_env) do
56
+ if fetch(:deploy_lock)
57
+ puts colorize('Deploy lock already created.', color: 33)
58
+ next
59
+ end
60
+
61
+ if fetch(:lock_message).nil?
62
+ set :lock_message, "Deploying #{fetch(:branch)} branch in #{fetch(:rails_env)}"
63
+ end
64
+
65
+ if fetch(:lock_expiry).nil?
66
+ set :lock_expiry, (Time.now + fetch(:default_lock_expiry)).utc
67
+ end
68
+
69
+ deploy_lock_data = {
70
+ created_at: Time.now.utc,
71
+ username: ENV['USER'],
72
+ expire_at: fetch(:lock_expiry),
73
+ message: fetch(:lock_message).to_s,
74
+ custom: !!fetch(:custom_deploy_lock)
75
+ }
76
+
77
+ write_deploy_lock(deploy_lock_data)
78
+ set :deploy_lock, deploy_lock_data
79
+ end
80
+ end
81
+ end
82
+
83
+ desc "Checks for a deploy lock. If present, deploy is aborted and message is displayed. Any expired locks are deleted."
84
+ task :check_lock do
85
+ on roles(fetch(:deploy_lock_roles)) do
86
+ with rails_env: fetch(:deploy_lock_rack_env) do
87
+ # Don't check the lock if we just created it
88
+ next if fetch(:deploy_lock)
89
+
90
+ fetch_deploy_lock
91
+
92
+ # Return if no lock
93
+ next unless fetch(:deploy_lock)
94
+
95
+ deploy_lock = fetch(:deploy_lock)
96
+
97
+ if deploy_lock[:expire_at] && deploy_lock[:expire_at] < Time.now
98
+ remove_deploy_lock
99
+ next
100
+ end
101
+
102
+ # Check if lock is a custom lock
103
+ set :custom_deploy_lock, deploy_lock[:custom]
104
+
105
+ # Unexpired lock is present, so display the lock message
106
+ puts message(fetch(:application), fetch(:stage), deploy_lock)
107
+
108
+ # Don't raise exception if current user owns the lock, and lock has an expiry time.
109
+ # Just sleep for a few seconds so they have a chance to cancel the deploy with Ctrl-C
110
+ if deploy_lock[:expire_at] && deploy_lock[:username] == ENV['USER']
111
+ 10.downto(1) do |i|
112
+ Kernel.print "\r\e[0;33mDeploy lock was created by you (#{ENV['USER']}). Continuing deploy in #{i}...\e[0m"
113
+ sleep 1
114
+ end
115
+ puts
116
+ else
117
+ exit 1
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ namespace :unlock do
124
+ desc "Unlocks the server for deployment"
125
+ task :default do
126
+ on roles(fetch(:deploy_lock_roles)) do
127
+ with rails_env: fetch(:deploy_lock_rack_env) do
128
+ # Don't automatically remove custom deploy locks created by deploy:lock task
129
+ if fetch(:custom_deploy_lock)
130
+ puts colorize('Not removing custom deploy lock.', color: 33)
131
+ else
132
+ remove_deploy_lock
133
+ puts colorize("Deploy unlocked.", color: 32)
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ task :force do
140
+ on roles(fetch(:deploy_lock_roles)) do
141
+ with rails_env: fetch(:deploy_lock_rack_env) do
142
+ remove_deploy_lock
143
+ puts colorize("Deploy unlocked.", color: 32)
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ before 'deploy:started', 'check_lock' do
150
+ invoke 'deploy:check_lock'
151
+ end
152
+ before 'deploy:started', 'create_lock' do
153
+ invoke 'deploy:create_lock'
154
+ end
155
+ after 'deploy:published', 'unlock' do
156
+ invoke 'deploy:unlock:default'
157
+ end
158
+ after 'deploy:rollback', 'unlock' do
159
+ invoke 'deploy:unlock:default'
160
+ end
161
+
162
+ end
163
+
164
+ # Fetch the deploy lock unless already cached
165
+ def fetch_deploy_lock
166
+ # Return if we know that the deploy lock has just been removed
167
+ return if fetch(:deploy_lock_removed)
168
+
169
+ unless fetch(:deploy_lock)
170
+ # Check all matching servers for a deploy lock.
171
+ on roles(fetch(:deploy_lock_roles)).to_a, in: :parallel do |host|
172
+ if test("[ -f #{fetch(:deploy_lock_file)} ]")
173
+ system "mkdir -p tmp"
174
+ download! fetch(:deploy_lock_file), "tmp/deploy-lock.yml"
175
+ output = File.read("tmp/deploy-lock.yml")
176
+ system "rm -f tmp/deploy-lock.yml"
177
+ if output && output != ""
178
+ set :deploy_lock, YAML.load(output)
179
+ next
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ def write_deploy_lock(deploy_lock)
187
+ sudo %{touch #{fetch(:deploy_lock_file)}}
188
+ upload! StringIO.new(deploy_lock.to_yaml), fetch(:deploy_lock_file)
189
+ end
190
+
191
+ def remove_deploy_lock
192
+ sudo %{rm -f #{fetch(:deploy_lock_file)}}
193
+ set :deploy_lock, nil
194
+ set :deploy_lock_removed, true
195
+ end
196
+
197
+ def message(application, stage, deploy_lock)
198
+ message = "#{application} (#{stage}) was locked"
199
+ message << " at #{deploy_lock[:created_at].localtime.strftime("%c %Z")}"
200
+ message << " by '#{deploy_lock[:username]}'\nMessage: #{deploy_lock[:message]}"
201
+
202
+ if deploy_lock[:expire_at]
203
+ message << "\n\e[0;33mLock expires at #{deploy_lock[:expire_at].localtime.strftime("%H:%M:%S")}\e[0m"
204
+ else
205
+ message << "\n\e[0;33mLock must be manually removed with: cap #{stage} deploy:unlock\e[0m"
206
+ end
207
+
208
+ colorize(message)
209
+ end
210
+
211
+ def colorize(text, options = {})
212
+ attribute = options[:attribute] || 0
213
+ color = options[:color] || 31
214
+ "\e[#{attribute};#{color}m" + text.strip + "\e[0m\n"
215
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-deploy-lock
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Maruf Hasan Bulbul
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-02-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: capistrano
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: Lock deploy when one deployment is running.
42
+ email:
43
+ - mhb.cse@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - CHANGELOG.md
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - capistrano-deploy-lock.gemspec
55
+ - lib/capistrano-deploy-lock.rb
56
+ - lib/capistrano/deploy-lock.rb
57
+ - lib/capistrano/tasks/deploy-lock.rake
58
+ homepage: https://github.com/maruf-freelancer/capistrano-deploy-lock
59
+ licenses:
60
+ - MIT
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubyforge_project:
78
+ rubygems_version: 2.4.8
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Deploy lock feature for Capistrano 3.x
82
+ test_files: []