deployinator 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/deployinator/config.rb +70 -12
- data/lib/deployinator/deploy.rb +296 -83
- data/lib/deployinator/examples/Capfile +27 -0
- data/lib/deployinator/examples/Dockerfile +16 -0
- data/lib/deployinator/examples/application_bluepill.rb.erb +27 -0
- data/lib/deployinator/examples/application_unicorn.rb.erb +40 -0
- data/lib/deployinator/examples/config/deploy/staging.rb +50 -0
- data/lib/deployinator/examples/config/deploy/staging_deployinator.rb +17 -0
- data/lib/deployinator/examples/config/deploy.rb +63 -0
- data/lib/deployinator/examples/config/deploy_deployinator.rb +56 -0
- data/lib/deployinator/examples/deployer_authorized_keys.erb +1 -0
- metadata +22 -9
- checksums.yaml +0 -7
data/lib/deployinator/config.rb
CHANGED
@@ -1,17 +1,75 @@
|
|
1
|
-
namespace :
|
2
|
-
|
3
|
-
desc '
|
4
|
-
task :
|
5
|
-
run_locally do
|
6
|
-
|
1
|
+
namespace :deployinator do
|
2
|
+
|
3
|
+
# desc 'Ensure all deployinator specific settings are set, and warn and raise if not.'
|
4
|
+
# task :check_settings do
|
5
|
+
# run_locally do
|
6
|
+
# deploy_rb = File.expand_path("./config/deploy.rb")
|
7
|
+
# deploy_dir = File.expand_path("./config/deploy")
|
8
|
+
# {
|
9
|
+
# "Do not \"set :bundle_binstubs, ....\", deployinator will overwrite it and you'll be confused." =>
|
10
|
+
# system("grep -R -q -E '^set\ :bundle_binstubs' #{deploy_rb} #{deploy_dir}"),
|
11
|
+
# "Do not \"set :bundle_gemfile, ....\", deployinator will overwrite it and you'll be confused." =>
|
12
|
+
# system("grep -R -q -E '^set\ :bundle_gemfile' #{deploy_rb} #{deploy_dir}"),
|
13
|
+
# "You need \"set :domain, 'your.domain.com'\" in your config/deploy/#{fetch(:stage)}.rb file." =>
|
14
|
+
# fetch(:domain).nil?,
|
15
|
+
# "You need \"set :nginx_container_name, 'your_nginx_container_name'\" in your config/deploy/#{fetch(:stage)}.rb file." =>
|
16
|
+
# fetch(:nginx_container_name).nil?,
|
17
|
+
# "You need \"set :external_socket_path, 'your_external_socket_path'\" in your config/deploy/#{fetch(:stage)}.rb file." =>
|
18
|
+
# fetch(:external_socket_path).nil?,
|
19
|
+
# "You need \"set :postgres_container_name, 'your_postgres_container_name'\" in your config/deploy/#{fetch(:stage)}.rb file." =>
|
20
|
+
# fetch(:postgres_container_name).nil?,
|
21
|
+
# "You need \"set :postgres_port, 'your_postgres_port_number'\" in your config/deploy/#{fetch(:stage)}.rb file." =>
|
22
|
+
# fetch(:postgres_port).nil?,
|
23
|
+
# "You need \"set :ruby_image_name, 'your_ruby_image_name'\" in your config/deploy/#{fetch(:stage)}.rb file." =>
|
24
|
+
# fetch(:ruby_image_name).nil?,
|
25
|
+
# "You need \"set :ruby_container_name, 'your_ruby_container_name'\" in your config/deploy/#{fetch(:stage)}.rb file." =>
|
26
|
+
# fetch(:ruby_container_name).nil?,
|
27
|
+
# "You need \"set :ruby_container_max_mem_mb, 'your_ruby_container_max_mem_mb'\" in your config/deploy/#{fetch(:stage)}.rb file." =>
|
28
|
+
# fetch(:ruby_container_max_mem_mb).nil?
|
29
|
+
# }.each do |message, true_false|
|
30
|
+
# fatal(message) and raise if true_false
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
# before 'deploy:starting', 'deployinator:check_settings'
|
7
35
|
|
8
|
-
|
9
|
-
|
10
|
-
|
36
|
+
# TODO make this better
|
37
|
+
task :check_templates do
|
38
|
+
run_locally do
|
39
|
+
keys_template = File.expand_path("./templates/deploy/deployer_authorized_keys.erb")
|
40
|
+
bluepill_template = File.expand_path("./templates/deploy/#{fetch(:application)}_bluepill.rb.erb")
|
41
|
+
unicorn_template = File.expand_path("./templates/deploy/#{fetch(:application)}_unicorn.rb.erb")
|
42
|
+
{
|
43
|
+
"You need a templates/deploy/deployer_authorized_keys.erb file." => keys_template,
|
44
|
+
"You need a templates/deploy/#{fetch(:application)}_bluepill.rb.erb file." => bluepill_template,
|
45
|
+
"You need a templates/deploy/#{fetch(:application)}_unicorn.rb.erb file." => unicorn_template,
|
46
|
+
}.each do |message, file|
|
47
|
+
fatal(message) and raise unless File.exists? file
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
before 'deploy:starting', 'deployinator:check_templates'
|
11
52
|
|
12
|
-
|
13
|
-
|
14
|
-
|
53
|
+
desc 'Write example config files'
|
54
|
+
task :install do
|
55
|
+
run_locally do
|
56
|
+
execute "mkdir -p config/deploy templates/deploy"
|
57
|
+
{
|
58
|
+
"examples/Capfile" => "Capfile_example",
|
59
|
+
"examples/config/deploy.rb" => "config/deploy_example.rb",
|
60
|
+
"examples/config/deploy_deployinator.rb" => "config/deploy_deployinator_example.rb",
|
61
|
+
"examples/config/deploy/staging.rb" => "config/deploy/staging_example.rb",
|
62
|
+
"examples/config/deploy/staging_deployinator.rb" => "config/deploy/staging_deployinator_example.rb",
|
63
|
+
"examples/Dockerfile" => "templates/deploy/Dockerfile_example",
|
64
|
+
"examples/deployer_authorized_keys.erb" => "templates/deploy/deployer_authorized_keys_example.erb",
|
65
|
+
"examples/application_unicorn.rb.erb" => "templates/deploy/#{fetch(:application, "my_app")}_unicorn_example.rb.erb",
|
66
|
+
"examples/application_bluepill.rb.erb" => "templates/deploy/#{fetch(:application, "my_app")}_bluepill_example.rb.erb"
|
67
|
+
}.each do |source, destination|
|
68
|
+
config = File.read(File.dirname(__FILE__) + "/#{source}")
|
69
|
+
File.open("./#{destination}", 'w') { |f| f.write(config) }
|
70
|
+
info "Wrote '#{destination}'"
|
71
|
+
end
|
72
|
+
info "Now remove the '_example' portion of their names or diff with existing files and add the needed lines."
|
15
73
|
end
|
16
74
|
end
|
17
75
|
end
|
data/lib/deployinator/deploy.rb
CHANGED
@@ -1,119 +1,332 @@
|
|
1
1
|
# config valid only for Capistrano 3.1
|
2
2
|
lock '3.2.1'
|
3
3
|
|
4
|
-
|
5
|
-
# locally changed code instead of the code in the git repo.
|
6
|
-
# TODO this is not working yet
|
7
|
-
if ENV['from_local']
|
8
|
-
set :repo_url, 'file://.'
|
9
|
-
set :scm, :none
|
10
|
-
else
|
11
|
-
set :repo_url, 'git@github.com:snarlysodboxer/example.git'
|
12
|
-
set :scm, :git
|
13
|
-
end
|
4
|
+
namespace :deploy do
|
14
5
|
|
15
|
-
|
16
|
-
|
6
|
+
task :set_bundle_command_map => [:set_deployer_user_id] do
|
7
|
+
SSHKit.config.command_map[:bundle] = [
|
8
|
+
"/usr/bin/env docker run --rm --tty",
|
9
|
+
"--user", fetch(:deployer_user_id),
|
10
|
+
"-e", "GEM_HOME=#{fetch(:deploy_to)}/shared/bundle",
|
11
|
+
"-e", "GEM_PATH=#{fetch(:deploy_to)}/shared/bundle",
|
12
|
+
"-e", "PATH=#{fetch(:deploy_to)}/shared/bundle/bin:$PATH",
|
13
|
+
"--entrypoint", "#{fetch(:deploy_to)}/shared/bundle/bin/bundle",
|
14
|
+
"--volume #{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
15
|
+
fetch(:ruby_image_name)
|
16
|
+
].join(' ')
|
17
|
+
end
|
18
|
+
before 'bundler:install', 'deploy:set_bundle_command_map'
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
+
task :set_rm_command_map do
|
21
|
+
SSHKit.config.command_map[:rm] = "/usr/bin/env sudo rm"
|
22
|
+
end
|
23
|
+
before 'deploy:started', 'deploy:set_rm_command_map'
|
20
24
|
|
21
|
-
#
|
22
|
-
|
25
|
+
# Append dependancy to existing cleanup task
|
26
|
+
task :cleanup => :set_rm_command_map
|
23
27
|
|
24
|
-
#
|
25
|
-
|
26
|
-
|
28
|
+
# Overwrite :assets:precompile to use docker
|
29
|
+
Rake::Task["deploy:assets:precompile"].clear
|
30
|
+
namespace :assets do
|
31
|
+
task :precompile do
|
32
|
+
on roles(fetch(:assets_roles)) do
|
33
|
+
execute(
|
34
|
+
"docker", "run", "--rm", "--tty",
|
35
|
+
"-w", fetch(:release_path, "#{fetch(:deploy_to)}/current"),
|
36
|
+
"--entrypoint", "#{fetch(:deploy_to)}/shared/bundle/bin/rake",
|
37
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
38
|
+
fetch(:ruby_image_name), "assets:precompile"
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
27
43
|
|
28
|
-
#
|
29
|
-
|
44
|
+
# Overwrite :cleanup_assets to use docker
|
45
|
+
Rake::Task["deploy:cleanup_assets"].clear
|
46
|
+
desc 'Cleanup expired assets'
|
47
|
+
task :cleanup_assets => [:set_rails_env] do
|
48
|
+
on roles(fetch(:assets_roles)) do
|
49
|
+
execute(
|
50
|
+
"docker", "run", "--rm", "--tty",
|
51
|
+
"-e", "RAILS_ENV=#{fetch(:rails_env)}",
|
52
|
+
"-w", fetch(:release_path, "#{fetch(:deploy_to)}/current"),
|
53
|
+
"--entrypoint", "#{fetch(:deploy_to)}/shared/bundle/bin/bundle",
|
54
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
55
|
+
fetch(:ruby_image_name), "exec", "rake", "assets:clean"
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
30
59
|
|
31
|
-
#
|
32
|
-
|
60
|
+
# Overwrite :migrate to use docker
|
61
|
+
Rake::Task["deploy:migrate"].clear
|
62
|
+
desc 'Runs rake db:migrate if migrations are set'
|
63
|
+
task :migrate => [:set_rails_env, :ensure_running_postgres] do
|
64
|
+
on primary fetch(:migration_role) do
|
65
|
+
conditionally_migrate = fetch(:conditionally_migrate)
|
66
|
+
info '[deploy:migrate] Checking changes in /db/migrate' if conditionally_migrate
|
67
|
+
if conditionally_migrate && test("diff -q #{release_path}/db/migrate #{current_path}/db/migrate")
|
68
|
+
info '[deploy:migrate] Skip `deploy:migrate` (nothing changed in db/migrate)'
|
69
|
+
else
|
70
|
+
info '[deploy:migrate] Run `rake db:migrate`' if conditionally_migrate
|
71
|
+
execute(
|
72
|
+
"docker", "run", "--rm", "--tty",
|
73
|
+
"--link", "#{fetch(:postgres_container_name)}:postgres",
|
74
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
75
|
+
"-e", "RAILS_ENV=#{fetch(:rails_env)}",
|
76
|
+
"--entrypoint", "#{fetch(:deploy_to)}/shared/bundle/bin/rake",
|
77
|
+
"-w", fetch(:release_path, "#{fetch(:deploy_to)}/current"),
|
78
|
+
fetch(:ruby_image_name), "db:migrate"
|
79
|
+
)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
33
83
|
|
34
|
-
#
|
35
|
-
|
84
|
+
# TODO make this better
|
85
|
+
task :ensure_running_postgres do
|
86
|
+
on primary fetch(:migration_role) do
|
87
|
+
unless capture("nc", "127.0.0.1", fetch(:postgres_port), "<", "/dev/null", ">", "/dev/null;", "echo", "$?").strip == "0"
|
88
|
+
fatal "Port #{fetch(:postgres_port)} is not responding, cannot db:migrate!"
|
89
|
+
raise
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
# task :ensure_running_postgres do
|
94
|
+
# on primary fetch(:migration_role) do
|
95
|
+
# if test "docker", "inspect", fetch(:postgres_container_name), "&>", "/dev/null"
|
96
|
+
# if (capture "docker", "inspect",
|
97
|
+
# "--format='{{.State.Running}}'",
|
98
|
+
# fetch(:postgres_container_name)).strip == "true"
|
99
|
+
# else
|
100
|
+
# execute "docker", "start", fetch(:postgres_container_name)
|
101
|
+
# end
|
102
|
+
# else
|
103
|
+
# set :run_pg_setup, ask("'true' or 'false', - #{fetch(:postgres_container_name)} is not running, would you like to run 'rake pg:setup'?", "false")
|
104
|
+
# if fetch(:run_pg_setup) == "true"
|
105
|
+
# #load Gem.bin_path('bundler', 'bundle')
|
106
|
+
# #import 'postgresinator'
|
107
|
+
# #load './infrastructure/Rakefile'
|
108
|
+
# Rake::Task['pg:setup'].invoke
|
109
|
+
# else
|
110
|
+
# raise "#{fetch(:postgres_container_name)} is not running, can't run db:migrate!"
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
# end
|
114
|
+
# end
|
115
|
+
before 'deploy:started', :ensure_running_postgres
|
36
116
|
|
37
|
-
|
38
|
-
#
|
117
|
+
before 'deploy:check', :setup_deployer_user do
|
118
|
+
on "#{ENV['USER']}@#{fetch(:domain)}" do
|
119
|
+
as :root do
|
120
|
+
unless test "id", fetch(:deploy_username)
|
121
|
+
execute "adduser", "--disabled-password", "--gecos", "\"\"", fetch(:deploy_username)
|
122
|
+
execute "usermod", "-a", "-G", "sudo", fetch(:deploy_username)
|
123
|
+
execute "usermod", "-a", "-G", "docker", fetch(:deploy_username)
|
124
|
+
end
|
125
|
+
execute "mkdir", "-p", "/home/#{fetch(:deploy_username)}/.ssh"
|
126
|
+
# not actually using ERB interpolation, no need for an instance variable.
|
127
|
+
template_path = File.expand_path("./templates/deploy/#{fetch(:deploy_username)}_authorized_keys.erb")
|
128
|
+
generated_config_file = ERB.new(File.new(template_path).read).result(binding)
|
129
|
+
# upload! does not yet honor "as" and similar scoping methods
|
130
|
+
upload! StringIO.new(generated_config_file), "/tmp/authorized_keys"
|
131
|
+
execute "mv", "-b", "/tmp/authorized_keys", "/home/#{fetch(:deploy_username)}/.ssh/authorized_keys"
|
132
|
+
execute "chown", "-R", "#{fetch(:deploy_username)}:#{fetch(:deploy_username)}", "/home/#{fetch(:deploy_username)}/.ssh"
|
133
|
+
execute "chmod", "700", "/home/#{fetch(:deploy_username)}/.ssh"
|
134
|
+
execute "chmod", "600", "/home/#{fetch(:deploy_username)}/.ssh/authorized_keys"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
39
138
|
|
40
|
-
|
41
|
-
#
|
139
|
+
task :ensure_www_data_user do
|
140
|
+
on "#{ENV['USER']}@#{fetch(:domain)}" do
|
141
|
+
as :root do
|
142
|
+
unless test "id", "www-data"
|
143
|
+
execute "adduser", "--disabled-password", "--gecos", "\"\"", "www-data"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
after 'deploy:started', :ensure_www_data_user
|
42
149
|
|
43
|
-
|
150
|
+
task :set_deployer_user_id do
|
151
|
+
on roles(:app), in: :sequence, wait: 5 do
|
152
|
+
set :deployer_user_id, capture("id", "-u", fetch(:deploy_username)).strip
|
153
|
+
end
|
154
|
+
end
|
44
155
|
|
45
|
-
|
46
|
-
|
156
|
+
task :set_www_data_user_id do
|
157
|
+
on roles(:app), in: :sequence, wait: 5 do
|
158
|
+
set :www_data_user_id, capture("id", "-u", "www-data").strip
|
159
|
+
end
|
160
|
+
end
|
47
161
|
|
48
|
-
task :
|
49
|
-
on roles(:
|
50
|
-
|
51
|
-
|
162
|
+
task :chown_log_dir => :set_www_data_user_id do
|
163
|
+
on roles(:app), in: :sequence, wait: 5 do
|
164
|
+
as :root do
|
165
|
+
unless test "[", "-d", "#{fetch(:deploy_to)}/shared/log", "]"
|
166
|
+
execute("mkdir", "-p", "#{fetch(:deploy_to)}/shared/log")
|
167
|
+
end
|
168
|
+
execute "chown", "-R", "#{fetch(:www_data_user_id)}:#{fetch(:www_data_user_id)}", "#{fetch(:deploy_to)}/shared/log"
|
169
|
+
end
|
52
170
|
end
|
53
171
|
end
|
172
|
+
before 'deploy:check:linked_dirs', :chown_log_dir
|
54
173
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
174
|
+
task :setup_deploy_to_dir => :set_deployer_user_id do
|
175
|
+
on roles(:app), in: :sequence, wait: 5 do
|
176
|
+
as :root do
|
177
|
+
[
|
178
|
+
fetch(:deploy_to),
|
179
|
+
"#{fetch(:deploy_to)}/shared",
|
180
|
+
"#{fetch(:deploy_to)}/releases"
|
181
|
+
].each do |dir|
|
182
|
+
unless test "[", "-d", dir, "]"
|
183
|
+
execute("mkdir", "-p", dir)
|
184
|
+
end
|
185
|
+
execute "chown", "#{fetch(:deployer_user_id)}:#{fetch(:deployer_user_id)}", dir
|
186
|
+
end
|
60
187
|
end
|
61
188
|
end
|
62
189
|
end
|
190
|
+
after :setup_deployer_user, :setup_deploy_to_dir
|
63
191
|
|
64
|
-
|
65
|
-
on roles(:
|
66
|
-
|
67
|
-
|
192
|
+
task :install_bundler => :set_deployer_user_id do
|
193
|
+
on roles(:app), in: :sequence, wait: 5 do
|
194
|
+
as :root do
|
195
|
+
unless test "[", "-f", "#{fetch(:deploy_to)}/shared/bundle/bin/bundle", "]"
|
196
|
+
execute(
|
197
|
+
"docker", "run", "--rm", "--tty",
|
198
|
+
"-e", "GEM_HOME=#{fetch(:deploy_to)}/shared/bundle",
|
199
|
+
"-e", "GEM_PATH=#{fetch(:deploy_to)}/shared/bundle",
|
200
|
+
"-e", "PATH=#{fetch(:deploy_to)}/shared/bundle/bin:$PATH",
|
201
|
+
"--entrypoint", "/usr/local/bin/gem",
|
202
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
203
|
+
fetch(:ruby_image_name), "install",
|
204
|
+
"--install-dir", "#{fetch(:deploy_to)}/shared/bundle",
|
205
|
+
"--bindir", "#{fetch(:deploy_to)}/shared/bundle/bin",
|
206
|
+
"--no-ri", "--no-rdoc", "--quiet", "bundler", "-v'#{fetch(:bundler_version)}'"
|
207
|
+
)
|
208
|
+
end
|
209
|
+
execute "chown", "-R", "#{fetch(:deployer_user_id)}:#{fetch(:deployer_user_id)}", "#{fetch(:deploy_to)}/shared/bundle"
|
210
|
+
end
|
68
211
|
end
|
69
212
|
end
|
213
|
+
before 'bundler:install', 'deploy:install_bundler'
|
70
214
|
|
71
|
-
|
72
|
-
|
73
|
-
on roles(:
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
215
|
+
desc 'Restart application'
|
216
|
+
task :restart => [:set_www_data_user_id, :install_config_files] do
|
217
|
+
on roles(:app), in: :sequence, wait: 5 do
|
218
|
+
if test "docker", "inspect", fetch(:ruby_container_name), "&>", "/dev/null"
|
219
|
+
if (capture "docker", "inspect",
|
220
|
+
"--format='{{.State.Restarting}}'",
|
221
|
+
fetch(:ruby_container_name)).strip == "true"
|
222
|
+
execute("docker", "stop", fetch(:ruby_container_name))
|
223
|
+
execute("docker", "wait", fetch(:ruby_container_name))
|
224
|
+
end
|
225
|
+
if (capture "docker", "inspect",
|
226
|
+
"--format='{{.State.Running}}'",
|
227
|
+
fetch(:ruby_container_name)).strip == "true"
|
228
|
+
execute(
|
229
|
+
"docker", "exec", "--tty",
|
230
|
+
fetch(:ruby_container_name),
|
231
|
+
"#{fetch(:deploy_to)}/shared/bundle/bin/bluepill",
|
232
|
+
fetch(:application), "stop"
|
233
|
+
)
|
234
|
+
sleep 5
|
235
|
+
execute("docker", "stop", fetch(:ruby_container_name))
|
236
|
+
execute("docker", "wait", fetch(:ruby_container_name))
|
237
|
+
end
|
238
|
+
sleep 2
|
239
|
+
begin
|
240
|
+
execute("docker", "rm", fetch(:ruby_container_name))
|
241
|
+
rescue
|
242
|
+
sleep 5
|
243
|
+
begin
|
244
|
+
execute("docker", "rm", fetch(:ruby_container_name))
|
245
|
+
rescue
|
246
|
+
fatal "We were not able to remove the container for some reason. Try running 'cap <stage> deploy:restart' again."
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
as :root do
|
251
|
+
[
|
252
|
+
fetch(:external_socket_path),
|
253
|
+
"#{fetch(:deploy_to)}/current/public",
|
254
|
+
"#{fetch(:deploy_to)}/shared/tmp",
|
255
|
+
"#{fetch(:deploy_to)}/shared/log/production.log"
|
256
|
+
].each do |directory|
|
257
|
+
execute "chown", "-R", "#{fetch(:www_data_user_id)}:#{fetch(:www_data_user_id)}", directory
|
258
|
+
end
|
259
|
+
execute "chown", "-R", "#{fetch(:deployer_user_id)}:#{fetch(:deployer_user_id)}", "#{fetch(:deploy_to)}/shared/bundle"
|
83
260
|
end
|
261
|
+
execute("docker", "run", fetch(:docker_run_bluepill_command))
|
84
262
|
end
|
85
263
|
end
|
264
|
+
after :publishing, :restart
|
86
265
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
266
|
+
after :publishing, :check_nginx_running do
|
267
|
+
on primary fetch(:migration_role) do
|
268
|
+
if test "docker", "inspect", fetch(:nginx_container_name), "&>", "/dev/null"
|
269
|
+
if (capture "docker", "inspect",
|
270
|
+
"--format='{{.State.Running}}'",
|
271
|
+
fetch(:nginx_container_name)).strip == "true"
|
272
|
+
else
|
273
|
+
warn "The nginx container named #{fetch(:nginx_container_name)} exists but is not running. (You need this, start it, or re-run setup with something like nginxinator.)"
|
274
|
+
end
|
275
|
+
else
|
276
|
+
warn "No nginx container named #{fetch(:nginx_container_name)} exists! (You need this, set it up with something like nginxinator.)"
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
after :publishing, :ensure_cadvisor do
|
282
|
+
on roles(:app), in: :sequence, wait: 5 do
|
283
|
+
if fetch(:use_cadvisor, true)
|
284
|
+
if test "docker", "inspect", "cadvisor", "&>", "/dev/null"
|
285
|
+
if (capture "docker", "inspect",
|
286
|
+
"--format='{{.State.Running}}'",
|
287
|
+
"cadvisor").strip == "true"
|
288
|
+
info "cadvisor is already running."
|
289
|
+
else
|
290
|
+
info "Restarting existing cadvisor container."
|
291
|
+
execute "docker", "start", "cadvisor"
|
101
292
|
end
|
102
|
-
|
293
|
+
else
|
294
|
+
execute("docker", "run", fetch(:docker_run_cadvisor_command))
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
after :restart, :clear_cache do
|
301
|
+
on roles(:web), in: :groups, limit: 3, wait: 10 do
|
302
|
+
# Here we can do anything such as:
|
303
|
+
# within release_path do
|
304
|
+
# execute :rake, 'cache:clear'
|
305
|
+
# end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
task :install_config_files => [:set_deployer_user_id] do
|
310
|
+
on roles(:app), in: :sequence, wait: 5 do
|
311
|
+
set :bluepill_config, -> { "#{fetch(:application)}_bluepill.rb" }
|
312
|
+
set :unicorn_config, -> { "#{fetch(:application)}_unicorn.rb" }
|
313
|
+
set :socket_path, -> { fetch(:internal_socket_path) }
|
314
|
+
as 'root' do
|
315
|
+
[fetch(:bluepill_config), fetch(:unicorn_config)].each do |config_file|
|
316
|
+
@deploy_to = fetch(:deploy_to) # needed for ERB
|
317
|
+
@internal_socket_path = fetch(:socket_path) # needed for ERB
|
318
|
+
@application = fetch(:application) # needed for ERB
|
319
|
+
template_path = File.expand_path("./templates/deploy/#{config_file}.erb")
|
320
|
+
current_path = Pathname.new("#{fetch(:deploy_to)}/current")
|
321
|
+
generated_config_file = ERB.new(File.new(template_path).read).result(binding)
|
322
|
+
set :final_path, -> { fetch(:release_path, current_path).join('config', config_file) }
|
323
|
+
upload! StringIO.new(generated_config_file), "/tmp/#{config_file}"
|
324
|
+
execute("mv", "/tmp/#{config_file}", fetch(:final_path))
|
325
|
+
execute("chown", "#{fetch(:deployer_user_id)}:#{fetch(:deployer_user_id)}", fetch(:final_path))
|
326
|
+
execute("chmod", "664", fetch(:final_path))
|
103
327
|
end
|
104
|
-
execute(
|
105
|
-
"docker", "run",
|
106
|
-
"--detach", "--tty",
|
107
|
-
"--name", container[:name],
|
108
|
-
container[:run_options],
|
109
|
-
container[:image]
|
110
|
-
)
|
111
|
-
sleep 2
|
112
|
-
error("Container #{container[:name]} did not stay running more than 2 seconds!") unless test(is_running)
|
113
328
|
end
|
114
329
|
end
|
115
330
|
end
|
116
331
|
|
117
|
-
# :publishing is the hook after which to set our service restart commands
|
118
|
-
after :publishing, :restart
|
119
332
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Load DSL and Setup Up Stages
|
2
|
+
require 'capistrano/setup'
|
3
|
+
|
4
|
+
# Includes default deployment tasks
|
5
|
+
require 'capistrano/deploy'
|
6
|
+
|
7
|
+
# Includes tasks from other gems included in your Gemfile
|
8
|
+
#
|
9
|
+
# For documentation on these, see for example:
|
10
|
+
#
|
11
|
+
# https://github.com/capistrano/rvm
|
12
|
+
# https://github.com/capistrano/rbenv
|
13
|
+
# https://github.com/capistrano/chruby
|
14
|
+
# https://github.com/capistrano/bundler
|
15
|
+
# https://github.com/capistrano/rails
|
16
|
+
#
|
17
|
+
# require 'capistrano/rvm'
|
18
|
+
# require 'capistrano/rbenv'
|
19
|
+
# require 'capistrano/chruby'
|
20
|
+
require 'capistrano/bundler'
|
21
|
+
require 'capistrano/rails/assets'
|
22
|
+
require 'capistrano/rails/migrations'
|
23
|
+
|
24
|
+
require 'deployinator'
|
25
|
+
|
26
|
+
# Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
|
27
|
+
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# vi: ft=config
|
2
|
+
FROM ubuntu:12.04
|
3
|
+
MAINTAINER david amick <docker@davidamick.com>
|
4
|
+
|
5
|
+
ENV DEBIAN_FRONTEND noninteractive
|
6
|
+
|
7
|
+
RUN /bin/bash -c "apt-get update -qq && apt-get install -qy wget curl bzip2 make gcc"
|
8
|
+
RUN wget -O ruby-install-0.5.0.tar.gz https://github.com/postmodern/ruby-install/archive/v0.5.0.tar.gz
|
9
|
+
RUN tar -xzvf ruby-install-0.5.0.tar.gz
|
10
|
+
RUN cd ruby-install-0.5.0/ && make install && ruby-install --system ruby 1.9.3-p547
|
11
|
+
RUN gem install bundler --no-ri --no-rdoc
|
12
|
+
|
13
|
+
RUN /bin/bash -c "apt-get update -qq && apt-get install -qy libxml2 libxml2-dev libxslt1-dev nodejs postgresql-contrib libpq-dev"
|
14
|
+
|
15
|
+
ENTRYPOINT ["/bin/bash"]
|
16
|
+
CMD ["-l"]
|
@@ -0,0 +1,27 @@
|
|
1
|
+
def red_unicorn_exec
|
2
|
+
"<%= @deploy_to %>/shared/bundle/bin/red_unicorn --env production --pid-file <%= @internal_socket_path %>/unicorn.pid --unicorn-exec <%= @deploy_to %>/shared/bundle/bin/unicorn_rails --unicorn-config <%= @deploy_to %>/current/config/<%= @application %>_unicorn.rb"
|
3
|
+
end
|
4
|
+
|
5
|
+
Bluepill.application("<%= @application %>", :log_file => "<%= @deploy_to %>/shared/log/bluepill.log", :foreground => true) do |app|
|
6
|
+
app.process("unicorn") do |process|
|
7
|
+
process.pid_file = "<%= @internal_socket_path %>/unicorn.pid"
|
8
|
+
process.working_dir = "<%= @deploy_to %>/current"
|
9
|
+
process.environment = {"BUNDLE_GEMFILE" => "<%= @deploy_to %>/current/Gemfile"}
|
10
|
+
process.start_command = "#{red_unicorn_exec} start"
|
11
|
+
process.stop_command = "#{red_unicorn_exec} stop"
|
12
|
+
process.restart_command = "'#{red_unicorn_exec} status; if [ $? = 0 ]; then #{red_unicorn_exec} restart; else #{red_unicorn_exec} start; fi'"
|
13
|
+
|
14
|
+
process.uid = process.gid = 'www-data'
|
15
|
+
|
16
|
+
process.start_grace_time = 30.seconds
|
17
|
+
process.stop_grace_time = 30.seconds
|
18
|
+
process.restart_grace_time = 60.seconds
|
19
|
+
|
20
|
+
process.monitor_children do |child_process|
|
21
|
+
child_process.stop_command = "kill -QUIT {{PID}}"
|
22
|
+
|
23
|
+
child_process.checks :mem_usage, :every => 30.seconds, :below => 300.megabytes, :times => [3,4], :fires => :stop
|
24
|
+
child_process.checks :cpu_usage, :every => 30.seconds, :below => 50, :times => [3,4], :fires => :stop
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
current_path = "<%= @deploy_to %>/current"
|
2
|
+
shared_path = "<%= @deploy_to %>/shared"
|
3
|
+
shared_bundler_gems_path = "<%= @deploy_to %>/shared/bundle"
|
4
|
+
|
5
|
+
worker_processes 4
|
6
|
+
working_directory current_path
|
7
|
+
listen "<%= @internal_socket_path %>/unicorn.socket", :backlog => 64
|
8
|
+
timeout 300
|
9
|
+
pid "<%= @internal_socket_path %>/unicorn.pid"
|
10
|
+
|
11
|
+
stderr_path "#{shared_path}/log/unicorn.stderr.log"
|
12
|
+
stdout_path "#{shared_path}/log/unicorn.stdout.log"
|
13
|
+
|
14
|
+
preload_app true
|
15
|
+
GC.respond_to?(:copy_on_write_friendly=) and
|
16
|
+
GC.copy_on_write_friendly = true
|
17
|
+
|
18
|
+
before_fork do |server, worker|
|
19
|
+
defined?(ActiveRecord::Base) and
|
20
|
+
ActiveRecord::Base.connection.disconnect!
|
21
|
+
end
|
22
|
+
|
23
|
+
after_fork do |server, worker|
|
24
|
+
worker.user('www-data', 'www-data') if Process.euid == 0
|
25
|
+
|
26
|
+
defined?(ActiveRecord::Base) and
|
27
|
+
ActiveRecord::Base.establish_connection
|
28
|
+
end
|
29
|
+
|
30
|
+
before_exec do |server|
|
31
|
+
# Configure bundler to use proper paths if app provides a Gemfile
|
32
|
+
if(File.exists?("#{current_path}/Gemfile"))
|
33
|
+
paths = ENV["PATH"].to_s.split(':')
|
34
|
+
paths.unshift "#{shared_bundler_gems_path}/bin"
|
35
|
+
ENV["PATH"] = paths.uniq.join(':')
|
36
|
+
|
37
|
+
ENV['GEM_HOME'] = ENV['GEM_PATH'] = shared_bundler_gems_path
|
38
|
+
ENV['BUNDLE_GEMFILE'] = "#{current_path}/Gemfile"
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Simple Role Syntax
|
2
|
+
# ==================
|
3
|
+
# Supports bulk-adding hosts to roles, the primary server in each group
|
4
|
+
# is considered to be the first unless any hosts have the primary
|
5
|
+
# property set. Don't declare `role :all`, it's a meta role.
|
6
|
+
|
7
|
+
set :domain, "my-app-staging.example.com"
|
8
|
+
set :deploy_username, "deployer"
|
9
|
+
set :user_host, "#{fetch(:deploy_username)}@#{fetch(:domain)}"
|
10
|
+
|
11
|
+
role :app, fetch(:user_host)
|
12
|
+
role :web, fetch(:user_host)
|
13
|
+
role :db, fetch(:user_host)
|
14
|
+
|
15
|
+
# Extended Server Syntax
|
16
|
+
# ======================
|
17
|
+
# This can be used to drop a more detailed server definition into the
|
18
|
+
# server list. The second argument is a, or duck-types, Hash and is
|
19
|
+
# used to set extended properties on the server.
|
20
|
+
|
21
|
+
#server 'example.com', user: 'deploy', roles: %w{web app}, my_property: :my_value
|
22
|
+
|
23
|
+
|
24
|
+
# Custom SSH Options
|
25
|
+
# ==================
|
26
|
+
# You may pass any option but keep in mind that net/ssh understands a
|
27
|
+
# limited set of options, consult[net/ssh documentation](http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start).
|
28
|
+
#
|
29
|
+
# Global options
|
30
|
+
# --------------
|
31
|
+
# set :ssh_options, {
|
32
|
+
# keys: %w(/home/rlisowski/.ssh/id_rsa),
|
33
|
+
# forward_agent: false,
|
34
|
+
# auth_methods: %w(password)
|
35
|
+
# }
|
36
|
+
#
|
37
|
+
# And/or per server (overrides global)
|
38
|
+
# ------------------------------------
|
39
|
+
# server 'example.com',
|
40
|
+
# user: 'user_name',
|
41
|
+
# roles: %w{web app},
|
42
|
+
# ssh_options: {
|
43
|
+
# user: 'user_name', # overrides user setting above
|
44
|
+
# keys: %w(/home/user_name/.ssh/id_rsa),
|
45
|
+
# forward_agent: false,
|
46
|
+
# auth_methods: %w(publickey password)
|
47
|
+
# # password: 'please use keys'
|
48
|
+
# }
|
49
|
+
|
50
|
+
require './config/deploy/staging_deployinator.rb'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
set :rails_env, 'production' # If the environment differs from the stage name
|
2
|
+
set :migration_role, 'app' # Defaults to 'db'
|
3
|
+
#set :conditionally_migrate, true # Defaults to false. If true, it's skip migration if files in db/migrate not modified
|
4
|
+
set :assets_roles, [:app] # Defaults to [:web]
|
5
|
+
#set :assets_prefix, 'prepackaged-assets' # Defaults to 'assets' this should match config.assets.prefix in your rails config/application.rb
|
6
|
+
|
7
|
+
# If you are using nginxinator and postgresinator, your settings would look similar to this:
|
8
|
+
set :nginx_container_name, "my-app-staging.example.com-nginx-80-443"
|
9
|
+
set :external_socket_path, "/my-app-staging.example.com-nginx-80-443-conf/run"
|
10
|
+
set :internal_socket_path, "/var/run/unicorn"
|
11
|
+
set :postgres_container_name, "my-app-staging.example.com-postgres-5432-master"
|
12
|
+
set :postgres_port, "5432"
|
13
|
+
set :ruby_image_name, "snarlysodboxer/ruby:1.9.3-p547"
|
14
|
+
set :ruby_container_name, "my-app-staging.example.com-ruby-bluepill"
|
15
|
+
set :ruby_container_max_mem_mb, "1024"
|
16
|
+
set :bundler_version, "1.7.4"
|
17
|
+
#set :use_cadvisor, true # this is default
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# config valid only for Capistrano 3.1
|
2
|
+
lock '3.2.1'
|
3
|
+
|
4
|
+
set :application, 'my_app_name'
|
5
|
+
set :repo_url, 'git@example.com:me/my_repo.git'
|
6
|
+
|
7
|
+
## Don't ask this here, only in staging or other non-production <stage>.rb files.
|
8
|
+
# Default branch is :master
|
9
|
+
# ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call
|
10
|
+
|
11
|
+
# Default deploy_to directory is /var/www/my_app
|
12
|
+
# set :deploy_to, '/var/www/my_app'
|
13
|
+
|
14
|
+
# Default value for :scm is :git
|
15
|
+
# set :scm, :git
|
16
|
+
|
17
|
+
# Default value for :format is :pretty
|
18
|
+
# set :format, :pretty
|
19
|
+
|
20
|
+
# Default value for :log_level is :debug
|
21
|
+
# set :log_level, :debug
|
22
|
+
|
23
|
+
# Default value for :pty is false
|
24
|
+
# set :pty, true
|
25
|
+
|
26
|
+
# Default value for :linked_files is []
|
27
|
+
# set :linked_files, %w{config/database.yml}
|
28
|
+
|
29
|
+
# Default value for linked_dirs is []
|
30
|
+
# set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}
|
31
|
+
set :linked_dirs, %w{log tmp}
|
32
|
+
|
33
|
+
# Default value for default_env is {}
|
34
|
+
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
|
35
|
+
|
36
|
+
# Default value for keep_releases is 5
|
37
|
+
# set :keep_releases, 5
|
38
|
+
|
39
|
+
namespace :deploy do
|
40
|
+
|
41
|
+
### No need to do anything here, deployinator defines this task.
|
42
|
+
desc 'Restart application'
|
43
|
+
task :restart do
|
44
|
+
on roles(:app), in: :sequence, wait: 5 do
|
45
|
+
# Your restart mechanism here, for example:
|
46
|
+
# execute :touch, release_path.join('tmp/restart.txt')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
after :publishing, :restart
|
51
|
+
|
52
|
+
after :restart, :clear_cache do
|
53
|
+
on roles(:web), in: :groups, limit: 3, wait: 10 do
|
54
|
+
# Here we can do anything such as:
|
55
|
+
# within release_path do
|
56
|
+
# execute :rake, 'cache:clear'
|
57
|
+
# end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
require './config/deploy_deployinator.rb'
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Use `cap <stage> deploy from_local=true` to deploy your
|
2
|
+
# locally changed code instead of the code in the git repo. You can also add --trace.
|
3
|
+
if ENV['from_local']
|
4
|
+
set :scm, :copy
|
5
|
+
else
|
6
|
+
set :scm, :git
|
7
|
+
end
|
8
|
+
|
9
|
+
# Always use the master branch in production:
|
10
|
+
set :current_stage, -> { fetch(:stage).to_s.strip }
|
11
|
+
unless fetch(:current_stage) == "production"
|
12
|
+
ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call
|
13
|
+
end
|
14
|
+
|
15
|
+
## The values in this file are not meant to be changed and shouldn't
|
16
|
+
## need to be under the majority of circumstances:
|
17
|
+
|
18
|
+
#set :bundle_roles, :all # this is default
|
19
|
+
#set :bundle_servers, -> { release_roles(fetch(:bundle_roles)) } # this is default
|
20
|
+
#set :bundle_binstubs, -> { shared_path.join('bin') } # this is default
|
21
|
+
set :bundle_binstubs, -> { shared_path.join('bundle', 'bin') } # this is required for deployinator
|
22
|
+
set :bundle_gemfile, -> { release_path.join('Gemfile') } # this is required for deployinator
|
23
|
+
#set :bundle_path, -> { shared_path.join('bundle') } # this is default
|
24
|
+
#set :bundle_without, %w{development test}.join(' ') # this is default
|
25
|
+
set :bundle_without, %w{development test deployment}.join(' ')
|
26
|
+
#set :bundle_flags, '--deployment --quiet' # this is default
|
27
|
+
#set :bundle_flags, '--deployment'
|
28
|
+
#set :bundle_env_variables, {} # this is default
|
29
|
+
|
30
|
+
set :docker_run_bluepill_command, -> { [
|
31
|
+
"--tty", "--detach",
|
32
|
+
"--name", fetch(:ruby_container_name),
|
33
|
+
"-e", "GEM_HOME=#{fetch(:deploy_to)}/shared/bundle",
|
34
|
+
"-e", "GEM_PATH=#{fetch(:deploy_to)}/shared/bundle",
|
35
|
+
"-e", "BUNDLE_GEMFILE=#{fetch(:deploy_to)}/current/Gemfile",
|
36
|
+
"-e", "PATH=#{fetch(:deploy_to)}/shared/bundle/bin:$PATH",
|
37
|
+
"--link", "#{fetch(:postgres_container_name)}:postgres",
|
38
|
+
"--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
|
39
|
+
"--volume", "#{fetch(:external_socket_path)}:#{fetch(:internal_socket_path)}:rw",
|
40
|
+
"--entrypoint", "#{fetch(:deploy_to)}/shared/bundle/bin/bluepill",
|
41
|
+
"--restart", "always", "--memory", "#{fetch(:ruby_container_max_mem_mb)}m",
|
42
|
+
fetch(:ruby_image_name), "load",
|
43
|
+
"#{fetch(:deploy_to)}/current/config/#{fetch(:application)}_bluepill.rb"
|
44
|
+
] }
|
45
|
+
|
46
|
+
set :docker_run_cadvisor_command, -> { [
|
47
|
+
"--detach",
|
48
|
+
"--name", "cadvisor",
|
49
|
+
"--volume", "/:/rootfs:ro",
|
50
|
+
"--volume", "/var/run:/var/run:rw",
|
51
|
+
"--volume", "/sys:/sys:ro",
|
52
|
+
"--volume", "/var/lib/docker/:/var/lib/docker:ro",
|
53
|
+
"--publish", "127.0.0.1:8080:8080",
|
54
|
+
"--restart", "always",
|
55
|
+
"google/cadvisor:latest"
|
56
|
+
] }
|
@@ -0,0 +1 @@
|
|
1
|
+
# Add your keys here:
|
metadata
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deployinator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- david amick
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2014-
|
12
|
+
date: 2014-11-10 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: capistrano
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
19
|
- - '='
|
18
20
|
- !ruby/object:Gem::Version
|
@@ -20,6 +22,7 @@ dependencies:
|
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
27
|
- - '='
|
25
28
|
- !ruby/object:Gem::Version
|
@@ -33,28 +36,38 @@ files:
|
|
33
36
|
- lib/deployinator.rb
|
34
37
|
- lib/deployinator/deploy.rb
|
35
38
|
- lib/deployinator/config.rb
|
36
|
-
|
39
|
+
- lib/deployinator/examples/Capfile
|
40
|
+
- lib/deployinator/examples/config/deploy.rb
|
41
|
+
- lib/deployinator/examples/config/deploy_deployinator.rb
|
42
|
+
- lib/deployinator/examples/config/deploy/staging.rb
|
43
|
+
- lib/deployinator/examples/config/deploy/staging_deployinator.rb
|
44
|
+
- lib/deployinator/examples/Dockerfile
|
45
|
+
- lib/deployinator/examples/deployer_authorized_keys.erb
|
46
|
+
- lib/deployinator/examples/application_unicorn.rb.erb
|
47
|
+
- lib/deployinator/examples/application_bluepill.rb.erb
|
48
|
+
homepage: https://github.com/snarlysodboxer/deployinator
|
37
49
|
licenses:
|
38
|
-
-
|
39
|
-
metadata: {}
|
50
|
+
- GNU
|
40
51
|
post_install_message:
|
41
52
|
rdoc_options: []
|
42
53
|
require_paths:
|
43
54
|
- lib
|
44
55
|
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
45
57
|
requirements:
|
46
|
-
- - '>='
|
58
|
+
- - ! '>='
|
47
59
|
- !ruby/object:Gem::Version
|
48
60
|
version: '0'
|
49
61
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
50
63
|
requirements:
|
51
|
-
- - '>='
|
64
|
+
- - ! '>='
|
52
65
|
- !ruby/object:Gem::Version
|
53
66
|
version: '0'
|
54
67
|
requirements: []
|
55
68
|
rubyforge_project:
|
56
|
-
rubygems_version:
|
69
|
+
rubygems_version: 1.8.23.2
|
57
70
|
signing_key:
|
58
|
-
specification_version:
|
71
|
+
specification_version: 3
|
59
72
|
summary: Deploy Applications
|
60
73
|
test_files: []
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 1118ca9720569f14d4453a2d96561b65395362f8
|
4
|
-
data.tar.gz: 1d9079e7d2e1a79ec2a612f2c47a0d14355a017a
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: a6fa60095a8adaa33144331cade009a5493def8f046f0d7d49c95bab97c0ecf686fce20c85efca467f67b79372b884ea9017b9e1aeaaab5ffc38b6a2a980457c
|
7
|
-
data.tar.gz: 9b8bf3e88297d083a9ef13de344a5b76455a23cf277a1d07c2a3fc961563eb148fedecd4fd9b0abc9744637fef53d7eca112424d978c51633a73b551e8c4874e
|