deployinator 0.1.5 → 0.1.6
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.
- data/lib/deployinator/built-in.rb +76 -45
- data/lib/deployinator/check.rb +15 -20
- data/lib/deployinator/config.rb +16 -8
- data/lib/deployinator/deploy.rb +73 -24
- data/lib/deployinator/examples/config/deploy.rb +7 -1
- data/lib/deployinator/examples/database.yml.erb +10 -0
- data/lib/deployinator/helpers.rb +40 -10
- data/lib/deployinator/jobs.rb +4 -3
- metadata +20 -2
@@ -1,13 +1,13 @@
|
|
1
|
-
set :deploy_log_level, "debug"
|
2
1
|
set :webserver_socket_path, -> { shared_path.join('run') }
|
3
2
|
set :deploy_templates_path, "templates/deploy"
|
4
3
|
set :jobs_app_name, "jobs"
|
4
|
+
set :deploy_custom_container_options, -> {} # Set customer Docker options w/o overriding methods below
|
5
5
|
|
6
6
|
# Default deploy_to directory is /var/www/my_app
|
7
7
|
# set :deploy_to, '/var/www/my_app'
|
8
8
|
|
9
9
|
# Default value for :log_level is :debug
|
10
|
-
|
10
|
+
set :log_level, :info
|
11
11
|
|
12
12
|
# Default value for :linked_files is []
|
13
13
|
# set :linked_files, %w{config/database.yml}
|
@@ -36,45 +36,50 @@ set :migration_role, :db # Defaults to 'db'
|
|
36
36
|
set :assets_roles, [:app] # Defaults to [:web]
|
37
37
|
#set :assets_prefix, 'prepackaged-assets' # Defaults to 'assets' this should match config.assets.prefix in your rails config/application.rb
|
38
38
|
|
39
|
-
# TODO: fix from_local, right now you have to copy-paste the set_scm method to your deploy.rb
|
40
|
-
# Use `cap <stage> deploy from_local=true` to deploy your locally changed code
|
41
|
-
# instead of the code in the git repo. You can also add --trace.
|
42
|
-
# You can set include_dir and exclude_dir settings (from capistrano-scm-copy gem).
|
43
|
-
# These will only apply when using the from_local=true option
|
44
|
-
# set :include_dir, '../.*'
|
45
|
-
# set :exclude_dir, ["../.$", "../..", '.././infrastructure']
|
46
|
-
def set_scm
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
set_scm
|
39
|
+
# # TODO: fix from_local, right now you have to copy-paste the set_scm method to your deploy.rb
|
40
|
+
# # Use `cap <stage> deploy from_local=true` to deploy your locally changed code
|
41
|
+
# # instead of the code in the git repo. You can also add --trace.
|
42
|
+
# # You can set include_dir and exclude_dir settings (from capistrano-scm-copy gem).
|
43
|
+
# # These will only apply when using the from_local=true option
|
44
|
+
# # set :include_dir, '../.*'
|
45
|
+
# # set :exclude_dir, ["../.$", "../..", '.././infrastructure']
|
46
|
+
# def set_scm
|
47
|
+
# if ENV['from_local']
|
48
|
+
# if "#{fetch(:stage)}" == "production"
|
49
|
+
# run_locally do
|
50
|
+
# fatal("You are trying to deploy to production using from_local, " +
|
51
|
+
# "this should pretty much never be done.")
|
52
|
+
# end
|
53
|
+
# ask :yes_no, "Are you positive you want to continue?"
|
54
|
+
# case fetch(:yes_no).chomp.downcase
|
55
|
+
# when "yes"
|
56
|
+
# when "no"
|
57
|
+
# exit
|
58
|
+
# else
|
59
|
+
# warn "Please enter 'yes' or 'no'"
|
60
|
+
# set_scm
|
61
|
+
# end
|
62
|
+
# end
|
63
|
+
# set :scm, :copy
|
64
|
+
# else
|
65
|
+
# set :scm, :git
|
66
|
+
# end
|
67
|
+
# end
|
68
|
+
# set_scm
|
69
69
|
|
70
70
|
def deploy_run_bluepill(host)
|
71
|
+
warn "Starting a new container named #{fetch(:ruby_container_name)} on #{host}"
|
71
72
|
execute(
|
72
73
|
"docker", "run", "--tty", "--detach",
|
74
|
+
# "--user", fetch(:webserver_username), TODO find out of this can run as the deployer user instead of root, if so, set the user, if not, fix rails console to su to www-data first
|
73
75
|
"--name", fetch(:ruby_container_name),
|
76
|
+
"-e", "APP_STAGE=#{fetch(:stage)}",
|
77
|
+
"-e", "RAILS_ROOT=#{current_path}",
|
74
78
|
"-e", "GEM_HOME=#{shared_path.join('bundle')}",
|
75
79
|
"-e", "GEM_PATH=#{shared_path.join('bundle')}",
|
76
80
|
"-e", "BUNDLE_GEMFILE=#{current_path.join('Gemfile')}",
|
77
81
|
"-e", "PATH=#{shared_path.join('bundle', 'bin')}:$PATH",
|
82
|
+
fetch(:deploy_custom_container_options),
|
78
83
|
"--restart", "always", "--memory", "#{fetch(:ruby_container_max_mem_mb)}m",
|
79
84
|
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
80
85
|
"--entrypoint", shared_path.join('bundle', 'bin', 'bluepill'),
|
@@ -83,26 +88,34 @@ def deploy_run_bluepill(host)
|
|
83
88
|
)
|
84
89
|
end
|
85
90
|
def deploy_bluepill_restart(host)
|
86
|
-
execute(
|
91
|
+
execute(
|
92
|
+
"docker", "exec", "--tty",
|
87
93
|
fetch(:ruby_container_name),
|
88
94
|
shared_path.join('bundle', 'bin', 'bluepill'),
|
89
|
-
fetch(:application), "restart"
|
95
|
+
fetch(:application), "restart"
|
96
|
+
)
|
90
97
|
end
|
91
98
|
def deploy_bluepill_stop(host)
|
92
|
-
execute(
|
99
|
+
execute(
|
100
|
+
"docker", "exec", "--tty",
|
93
101
|
fetch(:ruby_container_name),
|
94
102
|
shared_path.join('bundle', 'bin', 'bluepill'),
|
95
|
-
fetch(:application), "stop"
|
103
|
+
fetch(:application), "stop"
|
104
|
+
)
|
96
105
|
end
|
97
106
|
def deploy_run_bluepill_jobs(host)
|
98
107
|
execute(
|
99
108
|
"docker", "run", "--tty", "--detach",
|
109
|
+
"-w", current_path,
|
100
110
|
"--user", fetch(:webserver_username),
|
101
111
|
"--name", fetch(:ruby_jobs_container_name),
|
112
|
+
"-e", "APP_STAGE=#{fetch(:stage)}",
|
113
|
+
"-e", "RAILS_ROOT=#{current_path}",
|
102
114
|
"-e", "GEM_HOME=#{shared_path.join('bundle')}",
|
103
115
|
"-e", "GEM_PATH=#{shared_path.join('bundle')}",
|
104
116
|
"-e", "BUNDLE_GEMFILE=#{current_path.join('Gemfile')}",
|
105
117
|
"-e", "PATH=#{shared_path.join('bundle', 'bin')}:$PATH",
|
118
|
+
fetch(:deploy_custom_container_options),
|
106
119
|
"--restart", "always", "--memory", "#{fetch(:ruby_jobs_container_max_mem_mb)}m",
|
107
120
|
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
108
121
|
"--entrypoint", shared_path.join('bundle', 'bin', 'rabid_jobs_tasker'),
|
@@ -123,10 +136,13 @@ def deploy_run_cadvisor(host)
|
|
123
136
|
"google/cadvisor:latest"
|
124
137
|
)
|
125
138
|
end
|
139
|
+
# TODO change these both to run as webserver_username
|
140
|
+
# also offer Rails 2.X versions
|
126
141
|
def deploy_rails_console(host)
|
127
142
|
[
|
128
143
|
"ssh", "-t", "#{host}", "\"docker", "exec", "--interactive", "--tty",
|
129
144
|
fetch(:ruby_container_name),
|
145
|
+
# "sudo", "-u", fetch(:webserver_username), TODO, find out if running bluepill as www-data works, otherwise add this line
|
130
146
|
"bash", "-c", "'cd", current_path, "&&",
|
131
147
|
shared_path.join('bundle', 'bin', 'rails'),
|
132
148
|
"console", "#{fetch(:rails_env)}'\""
|
@@ -149,7 +165,7 @@ def sshkit_bundle_command_map
|
|
149
165
|
"-e", "GEM_PATH=#{shared_path.join('bundle')}",
|
150
166
|
"-e", "PATH=#{shared_path.join('bundle', 'bin')}:$PATH",
|
151
167
|
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
152
|
-
"--volume", "$SSH_AUTH_SOCK:/ssh-agent --env SSH_AUTH_SOCK=/ssh-agent",
|
168
|
+
"--volume", "$SSH_AUTH_SOCK:/ssh-agent:rw", "--env SSH_AUTH_SOCK=/ssh-agent",
|
153
169
|
"--volume", "/home:/home:rw",
|
154
170
|
"--volume", "/etc/passwd:/etc/passwd:ro",
|
155
171
|
"--volume", "/etc/group:/etc/group:ro",
|
@@ -158,35 +174,49 @@ def sshkit_bundle_command_map
|
|
158
174
|
].join(' ')
|
159
175
|
end
|
160
176
|
def deploy_assets_precompile(host)
|
161
|
-
execute(
|
177
|
+
execute(
|
178
|
+
"docker", "run", "--rm", "--tty", "--user", fetch(:webserver_username),
|
179
|
+
"-e", "APP_STAGE=#{fetch(:stage)}",
|
180
|
+
"-e", "RAILS_ROOT=#{current_path}",
|
162
181
|
"-w", release_path,
|
163
182
|
"--volume", "/home:/home:rw",
|
164
183
|
"--volume", "/etc/passwd:/etc/passwd:ro",
|
165
184
|
"--volume", "/etc/group:/etc/group:ro",
|
166
185
|
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
186
|
+
fetch(:deploy_custom_container_options),
|
167
187
|
"--entrypoint", "/bin/bash",
|
168
188
|
fetch(:ruby_image_name), "-c",
|
169
189
|
"\"umask", "0007", "&&", "#{shared_path.join('bundle', 'bin', 'rake')}",
|
170
|
-
"assets:precompile\""
|
190
|
+
"assets:precompile\""
|
191
|
+
)
|
171
192
|
end
|
172
193
|
def deploy_assets_cleanup(host)
|
173
|
-
execute(
|
194
|
+
execute(
|
195
|
+
"docker", "run", "--rm", "--tty",
|
174
196
|
"-e", "RAILS_ENV=#{fetch(:rails_env)}",
|
175
197
|
"-w", release_path,
|
198
|
+
fetch(:deploy_custom_container_options),
|
176
199
|
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
177
200
|
"--entrypoint", shared_path.join('bundle', 'bin', 'bundle'),
|
178
|
-
fetch(:ruby_image_name), "exec", "rake", "assets:clean"
|
201
|
+
fetch(:ruby_image_name), "exec", "rake", "assets:clean"
|
202
|
+
)
|
179
203
|
end
|
180
204
|
def deploy_rake_db_migrate(host)
|
181
|
-
execute(
|
205
|
+
execute(
|
206
|
+
"docker", "run", "--rm", "--tty",
|
182
207
|
"-w", release_path,
|
208
|
+
"-e", "APP_STAGE=#{fetch(:stage)}",
|
209
|
+
"-e", "RAILS_ROOT=#{current_path}",
|
183
210
|
"-e", "RAILS_ENV=#{fetch(:rails_env)}",
|
211
|
+
fetch(:deploy_custom_container_options),
|
184
212
|
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
185
213
|
"--entrypoint", shared_path.join('bundle', 'bin', 'rake'),
|
186
|
-
fetch(:ruby_image_name), "db:migrate"
|
214
|
+
fetch(:ruby_image_name), "db:migrate"
|
215
|
+
)
|
187
216
|
end
|
188
217
|
def deploy_install_bundler(host)
|
189
|
-
execute(
|
218
|
+
execute(
|
219
|
+
"docker", "run", "--rm", "--tty", "--user", fetch(:deployment_username),
|
190
220
|
"-e", "GEM_HOME=#{shared_path.join('bundle')}",
|
191
221
|
"-e", "GEM_PATH=#{shared_path.join('bundle')}",
|
192
222
|
"-e", "PATH=#{shared_path.join('bundle', 'bin')}:$PATH",
|
@@ -199,5 +229,6 @@ def deploy_install_bundler(host)
|
|
199
229
|
"\"umask", "0007", "&&" "/usr/local/bin/gem", "install",
|
200
230
|
"--install-dir", "#{shared_path.join('bundle')}",
|
201
231
|
"--bindir", shared_path.join('bundle', 'bin'),
|
202
|
-
"--no-ri", "--no-rdoc", "--quiet", "bundler", "-v'#{fetch(:bundler_version)}'\""
|
232
|
+
"--no-ri", "--no-rdoc", "--quiet", "bundler", "-v'#{fetch(:bundler_version)}'\""
|
233
|
+
)
|
203
234
|
end
|
data/lib/deployinator/check.rb
CHANGED
@@ -1,33 +1,27 @@
|
|
1
1
|
namespace :deploy do
|
2
2
|
namespace :check do
|
3
3
|
|
4
|
-
task :bundle_command_map do
|
4
|
+
task :bundle_command_map => 'deployinator:load_settings' do
|
5
5
|
set :bundle_binstubs, -> { shared_path.join('bundle', 'bin') }
|
6
6
|
set :bundle_gemfile, -> { release_path.join('Gemfile') }
|
7
7
|
SSHKit.config.command_map[:bundle] = sshkit_bundle_command_map
|
8
8
|
end
|
9
|
-
|
9
|
+
if Rake::Task.task_defined?("bundler:install")
|
10
|
+
before 'bundler:install', 'deploy:check:bundle_command_map'
|
11
|
+
end
|
10
12
|
|
11
13
|
# Ensure Capistrano's inner rm commands always run using sudo
|
12
|
-
|
14
|
+
task :rm_command_map => 'deployinator:load_settings' do
|
13
15
|
SSHKit.config.command_map[:rm] = "/usr/bin/env sudo rm"
|
14
16
|
end
|
15
|
-
|
16
|
-
before 'deploy:check', :brakeman_reminder do
|
17
|
-
run_locally do
|
18
|
-
warn "Remember to run brakeman before deploying!"
|
19
|
-
ask :return_to_continue, nil
|
20
|
-
set :nothing, fetch(:return_to_continue)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
17
|
+
before 'deploy:started', 'deploy:check:rm_command_map'
|
24
18
|
if Rake::Task.task_defined?("deploy:cleanup")
|
25
19
|
# Append dependancy to existing cleanup task
|
26
20
|
task 'deploy:cleanup' => 'deploy:check:rm_command_map'
|
27
21
|
end
|
28
22
|
|
29
23
|
desc 'Ensure all deployinator specific settings are set, and warn and raise if not.'
|
30
|
-
|
24
|
+
task :settings => 'deployinator:load_settings' do
|
31
25
|
{
|
32
26
|
(File.dirname(__FILE__) + "/examples/config/deploy.rb") => 'config/deploy.rb',
|
33
27
|
(File.dirname(__FILE__) + "/examples/config/deploy/staging.rb") => "config/deploy/#{fetch(:stage)}.rb"
|
@@ -36,9 +30,10 @@ namespace :deploy do
|
|
36
30
|
Rake::Task['deployinator:settings'].reenable
|
37
31
|
end
|
38
32
|
end
|
33
|
+
before 'deploy:check', 'deploy:check:settings'
|
39
34
|
|
40
35
|
# TODO make this better
|
41
|
-
|
36
|
+
task :templates => 'deployinator:load_settings' do
|
42
37
|
run_locally do
|
43
38
|
path = fetch(:deploy_templates_path)
|
44
39
|
keys_template = File.expand_path("./#{path}/deployment_authorized_keys.erb")
|
@@ -50,11 +45,9 @@ namespace :deploy do
|
|
50
45
|
end
|
51
46
|
end
|
52
47
|
end
|
48
|
+
before 'deploy:check', 'deploy:check:templates'
|
53
49
|
|
54
|
-
|
55
|
-
before 'deploy:check', 'deployinator:webserver_user'
|
56
|
-
|
57
|
-
task :root_dir_permissions => ['deployinator:deployment_user', 'deployinator:webserver_user'] do
|
50
|
+
task :root_dir_permissions => ['deployinator:load_settings', 'deployinator:deployment_user', 'deployinator:webserver_user'] do
|
58
51
|
on roles(:app) do
|
59
52
|
as :root do
|
60
53
|
[fetch(:deploy_to), Pathname.new(fetch(:deploy_to)).join("../"), shared_path].each do |dir|
|
@@ -68,7 +61,7 @@ namespace :deploy do
|
|
68
61
|
end
|
69
62
|
before 'deploy:check:directories', 'deploy:check:root_dir_permissions'
|
70
63
|
|
71
|
-
|
64
|
+
task :postgres_running => 'deployinator:load_settings' do
|
72
65
|
on roles(:app) do
|
73
66
|
unless localhost_port_responding?(fetch(:postgres_port))
|
74
67
|
fatal "Port #{fetch(:postgres_port)} is not responding, we won't be able to db:migrate!"
|
@@ -76,8 +69,9 @@ namespace :deploy do
|
|
76
69
|
end
|
77
70
|
end
|
78
71
|
end
|
72
|
+
before 'deploy:check', 'deploy:check:postgres_running'
|
79
73
|
|
80
|
-
|
74
|
+
task :ensure_cadvisor => 'deployinator:load_settings' do
|
81
75
|
on roles(:app) do |host|
|
82
76
|
if fetch(:use_cadvisor, true)
|
83
77
|
if container_exists?("cadvisor")
|
@@ -97,6 +91,7 @@ namespace :deploy do
|
|
97
91
|
end
|
98
92
|
end
|
99
93
|
end
|
94
|
+
before 'deploy:check', 'deploy:check:ensure_cadvisor'
|
100
95
|
|
101
96
|
end
|
102
97
|
end
|
data/lib/deployinator/config.rb
CHANGED
@@ -12,11 +12,14 @@ module Capistrano
|
|
12
12
|
end
|
13
13
|
|
14
14
|
namespace :deployinator do
|
15
|
+
task :load_settings do
|
16
|
+
load "./config/deploy.rb"
|
17
|
+
SSHKit.config.output_verbosity = fetch(:log_level)
|
18
|
+
end
|
15
19
|
|
16
20
|
set :example, "_example"
|
17
|
-
|
18
21
|
desc 'Write example config files'
|
19
|
-
task :write_example_configs do
|
22
|
+
task :write_example_configs => 'deployinator:load_settings' do
|
20
23
|
run_locally do
|
21
24
|
path = fetch(:deploy_templates_path, 'templates/deploy')
|
22
25
|
execute "mkdir", "-p", "config/deploy", path
|
@@ -28,6 +31,7 @@ namespace :deployinator do
|
|
28
31
|
"examples/deployment_authorized_keys.erb" =>
|
29
32
|
"#{path}/deployment_authorized_keys#{fetch(:example)}.erb",
|
30
33
|
"examples/unicorn.rb.erb" => "#{path}/unicorn#{fetch(:example)}.rb.erb",
|
34
|
+
"examples/database.yml.erb" => "#{path}/database#{fetch(:example)}.yml.erb",
|
31
35
|
"examples/bluepill.rb.erb" => "#{path}/bluepill#{fetch(:example)}.rb.erb",
|
32
36
|
}.each do |source, destination|
|
33
37
|
config = File.read(File.dirname(__FILE__) + "/#{source}")
|
@@ -43,14 +47,14 @@ namespace :deployinator do
|
|
43
47
|
|
44
48
|
desc 'Write example config files (will overwrite any existing config files).'
|
45
49
|
namespace :write_example_configs do
|
46
|
-
task :in_place do
|
50
|
+
task :in_place => 'deployinator:load_settings' do
|
47
51
|
set :example, ""
|
48
52
|
Rake::Task['deployinator:write_example_configs'].invoke
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
52
56
|
desc 'Write a file showing the built-in overridable settings.'
|
53
|
-
task :write_built_in do
|
57
|
+
task :write_built_in => 'deployinator:load_settings' do
|
54
58
|
run_locally do
|
55
59
|
{
|
56
60
|
'built-in.rb' => 'built-in.rb',
|
@@ -66,7 +70,7 @@ namespace :deployinator do
|
|
66
70
|
# These are the only two tasks using :preexisting_ssh_user
|
67
71
|
namespace :deployment_user do
|
68
72
|
#desc "Setup or re-setup the deployment user, idempotently"
|
69
|
-
task :setup do
|
73
|
+
task :setup => 'deployinator:load_settings' do
|
70
74
|
on roles(:all) do |h|
|
71
75
|
on "#{fetch(:preexisting_ssh_user)}@#{h}" do |host|
|
72
76
|
as :root do
|
@@ -77,7 +81,7 @@ namespace :deployinator do
|
|
77
81
|
end
|
78
82
|
end
|
79
83
|
|
80
|
-
task :deployment_user do
|
84
|
+
task :deployment_user => 'deployinator:load_settings' do
|
81
85
|
on roles(:all) do |h|
|
82
86
|
on "#{fetch(:preexisting_ssh_user)}@#{h}" do |host|
|
83
87
|
as :root do
|
@@ -90,22 +94,26 @@ namespace :deployinator do
|
|
90
94
|
end
|
91
95
|
end
|
92
96
|
end
|
97
|
+
before 'deploy:check', 'deployinator:deployment_user'
|
93
98
|
|
94
|
-
task :webserver_user do
|
99
|
+
task :webserver_user => 'deployinator:load_settings' do
|
95
100
|
on roles(:app) do
|
96
101
|
as :root do
|
97
102
|
unix_user_add(fetch(:webserver_username)) unless unix_user_exists?(fetch(:webserver_username))
|
98
103
|
end
|
99
104
|
end
|
100
105
|
end
|
106
|
+
before 'deploy:check', 'deployinator:webserver_user'
|
101
107
|
|
102
|
-
task :file_permissions => [:deployment_user, :webserver_user] do
|
108
|
+
task :file_permissions => [:load_settings, :deployment_user, :webserver_user] do
|
103
109
|
on roles(:app) do
|
104
110
|
as :root do
|
105
111
|
setup_file_permissions
|
106
112
|
end
|
107
113
|
end
|
108
114
|
end
|
115
|
+
# TODO the file_permissions task after 'deploy:check' may be able to be replaced
|
116
|
+
# with only chowning the releases dir and another dir or two.
|
109
117
|
after 'deploy:check', 'deployinator:file_permissions'
|
110
118
|
before 'deploy:restart', 'deployinator:file_permissions'
|
111
119
|
|
data/lib/deployinator/deploy.rb
CHANGED
@@ -3,14 +3,8 @@ lock '3.2.1'
|
|
3
3
|
|
4
4
|
namespace :deploy do
|
5
5
|
|
6
|
-
before :starting, :log_level do
|
7
|
-
SSHKit.config.output_verbosity = fetch(:deploy_log_level)
|
8
|
-
end
|
9
|
-
|
10
|
-
before :starting, 'deployinator:sshkit_umask'
|
11
|
-
|
12
6
|
# Default branch is :master
|
13
|
-
|
7
|
+
task :set_branch => 'deployinator:load_settings' do
|
14
8
|
unless ENV['from_local']
|
15
9
|
# Always use the master branch in production:
|
16
10
|
unless "#{fetch(:stage)}" == "production"
|
@@ -18,9 +12,10 @@ namespace :deploy do
|
|
18
12
|
end
|
19
13
|
end
|
20
14
|
end
|
15
|
+
before :starting, :set_branch
|
21
16
|
|
22
17
|
#desc 'Copies .git folder to support .gemspecs that run git commands'
|
23
|
-
task :copy_git do
|
18
|
+
task :copy_git => 'deployinator:load_settings' do
|
24
19
|
unless ENV['from_local'] == "true"
|
25
20
|
on roles(:app) do
|
26
21
|
within release_path do
|
@@ -29,13 +24,15 @@ namespace :deploy do
|
|
29
24
|
end
|
30
25
|
end
|
31
26
|
end
|
32
|
-
|
27
|
+
if Rake::Task.task_defined?("bundler:install")
|
28
|
+
before 'bundler:install', 'deploy:copy_git'
|
29
|
+
end
|
33
30
|
|
34
31
|
if Rake::Task.task_defined?("deploy:assets:precompile")
|
35
32
|
# Overwrite :assets:precompile to use docker
|
36
33
|
Rake::Task["deploy:assets:precompile"].clear_actions
|
37
34
|
namespace :assets do
|
38
|
-
task :precompile do
|
35
|
+
task :precompile => 'deployinator:load_settings' do
|
39
36
|
on roles(fetch(:assets_roles)) do |host|
|
40
37
|
deploy_assets_precompile(host)
|
41
38
|
end
|
@@ -47,7 +44,7 @@ namespace :deploy do
|
|
47
44
|
# Overwrite :cleanup_assets to use docker
|
48
45
|
Rake::Task["deploy:cleanup_assets"].clear_actions
|
49
46
|
desc 'Cleanup expired assets'
|
50
|
-
task :cleanup_assets => [:set_rails_env] do
|
47
|
+
task :cleanup_assets => ['deployinator:load_settings', :set_rails_env] do
|
51
48
|
on roles(fetch(:assets_roles)) do |host|
|
52
49
|
deploy_assets_cleanup(host)
|
53
50
|
end
|
@@ -58,7 +55,7 @@ namespace :deploy do
|
|
58
55
|
# Overwrite :migrate to use docker
|
59
56
|
Rake::Task["deploy:migrate"].clear_actions
|
60
57
|
desc 'Runs rake db:migrate if migrations are set'
|
61
|
-
task :migrate => [:set_rails_env, 'deploy:check:postgres_running'] do
|
58
|
+
task :migrate => ['deployinator:load_settings', :set_rails_env, 'deploy:check:postgres_running'] do
|
62
59
|
on primary fetch(:migration_role) do |host|
|
63
60
|
conditionally_migrate = fetch(:conditionally_migrate)
|
64
61
|
info '[deploy:migrate] Checking changes in /db/migrate' if conditionally_migrate
|
@@ -72,17 +69,35 @@ namespace :deploy do
|
|
72
69
|
end
|
73
70
|
end
|
74
71
|
|
75
|
-
task :install_bundler do
|
72
|
+
task :install_bundler => 'deployinator:load_settings' do
|
76
73
|
on roles(:app) do |host|
|
77
74
|
unless file_exists?(shared_path.join('bundle', 'bin', 'bundle'))
|
78
75
|
deploy_install_bundler(host)
|
79
76
|
end
|
80
77
|
end
|
81
78
|
end
|
82
|
-
|
79
|
+
if Rake::Task.task_defined?("bundler:install")
|
80
|
+
before 'bundler:install', 'deploy:install_bundler'
|
81
|
+
end
|
82
|
+
|
83
|
+
task :install_database_yml => 'deployinator:load_settings' do
|
84
|
+
on roles(:app) do |host|
|
85
|
+
config_file = "database.yml"
|
86
|
+
template_path = File.expand_path("./#{fetch(:deploy_templates_path)}/#{config_file}.erb")
|
87
|
+
generated_config_file = ERB.new(File.new(template_path).read).result(binding)
|
88
|
+
set :final_path, -> { release_path.join('config', config_file) }
|
89
|
+
upload! StringIO.new(generated_config_file), "/tmp/#{config_file}"
|
90
|
+
execute("mv", "/tmp/#{config_file}", fetch(:final_path))
|
91
|
+
as :root do
|
92
|
+
execute("chown", "#{fetch(:deployment_username)}:#{fetch(:webserver_username)}", fetch(:final_path))
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
before 'deploy:updated', 'deploy:install_database_yml'
|
97
|
+
|
83
98
|
|
84
99
|
desc 'Restart application using bluepill restart inside the docker container.'
|
85
|
-
task :restart => [:install_config_files, 'deploy:check:settings'] do
|
100
|
+
task :restart => ['deployinator:load_settings', :install_config_files, 'deploy:check:settings'] do
|
86
101
|
on roles(:app) do |host|
|
87
102
|
name = fetch(:ruby_container_name)
|
88
103
|
if container_exists?(name)
|
@@ -98,7 +113,6 @@ namespace :deploy do
|
|
98
113
|
as :root do
|
99
114
|
execute("rm", "-f", fetch(:webserver_socket_path).join('unicorn.pid'))
|
100
115
|
end
|
101
|
-
warn "Starting a new container named #{name} on #{host}"
|
102
116
|
deploy_run_bluepill(host)
|
103
117
|
check_stayed_running(name)
|
104
118
|
end
|
@@ -106,9 +120,9 @@ namespace :deploy do
|
|
106
120
|
end
|
107
121
|
after :publishing, :restart
|
108
122
|
|
109
|
-
desc 'Restart application by recreating the docker container.'
|
110
123
|
namespace :restart do
|
111
|
-
|
124
|
+
desc 'Restart application by recreating the Docker container'
|
125
|
+
task :force => ['deployinator:load_settings', :install_config_files, 'deploy:check:settings'] do
|
112
126
|
on roles(:app) do |host|
|
113
127
|
name = fetch(:ruby_container_name)
|
114
128
|
if container_exists?(name)
|
@@ -125,7 +139,7 @@ namespace :deploy do
|
|
125
139
|
begin
|
126
140
|
execute("docker", "rm", name)
|
127
141
|
rescue
|
128
|
-
fatal "We were not able to remove the container for some reason. Try running 'cap <stage> deploy:restart:force' again."
|
142
|
+
fatal "We were not able to remove the container #{name} for some reason. Try running 'cap <stage> deploy:restart:force' again."
|
129
143
|
end
|
130
144
|
end
|
131
145
|
end
|
@@ -143,7 +157,7 @@ namespace :deploy do
|
|
143
157
|
# end
|
144
158
|
# end
|
145
159
|
|
146
|
-
task :install_config_files do
|
160
|
+
task :install_config_files => 'deployinator:load_settings' do
|
147
161
|
on roles(:app) do |host|
|
148
162
|
["bluepill.rb", "unicorn.rb"].each do |config_file|
|
149
163
|
template_path = File.expand_path("./#{fetch(:deploy_templates_path)}/#{config_file}.erb")
|
@@ -159,7 +173,7 @@ namespace :deploy do
|
|
159
173
|
end
|
160
174
|
|
161
175
|
desc "Enter the Rails console."
|
162
|
-
task :rails_console do
|
176
|
+
task :rails_console => 'deployinator:load_settings' do
|
163
177
|
on roles(:app) do |host|
|
164
178
|
info "Entering Rails Console inside #{fetch(:ruby_container_name)} on #{host}"
|
165
179
|
system deploy_rails_console(host)
|
@@ -167,7 +181,7 @@ namespace :deploy do
|
|
167
181
|
end
|
168
182
|
|
169
183
|
namespace :rails_console do
|
170
|
-
task :print do
|
184
|
+
task :print => 'deployinator:load_settings' do
|
171
185
|
on roles(:app) do |host|
|
172
186
|
info "You can SSH into #{host} and run the following command to enter the Rails Console."
|
173
187
|
info deploy_rails_console_print(host)
|
@@ -176,7 +190,7 @@ namespace :deploy do
|
|
176
190
|
end
|
177
191
|
|
178
192
|
desc "Write Version file on server"
|
179
|
-
|
193
|
+
task :write_version_file => 'deployinator:load_settings' do
|
180
194
|
on roles(:app) do |host|
|
181
195
|
execute "echo", "\"<version>", "<release>#{fetch(:current_revision)}</release>",
|
182
196
|
"<deployed_at>#{Time.now.strftime('%m/%d/%Y at %H:%M %Z')}</deployed_at>",
|
@@ -184,11 +198,46 @@ namespace :deploy do
|
|
184
198
|
"</version>\"", ">", current_path.join('public', 'version.xml')
|
185
199
|
end
|
186
200
|
end
|
201
|
+
after 'deploy:finished', 'deploy:write_version_file'
|
187
202
|
|
188
|
-
|
203
|
+
task :success_message => 'deployinator:load_settings' do
|
189
204
|
run_locally do
|
190
205
|
info "That was a successful deploy!"
|
191
206
|
end
|
192
207
|
end
|
208
|
+
after 'deploy:finished', 'deploy:success_message'
|
209
|
+
|
210
|
+
# the purpose of this task is to prevent hang during a bundle
|
211
|
+
# install that needs to reach github for the first time and will otherwise
|
212
|
+
# block asking "Are you sure you want to continue connecting (yes/no)?"
|
213
|
+
# this is only needed when deploying to a server for the first time using from_local=true.
|
214
|
+
task :add_repo_hostkeys => 'deployinator:load_settings' do
|
215
|
+
on roles(:app) do
|
216
|
+
if fetch(:repo_url).include? "@"
|
217
|
+
host = fetch(:repo_url).split(":").shift
|
218
|
+
socket = capture "echo", "$SSH_AUTH_SOCK"
|
219
|
+
with :ssh_auth_sock => socket do
|
220
|
+
if test(
|
221
|
+
"ssh", "-T", "-o", "StrictHostKeyChecking=no", "#{host};",
|
222
|
+
"EXIT_CODE=$?;",
|
223
|
+
"if", "[", "$EXIT_CODE", "-eq", "1", "];",
|
224
|
+
"then", "exit", "0;",
|
225
|
+
"else",
|
226
|
+
"exit", "$EXIT_CODE;",
|
227
|
+
"fi"
|
228
|
+
)
|
229
|
+
info "Successfully added #{host} to known host keys"
|
230
|
+
else
|
231
|
+
fatal "Not able to add #{host}'s ssh keys to the known hosts"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
else
|
235
|
+
warn "Repo URL does not appear to use SSH, not adding to known hosts"
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
if Rake::Task.task_defined?("bundler:install")
|
240
|
+
before 'bundler:install', 'deploy:add_repo_hostkeys'
|
241
|
+
end
|
193
242
|
|
194
243
|
end
|
@@ -8,10 +8,16 @@ set :application, 'my_app_name'
|
|
8
8
|
set :preexisting_ssh_user, ENV['USER']
|
9
9
|
set :deployment_username, "deployer" # user with SSH access and passwordless sudo rights
|
10
10
|
set :webserver_username, "www-data" # less trusted web server user with limited write permissions
|
11
|
+
set :database_name, "db_name"
|
12
|
+
set :database_username, "db_username"
|
13
|
+
set :database_password, "db_password"
|
14
|
+
# All permissions changes are recursive, and unless overridden below,
|
15
|
+
# all folders will be "deployer www-data drwxr-s---",
|
16
|
+
# all files will be "deployer www-data -rw-r-----"
|
11
17
|
set :webserver_owned_dirs, [shared_path.join('tmp', 'cache'), shared_path.join('public', 'assets')]
|
12
18
|
set :webserver_writeable_dirs, [shared_path.join('run'), shared_path.join("tmp"), shared_path.join("log")]
|
13
19
|
set :webserver_executable_dirs, [shared_path.join("bundle", "bin")]
|
14
|
-
set :ignore_permissions_dirs, [shared_path.join("postgres"), shared_path.join("nginx")]
|
20
|
+
set :ignore_permissions_dirs, [shared_path.join("postgres"), shared_path.join("nginx"), "#{fetch(:deploy_to)}/releases"]
|
15
21
|
|
16
22
|
# Default value for linked_dirs is []
|
17
23
|
# set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
|
data/lib/deployinator/helpers.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
namespace :deployinator do
|
2
2
|
|
3
|
-
task :sshkit_umask do
|
3
|
+
task :sshkit_umask => 'deployinator:load_settings' do
|
4
4
|
SSHKit.config.umask = "0027"
|
5
5
|
end
|
6
|
+
before 'deploy:starting', 'deployinator:sshkit_umask'
|
6
7
|
|
7
|
-
task :settings, [:absolute_path, :relative_path] do |t, args|
|
8
|
+
task :settings, [:absolute_path, :relative_path] => 'deployinator:load_settings' do |t, args|
|
8
9
|
run_locally do
|
9
10
|
if fetch(:print_all)
|
10
11
|
lines = "\nThe following settings are needed in your config (#{args.relative_path}).\n"
|
@@ -33,7 +34,7 @@ end
|
|
33
34
|
|
34
35
|
|
35
36
|
def deployment_user_setup(templates_path)
|
36
|
-
require 'erb'
|
37
|
+
require 'erb'
|
37
38
|
name = fetch(:deployment_username)
|
38
39
|
unix_user_add(name) unless unix_user_exists?(name)
|
39
40
|
execute "usermod", "-a", "-G", "sudo,docker,#{fetch(:webserver_username)}", name
|
@@ -48,46 +49,75 @@ def deployment_user_setup(templates_path)
|
|
48
49
|
execute "chmod", "600", "/home/#{name}/.ssh/authorized_keys"
|
49
50
|
end
|
50
51
|
|
52
|
+
# TODO when replacing this method with the new one, make sure the releases dir itself gets permissioned, just not it's contents.
|
51
53
|
def setup_file_permissions
|
54
|
+
|
52
55
|
ignore_options = fetch(:ignore_permissions_dirs).collect do |dir|
|
53
56
|
["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
|
54
57
|
end
|
58
|
+
ignore_options += ["-not", "-path", "\"#{fetch(:deploy_to)}/releases/*\""]
|
55
59
|
chown_ignore_options = fetch(:webserver_owned_dirs).collect do |dir|
|
56
60
|
["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
|
57
61
|
end
|
62
|
+
|
58
63
|
# chown webserver owned
|
59
64
|
fetch(:webserver_owned_dirs).each do |dir|
|
60
65
|
if directory_exists?(dir)
|
61
66
|
execute "find", dir, ignore_options,
|
62
|
-
"-
|
67
|
+
'\(', "-not", "-user", fetch(:webserver_username), "-or",
|
68
|
+
"-not", "-group", fetch(:webserver_username), '\)',
|
69
|
+
"-print0", "|", "xargs", "--no-run-if-empty", "--null",
|
70
|
+
"chown", "#{fetch(:webserver_username)}:#{fetch(:webserver_username)}"
|
71
|
+
else
|
72
|
+
execute "mkdir", "-p", dir
|
73
|
+
execute "chown", "#{fetch(:webserver_username)}:#{fetch(:webserver_username)}", dir
|
63
74
|
end
|
64
75
|
end
|
76
|
+
|
65
77
|
# chown
|
66
78
|
execute "find", fetch(:deploy_to), ignore_options, chown_ignore_options,
|
67
|
-
"-
|
79
|
+
'\(', "-not", "-user", fetch(:deployment_username), "-or",
|
80
|
+
"-not", "-group", fetch(:webserver_username), '\)',
|
81
|
+
"-print0", "|", "xargs", "--no-run-if-empty", "--null",
|
82
|
+
"chown", "#{fetch(:deployment_username)}:#{fetch(:webserver_username)}"
|
83
|
+
|
68
84
|
# chmod executable
|
69
85
|
fetch(:webserver_executable_dirs).each do |dir|
|
70
86
|
if directory_exists?(dir)
|
71
87
|
execute "find", dir, "-type", "f",
|
72
|
-
"-
|
88
|
+
"-not", "-perm", "0750",
|
89
|
+
"-print0", "|", "xargs", "--no-run-if-empty", "--null", "chmod", "0750"
|
90
|
+
# else # don't do this mkdir because it gets run as root and doesn't chown parent dirs
|
91
|
+
# execute "mkdir", "-p", dir
|
92
|
+
# execute "chown", "#{fetch(:deployment_username)}:#{fetch(:webserver_username)}", dir
|
73
93
|
end
|
74
94
|
ignore_options += ["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
|
75
95
|
end
|
96
|
+
|
76
97
|
# chmod writable
|
77
98
|
fetch(:webserver_writeable_dirs).each do |dir|
|
78
99
|
if directory_exists?(dir)
|
79
100
|
execute "find", "-L", dir, "-type", "d",
|
80
|
-
"-
|
101
|
+
"-not", "-perm", "2770",
|
102
|
+
"-print0", "|", "xargs", "--no-run-if-empty", "--null", "chmod", "2770"
|
81
103
|
execute "find", "-L", dir, "-type", "f",
|
82
|
-
"-
|
104
|
+
"-not", "-perm", "0660",
|
105
|
+
"-print0", "|", "xargs", "--no-run-if-empty", "--null", "chmod", "0660"
|
106
|
+
else
|
107
|
+
execute "mkdir", "-p", dir
|
108
|
+
execute "chown", "#{fetch(:deployment_username)}:#{fetch(:webserver_username)}", dir
|
109
|
+
execute "chmod", "2770", dir
|
83
110
|
end
|
84
111
|
ignore_options += ["-not", "-path", "\"#{dir}\"", "-not", "-path", "\"#{dir}/*\""]
|
85
112
|
end
|
113
|
+
|
86
114
|
# chmod
|
87
115
|
execute "find", fetch(:deploy_to), "-type", "d", ignore_options,
|
88
|
-
"-
|
116
|
+
"-not", "-perm", "2750",
|
117
|
+
"-print0", "|", "xargs", "--no-run-if-empty", "--null", "chmod", "2750"
|
89
118
|
execute "find", fetch(:deploy_to), "-type", "f", ignore_options,
|
90
|
-
"-
|
119
|
+
"-not", "-perm", "0640",
|
120
|
+
"-print0", "|", "xargs", "--no-run-if-empty", "--null", "chmod", "0640"
|
91
121
|
end
|
92
122
|
|
93
123
|
def container_exists?(container_name)
|
data/lib/deployinator/jobs.rb
CHANGED
@@ -2,7 +2,7 @@ namespace :deploy do
|
|
2
2
|
namespace :jobs do
|
3
3
|
|
4
4
|
desc 'Restart jobs using bluepill restart inside the docker container.'
|
5
|
-
task :restart => ['deploy:check:settings'] do
|
5
|
+
task :restart => ['deployinator:load_settings', 'deploy:check:settings'] do
|
6
6
|
on roles(:app) do |host|
|
7
7
|
name = fetch(:ruby_jobs_container_name)
|
8
8
|
if container_exists?(name)
|
@@ -24,11 +24,11 @@ namespace :deploy do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
27
|
-
after 'deploy:restart', :restart
|
27
|
+
after 'deploy:restart', 'deploy:jobs:restart'
|
28
28
|
|
29
29
|
desc 'Restart application by recreating the docker container.'
|
30
30
|
namespace :restart do
|
31
|
-
task :force => ['deploy:check:settings'] do
|
31
|
+
task :force => ['deployinator:load_settings', 'deploy:check:settings'] do
|
32
32
|
on roles(:app) do |host|
|
33
33
|
name = fetch(:ruby_jobs_container_name)
|
34
34
|
if container_exists?(name)
|
@@ -50,6 +50,7 @@ namespace :deploy do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
53
|
+
before 'deploy:restart:force', 'deploy:jobs:restart:force'
|
53
54
|
|
54
55
|
end
|
55
56
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deployinator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-02-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: capistrano
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 3.2.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: net-ssh
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.9.4
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.9.4
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
47
|
name: rake
|
32
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -78,6 +94,7 @@ files:
|
|
78
94
|
- lib/deployinator/examples/Dockerfile
|
79
95
|
- lib/deployinator/examples/deployment_authorized_keys.erb
|
80
96
|
- lib/deployinator/examples/unicorn.rb.erb
|
97
|
+
- lib/deployinator/examples/database.yml.erb
|
81
98
|
- lib/deployinator/examples/bluepill.rb.erb
|
82
99
|
homepage: https://github.com/snarlysodboxer/deployinator
|
83
100
|
licenses:
|
@@ -106,3 +123,4 @@ signing_key:
|
|
106
123
|
specification_version: 3
|
107
124
|
summary: Deploy Applications
|
108
125
|
test_files: []
|
126
|
+
has_rdoc:
|