meataxe 0.5.0 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/meataxe.rb +1 -9
- data/lib/meataxe/capistrano.rb +9 -5
- data/lib/meataxe/capistrano/dsl/rbenv_install.rb +23 -0
- data/lib/meataxe/capistrano/tasks/compile_assets_locally.cap +9 -4
- data/lib/meataxe/capistrano/tasks/monit.cap +2 -2
- data/lib/meataxe/capistrano/tasks/nginx.cap +1 -1
- data/lib/meataxe/capistrano/tasks/postgres.cap +227 -0
- data/lib/meataxe/capistrano/tasks/rbenv_install.cap +67 -0
- data/lib/meataxe/capistrano/tasks/run_tests.cap +12 -10
- data/lib/meataxe/capistrano/tasks/setup_config.cap +21 -16
- data/lib/meataxe/capistrano/tasks/tasks.cap +1 -1
- data/lib/meataxe/capistrano/templates/database.yml.erb +8 -0
- data/lib/meataxe/capistrano/templates/log_rotation.erb +11 -0
- data/lib/meataxe/capistrano/templates/monit.conf.erb +30 -0
- data/lib/meataxe/capistrano/templates/nginx.conf.erb +75 -0
- data/lib/meataxe/capistrano/templates/nginx_ssl.conf.erb +92 -0
- data/lib/meataxe/capistrano/templates/node_server.service.erb +22 -0
- data/lib/meataxe/capistrano/templates/puma.rb.erb +10 -0
- data/lib/meataxe/version.rb +1 -1
- metadata +13 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9c50c66b46f3e9be7a11d31fd446291a9ee2225a85e024f489dadfa1da438bcf
|
4
|
+
data.tar.gz: b899e16f810426b8610d3af6cfe1253be06d38b0b72d19153df753c61579f0ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3ae4bb181d3e74d8d8ca4361e5a167e93840d6928aab5ed728c61d258a91ffc05ad33656e9052d5ee40b5182a28e59a3ad59afdf7749869c45e1ffa4783119c
|
7
|
+
data.tar.gz: eb0c25853a74eccb18bcb57aedf0aa93f30c3be114f480ede7dbfda98e4ba1162fe19ea6721ecabb2cc9f6ae9394a82d0d27e5330a8821e7cb1aae98fa66c016
|
data/lib/meataxe.rb
CHANGED
@@ -1,9 +1 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# # Load custom tasks from `lib/capistrano/*` if you have any defined
|
4
|
-
# # Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r }
|
5
|
-
# # Dir.glob('lib/capistrano/**/*.rb').each { |r| import r }
|
6
|
-
#
|
7
|
-
# module Meataxe
|
8
|
-
# # :)
|
9
|
-
# end
|
1
|
+
# :)
|
data/lib/meataxe/capistrano.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Dir.glob(File.join(File.dirname(__FILE__), 'capistrano/tasks/*.cap')).each { |r| load r }
|
2
2
|
|
3
3
|
# First try and copy the file `config/deploy/#{full_app_name}/#{from}.erb`
|
4
|
-
# to `shared/config
|
4
|
+
# to `shared/config/#{to}`
|
5
5
|
#
|
6
6
|
# If the original source path doesn exist then it will search in:
|
7
7
|
# `config/deploy/shared/#{from}.erb`
|
@@ -15,16 +15,20 @@ def smart_template(from, to=nil)
|
|
15
15
|
if from_erb_path = template_file(from)
|
16
16
|
from_erb = StringIO.new(ERB.new(File.read(from_erb_path)).result(binding))
|
17
17
|
upload! from_erb, full_to_path
|
18
|
-
info "copying
|
18
|
+
info "copying #{from_erb_path} to #{full_to_path}"
|
19
19
|
else
|
20
20
|
error "error #{from} not found"
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
# Load templates from the local config directory, or fallback to default
|
25
|
+
# templates.
|
24
26
|
def template_file(name)
|
25
|
-
if File.exist?((file = "config/deploy/#{
|
27
|
+
if File.exist?((file = "config/deploy/shared/#{name}.erb"))
|
26
28
|
return file
|
27
|
-
elsif File.exist?((file = "config/deploy/
|
29
|
+
elsif File.exist?((file = "config/deploy/templates/#{name}.erb"))
|
30
|
+
return file
|
31
|
+
elsif File.exist?((file = File.join(File.dirname(__FILE__), "capistrano/templates/#{name}.erb")))
|
28
32
|
return file
|
29
33
|
end
|
30
34
|
return nil
|
@@ -46,6 +50,6 @@ def host_architecture
|
|
46
50
|
end
|
47
51
|
|
48
52
|
def update_repo(repo_url, target_path)
|
49
|
-
|
53
|
+
execute "if [ -d #{target_path} ]; then (cd #{target_path} && git pull); else git clone #{repo_url} #{target_path}; fi"
|
50
54
|
#run "cd #{target_path} && if [ -d #{target_path} ]; then (git pull); else (cd #{target_path} && cd.. && git clone #{repo_url} #{target_path}); fi"
|
51
55
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Capistrano
|
2
|
+
module DSL
|
3
|
+
module RbenvInstall
|
4
|
+
|
5
|
+
def rbenv_ruby_build_path
|
6
|
+
"#{fetch(:rbenv_path)}/plugins/ruby-build"
|
7
|
+
end
|
8
|
+
|
9
|
+
def rbenv_bin_executable_path
|
10
|
+
"#{fetch(:rbenv_path)}/bin/rbenv"
|
11
|
+
end
|
12
|
+
|
13
|
+
def rbenv_repo_url
|
14
|
+
'https://github.com/sstephenson/rbenv.git'
|
15
|
+
end
|
16
|
+
|
17
|
+
def ruby_build_repo_url
|
18
|
+
'https://github.com/sstephenson/ruby-build.git'
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,17 +1,22 @@
|
|
1
1
|
namespace :deploy do
|
2
|
-
|
2
|
+
# Rake::Task["deploy:assets:precompile"].clear_actions
|
3
|
+
|
4
|
+
desc "Compiles assets locally then rsync to server"
|
3
5
|
task :compile_assets_locally do
|
6
|
+
asset_prefix = fetch(:asset_prefix, "assets")
|
4
7
|
run_locally do
|
5
8
|
execute "RAILS_ENV=#{fetch(:rails_env)} bundle exec rake assets:precompile"
|
6
9
|
end
|
7
10
|
on roles(:app) do |role|
|
8
11
|
run_locally do
|
9
|
-
execute "rsync -av ./public/
|
12
|
+
execute "rsync -av --delete ./public/#{asset_prefix}/ #{role.user}@#{role.hostname}:#{shared_path}/public/#{asset_prefix}/;"
|
13
|
+
execute "rsync -av --delete ./public/packs/ #{role.user}@#{role.hostname}:#{shared_path}/public/packs/;"
|
10
14
|
end
|
11
|
-
|
15
|
+
execute "chmod -R 755 #{shared_path}/public/#{asset_prefix}"
|
12
16
|
end
|
13
17
|
run_locally do
|
14
|
-
execute "rm -rf ./public
|
18
|
+
execute "rm -rf ./public/#{asset_prefix}"
|
19
|
+
execute "rm -rf ./public/packs"
|
15
20
|
end
|
16
21
|
end
|
17
22
|
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
namespace :load do
|
2
|
+
task :defaults do
|
3
|
+
set :postgres_backup_dir, -> { 'postgres_backup' }
|
4
|
+
set :postgres_role, :db
|
5
|
+
set :postgres_env, -> { fetch(:rack_env, fetch(:rails_env, fetch(:stage))) }
|
6
|
+
set :postgres_keep_local_dumps, 0
|
7
|
+
set :postgres_backup_compression_level, 0
|
8
|
+
set :postgres_remote_sqlc_file_path, -> { nil }
|
9
|
+
set :postgres_local_database_config, -> { nil }
|
10
|
+
set :postgres_remote_database_config, -> { nil }
|
11
|
+
set :postgres_remote_cluster, -> { nil }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
namespace :postgres do
|
16
|
+
namespace :backup do
|
17
|
+
desc 'Create database dump'
|
18
|
+
task :create do
|
19
|
+
on roles(fetch(:postgres_role)) do |role|
|
20
|
+
grab_remote_database_config
|
21
|
+
config = fetch(:postgres_remote_database_config)
|
22
|
+
|
23
|
+
unless fetch(:postgres_remote_sqlc_file_path)
|
24
|
+
file_name = "db_backup.#{Time.now.strftime('%Y-%m-%d_%H-%M-%S')}.sqlc"
|
25
|
+
set :postgres_remote_sqlc_file_path, "#{shared_path}/#{fetch(:postgres_backup_dir)}/#{file_name}"
|
26
|
+
end
|
27
|
+
execute [
|
28
|
+
"PGPASSWORD=#{config['password']}",
|
29
|
+
"pg_dump #{user_option(config)}",
|
30
|
+
"-h #{config['host']}",
|
31
|
+
config['port'] ? "-p #{config['port']}" : nil,
|
32
|
+
"-Fc",
|
33
|
+
"--file=#{fetch(:postgres_remote_sqlc_file_path)}",
|
34
|
+
"-Z #{fetch(:postgres_backup_compression_level)}",
|
35
|
+
fetch(:postgres_remote_cluster) ? "--cluster #{fetch(:postgres_remote_cluster)}" : nil,
|
36
|
+
"#{config['database']}"
|
37
|
+
].compact.join(' ')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'Download last database dump'
|
42
|
+
task :download do
|
43
|
+
on roles(fetch(:postgres_role)) do |role|
|
44
|
+
unless fetch(:postgres_remote_sqlc_file_path)
|
45
|
+
file_name = capture("ls -v #{shared_path}/#{fetch :postgres_backup_dir}").split(/\n/).last
|
46
|
+
set :postgres_remote_sqlc_file_path, "#{shared_path}/#{fetch :postgres_backup_dir}/#{file_name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
download!(fetch(:postgres_remote_sqlc_file_path), "tmp/#{fetch :postgres_backup_dir}/#{Pathname.new(fetch(:postgres_remote_sqlc_file_path)).basename}")
|
50
|
+
begin
|
51
|
+
remote_file = fetch(:postgres_remote_sqlc_file_path)
|
52
|
+
rescue SSHKit::Command::Failed => e
|
53
|
+
warn e.inspect
|
54
|
+
ensure
|
55
|
+
execute "rm #{remote_file}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "Import last dump"
|
61
|
+
task :import do
|
62
|
+
grab_local_database_config
|
63
|
+
run_locally do
|
64
|
+
config = fetch(:postgres_local_database_config)
|
65
|
+
|
66
|
+
unless fetch(:database_name)
|
67
|
+
ask(:database_name, config['database'])
|
68
|
+
end
|
69
|
+
|
70
|
+
with rails_env: :development do
|
71
|
+
file_name = capture("ls -v tmp/#{fetch :postgres_backup_dir}").split(/\n/).last
|
72
|
+
file_path = "tmp/#{fetch :postgres_backup_dir}/#{file_name}"
|
73
|
+
begin
|
74
|
+
pgpass_path = File.join(Dir.pwd, '.pgpass')
|
75
|
+
File.open(pgpass_path, 'w+', 0600) { |file| file.write("*:*:*:#{config['username'] || config['user']}:#{config['password']}") }
|
76
|
+
execute "PGPASSFILE=#{pgpass_path} pg_restore -c #{user_option(config)} --no-owner -h #{config['host']} -p #{config['port'] || 5432 } -d #{fetch(:database_name)} #{file_path}"
|
77
|
+
rescue SSHKit::Command::Failed => e
|
78
|
+
warn e.inspect
|
79
|
+
info 'Import performed successfully!'
|
80
|
+
ensure
|
81
|
+
File.delete(pgpass_path) if File.exist?(pgpass_path)
|
82
|
+
File.delete(file_path) if (fetch(:postgres_keep_local_dumps) == 0) && File.exist?(file_path)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Ensure that remote dirs for postgres backup exist
|
89
|
+
before :create, :ensure_remote_dirs do
|
90
|
+
on roles(fetch(:postgres_role)) do |role|
|
91
|
+
execute :mkdir, "-p #{shared_path}/#{fetch(:postgres_backup_dir)}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Ensure that loca dirs for postgres backup exist
|
96
|
+
before :download, :ensure_local_dirs do
|
97
|
+
on roles(fetch(:postgres_role)) do |role|
|
98
|
+
run_locally do
|
99
|
+
execute :mkdir, "-p tmp/#{fetch :postgres_backup_dir}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
desc "Cleanup old local dumps"
|
105
|
+
task :cleanup do
|
106
|
+
run_locally do
|
107
|
+
dir = "tmp/#{fetch :postgres_backup_dir}"
|
108
|
+
file_names = capture("ls -v #{dir}").split(/\n/).sort
|
109
|
+
file_names[0...-fetch(:postgres_keep_local_dumps)].each {|file_name| File.delete("#{dir}/#{file_name}") }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
desc 'Replicate database locally'
|
115
|
+
task :replicate do
|
116
|
+
grab_local_database_config
|
117
|
+
config = fetch(:postgres_local_database_config)
|
118
|
+
ask(:database_name, config['database'])
|
119
|
+
invoke "postgres:backup:create"
|
120
|
+
invoke "postgres:backup:download"
|
121
|
+
invoke "postgres:backup:import"
|
122
|
+
invoke("postgres:backup:cleanup") if fetch(:postgres_keep_local_dumps) > 0
|
123
|
+
end
|
124
|
+
|
125
|
+
def user_option(config)
|
126
|
+
if config['user'] || config['username']
|
127
|
+
"-U #{config['user'] || config['username']}"
|
128
|
+
else
|
129
|
+
'' # assume ident auth is being used
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Grabs local database config before importing dump
|
134
|
+
def grab_local_database_config
|
135
|
+
return if fetch(:postgres_local_database_config)
|
136
|
+
on roles(fetch(:postgres_role)) do |role|
|
137
|
+
run_locally do
|
138
|
+
env = 'development'
|
139
|
+
preload_env_variables(env)
|
140
|
+
yaml_content = ERB.new(capture 'cat config/database.yml').result
|
141
|
+
set :postgres_local_database_config, database_config_defaults.merge(YAML::load(yaml_content)[env])
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Grabs remote database config before creating dump
|
147
|
+
def grab_remote_database_config
|
148
|
+
return if fetch(:postgres_remote_database_config)
|
149
|
+
on roles(fetch(:postgres_role)) do |role|
|
150
|
+
within release_path do
|
151
|
+
env = fetch(:postgres_env).to_s.downcase
|
152
|
+
filename = "#{deploy_to}/current/config/database.yml"
|
153
|
+
eval_yaml_with_erb = <<-RUBY.strip
|
154
|
+
#{env_variables_loader_code(env)}
|
155
|
+
require 'erb'
|
156
|
+
puts ERB.new(File.read('#{filename}')).result
|
157
|
+
RUBY
|
158
|
+
|
159
|
+
capture_config_cmd = "ruby -e \"#{eval_yaml_with_erb}\""
|
160
|
+
yaml_content = test('ruby -v') ? capture(capture_config_cmd) : capture(:bundle, :exec, capture_config_cmd)
|
161
|
+
set :postgres_remote_database_config, database_config_defaults.merge(YAML::load(yaml_content)[env])
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def database_config_defaults
|
167
|
+
{ 'host' => 'localhost' }
|
168
|
+
end
|
169
|
+
|
170
|
+
# Load environment variables for configurations.
|
171
|
+
# Useful for such gems as Dotenv, Figaro, etc.
|
172
|
+
def preload_env_variables(env)
|
173
|
+
safely_require_gems('dotenv', 'figaro')
|
174
|
+
|
175
|
+
if defined?(Dotenv)
|
176
|
+
load_env_variables_with_dotenv(env)
|
177
|
+
elsif defined?(Figaro)
|
178
|
+
load_env_variables_with_figaro(env)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def load_env_variables_with_dotenv(env)
|
183
|
+
Dotenv.load(
|
184
|
+
File.expand_path('.env.local'),
|
185
|
+
File.expand_path(".env.#{env}"),
|
186
|
+
File.expand_path('.env')
|
187
|
+
)
|
188
|
+
end
|
189
|
+
|
190
|
+
def load_env_variables_with_figaro(env)
|
191
|
+
config = 'config/application.yml'
|
192
|
+
|
193
|
+
Figaro.application = Figaro::Application.new(environment: env, path: config)
|
194
|
+
Figaro.load
|
195
|
+
end
|
196
|
+
|
197
|
+
def safely_require_gems(*gem_names)
|
198
|
+
gem_names.each do |name|
|
199
|
+
begin
|
200
|
+
require name
|
201
|
+
rescue LoadError
|
202
|
+
# Ignore if gem doesn't exist
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Requires necessary gems (Dotenv, Figaro, ...) if present
|
208
|
+
# and loads environment variables for configurations
|
209
|
+
def env_variables_loader_code(env)
|
210
|
+
<<-RUBY.strip
|
211
|
+
begin
|
212
|
+
require 'dotenv'
|
213
|
+
Dotenv.load(File.expand_path('.env.#{env}'), File.expand_path('.env'))
|
214
|
+
rescue LoadError
|
215
|
+
end
|
216
|
+
|
217
|
+
begin
|
218
|
+
require 'figaro'
|
219
|
+
config = File.expand_path('../config/application.yml', __FILE__)
|
220
|
+
|
221
|
+
Figaro.application = Figaro::Application.new(environment: '#{env}', path: config)
|
222
|
+
Figaro.load
|
223
|
+
rescue LoadError
|
224
|
+
end
|
225
|
+
RUBY
|
226
|
+
end
|
227
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'meataxe/capistrano/dsl/rbenv_install'
|
2
|
+
|
3
|
+
include Capistrano::DSL::RbenvInstall
|
4
|
+
|
5
|
+
# Heavily depends on 'capistrano-rbenv' variables:
|
6
|
+
# https://github.com/capistrano/rbenv/blob/master/lib/capistrano/tasks/rbenv.rake#L33-49
|
7
|
+
# set :rbenv_type # :user or :system
|
8
|
+
# set :rbenv_ruby, '2.5.3' # ruby version
|
9
|
+
# set :rbenv_roles, :all # where rbenv should be installed
|
10
|
+
# set :rbenv_path, # ~/.rbenv or /usr/local/rbenv, depends on :rbenv_type
|
11
|
+
# set :rbenv_ruby_dir # "#{fetch(:rbenv_path)}/versions/#{fetch(:rbenv_ruby)}" }
|
12
|
+
|
13
|
+
namespace :rbenv do
|
14
|
+
desc 'Install rbenv'
|
15
|
+
task :install_rbenv do
|
16
|
+
on roles fetch(:rbenv_roles) do
|
17
|
+
next if test "[ -d #{fetch(:rbenv_path)} ]"
|
18
|
+
execute :git, :clone, rbenv_repo_url, fetch(:rbenv_path)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Install ruby build - rbenv plugin'
|
23
|
+
task :install_ruby_build do
|
24
|
+
on roles fetch(:rbenv_roles) do
|
25
|
+
next if test "[ -d #{rbenv_ruby_build_path} ]"
|
26
|
+
execute :git, :clone, ruby_build_repo_url, rbenv_ruby_build_path
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'Update ruby build - rbenv plugin'
|
31
|
+
task :update_ruby_build do
|
32
|
+
on roles fetch(:rbenv_roles) do
|
33
|
+
next unless test "[ -d #{rbenv_ruby_build_path} ]"
|
34
|
+
within rbenv_ruby_build_path do
|
35
|
+
execute :git, :pull
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
desc 'Install ruby'
|
41
|
+
task :install_ruby do
|
42
|
+
on roles fetch(:rbenv_roles) do
|
43
|
+
next if test "[ -d #{fetch(:rbenv_ruby_dir)} ]"
|
44
|
+
invoke 'rbenv:update_ruby_build'
|
45
|
+
execute rbenv_bin_executable_path, :install, fetch(:rbenv_ruby)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'Install bundler gem'
|
50
|
+
task install_bundler: ['rbenv:map_bins'] do
|
51
|
+
on roles fetch(:rbenv_roles) do
|
52
|
+
next if test :gem, :query, '--quiet --installed --name-matches ^bundler$'
|
53
|
+
execute :gem, :install, :bundler, '--quiet --no-rdoc --no-ri'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
desc 'Install rbenv, ruby build and ruby version'
|
58
|
+
task :install do
|
59
|
+
invoke 'rbenv:install_rbenv'
|
60
|
+
invoke 'rbenv:install_ruby_build'
|
61
|
+
invoke 'rbenv:install_ruby'
|
62
|
+
invoke 'rbenv:install_bundler'
|
63
|
+
end
|
64
|
+
|
65
|
+
before 'rbenv:validate', 'rbenv:install'
|
66
|
+
before 'bundler:map_bins', 'rbenv:install' if Rake::Task.task_defined?('bundler:map_bins')
|
67
|
+
end
|
@@ -1,18 +1,20 @@
|
|
1
1
|
namespace :deploy do
|
2
|
-
desc "Runs test before deploying,
|
2
|
+
desc "Runs test before deploying, and don't deploy unless they pass"
|
3
3
|
task :run_tests do
|
4
4
|
test_log = "log/capistrano.test.log"
|
5
5
|
tests = fetch(:tests)
|
6
|
-
tests
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
if tests&.any?
|
7
|
+
tests.each do |test|
|
8
|
+
puts "--> Running tests: '#{test}', please wait ..."
|
9
|
+
unless system "bundle exec rspec #{test} > #{test_log} 2>&1"
|
10
|
+
puts "--> Tests: '#{test}' failed. Results in: #{test_log} and below:"
|
11
|
+
system "cat #{test_log}"
|
12
|
+
exit;
|
13
|
+
end
|
14
|
+
puts "--> '#{test}' passed"
|
12
15
|
end
|
13
|
-
puts "-->
|
16
|
+
puts "--> All tests passed"
|
17
|
+
system "rm #{test_log}"
|
14
18
|
end
|
15
|
-
puts "--> All tests passed"
|
16
|
-
system "rm #{test_log}"
|
17
19
|
end
|
18
20
|
end
|
@@ -1,32 +1,37 @@
|
|
1
1
|
namespace :deploy do
|
2
2
|
task :setup_config do
|
3
3
|
on roles(:app) do
|
4
|
-
#
|
4
|
+
# Make the config dir
|
5
5
|
execute :mkdir, "-p #{shared_path}/config"
|
6
6
|
full_app_name = fetch(:full_app_name)
|
7
7
|
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# Essentially looks for
|
11
|
-
# and if it isn't there, falls back to deploy/#{shared}
|
12
|
-
# everything should be in deploy/shared with params which differ
|
13
|
-
# set in the stage files
|
8
|
+
# Config files to be uploaded to shared/config, see the definition of
|
9
|
+
# `smart_template` for details of operation.
|
10
|
+
# Essentially looks for `#{filename}.erb` in `deploy/#{full_app_name}/`
|
11
|
+
# and if it isn't there, falls back to `deploy/#{shared}`. Generally
|
12
|
+
# everything should be in `deploy/shared` with params which differ
|
13
|
+
# set in the stage files.
|
14
14
|
config_files = fetch(:config_files)
|
15
|
-
config_files
|
16
|
-
|
15
|
+
if config_files&.any?
|
16
|
+
config_files.each do |file|
|
17
|
+
smart_template file
|
18
|
+
end
|
17
19
|
end
|
18
20
|
|
19
|
-
#
|
21
|
+
# Which of the above files should be marked as executable
|
20
22
|
executable_files = fetch(:executable_config_files)
|
21
|
-
|
22
|
-
|
23
|
+
if config_files&.any?
|
24
|
+
executable_files.each do |file|
|
25
|
+
execute :chmod, "+x #{shared_path}/config/#{file}"
|
26
|
+
end
|
23
27
|
end
|
24
28
|
|
25
|
-
#
|
29
|
+
# Symlink stuff that should be... symlinked
|
26
30
|
symlinks = fetch(:symlinks)
|
27
|
-
|
28
|
-
|
29
|
-
|
31
|
+
if symlinks&.any?
|
32
|
+
symlinks.each do |symlink|
|
33
|
+
sudo "ln -nfs #{shared_path}/config/#{symlink[:source]} #{sub_strings(symlink[:link])}"
|
34
|
+
end
|
30
35
|
end
|
31
36
|
end
|
32
37
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<%= fetch(:rails_env) %>:
|
2
|
+
adapter: <%= fetch(:database_adapter) || 'postgresql' %>
|
3
|
+
encoding: <%= fetch(:database_encoding) || 'utf8' %>
|
4
|
+
database: <%= "#{fetch(:application)}_#{fetch(:rails_env)}" %>
|
5
|
+
pool: <%%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
|
6
|
+
username: <%%= ENV['DATABASE_USER'] %>
|
7
|
+
password: <%%= ENV['DATABASE_PASSWORD'] %>
|
8
|
+
host: <%= fetch(:database_host) || 'localhost' %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<% if fetch(:puma_pid) %>
|
2
|
+
check process <%= fetch(:full_app_name) %>_puma
|
3
|
+
with pidfile "<%= fetch(:puma_pid) %>"
|
4
|
+
start program = "/usr/bin/sudo -iu <%= fetch(:user) %> /bin/bash -c 'cd <%= current_path %> && <%= SSHKit.config.command_map[:puma] %> -C <%= fetch(:puma_conf) %> --daemon'"
|
5
|
+
stop program = "/usr/bin/sudo -iu <%= fetch(:user) %> /bin/bash -c 'cd <%= current_path %> && <%= SSHKit.config.command_map[:pumactl] %> -S <%= fetch(:puma_state) %> stop'"
|
6
|
+
if mem is greater than 300.0 MB for 1 cycles then restart # eating up memory?
|
7
|
+
if cpu is greater than 50% for 2 cycles then alert # send an email to admin
|
8
|
+
if cpu is greater than 80% for 30 cycles then restart # hung process?
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% if fetch(:delayed_job_pid) %>
|
12
|
+
check process <%= fetch(:full_app_name) %>_delayed_job
|
13
|
+
with pidfile "<%= fetch(:delayed_job_pid) %>"
|
14
|
+
start program = "/usr/bin/sudo -iu <%= fetch(:user) %> /bin/bash -c 'cd <%= current_path %> && RAILS_ENV=<%= fetch(:rails_env) %> <%= SSHKit.config.command_map[:bundle] %> exec bin/delayed_job start'"
|
15
|
+
stop program = "/usr/bin/sudo -iu <%= fetch(:user) %> /bin/bash -c 'cd <%= current_path %> && RAILS_ENV=<%= fetch(:rails_env) %> <%= SSHKit.config.command_map[:bundle] %> exec bin/delayed_job stop'"
|
16
|
+
if mem is greater than 300.0 MB for 1 cycles then restart # eating up memory?
|
17
|
+
if cpu is greater than 50% for 2 cycles then alert # send an email to admin
|
18
|
+
if cpu is greater than 80% for 30 cycles then restart # hung process?
|
19
|
+
<% end %>
|
20
|
+
|
21
|
+
<% if fetch(:node_pid) %>
|
22
|
+
# Using systemd to manage node server
|
23
|
+
# check process <%= fetch(:full_app_name) %>_node
|
24
|
+
# with pidfile "<%= fetch(:node_pid) %>"
|
25
|
+
# start program = "/etc/init/<%= fetch(:full_app_name) %>_node start"
|
26
|
+
# stop program = "/etc/init/<%= fetch(:full_app_name) %>_node stop"
|
27
|
+
# if mem is greater than 300.0 MB for 1 cycles then restart # eating up memory?
|
28
|
+
# if cpu is greater than 50% for 2 cycles then alert # send an email to admin
|
29
|
+
# if cpu is greater than 80% for 30 cycles then restart # hung process?
|
30
|
+
<% end %>
|
@@ -0,0 +1,75 @@
|
|
1
|
+
upstream puma_<%= fetch(:full_app_name) %> { <%
|
2
|
+
flags = 'fail_timeout=0'
|
3
|
+
@backends = [fetch(:puma_bind)].flatten.map do |m|
|
4
|
+
etype, address = /(tcp|unix|ssl):\/{1,2}(.+)/.match(m).captures
|
5
|
+
if etype =='unix'
|
6
|
+
"server #{etype}:#{address} #{fetch(:nginx_socket_flags)};"
|
7
|
+
else
|
8
|
+
"server #{address.gsub(/0\.0\.0\.0(.+)/, "127.0.0.1\\1")} #{fetch(:nginx_http_flags)};"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
%><% @backends.each do |server| %>
|
12
|
+
<%= server %><% end %>
|
13
|
+
}
|
14
|
+
|
15
|
+
server {
|
16
|
+
listen 80;
|
17
|
+
server_name <%= fetch(:server_name) %>;
|
18
|
+
|
19
|
+
root <%= current_path %>/public;
|
20
|
+
try_files $uri/index.html $uri @puma_<%= fetch(:full_app_name) %>;
|
21
|
+
|
22
|
+
location @puma_<%= fetch(:full_app_name) %> {
|
23
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
24
|
+
proxy_set_header Host $http_host;
|
25
|
+
proxy_redirect off;
|
26
|
+
proxy_pass http://puma_<%= fetch(:full_app_name) %>;
|
27
|
+
# limit_req zone=one;
|
28
|
+
access_log <%= shared_path %>/log/nginx.access.log;
|
29
|
+
error_log <%= shared_path %>/log/nginx.error.log;
|
30
|
+
}
|
31
|
+
|
32
|
+
location ^~ /assets/ {
|
33
|
+
gzip_static on;
|
34
|
+
expires max;
|
35
|
+
add_header Cache-Control public;
|
36
|
+
}
|
37
|
+
|
38
|
+
client_max_body_size 10M;
|
39
|
+
keepalive_timeout 10;
|
40
|
+
|
41
|
+
error_page 500 502 504 /500.html;
|
42
|
+
error_page 503 @503;
|
43
|
+
|
44
|
+
location = /50x.html {
|
45
|
+
root html;
|
46
|
+
}
|
47
|
+
|
48
|
+
location = /404.html {
|
49
|
+
root html;
|
50
|
+
}
|
51
|
+
|
52
|
+
location @503 {
|
53
|
+
error_page 405 = /system/maintenance.html;
|
54
|
+
if (-f $document_root/system/maintenance.html) {
|
55
|
+
rewrite ^(.*)$ /system/maintenance.html break;
|
56
|
+
}
|
57
|
+
rewrite ^(.*)$ /503.html break;
|
58
|
+
}
|
59
|
+
|
60
|
+
if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
|
61
|
+
return 405;
|
62
|
+
}
|
63
|
+
|
64
|
+
if (-f $document_root/system/maintenance.html) {
|
65
|
+
return 503;
|
66
|
+
}
|
67
|
+
|
68
|
+
location ~ \.(php)$ {
|
69
|
+
return 405;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
<% if fetch(:enable_ssl) %>
|
74
|
+
<% raise 'SSL not implemented' %>
|
75
|
+
<% end %>
|
@@ -0,0 +1,92 @@
|
|
1
|
+
upstream puma_<%= fetch(:full_app_name) %> { <%
|
2
|
+
flags = 'fail_timeout=0'
|
3
|
+
@backends = [fetch(:puma_bind)].flatten.map do |m|
|
4
|
+
etype, address = /(tcp|unix|ssl):\/{1,2}(.+)/.match(m).captures
|
5
|
+
if etype =='unix'
|
6
|
+
"server #{etype}:#{address} #{fetch(:nginx_socket_flags)};"
|
7
|
+
else
|
8
|
+
"server #{address.gsub(/0\.0\.0\.0(.+)/, "127.0.0.1\\1")} #{fetch(:nginx_http_flags)};"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
%><% @backends.each do |server| %>
|
12
|
+
<%= server %><% end %>
|
13
|
+
}
|
14
|
+
|
15
|
+
server {
|
16
|
+
listen 80;
|
17
|
+
listen [::]:80;
|
18
|
+
server_name <%= fetch(:server_name) %> www.<%= fetch(:server_name) %>;
|
19
|
+
return 301 https://$server_name$request_uri;
|
20
|
+
}
|
21
|
+
|
22
|
+
server {
|
23
|
+
listen 443 ssl;
|
24
|
+
server_name <%= fetch(:server_name) %>;
|
25
|
+
|
26
|
+
root <%= current_path %>/public;
|
27
|
+
try_files $uri/index.html $uri @puma_<%= fetch(:full_app_name) %>;
|
28
|
+
|
29
|
+
location ^~ /assets/ {
|
30
|
+
gzip_static on;
|
31
|
+
expires max;
|
32
|
+
access_log off;
|
33
|
+
add_header Cache-Control public;
|
34
|
+
}
|
35
|
+
|
36
|
+
location @puma_<%= fetch(:full_app_name) %> {
|
37
|
+
proxy_set_header Host $http_host;
|
38
|
+
proxy_set_header X-Real-IP $remote_addr;
|
39
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
40
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
41
|
+
proxy_redirect off;
|
42
|
+
proxy_pass http://puma_<%= fetch(:full_app_name) %>;
|
43
|
+
# limit_req zone=one;
|
44
|
+
}
|
45
|
+
|
46
|
+
# Setup SSL certs
|
47
|
+
ssl on;
|
48
|
+
ssl_certificate <%= fetch(:ssl_certificate) %>;
|
49
|
+
ssl_certificate_key <%= fetch(:ssl_certificate_key) %>;
|
50
|
+
|
51
|
+
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
|
52
|
+
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
|
53
|
+
|
54
|
+
# Logging and miscellaneous settings
|
55
|
+
access_log <%= shared_path %>/log/nginx.access.log;
|
56
|
+
error_log <%= shared_path %>/log/nginx.error.log;
|
57
|
+
rewrite_log on;
|
58
|
+
|
59
|
+
client_max_body_size 25m;
|
60
|
+
keepalive_timeout 10;
|
61
|
+
|
62
|
+
# Redirect server error pages to the static page /50x.html
|
63
|
+
error_page 500 502 503 504 /50x.html;
|
64
|
+
|
65
|
+
location = /50x.html {
|
66
|
+
root html;
|
67
|
+
}
|
68
|
+
|
69
|
+
location = /404.html {
|
70
|
+
root html;
|
71
|
+
}
|
72
|
+
|
73
|
+
location @503 {
|
74
|
+
error_page 405 = /system/maintenance.html;
|
75
|
+
if (-f $document_root/system/maintenance.html) {
|
76
|
+
rewrite ^(.*)$ /system/maintenance.html break;
|
77
|
+
}
|
78
|
+
rewrite ^(.*)$ /503.html break;
|
79
|
+
}
|
80
|
+
|
81
|
+
if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
|
82
|
+
return 405;
|
83
|
+
}
|
84
|
+
|
85
|
+
if (-f $document_root/system/maintenance.html) {
|
86
|
+
return 503;
|
87
|
+
}
|
88
|
+
|
89
|
+
location ~ \.(php)$ {
|
90
|
+
return 405;
|
91
|
+
}
|
92
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
[Unit]
|
2
|
+
Description=<%= fetch(:full_app_name) %>
|
3
|
+
After=network.target
|
4
|
+
|
5
|
+
[Service]
|
6
|
+
Environment=NODE_ENV=<%= fetch(:node_env, 'production') %> NODE_PORT=3001
|
7
|
+
# HOME=/home/<%= fetch(:user) %>
|
8
|
+
StandardOutput=file:<%= shared_path %>/log/node_<%= fetch(:node_env, 'production') %>.log
|
9
|
+
StandardError=file:<%= shared_path %>/log/node_<%= fetch(:node_env, 'production') %>.log
|
10
|
+
User=<%= fetch(:user) %>
|
11
|
+
WorkingDirectory=<%= current_path %>/<%= fetch(:node_prefix) %>/
|
12
|
+
ExecStart=/usr/bin/node <%= fetch(:node_file) %>
|
13
|
+
Restart=on-failure
|
14
|
+
|
15
|
+
# limit CPU and RAM quota for our service
|
16
|
+
# CPUAccounting=true
|
17
|
+
# CPUQuota=10%
|
18
|
+
# MemoryAccounting=true
|
19
|
+
# MemoryLimit=50M
|
20
|
+
|
21
|
+
[Install]
|
22
|
+
WantedBy=multi-user.target
|
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env puma
|
2
|
+
|
3
|
+
directory '<%= current_path %>'
|
4
|
+
environment '<%= fetch(:rails_env) %>'
|
5
|
+
daemonize
|
6
|
+
#quiet
|
7
|
+
threads <%= fetch(:puma_threads) %>
|
8
|
+
pidfile '<%= fetch(:puma_pid) %>'
|
9
|
+
state_path '<%= fetch(:puma_state) %>'
|
10
|
+
bind '<%= fetch(:puma_bind) %>'
|
data/lib/meataxe/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: meataxe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kam Low
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-11-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,14 +52,24 @@ files:
|
|
52
52
|
- Rakefile
|
53
53
|
- lib/meataxe.rb
|
54
54
|
- lib/meataxe/capistrano.rb
|
55
|
+
- lib/meataxe/capistrano/dsl/rbenv_install.rb
|
55
56
|
- lib/meataxe/capistrano/tasks/check_revision.cap
|
56
57
|
- lib/meataxe/capistrano/tasks/compile_assets_locally.cap
|
57
58
|
- lib/meataxe/capistrano/tasks/logs.cap
|
58
59
|
- lib/meataxe/capistrano/tasks/monit.cap
|
59
60
|
- lib/meataxe/capistrano/tasks/nginx.cap
|
61
|
+
- lib/meataxe/capistrano/tasks/postgres.cap
|
62
|
+
- lib/meataxe/capistrano/tasks/rbenv_install.cap
|
60
63
|
- lib/meataxe/capistrano/tasks/run_tests.cap
|
61
64
|
- lib/meataxe/capistrano/tasks/setup_config.cap
|
62
65
|
- lib/meataxe/capistrano/tasks/tasks.cap
|
66
|
+
- lib/meataxe/capistrano/templates/database.yml.erb
|
67
|
+
- lib/meataxe/capistrano/templates/log_rotation.erb
|
68
|
+
- lib/meataxe/capistrano/templates/monit.conf.erb
|
69
|
+
- lib/meataxe/capistrano/templates/nginx.conf.erb
|
70
|
+
- lib/meataxe/capistrano/templates/nginx_ssl.conf.erb
|
71
|
+
- lib/meataxe/capistrano/templates/node_server.service.erb
|
72
|
+
- lib/meataxe/capistrano/templates/puma.rb.erb
|
63
73
|
- lib/meataxe/version.rb
|
64
74
|
- meataxe.gemspec
|
65
75
|
homepage: http://github.com/sourcey/meataxe
|
@@ -82,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
92
|
version: '0'
|
83
93
|
requirements: []
|
84
94
|
rubyforge_project:
|
85
|
-
rubygems_version: 2.
|
95
|
+
rubygems_version: 2.7.6
|
86
96
|
signing_key:
|
87
97
|
specification_version: 4
|
88
98
|
summary: Killer Capistrano 3 deployment scripts.
|