new_artrails_capistrano 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in new_artrails_capistrano.gemspec
6
+ gemspec
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A sample Guardfile
4
+ # More info at https://github.com/guard/guard#readme
5
+
6
+ ## Uncomment and set this to only include directories you want to watch
7
+ # directories %w(app lib config test spec features) \
8
+ # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
9
+
10
+ ## Note: if you are using the `directories` clause above and you are not
11
+ ## watching the project directory ('.'), then you will want to move
12
+ ## the Guardfile to a watched dir and symlink it back, e.g.
13
+ #
14
+ # $ mkdir config
15
+ # $ mv Guardfile config/
16
+ # $ ln -s config/Guardfile .
17
+ #
18
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
19
+
20
+ # USE PRIVATE GLOBAL CONFIG TO CUSTOMIZE:
21
+ # ~/.guard.rb
22
+ # notification :growl # on OSX with growl notifications installed
23
+ # clearing :on # clears terminal
24
+ #
25
+
26
+ guard 'reek' do
27
+ watch(/.+\.rb$/)
28
+ watch('.reek')
29
+ end
30
+
31
+ # Note: The cmd option is now required due to the increasing number of ways
32
+ # rspec may be run, below are examples of the most common uses.
33
+ # * bundler: 'bundle exec rspec'
34
+ # * bundler binstubs: 'bin/rspec'
35
+ # * spring: 'bin/rspec' (This will use spring if running and you have
36
+ # installed the spring binstubs per the docs)
37
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
38
+ # * 'just' rspec: 'rspec'
39
+
40
+ guard :rspec, cmd: 'bundle exec rspec' do
41
+ require 'guard/rspec/dsl'
42
+ dsl = Guard::RSpec::Dsl.new(self)
43
+
44
+ # Feel free to open issues for suggestions and improvements
45
+
46
+ # RSpec files
47
+ rspec = dsl.rspec
48
+ watch(rspec.spec_helper) { rspec.spec_dir }
49
+ watch(rspec.spec_support) { rspec.spec_dir }
50
+ watch(rspec.spec_files)
51
+
52
+ # Ruby files
53
+ ruby = dsl.ruby
54
+ dsl.watch_spec_files_for(ruby.lib_files)
55
+
56
+ # Rails files
57
+ rails = dsl.rails(view_extensions: %w[erb haml slim])
58
+ dsl.watch_spec_files_for(rails.app_files)
59
+ dsl.watch_spec_files_for(rails.views)
60
+
61
+ watch(rails.controllers) do |m|
62
+ [
63
+ rspec.spec.call("routing/#{m[1]}_routing"),
64
+ rspec.spec.call("controllers/#{m[1]}_controller"),
65
+ rspec.spec.call("acceptance/#{m[1]}")
66
+ ]
67
+ end
68
+
69
+ # Rails config changes
70
+ watch(rails.spec_helper) { rspec.spec_dir }
71
+ watch(rails.routes) { "#{rspec.spec_dir}/routing" }
72
+ watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
73
+
74
+ # Capybara features specs
75
+ watch(rails.view_dirs) { |m| rspec.spec.call("features/#{m[1]}") }
76
+ watch(rails.layouts) { |m| rspec.spec.call("features/#{m[1]}") }
77
+
78
+ # Turnip features and steps
79
+ watch(%r{^spec/acceptance/(.+)\.feature$})
80
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
81
+ Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance'
82
+ end
83
+ end
84
+
85
+ # guard :rubocop do
86
+ # watch(/.+\.rb$/)
87
+ # watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
88
+ # watch(%r{(?:.+/)?\.rubocop_todo\.yml$}) { |m| File.dirname(m[0]) }
89
+ # end
90
+ # split the development into parts (e.g. frontend and backend)
91
+ # guard -g <group>
92
+ scope group: :specs
93
+
94
+ group 'specs', halt_on_fail: false do
95
+ guard :bundler do
96
+ require 'guard/bundler'
97
+ require 'guard/bundler/verify'
98
+ helper = Guard::Bundler::Verify.new
99
+
100
+ files = ['Gemfile']
101
+ files += Dir['*.gemspec'] if files.any? { |f| helper.uses_gemspec?(f) }
102
+
103
+ # Assume files are symlinked from somewhere
104
+ files.each { |file| watch(helper.real_path(file)) }
105
+ end
106
+
107
+ # cmd: show less output, but still provide enough info on a failed test
108
+ guard :rspec, all_on_start: true, cmd: 'rspec -c -fp' do
109
+ watch(%r{^spec/.+_spec\.rb$})
110
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
111
+ watch('spec/spec_helper.rb') { 'spec/lib' }
112
+ end
113
+
114
+ guard :rubocop, all_on_start: true, cmd: 'rubocop --format fuubar -F -D' do
115
+ watch(%r{^spec/.+_spec\.rb$})
116
+ watch(%r{^lib/(.+)\.rb$})
117
+ end
118
+ end
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Efigence S.A.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,28 @@
1
+ .codeclimate.yml
2
+ .gitignore
3
+ .rspec_status
4
+ .rubocop.yml
5
+ .rubocop_todo.yml
6
+ .travis.yml
7
+ CHANGELOG.md
8
+ CODE_OF_CONDUCT.md
9
+ Gemfile
10
+ Guardfile
11
+ LICENSE.txt
12
+ Manifest.txt
13
+ README.md
14
+ Rakefile
15
+ bin/console
16
+ bin/setup
17
+ config.reek
18
+ lib/.keep
19
+ lib/capistrano/new_artrails_capistrano.rb
20
+ lib/capistrano/new_artrails_capistrano/version.rb
21
+ lib/capistrano/tasks/new_artrails_capistrano.rake
22
+ lib/new_artrails_capistrano.rb
23
+ new_artrails_capistrano.gemspec
24
+ rubocop_output.json
25
+ spec/lib/.keep
26
+ spec/lib/capistrano/new_artrails_capistrano_spec.rb
27
+ spec/new_artrails_capistrano_spec.rb
28
+ spec/spec_helper.rb
@@ -0,0 +1,54 @@
1
+ # Capistrano [![Gem Version](https://badge.fury.io/rb/new_artrails_capistrano.svg)](https://badge.fury.io/rb/new_artrails_capistrano) [![Build Status](https://travis-ci.org/efigence/new_artrails_capistrano.svg?branch=master)](https://travis-ci.org/efigence/new_artrails_capistrano) [![Coverage Status](https://coveralls.io/repos/github/efigence/new_artrails_capistrano/badge.svg?branch=master)](https://coveralls.io/github/efigence/new_artrails_capistrano?branch=master) [![Code Climate](https://codeclimate.com/github/efigence/new_artrails_capistrano/badges/gpa.svg)](https://codeclimate.com/github/efigence/new_artrails_capistrano)
2
+
3
+ Capistrano 3 deployment using Rsync, a local Git repository and sudo as user.
4
+
5
+ This gem is a viable alternative to Git deployments on production machines. Commands can be run under a different user than the `deploy` user.
6
+
7
+ ## Dependencies
8
+
9
+ * None
10
+
11
+ ## Installation
12
+
13
+ ```
14
+ $ echo '2.1.1' > .ruby-version
15
+ $ rvm use
16
+ ```
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem 'new_artrails_capistrano'
22
+ ```
23
+
24
+ And then execute:
25
+
26
+ $ bundle
27
+
28
+ Or install it yourself as:
29
+
30
+ $ gem install new_artrails_capistrano
31
+
32
+ ## Usage
33
+
34
+ ```
35
+ ```
36
+
37
+ ## Development
38
+
39
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
40
+
41
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
42
+
43
+ ```
44
+ $ guard # require './lib/new_artrails_capistrano'
45
+ ```
46
+
47
+ ## Contributing
48
+
49
+ Bug reports and pull requests are welcome on GitHub at https://github.com/efigence/new_artrails_capistrano. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
50
+
51
+
52
+ ## License
53
+
54
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ RuboCop::RakeTask.new(:rubocop) do |task|
10
+ task.requires << 'rubocop-rspec'
11
+ task.formatters = ['json']
12
+ task.options = ['--display-cop-names', '-orubocop_output.json']
13
+ end
14
+
15
+ task default: :spec
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'new_artrails_capistrano'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require 'irb'
15
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1 @@
1
+ # https://github.com/troessner/reek/blob/master/defaults.reek
File without changes
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ load File.expand_path('../tasks/new_artrails_capistrano.rake', __FILE__)
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capistrano
4
+ module NewArtrailsCapistrano
5
+ VERSION = '0.0.1'
6
+ end
7
+ end
@@ -0,0 +1,742 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake'
4
+ require 'capistrano/all'
5
+ # require 'capistrano/setup'
6
+ require 'capistrano/deploy'
7
+ include Capistrano::DSL
8
+ # require 'capistrano/rails'
9
+ # require 'capistrano/bundler'
10
+ require 'capistrano/rails/assets'
11
+ # require 'capistrano/rails/migrations'
12
+ require "capistrano/scm/git"
13
+ install_plugin Capistrano::SCM::Git
14
+ require 'capistrano/new_artrails_capistrano/helpers'
15
+ require 'capistrano/new_artrails_capistrano/front_helpers'
16
+
17
+ include Capistrano::NewArtrailsCapistrano::Helpers
18
+ include Capistrano::NewArtrailsCapistrano::FrontHelpers
19
+
20
+ remote_cache = lambda do
21
+ cache = fetch(:remote_cache) || 'shared/cached-copy-deploy'
22
+ cache = deploy_to + '/' + cache if cache && cache !~ /^\//
23
+ cache
24
+ end
25
+
26
+ namespace :load do
27
+ task :defaults do
28
+ set :new_artrails_capistrano_sudo_as, -> { new_artrails_capistrano_sudo_as }
29
+ # rsync
30
+ if RUBY_PLATFORM =~ /mswin|mingw/
31
+ set :rsync_options, '-az --delete --exclude=\'.git*\' --exclude=\'.rvmrc\' --exclude=\'vendor/bundle\' --exclude=\'doc\' --delete-excluded -e "ssh -i C:\\keys\\openssh-private-key.pub"'
32
+ else # linux, mac
33
+ set :rsync_exclude, %w[.git* .rvmrc* vendor/bundle doc]
34
+ set :rsync_options, %w[-az --delete --delete-excluded]
35
+ end
36
+ set :rsync_include, %w[]
37
+
38
+ set :local_cache, -> { "/tmp/.#{fetch(:application)}_rsync_cache" }
39
+
40
+ set :repo_url, File.expand_path('.')
41
+
42
+ # :auto (default): just tries to find the correct path. ~/.rvm wins over /usr/local/rvm
43
+ # :system: defines the RVM path to /usr/local/rvm
44
+ # :user: defines the RVM path to ~/.rvm
45
+ # deploy.rb or stage file (staging.rb, production.rb or else)
46
+ set :rvm_type, :system # Defaults to: :auto
47
+ set :rvm_ruby_version, :default # Defaults to: 'default'
48
+ # set :rvm_custom_path, '~/.myveryownrvm' # only needed if not detected
49
+
50
+ set :new_artrails_capistrano_log_dir_name, -> { File.basename(fetch(:deploy_to) || fetch(:application)) }
51
+
52
+ set :ssh_options, {
53
+ keys: %w(/home/#{user}/.ssh/id_rsa),
54
+ auth_methods: %w(publickey password)
55
+ }
56
+
57
+ set :asset_env, "RAILS_GROUPS=assets"
58
+ set :assets_prefix, "assets"
59
+
60
+ set :use_sudo, false
61
+
62
+ set :remote_cache, -> { "shared/cached-copy-#{fetch(:local_user) || 'deploy'}" }
63
+
64
+ # no proxy for localhost
65
+ set :proxy_host, nil # e.g. 'proxy.non.3dart.com'
66
+ set :proxy_port, nil # e.g. '3128'
67
+
68
+ set :app_address, nil
69
+
70
+ set :skip_deploy_tagging, true
71
+ end
72
+ end
73
+
74
+ namespace :artrails do
75
+ task :set_current_revision do
76
+ on roles :app, exclude: :no_release do |task|
77
+ run_locally do
78
+ File.open(File.join(backend_local_cache, 'REVISION'), 'w') { |f| f.puts(backend_revision) }
79
+ File.open(File.join(backend_local_cache, 'BRANCH'), 'w+') { |f| f.puts(backend_branch) }
80
+
81
+ # FIXME:
82
+ # find_servers(:roles => :app, :except => { :no_release => true }).each do |server|
83
+ server = host
84
+
85
+ system("mkdir -p #{backend_local_cache}")
86
+ system("cp #{backend_local_cache}/REVISION #{backend_local_cache}/")
87
+ system("cp #{backend_local_cache}/BRANCH #{backend_local_cache}/")
88
+ end
89
+ end
90
+ end
91
+ task :update_versions_html do
92
+ on roles :app, exclude: :no_release do |task|
93
+ versions_file = "#{shared_path}/versions.html"
94
+ revision_log_message_cleaned = %Q{#{revision_log_message}}
95
+ cmd = <<-CMD
96
+ sudo -iu #{new_artrails_capistrano_sudo_as} touch #{versions_file} &&
97
+ sudo -iu #{new_artrails_capistrano_sudo_as} chmod g+w #{versions_file} &&
98
+ sudo -iu #{new_artrails_capistrano_sudo_as} chgrp mongrel #{versions_file} &&
99
+ echo "#{revision_log_message_cleaned}<br />"|cat - #{versions_file} > /tmp/#{fetch(:application)}_#{fetch(:stage)}_versions.html &&
100
+ chmod g+rw /tmp/#{fetch(:application)}_#{fetch(:stage)}_versions.html &&
101
+ chmod g+rw /tmp/#{fetch(:application)}_#{fetch(:stage)}_versions.html &&
102
+ sudo -iu #{new_artrails_capistrano_sudo_as} cp /tmp/#{fetch(:application)}_#{fetch(:stage)}_versions.html #{versions_file} &&
103
+ sudo -iu #{new_artrails_capistrano_sudo_as} ln -fs #{versions_file} #{release_path}/public/versions.html
104
+ CMD
105
+ new_artrails_capistrano_run cmd.gsub(/\r?\n/, '').gsub(/\s+/, ' ')
106
+ end
107
+ end
108
+ desc <<-DESC
109
+ set symlinks for configs logs, set rights and check is it working
110
+ DESC
111
+ namespace :symlink do
112
+ task :config do
113
+ on roles :app, exclude: :no_release do |task|
114
+ # FIXME:
115
+ # servers = find_servers_for_task(current_task)
116
+ # servers.each do |server|
117
+ server = host
118
+ fetch(:new_artrails_capistrano_config_files).each do |cf|
119
+ new_artrails_capistrano_run "ln -fs #{shared_path}/config/#{cf} #{release_path}/config/#{cf}"
120
+ end
121
+ end
122
+ end
123
+
124
+ task :log do
125
+ on roles :app, exclude: :no_release do
126
+ new_artrails_capistrano_run "rm -rf #{release_path}/log"
127
+ new_artrails_capistrano_run "ln -s /var/log/#{fetch(:new_artrails_capistrano_sudo_as)}/#{fetch(:new_artrails_capistrano_log_dir_name)}/ #{release_path}/log"
128
+ end
129
+ end
130
+ end
131
+
132
+ task :check_is_it_working do
133
+ on roles :app, exclude: :no_release do
134
+ puts "Sleeping 5 seconds..."
135
+ sleep( 5 )
136
+ puts "Asking is it working..."
137
+ if fetch(:app_address).to_s[/8080/]
138
+ proxy_host = nil
139
+ proxy_port = nil
140
+ else
141
+ proxy_host = fetch(:proxy_host)
142
+ proxy_port = fetch(:proxy_port)
143
+ end
144
+ http = Net::HTTP::Proxy(proxy_host, proxy_port).start(*fetch(:app_address).split(':'))
145
+ path='/isItWorking'
146
+ resp, data = http.get(path)
147
+ puts "#{resp.code} #{resp.message} : #{data}"
148
+ end
149
+ end
150
+
151
+ task :tailf do
152
+ log_file = "#{current_path}/log/production.log"
153
+ new_artrails_capistrano_run "tail -f #{log_file}" do |channel, stream, data|
154
+ puts data if stream == :out
155
+ if stream == :err
156
+ puts "[Error: #{channel[:host]}] #{data}"
157
+ break
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ namespace :maintenance do
164
+ desc "Maintenance start"
165
+ task :on do
166
+ on roles :web do
167
+ if test "[ -f #{release_path}/config/maintenance.yml ]"
168
+ new_artrails_capistrano_run "cp #{release_path}/config/maintenance.yml #{release_path}/tmp/maintenance.yml"
169
+ end
170
+ end
171
+ end
172
+
173
+ desc "Maintenance stop"
174
+ task :off do
175
+ on roles :web do
176
+ new_artrails_capistrano_run "rm -rf #{release_path}/tmp/maintenance.yml"
177
+ end
178
+ end
179
+ end
180
+
181
+ namespace :deploy do
182
+ desc "Tag deployed release"
183
+ task :tag do
184
+ run_locally do
185
+ if ENV['SKIP_DEPLOY_TAGGING'] || fetch(:skip_deploy_tagging, false)
186
+ info "Skipped deploy tagging"
187
+ else
188
+ tag_name = "#{fetch(:deploy_tag, "deployed")}_#{fetch(:stage)}"
189
+ latest_revision = fetch(:current_revision)
190
+ unless fetch(:sshkit_backend) == SSHKit::Backend::Printer # unless --dry-run flag present
191
+ execute :git, "tag -f #{tag_name} #{latest_revision}"
192
+ execute :git, "push -f --tags"
193
+ end
194
+ info "Tagged #{latest_revision} with #{tag_name}"
195
+ end
196
+ end
197
+ end
198
+
199
+ task :front do
200
+ on roles :app, exclude: :no_release do
201
+ puts '[FRONT] updating local cache'
202
+ system(front_command)
203
+
204
+ File.open(File.join(front_local_cache, "REVISION"), "w") { |f| f.puts(backend_revision) }
205
+ File.open(File.join(front_local_cache, "BRANCH"), "w") { |f| f.puts(backend_branch) }
206
+
207
+ File.open(File.join(front_local_cache, 'FRONT_REVISION'), 'w') { |f| f.puts(front_revision) }
208
+ File.open(File.join(front_local_cache, 'FRONT_BRANCH'), 'w+') { |f| f.puts(front_branch) }
209
+
210
+ # FIXME:
211
+ # find_servers(:roles => :app, :except => { :no_release => true }).each do |server|
212
+ server = host
213
+
214
+ system("mkdir -p #{front_local_cache}/#{front_dist_dir_name}")
215
+
216
+ system("cp #{front_local_cache}/REVISION #{front_local_cache}/#{front_dist_dir_name}/")
217
+ system("cp #{front_local_cache}/BRANCH #{front_local_cache}/#{front_dist_dir_name}/")
218
+
219
+ system("cp #{front_local_cache}/FRONT_REVISION #{front_local_cache}/#{front_dist_dir_name}/")
220
+ system("cp #{front_local_cache}/FRONT_BRANCH #{front_local_cache}/#{front_dist_dir_name}/")
221
+
222
+ release_roles(:all).each do |role|
223
+ user = role.user || fetch(:user)
224
+ user = user + "@" unless user.nil?
225
+
226
+ rsync_args = []
227
+ rsync_args.concat front_rsync_options
228
+ rsync_args.concat (front_rsync_include || []).map{|e| "--include #{e}"}
229
+ rsync_args.concat (front_rsync_exclude || []).map{|e| "--exclude #{e}"}
230
+ rsync_args << front_local_cache + "/#{front_dist_dir_name}/"
231
+ rsync_args << "#{user}#{role.hostname}:#{front_remote_cache.call}"
232
+
233
+ run_locally do
234
+ execute :rsync, *rsync_args
235
+ end
236
+
237
+ new_artrails_capistrano_run( "chmod +r+w+x -R #{front_remote_cache.call}" )
238
+ new_artrails_capistrano_run( "chmod g+w -R #{front_remote_cache.call}" )
239
+ new_artrails_capistrano_run( "chgrp -R mongrel #{front_remote_cache.call}" )
240
+
241
+ copy = %(#{front_copy_command} "#{front_remote_cache.call}/" "#{front_release_path}/")
242
+ on release_roles(:all) do
243
+ puts copy
244
+ new_artrails_capistrano_run copy
245
+ end
246
+ end
247
+ end
248
+ end
249
+
250
+ Rake::Task["deploy:set_current_revision"].clear_actions
251
+ desc "Place a REVISION file with the current revision SHA in the current release path and a BRANCH file with name"
252
+ task :set_current_revision do
253
+ on release_roles(:all) do
254
+ # NOTE: cannot use this with :front deployment
255
+ # # NOTE: echo called twice on purpose, because only that way it works...
256
+ # cmd =<<-CMD
257
+ # sudo -iu #{fetch(:new_artrails_capistrano_sudo_as)} bash -c "
258
+ # echo '#{fetch(:current_revision)}' > #{release_path}/REVISION &&
259
+ # echo -e '#{fetch(:current_revision)}' > #{release_path}/REVISION &&
260
+ # chmod g+w -R #{release_path}/REVISION &&
261
+ # chgrp #{fetch(:new_artrails_capistrano_sudo_as)} #{release_path}/REVISION
262
+ # "
263
+ # CMD
264
+ # new_artrails_capistrano_run cmd.gsub(/\r?\n/, '').gsub(/\s+/, ' ')
265
+ # # NOTE: echo called twice on purpose, because only that way it works...
266
+ # cmd =<<-CMD
267
+ # sudo -iu #{fetch(:new_artrails_capistrano_sudo_as)} bash -c "
268
+ # echo '#{fetch(:branch)}' > #{release_path}/BRANCH &&
269
+ # echo -e '#{fetch(:branch)}' > #{release_path}/BRANCH &&
270
+ # chmod g+w -R #{release_path}/BRANCH &&
271
+ # chgrp #{fetch(:new_artrails_capistrano_sudo_as)} #{release_path}/BRANCH
272
+ # "
273
+ # CMD
274
+ # new_artrails_capistrano_run cmd.gsub(/\r?\n/, '').gsub(/\s+/, ' ')
275
+ end
276
+ end
277
+
278
+ Rake::Task["deploy:cleanup"].clear_actions
279
+ desc "Clean up old releases"
280
+ task :cleanup do
281
+ on release_roles :all do |host|
282
+ releases = capture(:ls, "-x", releases_path).split
283
+ if !(releases.all? { |e| /^\d{14}$/ =~ e })
284
+ warn t(:skip_cleanup, host: host.to_s)
285
+ elsif releases.count >= fetch(:keep_releases)
286
+ info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: releases.count)
287
+ directories = (releases - releases.last(fetch(:keep_releases)))
288
+ if directories.any?
289
+ directories_str = directories.map do |release|
290
+ releases_path.join(release)
291
+ end.join(" ")
292
+ new_artrails_capistrano_run "rm -rf #{directories_str}" if directories_str.to_s[/\/releases\//]
293
+ else
294
+ info t(:no_old_releases, host: host.to_s, keep_releases: fetch(:keep_releases))
295
+ end
296
+ end
297
+ end
298
+ end
299
+
300
+ Rake::Task["deploy:log_revision"].clear_actions
301
+ desc "Log details of the deploy"
302
+ task :log_revision do
303
+ on release_roles(:all) do
304
+ within releases_path do
305
+ execute :echo, %Q{"#{revision_log_message}" >> #{revision_log}}
306
+ execute :chmod, "g+w #{revision_log}"
307
+ end
308
+ end
309
+ end
310
+
311
+ namespace :bundler do
312
+ task :install do
313
+ on fetch(:bundle_servers) do
314
+ within release_path do
315
+ with fetch(:bundle_env_variables, {}) do
316
+ options = []
317
+ options << "--gemfile #{fetch(:bundle_gemfile)}" if fetch(:bundle_gemfile)
318
+ options << "--path #{fetch(:bundle_path)}" if fetch(:bundle_path)
319
+ unless test(:bundle, :check, *options)
320
+ options << "--binstubs #{fetch(:bundle_binstubs)}" if fetch(:bundle_binstubs)
321
+ options << "--jobs #{fetch(:bundle_jobs)}" if fetch(:bundle_jobs)
322
+ options << "--without #{fetch(:bundle_without)}" if fetch(:bundle_without)
323
+ options << "#{fetch(:bundle_flags)}" if fetch(:bundle_flags)
324
+ new_artrails_capistrano_run_with_rvm_in_release_path "bundle install #{options.join(' ')}"
325
+ end
326
+ end
327
+ end
328
+ end
329
+ end
330
+
331
+ desc "Remove unused gems installed by bundler"
332
+ task :clean do
333
+ on fetch(:bundle_servers) do
334
+ within release_path do
335
+ with fetch(:bundle_env_variables, {}) do
336
+ new_artrails_capistrano_run "bundle clean #{fetch(:bundle_clean_options, "")}"
337
+ end
338
+ end
339
+ end
340
+ end
341
+ end
342
+
343
+ namespace :symlink do
344
+ Rake::Task["deploy:symlink:linked_dirs"].clear_actions
345
+ desc "Symlink linked directories"
346
+ task :linked_dirs do
347
+ next unless any? :linked_dirs
348
+ on release_roles :all do
349
+ new_artrails_capistrano_run "mkdir -p #{linked_dir_parents(release_path).map(&:to_s).join(' ')}"
350
+ fetch(:linked_dirs).each do |dir|
351
+ target = release_path.join(dir)
352
+ source = shared_path.join(dir)
353
+ next if test "[ -L #{target} ]"
354
+ new_artrails_capistrano_run "rm -rf #{target.to_s}" if test "[ -d #{target.to_s} ]"
355
+ new_artrails_capistrano_run "ln -s #{source.to_s} #{target.to_s}"
356
+ end
357
+ end
358
+ end
359
+
360
+ Rake::Task["deploy:symlink:linked_files"].clear_actions
361
+ desc "Symlink linked files"
362
+ task :linked_files do
363
+ next unless any? :linked_files
364
+ on release_roles :all do
365
+ new_artrails_capistrano_run "mkdir -p #{linked_file_dirs(release_path).map(&:to_s).join(' ')}"
366
+ fetch(:linked_files).each do |file|
367
+ target = release_path.join(file)
368
+ source = shared_path.join(file)
369
+ next if test "[ -L #{target} ]"
370
+ new_artrails_capistrano_run "rm -rf #{target.to_s}" if test "[ -f #{target.to_s} ]"
371
+ new_artrails_capistrano_run "ln -s #{source.to_s} #{target.to_s}"
372
+ end
373
+ end
374
+ end
375
+ desc "Symlink release to current"
376
+ task :release do
377
+ on release_roles :all do
378
+ tmp_current_path = release_path.parent.join(current_path.basename)
379
+ new_artrails_capistrano_run "ln -s #{release_path} #{tmp_current_path}"
380
+ new_artrails_capistrano_run "mv #{tmp_current_path} #{current_path.parent}"
381
+ end
382
+ end
383
+ end
384
+ namespace :isItWorking do
385
+ task :activate do
386
+ on roles :web, exclude: :no_release do
387
+ new_artrails_capistrano_run "touch #{current_path}/tmp/isItWorking.txt"
388
+ end
389
+ end
390
+ task :deactivate do
391
+ on roles :web, exclude: :no_release do
392
+ new_artrails_capistrano_run "rm -f #{current_path}/tmp/isItWorking.txt"
393
+ end
394
+ end
395
+ end
396
+
397
+ desc 'Normalize asset timestamps'
398
+ task :normalize_assets => [:set_rails_env] do
399
+ on release_roles(fetch(:assets_roles)) do
400
+ assets = Array(fetch(:normalize_asset_timestamps, []))
401
+ if assets.any?
402
+ within release_path do
403
+ new_artrails_capistrano_run "find #{assets.join(' ')} -exec touch -t #{asset_timestamp} {} ';'; true"
404
+ end
405
+ end
406
+ end
407
+ end
408
+
409
+ desc 'Cleanup expired assets'
410
+ task :cleanup_assets => [:set_rails_env] do
411
+ next unless fetch(:keep_assets)
412
+ on release_roles(fetch(:assets_roles)) do
413
+ within release_path do
414
+ with rails_env: fetch(:rails_env) do
415
+ new_artrails_capistrano_run "rake 'assets:clean[#{fetch(:keep_assets)}]'"
416
+ end
417
+ end
418
+ end
419
+ end
420
+
421
+ desc 'Clobber assets'
422
+ task :clobber_assets => [:set_rails_env] do
423
+ on release_roles(fetch(:assets_roles)) do
424
+ within release_path do
425
+ with rails_env: fetch(:rails_env) do
426
+ new_artrails_capistrano_run "rake assets:clobber"
427
+ end
428
+ end
429
+ end
430
+ end
431
+
432
+ desc 'Rollback assets'
433
+ task :rollback_assets => [:set_rails_env] do
434
+ begin
435
+ invoke 'deploy:assets:restore_manifest'
436
+ rescue Capistrano::FileNotFound
437
+ invoke 'deploy:compile_assets'
438
+ end
439
+ end
440
+
441
+ namespace :assets do
442
+
443
+ # task :symlink do
444
+ # on roles :web, exclude: :no_release do
445
+ # cmd =<<-CMD
446
+ # sudo -iu #{fetch(:new_artrails_capistrano_sudo_as)} rm -rf #{release_path}/public/#{fetch(:assets_prefix)} &&
447
+ # sudo -iu #{fetch(:new_artrails_capistrano_sudo_as)} mkdir -p #{release_path}/public &&
448
+ # sudo -iu #{fetch(:new_artrails_capistrano_sudo_as)} mkdir -p #{shared_path}/public/#{fetch(:assets_prefix)} &&
449
+ # sudo -iu #{fetch(:new_artrails_capistrano_sudo_as)} ln -s #{shared_path}/assets #{release_path}/public/#{fetch(:assets_prefix)} &&
450
+ # sudo -iu #{fetch(:new_artrails_capistrano_sudo_as)} chmod g+w -R #{release_path}/public/#{fetch(:assets_prefix)} &&
451
+ # sudo -iu #{fetch(:new_artrails_capistrano_sudo_as)} chgrp -R #{fetch(:new_artrails_capistrano_sudo_as)} #{release_path}/public/#{fetch(:assets_prefix)} &&
452
+ # sudo -iu #{fetch(:new_artrails_capistrano_sudo_as)} chmod g+w -R #{shared_path}/public/#{fetch(:assets_prefix)} &&
453
+ # sudo -iu #{fetch(:new_artrails_capistrano_sudo_as)} chgrp -R #{fetch(:new_artrails_capistrano_sudo_as)} #{shared_path}/public/#{fetch(:assets_prefix)}
454
+ # CMD
455
+ # new_artrails_capistrano_run cmd.gsub(/\r?\n/, '').gsub(/\s+/, ' ')
456
+ # end
457
+ # end
458
+
459
+ # Rails 5 only
460
+ Rake::Task['deploy:assets:backup_manifest'].clear_actions
461
+ task :backup_manifest do
462
+ on release_roles(fetch(:assets_roles)) do
463
+ within release_path do
464
+ backup_path = release_path.join('assets_manifest_backup')
465
+ target = new_artrails_capistrano_detect_manifest_path
466
+ new_artrails_capistrano_run "mkdir -p #{backup_path}"
467
+ if test "[[ -f #{target} ]]"
468
+ new_artrails_capistrano_run "cp #{target} #{backup_path}"
469
+ else
470
+ msg = 'Rails assets manifest file not found.'
471
+ warn msg
472
+ # FIXME: Rails 5 only
473
+ # fail Capistrano::FileNotFound, msg
474
+ end
475
+ end
476
+ end
477
+ end
478
+
479
+ # Rails 5 only
480
+ Rake::Task['deploy:assets:restore_manifest'].clear_actions
481
+ task :restore_manifest do
482
+ on release_roles(fetch(:assets_roles)) do
483
+ within release_path do
484
+ target = new_artrails_capistrano_detect_manifest_path
485
+ source = release_path.join('assets_manifest_backup', File.basename(target))
486
+ if test "[[ -f #{source} && -f #{target} ]]"
487
+ new_artrails_capistrano_run "cp #{source} #{target}"
488
+ else
489
+ msg = 'Rails assets manifest file (or backup file) not found.'
490
+ warn msg
491
+ # FIXME: Rails 5 only
492
+ # fail Capistrano::FileNotFound, msg
493
+ end
494
+ end
495
+ end
496
+ end
497
+
498
+ Rake::Task['deploy:assets:precompile'].clear_actions
499
+ task :precompile do
500
+ on release_roles(fetch(:assets_roles)) do
501
+ within release_path do
502
+ with rails_env: fetch(:rails_env), rails_groups: fetch(:rails_assets_groups) do
503
+ # execute :rake, "assets:precompile"
504
+ # require 'byebug'
505
+ # byebug
506
+ cmd =<<-CMD
507
+ sudo -iu #{fetch(:new_artrails_capistrano_sudo_as)} sh -c "
508
+ source\\\\ '/usr/local/rvm/scripts/rvm' &&
509
+ cd #{release_path} &&
510
+ RAILS_ENV=#{fetch(:rails_env)} #{fetch(:asset_env)} bundle exec rake assets:precompile &&
511
+ chmod g+w -R #{shared_path}/public/#{fetch(:assets_prefix)} &&
512
+ chgrp -R #{fetch(:new_artrails_capistrano_sudo_as)} #{shared_path}/public/#{fetch(:assets_prefix)}
513
+ "
514
+ CMD
515
+ new_artrails_capistrano_run cmd.gsub(/\r?\n/, '').gsub(/\s+/, ' ')
516
+ end
517
+ end
518
+ end
519
+ end
520
+ end
521
+
522
+ namespace :web_server do
523
+ task :start do
524
+ on roles :app do
525
+ new_artrails_capistrano_run "nohup #{current_path}/script/production start"
526
+ end
527
+ end
528
+
529
+ task :stop do
530
+ on roles :app do
531
+ new_artrails_capistrano_run "nohup #{current_path}/script/production stop"
532
+ end
533
+ end
534
+
535
+ task :restart do
536
+ on roles :app, exclude: :no_release do
537
+ new_artrails_capistrano_run "nohup #{current_path}/script/production restart"
538
+ end
539
+ end
540
+ end
541
+
542
+ # custom task
543
+ task :setup do # |task|
544
+ on roles :app, exclude: :no_release do
545
+ dirs = [deploy_to, releases_path, shared_path]
546
+ dirs += fetch(:linked_dirs).map { |d| File.join(shared_path, d) }
547
+ new_artrails_capistrano_run "mkdir -p #{dirs.join(' ')}"
548
+ # FIXME:
549
+ # servers = find_servers_for_task(current_task)
550
+ # servers.each do |server|
551
+ server = host
552
+ fetch(:new_artrails_capistrano_config_files).each do |cf|
553
+ new_artrails_capistrano_run("mkdir -p #{shared_path}/config")
554
+ if file_exists?("#{shared_path}/config/#{cf}")
555
+ puts "Skip. File exists: #{shared_path}/config/#{cf}"
556
+ else
557
+ new_artrails_capistrano_run("touch #{shared_path}/config/#{cf}")
558
+ new_artrails_capistrano_run("chmod g+rw #{shared_path}/config/#{cf}")
559
+ cf_path = "#{local_user}@#{server}:#{shared_path}/config/#{cf}"
560
+ puts "scp config/#{cf} #{cf_path}"
561
+ system("scp config/#{cf} #{cf_path}")
562
+ end
563
+ end
564
+ # FIXME:
565
+ # servers = find_servers_for_task(current_task)
566
+ # servers.each do |server|
567
+
568
+ # obsolete
569
+ # new_artrails_capistrano_run("mkdir -p #{shared_path}/pids")
570
+
571
+ if revision_log.to_s[/\.log\z/]
572
+ new_artrails_capistrano_run "pwd && rm -rf #{revision_log}" # don't reject command below
573
+ end
574
+ if rsync_remote_cache.to_s[/cached\-copy\-/]
575
+ new_artrails_capistrano_run "pwd && rm -rf #{deploy_to}/#{rsync_remote_cache}" # don't reject command below
576
+ end
577
+ if front_rsync_remote_cache.to_s[/cached\-copy\-/]
578
+ new_artrails_capistrano_run "pwd && rm -rf #{deploy_to}/#{front_rsync_remote_cache}" # don't reject command below
579
+ end
580
+ new_artrails_capistrano_run "sudo -u #{fetch(:new_artrails_capistrano_sudo_as)} chmod -R g+rw #{deploy_to}"
581
+ new_artrails_capistrano_run "sudo -u #{fetch(:new_artrails_capistrano_sudo_as)} chgrp -R #{fetch(:new_artrails_capistrano_sudo_as)} #{deploy_to}"
582
+
583
+ unless file_exists?("#{deploy_to}/#{rsync_remote_cache}")
584
+ new_artrails_capistrano_run "sudo -u #{fetch(:new_artrails_capistrano_sudo_as)} chmod g+w -R #{shared_path}"
585
+ new_artrails_capistrano_run "pwd && mkdir -p #{deploy_to}/#{rsync_remote_cache}"
586
+ new_artrails_capistrano_run "chgrp -R #{fetch(:new_artrails_capistrano_sudo_as)} #{deploy_to}/#{rsync_remote_cache}"
587
+ new_artrails_capistrano_run "chmod g+w #{deploy_to}/#{rsync_remote_cache}"
588
+ end
589
+
590
+ # prepare custom log dir for symlink
591
+ new_artrails_capistrano_run "mkdir -p /var/log/#{fetch(:new_artrails_capistrano_sudo_as)}/#{fetch(:new_artrails_capistrano_log_dir_name)}"
592
+ end
593
+ end
594
+
595
+ namespace :git do
596
+ desc "Upload the git wrapper script, this script guarantees that we can script git without getting an interactive prompt"
597
+ task :wrapper do
598
+ on release_roles :all do
599
+ puts "Doing nothing"
600
+ # execute :mkdir, "-p", File.dirname(fetch(:git_wrapper_path)).shellescape
601
+ # upload! StringIO.new("#!/bin/sh -e\nexec /usr/bin/ssh -o PasswordAuthentication=no -o StrictHostKeyChecking=no \"$@\"\n"), fetch(:git_wrapper_path)
602
+ # execute :chmod, "700", fetch(:git_wrapper_path).shellescape
603
+ end
604
+ end
605
+
606
+ desc "Check that the repository is reachable"
607
+ task check: :'git:wrapper' do
608
+ fetch(:branch)
609
+ on release_roles :all do
610
+ puts "Doing nothing"
611
+ # with fetch(:git_environmental_variables) do
612
+ # git_plugin.check_repo_is_reachable
613
+ # end
614
+ end
615
+ end
616
+
617
+ desc "Clone the repo to the cache"
618
+ task clone: :'git:wrapper' do
619
+ on release_roles :all do
620
+ puts "Doing nothing"
621
+ # if git_plugin.repo_mirror_exists?
622
+ # info t(:mirror_exists, at: repo_path)
623
+ # else
624
+ # within deploy_path do
625
+ # with fetch(:git_environmental_variables) do
626
+ # git_plugin.clone_repo
627
+ # end
628
+ # end
629
+ # end
630
+ end
631
+ end
632
+
633
+ desc "Update the repo mirror to reflect the origin state"
634
+ task update: :'git:clone' do
635
+ on release_roles :all do
636
+ puts "Doing nothing"
637
+ # within repo_path do
638
+ # with fetch(:git_environmental_variables) do
639
+ # git_plugin.update_mirror
640
+ # end
641
+ # end
642
+ end
643
+ end
644
+
645
+ task :create_cache do
646
+ next if File.directory?(File.expand_path(fetch(:local_cache) + '/.git'))
647
+ run_locally do
648
+ execute :git, 'clone', fetch(:repo_url), fetch(:local_cache)
649
+ end
650
+ end
651
+
652
+ desc "stage the repository in a local directory"
653
+ task :stage => [ :create_cache ] do
654
+ run_locally do
655
+ within fetch(:local_cache) do
656
+ execute :git, "fetch", "--quiet", "--all", "--prune"
657
+ execute :git, "reset", "--hard", "origin/#{fetch(:branch)}"
658
+ end
659
+ end
660
+ end
661
+
662
+ desc "stage and rsync to the server"
663
+ task :sync => [ :stage ] do
664
+ release_roles(:all).each do |role|
665
+
666
+ user = role.user || fetch(:user)
667
+ user = user + "@" unless user.nil?
668
+
669
+ rsync_args = []
670
+ rsync_args.concat fetch(:rsync_options)
671
+ rsync_args.concat fetch(:rsync_include, []).map{|e| "--include #{e}"}
672
+ rsync_args.concat fetch(:rsync_exclude, []).map{|e| "--exclude #{e}"}
673
+ rsync_args << fetch(:local_cache) + "/"
674
+ rsync_args << "#{user}#{role.hostname}:#{remote_cache.call}"
675
+
676
+ run_locally do
677
+ execute :rsync, *rsync_args
678
+ end
679
+
680
+ on roles(:app) do
681
+ new_artrails_capistrano_run( "chmod +r+w+x -R #{remote_cache.call}" )
682
+ new_artrails_capistrano_run( "chmod g+w -R #{remote_cache.call}" )
683
+ new_artrails_capistrano_run( "chgrp -R mongrel #{remote_cache.call}" )
684
+ end
685
+ end
686
+ end
687
+
688
+ desc "stage, rsync to the server, and copy the code to the releases directory"
689
+ task :release => [ :sync ] do
690
+ copy = %(#{copy_command} "#{remote_cache.call}/" "#{release_path}/")
691
+ on release_roles(:all) do
692
+ new_artrails_capistrano_run copy
693
+ end
694
+ end
695
+
696
+ desc "Copy repo to releases"
697
+ # task create_release: :'git:update' do
698
+ # on release_roles :all do
699
+ # with fetch(:git_environmental_variables) do
700
+ # within repo_path do
701
+ # execute :mkdir, "-p", release_path
702
+ # git_plugin.archive_to_release_path
703
+ # end
704
+ # end
705
+ # end
706
+ # end
707
+ task create_release: [:release] do
708
+ # expected by the framework, delegate to better named task
709
+ end
710
+
711
+ Rake::Task['git:set_current_revision'].clear_actions
712
+ desc "Determine the revision that will be deployed"
713
+ # task :set_current_revision do
714
+ # on release_roles :all do
715
+ # within repo_path do
716
+ # with fetch(:git_environmental_variables) do
717
+ # set :current_revision, git_plugin.fetch_revision
718
+ # end
719
+ # end
720
+ # end
721
+ # end
722
+ task :set_current_revision do
723
+ run_locally do
724
+ run_locally do
725
+ set :current_revision, capture(:git, 'rev-parse', fetch(:branch))
726
+ end
727
+ end
728
+ end
729
+ end
730
+ end
731
+
732
+ # hooks
733
+ before 'deploy:updating', "artrails:set_current_revision"
734
+ before "deploy:web_server:restart", "maintenance:on"
735
+ after 'deploy:finished', 'artrails:update_versions_html'
736
+ after 'deploy:publishing', 'deploy:web_server:restart'
737
+ after "deploy:updated", "artrails:symlink:config"
738
+ after "deploy:symlink:release", "artrails:symlink:log"
739
+ after "maintenance:on", "deploy:isItWorking:deactivate"
740
+ after "maintenance:off", "deploy:isItWorking:activate"
741
+ after "maintenance:off", "artrails:check_is_it_working"
742
+ after "deploy:cleanup", "deploy:tag"