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 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