matross 0.1.0 → 0.2.0

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/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
- gem 'matross', :git => 'git://github.com/innvent/matross.git'
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)
@@ -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
@@ -0,0 +1,4 @@
1
+ module Matross
2
+ Error = Class.new(RuntimeError)
3
+ MissingDepError = Class.new(Error)
4
+ end
@@ -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 #{release_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
@@ -0,0 +1,9 @@
1
+ <%= shared_path %>/log/<%= rails_env %>.log {
2
+ weekly
3
+ missingok
4
+ rotate 52
5
+ compress
6
+ delaycompress
7
+ notifempty
8
+ copytruncate
9
+ }
@@ -0,0 +1,9 @@
1
+ <%= rails_env %>:
2
+ adapter: mysql2
3
+ host: <%= mysql_host %>
4
+ database: <%= mysql_database %>
5
+ username: <%= mysql_user %>
6
+ password: <%= mysql_passwd %>
7
+ pool: 5
8
+ encoding: utf8
9
+ reconnect: true
@@ -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 %>
@@ -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.app"
22
+ put procfile.result(binding), "#{shared_path}/Procfile.web"
21
23
  end
22
24
  after "foreman:pre_setup", "unicorn:procfile"
23
25
 
@@ -1,3 +1,3 @@
1
1
  module Matross
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -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" , "Joao Sa"]
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.5"
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.1.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-09-06 00:00:00.000000000 Z
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.5
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.5
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: 2.0.7
114
+ rubygems_version: 1.8.23
89
115
  signing_key:
90
- specification_version: 4
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