matross 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +22 -2
- data/lib/matross/base.rb +21 -0
- data/lib/matross/delayed_job.rb +15 -0
- data/lib/matross/errors.rb +4 -0
- data/lib/matross/foreman.rb +47 -5
- data/lib/matross/mysql.rb +43 -0
- data/lib/matross/templates/base/logrotate.erb +9 -0
- data/lib/matross/templates/mysql/database.yml.erb +9 -0
- data/lib/matross/templates/unicorn/unicorn.rb.erb +0 -2
- data/lib/matross/unicorn.rb +3 -1
- data/lib/matross/version.rb +1 -1
- data/matross.gemspec +3 -2
- metadata +35 -8
- checksums.yaml +0 -15
- data/VERSION +0 -1
data/README.md
CHANGED
@@ -6,7 +6,7 @@ Put matross in the `:development` group of your `Gemfile`:
|
|
6
6
|
|
7
7
|
```ruby
|
8
8
|
group :development do
|
9
|
-
|
9
|
+
gem 'matross', :git => 'git://github.com/innvent/matross.git'
|
10
10
|
end
|
11
11
|
```
|
12
12
|
|
@@ -23,5 +23,25 @@ We made a bunch of additions and customizations. Below we list the most relevant
|
|
23
23
|
|
24
24
|
* **Foreman by default**:
|
25
25
|
* **Custom foreman upstart template**: we use a custom upstart template, that enables `console log`, allowing `logrotate` to work properly.
|
26
|
-
* **User template overwrite**:
|
27
26
|
|
27
|
+
## Overriding default templates
|
28
|
+
We have our opinions, but don't know everything. What works for us, may not fit your needs since each app is a unique snowflake. To take care of that `matross` allows you to define your own templates to use instead of the built in ones. Look at the included ones in `lib/matross/templates` to see how we think things should go.
|
29
|
+
|
30
|
+
For example to override the default `lib/matross/templates/unicorn.rb.erb` simply put your template in your applications `config/matross/unicorn/unicorn.rb.erb`. The general idea is `config/matross/#{recipe_name}/#{erb_template}`
|
31
|
+
|
32
|
+
## Managing application daemons with Foreman
|
33
|
+
|
34
|
+
Foreman has freed us of the tedious task of writing `init` and `upstart` scripts. Some of our `matross` recipes automatically add processes - such as the `unicorn` server - to the Procfile.
|
35
|
+
|
36
|
+
If you have an application Procfile with custom daemons defined, such as `delayed_job`, they will be concantenated with all the processes defined in `matross`, resulting in one final Procfile-matross file that will be used to start your app and export init scrips.
|
37
|
+
|
38
|
+
You can specify the number of each instance defined in Procfile-matross using the `foreman_procs` capistrano variable.
|
39
|
+
Supose you have a process called `dj` and want to export 3 instances of it:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
set :foreman_procs, {
|
43
|
+
dj: 3
|
44
|
+
}
|
45
|
+
```
|
46
|
+
|
47
|
+
We also modified the default upstart template to log through upstart instead of just piping stdout and stderr into files. Goodbye nocturnal logexplosion. (Like all templates you can override it)
|
data/lib/matross/base.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'matross/errors'
|
3
|
+
|
1
4
|
def template(from, to)
|
2
5
|
override_template = File.join(Dir.pwd, 'config/matross', from)
|
3
6
|
if File.exist?(override_template)
|
@@ -7,3 +10,21 @@ def template(from, to)
|
|
7
10
|
end
|
8
11
|
put ERB.new(erb).result(binding), to
|
9
12
|
end
|
13
|
+
|
14
|
+
def dep_included?(dependency)
|
15
|
+
lockfile = Bundler::LockfileParser.new(Bundler.read_file(Bundler.default_lockfile))
|
16
|
+
if not lockfile.specs.any? { |gem| gem.name == dependency} then
|
17
|
+
raise Matross::MissingDepError, "recipe requires the #{dependency} gem"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
namespace :base do
|
22
|
+
|
23
|
+
task :logrotate, :roles => :app do
|
24
|
+
run "mkdir -p #{shared_path}/config"
|
25
|
+
template "base/logrotate.erb", "#{shared_path}/config/logrotate"
|
26
|
+
run "#{sudo} ln -nfs #{shared_path}/config/logrotate /etc/logrotate.d/#{application}"
|
27
|
+
end
|
28
|
+
after "deploy:setup", "base:logrotate"
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
dep_included? 'delayed_job'
|
2
|
+
|
3
|
+
namespace :delayed_job do
|
4
|
+
|
5
|
+
desc "Writes the delayed job part of the Procfile"
|
6
|
+
task :procfile, :roles => :dj do
|
7
|
+
procfile_template = <<-EOF.gsub(/^\s+/, '')
|
8
|
+
dj: bundle exec rake jobs:work
|
9
|
+
EOF
|
10
|
+
procfile = ERB.new(procfile_template, nil, '-')
|
11
|
+
put procfile.result(binding), "#{shared_path}/Procfile.dj"
|
12
|
+
end
|
13
|
+
after "foreman:pre_setup", "delayed_job:procfile"
|
14
|
+
|
15
|
+
end
|
data/lib/matross/foreman.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
dep_included? 'foreman'
|
2
|
+
|
1
3
|
_cset(:foreman_user) { user }
|
2
4
|
_cset :foreman_bin, "bundle exec foreman"
|
5
|
+
_cset :foreman_procs, {}
|
3
6
|
|
4
7
|
namespace :foreman do
|
5
8
|
|
@@ -9,10 +12,18 @@ namespace :foreman do
|
|
9
12
|
end
|
10
13
|
before "foreman:setup", "foreman:pre_setup"
|
11
14
|
|
12
|
-
desc "Merges all partial Procfiles"
|
15
|
+
desc "Merges all partial Procfiles and defines a specific dotenv"
|
13
16
|
task :setup do
|
14
|
-
run "cat #{shared_path}/Procfile.* > #{shared_path}/Procfile"
|
17
|
+
run "cat $(test -f #{current_path}/Procfile && echo -n \"#{current_path}/Procfile\") #{shared_path}/Procfile.* > #{shared_path}/Procfile-matross"
|
15
18
|
run "rm #{shared_path}/Procfile.*"
|
19
|
+
|
20
|
+
dotenv_template = <<-EOF.gsub(/^\s+/, '')
|
21
|
+
RAILS_ENV=#{rails_env.to_s.shellescape}
|
22
|
+
EOF
|
23
|
+
dotenv = ERB.new(dotenv_template, nil, '-')
|
24
|
+
put dotenv.result(binding), "#{shared_path}/.env-matross-partial"
|
25
|
+
run "cat $(test -f #{current_path}/.env && echo \"$_\") #{shared_path}/.env-matross-partial > #{shared_path}/.env-matross"
|
26
|
+
run "rm #{shared_path}/.env-matross-partial"
|
16
27
|
end
|
17
28
|
before "foreman:export", "foreman:setup"
|
18
29
|
|
@@ -23,22 +34,53 @@ namespace :foreman do
|
|
23
34
|
upload File.expand_path("../templates/foreman", __FILE__), matross_path,
|
24
35
|
:via => :scp, :recursive => true
|
25
36
|
|
37
|
+
# By default spawn one instance of every process
|
38
|
+
procs = {}
|
39
|
+
capture("cat #{current_path}/Procfile-matross").split("\n").each { |line|
|
40
|
+
process = line[/^([A-Za-z0-9_]+):\s*(.+)$/, 1]
|
41
|
+
procs[process] = 1
|
42
|
+
}
|
43
|
+
procs.merge!(foreman_procs)
|
44
|
+
|
45
|
+
proc_list = ""
|
46
|
+
procs.each { |process, num|
|
47
|
+
proc_list << ',' unless proc_list.empty?
|
48
|
+
proc_list << "#{process}=#{num}"
|
49
|
+
}
|
50
|
+
proc_list = " -c #{proc_list}" unless proc_list.empty?
|
51
|
+
|
26
52
|
run "cd #{current_path} && #{foreman_bin} export upstart #{shared_path}/upstart "\
|
27
|
-
"-f #{current_path}/Procfile "\
|
53
|
+
"-f #{current_path}/Procfile-matross "\
|
28
54
|
"-a #{application} "\
|
29
55
|
"-u #{foreman_user} "\
|
30
56
|
"-l #{shared_path}/log "\
|
31
|
-
"-t #{matross_path}/foreman"
|
57
|
+
"-t #{matross_path}/foreman "\
|
58
|
+
"-e #{shared_path}/.env-matross"\
|
59
|
+
<< proc_list
|
32
60
|
run "cd #{shared_path}/upstart && #{sudo} cp * /etc/init/"
|
33
61
|
end
|
34
62
|
before "deploy:restart", "foreman:export"
|
35
63
|
|
36
64
|
desc "Symlink configuration scripts"
|
37
65
|
task :symlink, :roles => [:app, :dj], :except => { :no_release => true } do
|
38
|
-
run "ln -nfs #{shared_path}/Procfile #{
|
66
|
+
run "ln -nfs #{shared_path}/Procfile-matross #{current_path}/Procfile-matross"
|
67
|
+
run "ln -nfs #{shared_path}/.env-matross #{current_path}/.env-matross"
|
39
68
|
end
|
40
69
|
after "foreman:setup", "foreman:symlink"
|
41
70
|
|
71
|
+
desc "Symlink upstart logs to application shared/log"
|
72
|
+
task :log, :roles => [:app, :dj] do
|
73
|
+
capture("ls #{shared_path}/upstart -1").split(/\r?\n/).each { |line|
|
74
|
+
log = File.basename(line.sub(/\.conf\Z/, ".log"))
|
75
|
+
run <<-EOF.gsub(/^\s+/, '')
|
76
|
+
#{sudo} touch /var/log/upstart/#{log} &&
|
77
|
+
#{sudo} chmod o+r /var/log/upstart/#{log} &&
|
78
|
+
ln -nfs /var/log/upstart/#{log} #{shared_path}/log/#{log}
|
79
|
+
EOF
|
80
|
+
}
|
81
|
+
end
|
82
|
+
after "foreman:export", "foreman:log"
|
83
|
+
|
42
84
|
desc "Restart services"
|
43
85
|
task :restart, :roles => [:app, :dj] do
|
44
86
|
run "#{sudo} start #{application} || #{sudo} restart #{application}"
|
@@ -0,0 +1,43 @@
|
|
1
|
+
dep_included? 'mysql2'
|
2
|
+
|
3
|
+
_cset(:database_config) { "#{shared_path}/config/database.yml" }
|
4
|
+
|
5
|
+
namespace :db do
|
6
|
+
|
7
|
+
desc "Creates the database.yml file in shared path"
|
8
|
+
task :setup, :roles => [:app, :dj] do
|
9
|
+
run "mkdir -p #{shared_path}/config"
|
10
|
+
template "mysql/database.yml.erb", database_config
|
11
|
+
end
|
12
|
+
after "deploy:setup", "db:setup"
|
13
|
+
|
14
|
+
desc "Updates the symlink for database.yml for the just deployed release"
|
15
|
+
task :symlink, :roles => [:app, :dj] do
|
16
|
+
run "ln -nfs #{database_config} #{current_path}/config/database.yml"
|
17
|
+
end
|
18
|
+
before "deploy:restart", "db:symlink"
|
19
|
+
|
20
|
+
desc "Creates the application database"
|
21
|
+
task :create, :roles => [:db] do
|
22
|
+
sql = <<-EOF.gsub(/^\s+/, '')
|
23
|
+
CREATE DATABASE IF NOT EXISTS #{mysql_database};
|
24
|
+
EOF
|
25
|
+
run "mysql --user=#{mysql_user} --password=#{mysql_passwd} --host=#{mysql_host} --execute=\"#{sql}\""
|
26
|
+
end
|
27
|
+
after "db:setup", "db:create"
|
28
|
+
|
29
|
+
desc "Loads the application schema into the database"
|
30
|
+
task :schema_load, :roles => [:db] do
|
31
|
+
sql = <<-EOF.gsub(/^\s+/, '')
|
32
|
+
SELECT count(*) FROM information_schema.TABLES WHERE (TABLE_SCHEMA = '#{mysql_database}');
|
33
|
+
EOF
|
34
|
+
table_count = capture("mysql --batch --skip-column-names "\
|
35
|
+
"--user=#{mysql_user} "\
|
36
|
+
"--password=#{mysql_passwd} "\
|
37
|
+
"--host=#{mysql_host} "\
|
38
|
+
"--execute=\"#{sql}\"").to_i
|
39
|
+
run "cd #{current_path} &&"\
|
40
|
+
"RAILS_ENV=#{rails_env.to_s.shellescape} bundle exec rake db:schema:load" if table_count == 0
|
41
|
+
end
|
42
|
+
after "db:symlink", "db:schema_load"
|
43
|
+
end
|
@@ -2,8 +2,6 @@ app_path = "<%= current_path %>"
|
|
2
2
|
|
3
3
|
working_directory "#{app_path}"
|
4
4
|
pid "#{app_path}/tmp/pids/unicorn.pid"
|
5
|
-
stderr_path "#{app_path}/log/unicorn.log"
|
6
|
-
stdout_path "#{app_path}/log/unicorn.log"
|
7
5
|
|
8
6
|
listen "/tmp/unicorn.sock"
|
9
7
|
worker_processes <%= unicorn_workers %>
|
data/lib/matross/unicorn.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
dep_included? 'unicorn'
|
2
|
+
|
1
3
|
_cset(:unicorn_config) { "#{shared_path}/config/unicorn.rb" }
|
2
4
|
_cset(:unicorn_log) { "#{shared_path}/log/unicorn.log" }
|
3
5
|
_cset :unicorn_workers, 1
|
@@ -17,7 +19,7 @@ namespace :unicorn do
|
|
17
19
|
web: bundle exec unicorn -c <%= unicorn_config %> -E <%= rails_env %>
|
18
20
|
EOF
|
19
21
|
procfile = ERB.new(procfile_template, nil, '-')
|
20
|
-
put procfile.result(binding), "#{shared_path}/Procfile.
|
22
|
+
put procfile.result(binding), "#{shared_path}/Procfile.web"
|
21
23
|
end
|
22
24
|
after "foreman:pre_setup", "unicorn:procfile"
|
23
25
|
|
data/lib/matross/version.rb
CHANGED
data/matross.gemspec
CHANGED
@@ -6,7 +6,7 @@ require "matross/version"
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "matross"
|
8
8
|
spec.version = Matross::VERSION
|
9
|
-
spec.authors = ["Artur Rodrigues"
|
9
|
+
spec.authors = ["Artur Rodrigues", "Joao Sa"]
|
10
10
|
spec.email = ["arturhoo@gmail.com", "me@joaomsa.com"]
|
11
11
|
spec.description = %q{Our collection of opnionated Capistrano recipes}
|
12
12
|
spec.summary = %q{Our collection of opnionated Capistrano recipes}
|
@@ -19,8 +19,9 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "pry"
|
22
23
|
|
23
|
-
spec.add_dependency "capistrano", "~> 2.15.
|
24
|
+
spec.add_dependency "capistrano", "~> 2.15.0"
|
24
25
|
end
|
25
26
|
|
26
27
|
|
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: matross
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Artur Rodrigues
|
@@ -9,11 +10,12 @@ authors:
|
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date: 2013-
|
13
|
+
date: 2013-10-04 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: bundler
|
16
17
|
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
17
19
|
requirements:
|
18
20
|
- - ~>
|
19
21
|
- !ruby/object:Gem::Version
|
@@ -21,24 +23,43 @@ dependencies:
|
|
21
23
|
type: :development
|
22
24
|
prerelease: false
|
23
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
24
27
|
requirements:
|
25
28
|
- - ~>
|
26
29
|
- !ruby/object:Gem::Version
|
27
30
|
version: '1.3'
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: pry
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
type: :development
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
28
47
|
- !ruby/object:Gem::Dependency
|
29
48
|
name: capistrano
|
30
49
|
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
31
51
|
requirements:
|
32
52
|
- - ~>
|
33
53
|
- !ruby/object:Gem::Version
|
34
|
-
version: 2.15.
|
54
|
+
version: 2.15.0
|
35
55
|
type: :runtime
|
36
56
|
prerelease: false
|
37
57
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
38
59
|
requirements:
|
39
60
|
- - ~>
|
40
61
|
- !ruby/object:Gem::Version
|
41
|
-
version: 2.15.
|
62
|
+
version: 2.15.0
|
42
63
|
description: Our collection of opnionated Capistrano recipes
|
43
64
|
email:
|
44
65
|
- arturhoo@gmail.com
|
@@ -53,13 +74,17 @@ files:
|
|
53
74
|
- LICENSE.txt
|
54
75
|
- README.md
|
55
76
|
- Rakefile
|
56
|
-
- VERSION
|
57
77
|
- lib/matross.rb
|
58
78
|
- lib/matross/base.rb
|
79
|
+
- lib/matross/delayed_job.rb
|
80
|
+
- lib/matross/errors.rb
|
59
81
|
- lib/matross/foreman.rb
|
60
82
|
- lib/matross/local_assets.rb
|
83
|
+
- lib/matross/mysql.rb
|
61
84
|
- lib/matross/nginx.rb
|
85
|
+
- lib/matross/templates/base/logrotate.erb
|
62
86
|
- lib/matross/templates/foreman/process.conf.erb
|
87
|
+
- lib/matross/templates/mysql/database.yml.erb
|
63
88
|
- lib/matross/templates/nginx/nginx_virtual_host_conf.erb
|
64
89
|
- lib/matross/templates/unicorn/unicorn.rb.erb
|
65
90
|
- lib/matross/unicorn.rb
|
@@ -68,25 +93,27 @@ files:
|
|
68
93
|
homepage: https://github.com/innvent/matross
|
69
94
|
licenses:
|
70
95
|
- MIT
|
71
|
-
metadata: {}
|
72
96
|
post_install_message:
|
73
97
|
rdoc_options: []
|
74
98
|
require_paths:
|
75
99
|
- lib
|
76
100
|
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
77
102
|
requirements:
|
78
103
|
- - ! '>='
|
79
104
|
- !ruby/object:Gem::Version
|
80
105
|
version: '0'
|
81
106
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
82
108
|
requirements:
|
83
109
|
- - ! '>='
|
84
110
|
- !ruby/object:Gem::Version
|
85
111
|
version: '0'
|
86
112
|
requirements: []
|
87
113
|
rubyforge_project:
|
88
|
-
rubygems_version:
|
114
|
+
rubygems_version: 1.8.23
|
89
115
|
signing_key:
|
90
|
-
specification_version:
|
116
|
+
specification_version: 3
|
91
117
|
summary: Our collection of opnionated Capistrano recipes
|
92
118
|
test_files: []
|
119
|
+
has_rdoc:
|
checksums.yaml
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
---
|
2
|
-
!binary "U0hBMQ==":
|
3
|
-
metadata.gz: !binary |-
|
4
|
-
Mjc1ZTA0NDY3NTgzOTE4ODFlNmU2NDM2ODkxYjBmOGIwMmYxYTg4NA==
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZjFkM2Q0OGMwNTZiMmJkMGRiNzliMjYwYTcwNTZiZjcyOGNhZDA1Nw==
|
7
|
-
!binary "U0hBNTEy":
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
MjA2MjczMGRjMDNjZDM5M2ZiOGIwMDRjMmNlYTY3NjM1NmE5MWJhODgxYmQ0
|
10
|
-
ZDM3MGZkMDhkMWM4YWY5ZjA5MzI0MzEzYjIxM2VkM2E1YWM2OTU2NWMzZWEy
|
11
|
-
MDBjODgxYmIyZWNmOTM0MmUxNzVhYmNhMjVlNGJjYWMzNzg1MmU=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MjZmMzllNzlkMjMxMjE1MGRmMjdjZjMxYjdkMmZiZTA5YmQ4MWE2YjdlYWVh
|
14
|
-
MjA3YTgyNTc5YjI4NzA3MzdhYWEzNmM3YjAyYjUyMmY5MjcyZmJlYWI4MGY2
|
15
|
-
ZWZjNzc5ZjhlNTVhZThiNmZlZTFmODg2ZWJmOTU5MDBjMjQ0Zjk=
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.0.0
|