production_chain 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *swp
2
+ .idea*
3
+ *.gem
data/README CHANGED
@@ -1 +1,6 @@
1
- A rails plugin that incorporate various libs, recipes and tasks
1
+ A rails gem that incorporate various libs, recipes and tasks
2
+
3
+ To add the recipes to capistrano, you have to add these two lines to `config/deploy.rb` :
4
+
5
+ require 'bundler/setup'
6
+ require 'production_chain'
@@ -0,0 +1,6 @@
1
+ class Numeric
2
+ # Rounds to the given decimal position.
3
+ def round_at(d)
4
+ (self * (10.0 ** d)).round.to_f / (10.0 ** d)
5
+ end
6
+ end
@@ -0,0 +1,16 @@
1
+ if defined?(Rails)
2
+ # Core Ext
3
+ require "core_ext/numeric"
4
+
5
+ # Rails
6
+ require "rails/action_controller/abstract_request"
7
+ require "rails/action_view/text_helper"
8
+
9
+ # Rake Tasks
10
+ require "tasks"
11
+ end
12
+
13
+ if defined?(Capistrano)
14
+ # Recipes
15
+ Dir[File.join(File.dirname(__FILE__), 'recipes/**/*.rb')].each { |file| load file }
16
+ end
@@ -0,0 +1,6 @@
1
+ class ActionController::AbstractRequest
2
+ # Test if request seems to come from a bot
3
+ def bot?
4
+ user_agent =~ /\b(Baidu|Gigabot|Googlebot|libwww-perl|lwp-trivial|msnbot|SiteUptime|Slurp|WordPress|ZIBB|ZyBorg)\b/i
5
+ end
6
+ end
@@ -0,0 +1,43 @@
1
+ module ActionView::Helpers::TextHelper
2
+ def truncate(text, *args)
3
+ options = args.extract_options!
4
+
5
+ # support either old or Rails 2.2 calling convention:
6
+ unless args.empty?
7
+ options[:length] = args[0] || 30
8
+ options[:omission] = args[1] || "..."
9
+ end
10
+ options.reverse_merge!(:length => 30, :omission => "...")
11
+
12
+ # support any of:
13
+ # * ruby 1.9 sane utf8 support
14
+ # * rails 2.1 workaround for crappy ruby 1.8 utf8 support
15
+ # * rails 2.2 workaround for crappy ruby 1.8 utf8 support
16
+ # hooray!
17
+ if text
18
+ chars = if text.respond_to?(:mb_chars)
19
+ text.mb_chars
20
+ elsif RUBY_VERSION < '1.9'
21
+ text.chars
22
+ else
23
+ text
24
+ end
25
+
26
+ omission = if options[:omission].respond_to?(:mb_chars)
27
+ options[:omission].mb_chars
28
+ elsif RUBY_VERSION < '1.9'
29
+ options[:omission].chars
30
+ else
31
+ options[:omission]
32
+ end
33
+
34
+ l = options[:length] - omission.length
35
+ if chars.length > options[:length]
36
+ result = (chars[/\A.{#{l}}\w*\;?/m][/.*[\w\;]/m]).to_s
37
+ ((options[:avoid_orphans] && result =~ /\A(.*?)\n+\W*\w*\W*\Z/m) ? $1 : result) + options[:omission]
38
+ else
39
+ text
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,28 @@
1
+ Capistrano::Configuration.instance.load do
2
+ namespace :db do
3
+ # this recipe needs the "mysql tasks" plugin
4
+ desc "Make a dump on the remote production box and restore on the local dev box"
5
+ task :dump_and_restore, :roles => :db, :only => {:primary => true} do
6
+ rake = fetch(:rake, "rake")
7
+ rails_env = fetch(:rails_env, "production")
8
+ file_env = ENV['FILE'] || "database"
9
+ run "cd #{current_release} && RAILS_ENV=#{rails_env} FILE=#{file_env} #{rake} db:backup"
10
+ get "#{current_release}/db/dump.tar.gz", "db/dump.tar.gz"
11
+ cmd = "RAILS_ENV=#{ ENV['RAILS_ENV'] || "development" } FILE=#{file_env} #{rake} db:restore"
12
+ puts cmd
13
+ system cmd
14
+ end
15
+ end
16
+
17
+ namespace :assets do
18
+ desc "Make a dump on the remote production box and restore on the local dev box"
19
+ task :dump_and_restore, :roles => :db, :only => {:primary => true} do
20
+ assets_backup_path = "#{current_path}/system.tar.gz"
21
+ run "cd #{current_path}/ && tar czfh #{assets_backup_path} public/system/"
22
+ get "#{assets_backup_path}", "system.tar.gz"
23
+ run "cd #{current_path}/ && rm #{assets_backup_path}"
24
+ `rm -rf public/system/*`
25
+ `tar xvzf system.tar.gz`
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ Capistrano::Configuration.instance.load do
2
+ namespace :thinking_sphinx do
3
+ desc "Generate the Sphinx configuration file"
4
+ task :configure do
5
+ rake "thinking_sphinx:configure"
6
+ end
7
+
8
+ desc "Index data"
9
+ task :index do
10
+ rake "thinking_sphinx:index"
11
+ end
12
+
13
+ desc "Start the Sphinx daemon"
14
+ task :start do
15
+ configure
16
+ rake "thinking_sphinx:start"
17
+ end
18
+
19
+ desc "Stop the Sphinx daemon"
20
+ task :stop do
21
+ configure
22
+ rake "thinking_sphinx:stop"
23
+ end
24
+
25
+ desc "Stop and then start the Sphinx daemon"
26
+ task :restart do
27
+ stop
28
+ start
29
+ end
30
+
31
+ desc "Stop, re-index and then start the Sphinx daemon"
32
+ task :rebuild do
33
+ stop
34
+ index
35
+ start
36
+ end
37
+
38
+ desc "Add the shared folder for sphinx files for the production environment"
39
+ task :shared_sphinx_folder, :roles => :web do
40
+ run "mkdir -p #{shared_path}/db/sphinx/production"
41
+ end
42
+
43
+ def rake(*tasks)
44
+ rails_env = fetch(:rails_env, "production")
45
+ rake = fetch(:rake, "rake")
46
+ tasks.each do |t|
47
+ run "if [ -d #{release_path} ]; then cd #{release_path}; else cd #{current_path}; fi; #{rake} RAILS_ENV=#{rails_env} #{t}"
48
+ end
49
+ end
50
+ end
51
+ end
data/lib/tasks.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'rails'
2
+
3
+ module ProductionChain
4
+ class Railtie < Rails::Railtie
5
+ rake_tasks do
6
+ Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each { |file| load file }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,56 @@
1
+ require 's3'
2
+
3
+ namespace :s3 do
4
+
5
+ desc "Backup code, database, and scm to S3"
6
+ task :backup => ["s3:backup:db", "s3:backup:shared"]
7
+
8
+ namespace :backup do
9
+ desc "Backup the database to S3"
10
+ task :db do
11
+ db_tmp_path = "#{Rails.root}/db/dump.tar.gz"
12
+ Rake::Task['db:backup'].invoke
13
+ send_to_s3(db_tmp_path)
14
+ end
15
+
16
+ desc "Backup the shared folder to S3"
17
+ task :shared do
18
+ cmd = " cd .. && tar czfh /tmp/shared.tar.gz shared/ --exclude=shared/log/* --exclude=shared/sphinx/*"
19
+ system(cmd)
20
+ shared_tmp_path = "/tmp/shared.tar.gz"
21
+ send_to_s3(shared_tmp_path)
22
+ end
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def conn
29
+ @s3_config ||= YAML.load_file("#{Rails.root}/config/backup_s3.yml")[Rails.env]
30
+ @conn ||= S3::Service.new(:access_key_id => @s3_config['access_key_id'],
31
+ :secret_access_key => @s3_config['secret_access_key'],
32
+ :use_ssl => true)
33
+ end
34
+
35
+ def bucket_name
36
+ @s3_config['bucket_name']
37
+ end
38
+
39
+ def backup_bucket
40
+ begin
41
+ bucket ||= conn.buckets.find(bucket_name)
42
+ rescue S3::Error::ResponseError
43
+ bucket = conn.buckets.build(bucket_name)
44
+ bucket.save
45
+ end
46
+ bucket
47
+ end
48
+
49
+ def send_to_s3 local_file_path
50
+ bucket = backup_bucket
51
+ s3_file_path = Time.now.strftime("%Y%m%d") + '/' + local_file_path.split('/').last
52
+
53
+ upload = bucket.objects.build(s3_file_path)
54
+ upload.content = File.open(local_file_path)
55
+ upload.save
56
+ end
data/lib/tasks/db.rake ADDED
@@ -0,0 +1,133 @@
1
+ namespace :db do
2
+ desc "Dump schema and data to a bzip file"
3
+ task :backup => :environment do
4
+ type, database, user, password, host = retrieve_db_info ENV['FILE']
5
+ type = "mysql" if type == "mysql2"
6
+ send("backup_#{type}_database", database, user, password, host)
7
+ end
8
+
9
+ desc "Load schema and data from a bzip file"
10
+ task :restore => :environment do
11
+ type, database, user, password, host = retrieve_db_info ENV['FILE']
12
+ type = "mysql" if type == "mysql2"
13
+ if type == "mongodb"
14
+ send("restore_#{type}_database", database, user, password, host)
15
+ else
16
+ send("drop_#{type}_database", database, user, password, host)
17
+ send("create_#{type}_database", database, user, password, host)
18
+ send("restore_#{type}_database", database, user, password, host)
19
+
20
+ #Rake::Task['db:migrate'].invoke
21
+ end
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def retrieve_db_info(filename)
28
+ filename ||= "database"
29
+ result = File.read "#{Rails.root}/config/#{filename}.yml"
30
+ # result.strip!
31
+ config_file = YAML::load(ERB.new(result).result)
32
+ type = filename == "mongoid" ? "mongodb" : config_file[Rails.env]['adapter']
33
+ return [
34
+ type,
35
+ config_file[Rails.env]['database'],
36
+ config_file[Rails.env]['username'],
37
+ config_file[Rails.env]['password'],
38
+ config_file[Rails.env]['host'] || "127.0.0.1"
39
+ ]
40
+ end
41
+
42
+ def archive_name
43
+ archive = "#{Rails.root}/db/dump.tar.gz"
44
+ end
45
+
46
+ def backup_mysql_database database, user, password, host
47
+ cmd = "/usr/bin/env mysqldump --opt --skip-add-locks -h #{host} -u #{user} "
48
+ puts cmd + "... [password filtered]"
49
+ cmd << " -p'#{password}' " unless password.nil?
50
+ cmd << " #{database} > dump.sql && tar czfh #{archive_name} dump.sql"
51
+
52
+ system(cmd)
53
+ end
54
+
55
+ def restore_mysql_database database, user, password, host
56
+ cmd = "tar xvzf #{archive_name} && "
57
+ cmd << "/usr/bin/env mysql -h #{host} -u #{user} #{database}"
58
+ puts cmd + "... [password filtered]"
59
+ cmd << " -p'#{password}'" unless password.nil?
60
+ cmd << " < dump.sql"
61
+
62
+ system(cmd)
63
+ end
64
+
65
+ # pg_dump does not allow to pass the password in the command line for security reasons.
66
+ # You need to define the password for your user in ~/.pgpass
67
+ # See : http://www.postgresql.org/docs/8.1/interactive/libpq-pgpass.html
68
+ #
69
+ # pg_dump -Fc option outputs a custom dump file which is compressed by default.
70
+ # See man pg_dump for more information.
71
+ #
72
+ def backup_postgresql_database database, user, password, host
73
+ cmd = "/usr/bin/env pg_dump -Fc -h #{host} -U #{user} #{database} -f db.dump"
74
+ cmd << " && tar czfh #{archive_name} db.dump"
75
+ puts cmd
76
+
77
+ system(cmd)
78
+ end
79
+
80
+ def restore_postgresql_database database, user, password, host
81
+ cmd = "tar xvzf #{archive_name}"
82
+ cmd << " && /usr/bin/env pg_restore -h #{host} -U #{user} -O -d #{database} db.dump"
83
+ puts cmd
84
+
85
+ system(cmd)
86
+ end
87
+
88
+ def backup_mongodb_database database, user, password, host
89
+ cmd = "rm -rf dump/ 2>/dev/null && /usr/bin/env mongodump -h #{host} -d #{database}"
90
+ cmd << " && tar czfh #{archive_name} dump/"
91
+
92
+ system(cmd)
93
+ end
94
+
95
+ def restore_mongodb_database database, user, password, host
96
+ cmd = "rm -rf dump/ 2>/dev/null && tar xvzf #{archive_name}"
97
+ cmd += " && /usr/bin/env mongorestore --drop -h #{host} -d #{database} --dir dump/*_*"
98
+ puts cmd
99
+
100
+ system(cmd)
101
+ end
102
+
103
+ def drop_mysql_database database, user, password, host
104
+ cmd = "/usr/bin/env mysql -h #{host} -u #{user}"
105
+ cmd << " -e \"DROP DATABASE #{database}\""
106
+ puts cmd + "... [password filtered]"
107
+ cmd << " -p'#{password}'" unless password.nil?
108
+
109
+ system(cmd)
110
+ end
111
+
112
+ # We cannot use dropdb command as the rake task seems to lock the database...
113
+ #
114
+ def drop_postgresql_database database, user, password, host
115
+ Rake::Task['db:drop'].invoke
116
+ end
117
+
118
+ def create_postgresql_database database, user, password, host
119
+ cmd = "/usr/bin/env createdb -h #{host} -U #{user} #{database}"
120
+ puts cmd
121
+
122
+ system(cmd)
123
+ end
124
+
125
+ def create_mysql_database database, user, password, host
126
+ cmd = "/usr/bin/env mysql -h #{host} -u #{user}"
127
+ cmd << " -e \"CREATE DATABASE #{database}\""
128
+ puts cmd + "... [password filtered]"
129
+ cmd << " -p'#{password}'" unless password.nil?
130
+
131
+ system(cmd)
132
+ end
133
+
@@ -0,0 +1,13 @@
1
+ namespace :doc do
2
+ namespace :diagram do
3
+ task :models do
4
+ sh "railroad -i -l -a -m -M | dot -Tsvg | sed 's/font-size:14.00/font-size:11.00/g' > doc/models.svg"
5
+ end
6
+
7
+ task :controllers do
8
+ sh "railroad -i -l -C | neato -Tsvg | sed 's/font-size:14.00/font-size:11.00/g' > doc/controllers.svg"
9
+ end
10
+ end
11
+
12
+ task :diagrams => %w(diagram:models diagram:controllers)
13
+ end
@@ -0,0 +1,22 @@
1
+ namespace :env do
2
+ desc "reset your dev environment with default reference datas"
3
+ task :reset => :environment do
4
+ Rake::Task['db:drop'].invoke
5
+ Rake::Task['db:create'].invoke
6
+ Rake::Task['db:migrate'].invoke
7
+ Rake::Task['spec:db:fixtures:load'].invoke
8
+ end
9
+
10
+ desc "Rebuild with production data"
11
+ task :rebuild_with_production_data => :environment do
12
+ env = Rails.env
13
+ # Recreate database
14
+ `RAILS_ENV=#{env} rake db:drop db:create`
15
+ # Fetch database data
16
+ `RAILS_ENV=#{env} cap production db:dump_and_restore`
17
+ # Play migrations
18
+ `RAILS_ENV=#{env} rake db:migrate`
19
+ # Fetch assets
20
+ `RAILS_ENV=#{env} cap production assets:dump_and_restore`
21
+ end
22
+ end
@@ -0,0 +1,17 @@
1
+ namespace :mongo do
2
+ desc "Drops the database for the current RAILS_ENV"
3
+ task :drop => :environment do
4
+ MongoMapper.connection.drop_database(MongoMapper.database.name)
5
+ end
6
+
7
+ desc "Create the database defined in config/database.yml for the current RAILS_ENV"
8
+ task :seed => :environment do
9
+ Rake::Task["db:seed"].invoke
10
+ end
11
+
12
+ desc "Drops and recreates the database"
13
+ task :reset => :environment do
14
+ Rake::Task["mongo:drop"].invoke
15
+ Rake::Task["mongo:seed"].invoke
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ namespace :revision do
2
+ desc "print revision number in admin template"
3
+ task :print do
4
+ svn_revision = ENV['SVN_REVISION'] || IO.popen("svn info").readlines[4].split(" ").last
5
+ release_number = ENV['RELEASE_NUMBER'] || Dir.pwd.split("/").last
6
+ revision = RAILS_ENV
7
+ revision += "-r#{svn_revision}"
8
+ revision += "-#{release_number}" if release_number.to_i != 0
9
+
10
+ path = "app/views/shared/_revision.html.haml"
11
+ `echo "#{revision}" > #{path}`
12
+ end
13
+ end
@@ -0,0 +1,22 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "production_chain"
3
+ s.version = "0.0.2"
4
+ s.platform = Gem::Platform::RUBY
5
+ s.authors = ["Novelys"]
6
+ s.email = ["contact@novelys.com"]
7
+ s.homepage = "http://github.com/novelys/production_chain"
8
+ s.summary = "Production Chain"
9
+ s.description = "A rails plugin that incorporate various libs, recipes and tasks"
10
+ s.rubyforge_project = s.name
11
+
12
+ s.required_rubygems_version = ">= 1.3.6"
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ # s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
16
+ # s.extensions = `git ls-files ext/extconf.rb`.split("\n")
17
+
18
+ s.require_path = 'lib'
19
+
20
+ # For C extensions
21
+ # s.extensions = "ext/extconf.rb"
22
+ end
data/rails/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ Dir[File.join(File.dirname(__FILE__), '../lib/*.rb')].each { |file| load file }
2
+ require "core_ext/numeric"
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: production_chain
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
7
  - 0
9
- - 1
10
- version: 0.0.1
8
+ - 2
9
+ version: 0.0.2
11
10
  platform: ruby
12
11
  authors:
13
12
  - Novelys
@@ -15,27 +14,13 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-08-19 00:00:00 +02:00
17
+ date: 2012-05-31 00:00:00 +02:00
19
18
  default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: aws
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 25
30
- segments:
31
- - 2
32
- - 3
33
- - 13
34
- version: 2.3.13
35
- type: :runtime
36
- version_requirements: *id001
37
- description: A rails plugin to setup a basic production chain (it also includes various libs, recipes and tasks)
38
- email: contact@novelys.com
19
+ dependencies: []
20
+
21
+ description: A rails plugin that incorporate various libs, recipes and tasks
22
+ email:
23
+ - contact@novelys.com
39
24
  executables: []
40
25
 
41
26
  extensions: []
@@ -43,7 +28,23 @@ extensions: []
43
28
  extra_rdoc_files: []
44
29
 
45
30
  files:
31
+ - .gitignore
46
32
  - README
33
+ - lib/core_ext/numeric.rb
34
+ - lib/production_chain.rb
35
+ - lib/rails/action_controller/abstract_request.rb
36
+ - lib/rails/action_view/text_helper.rb
37
+ - lib/recipes/dump_and_restore.rb
38
+ - lib/recipes/sphinx.rb
39
+ - lib/tasks.rb
40
+ - lib/tasks/backup.rake
41
+ - lib/tasks/db.rake
42
+ - lib/tasks/diagrams.rake
43
+ - lib/tasks/env.rake
44
+ - lib/tasks/mongo.rake
45
+ - lib/tasks/revision.rake
46
+ - production_chain.gemspec
47
+ - rails/init.rb
47
48
  has_rdoc: true
48
49
  homepage: http://github.com/novelys/production_chain
49
50
  licenses: []
@@ -54,29 +55,27 @@ rdoc_options: []
54
55
  require_paths:
55
56
  - lib
56
57
  required_ruby_version: !ruby/object:Gem::Requirement
57
- none: false
58
58
  requirements:
59
59
  - - ">="
60
60
  - !ruby/object:Gem::Version
61
- hash: 3
62
61
  segments:
63
62
  - 0
64
63
  version: "0"
65
64
  required_rubygems_version: !ruby/object:Gem::Requirement
66
- none: false
67
65
  requirements:
68
66
  - - ">="
69
67
  - !ruby/object:Gem::Version
70
- hash: 3
71
68
  segments:
72
- - 0
73
- version: "0"
69
+ - 1
70
+ - 3
71
+ - 6
72
+ version: 1.3.6
74
73
  requirements: []
75
74
 
76
- rubyforge_project:
77
- rubygems_version: 1.3.7
75
+ rubyforge_project: production_chain
76
+ rubygems_version: 1.3.6
78
77
  signing_key:
79
78
  specification_version: 3
80
- summary: Setup a basic production chain
79
+ summary: Production Chain
81
80
  test_files: []
82
81