porter 1.0.2 → 1.1.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/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
- source "http://rubygems.org"
1
+ source :rubygems
2
2
 
3
- # Specify your gem's dependencies in porter.gemspec
4
3
  gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,14 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ porter (1.0.2)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+
10
+ PLATFORMS
11
+ ruby
12
+
13
+ DEPENDENCIES
14
+ porter!
data/README.md ADDED
@@ -0,0 +1,69 @@
1
+ # Porter Gem
2
+
3
+ The Porter gem is comprised of Capistrano and Rake tasks that make cloning remote server data down to your local Rails application environment a cinch.
4
+
5
+ ## Dependencies
6
+
7
+ * Capistrano and a proper Capistrano Multistage configuration
8
+ * Rake
9
+ * A Rails app
10
+ * rsync (locally and remotely, if you want to sync assets)
11
+
12
+ ## Capistrano Multistage (capistrano-ext)
13
+
14
+ As of v1.1.0, Porter expects that your Capistrano setup utilizes the Capistrano Multistage Extension (capistrano-ext). This is a really great way to manage the various "stages" you deploy to and Porter is opinionated in that it requires you to organize your stage-specific settings into the Capistrano Multistage pattern.
15
+
16
+ More on the Capistrano Multistage Extension:
17
+ [https://github.com/capistrano/capistrano/wiki/2.x-Multistage-Extension](https://github.com/capistrano/capistrano/wiki/2.x-Multistage-Extension)
18
+
19
+ ## Installation
20
+
21
+ * Add gem "porter", "~> 1.1.0" to your Gemfile
22
+ * Run: bundle install
23
+ * Run: rails g porter
24
+ * Add require "porter/capistrano" to your config/deploy.rb
25
+ * Review the generated config/porter_config.yml (just so you're familiar, it's pretty straight-forward)
26
+
27
+ ## Usage
28
+
29
+ ### Purge your local database and reload data from a remote server's MySQL dump
30
+
31
+ $ bundle exec cap production porter:db
32
+
33
+ This will do the following:
34
+
35
+ * A mysqldump command will be remotely issued (via Capistrano) to the remote server, saving the result as a compressed (gz) file
36
+ * The database backup file from the server will be retrieved (via scp) and decompressed
37
+ * The database for the environment you are running the task in will be dropped, recreated, and restored from the backup
38
+
39
+ ### Synchronize a remote server's filesystem-stored assets to your local filesystem
40
+
41
+ $ bundle exec cap production porter:assets
42
+
43
+ This will do the following:
44
+
45
+ * Assets stored in directories you define will be rysnc'd down to your local application directory
46
+
47
+ ## License
48
+
49
+ The MIT License
50
+
51
+ Copyright (c) 2010-2011 Kenny Johnston
52
+
53
+ Permission is hereby granted, free of charge, to any person obtaining a copy
54
+ of this software and associated documentation files (the "Software"), to deal
55
+ in the Software without restriction, including without limitation the rights
56
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57
+ copies of the Software, and to permit persons to whom the Software is
58
+ furnished to do so, subject to the following conditions:
59
+
60
+ The above copyright notice and this permission notice shall be included in
61
+ all copies or substantial portions of the Software.
62
+
63
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
64
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
65
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
66
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
67
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
69
+ THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,2 +1,2 @@
1
- require 'bundler'
1
+ require "bundler"
2
2
  Bundler::GemHelper.install_tasks
@@ -1,19 +1,14 @@
1
- require 'rails/generators'
1
+ require "rails/generators"
2
2
 
3
3
  class PorterGenerator < Rails::Generators::Base
4
4
 
5
- attr_accessor :app, :domain
6
-
7
5
  def self.source_root
8
- @source_root ||= File.join(File.dirname(__FILE__), 'templates')
6
+ @source_root ||= File.join(File.dirname(__FILE__), "templates")
9
7
  end
10
8
 
11
9
  def create_config_file
12
- @app = Rails.root.to_s.split('/').last
13
- @domain = @app + (@app.include?('.') ? '' : '.com')
14
-
15
- template 'porter_config.yml', 'config/porter_config.yml'
16
- readme 'INSTALL'
10
+ template "porter_config.yml", "config/porter_config.yml"
11
+ readme "INSTALL"
17
12
  end
18
13
 
19
14
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  Add the following to the top of your config/deploy.rb:
4
4
 
5
- require 'porter'
5
+ require "porter/capistrano"
6
6
 
7
- *******************************************************
7
+ *******************************************************
@@ -1,16 +1,9 @@
1
1
  # Config file for porter gem
2
2
 
3
3
  production:
4
- user: deploy
5
- domain: <%= domain %>
6
- app_dir: /opt/apps/<%= app %>/current
7
4
  asset_dirs: public/system
8
5
  rsync_options: --verbose --progress --stats --recursive --times --compress --delete
9
6
 
10
7
  # staging:
11
- # user: deploy
12
- # domain: <%= domain %>
13
- # dir: /opt/apps/<%= app %>/current
14
8
  # asset_dirs: public/system
15
9
  # rsync_options: --verbose --progress --stats --recursive --times --compress --delete
16
-
data/lib/porter.rb CHANGED
@@ -1,5 +1,5 @@
1
- require "#{File.dirname(__FILE__)}/porter/recipes/porter"
1
+ require File.join(File.dirname(__FILE__), "porter", "capistrano")
2
2
 
3
3
  module Porter
4
- require 'porter/railtie'
5
- end
4
+ require "porter/railtie"
5
+ end
@@ -0,0 +1,36 @@
1
+ require "capistrano"
2
+
3
+ if instance = Capistrano::Configuration.instance
4
+ instance.load do
5
+
6
+ namespace :porter do
7
+
8
+ task :db do
9
+ set :user, ENV["AS"] || ENV["USER"]
10
+ puts "Connecting to #{domain} as #{user}..."
11
+
12
+ puts "Reading database.yml on #{domain}..."
13
+ database_yml = ""
14
+ run "cat #{deploy_to}/current/config/database.yml" do |channel, stream, data|
15
+ database_yml << data
16
+ end
17
+
18
+ config = YAML::load(database_yml)[stage.to_s]
19
+ database = config["database"]
20
+ username = config["username"]
21
+ password = config["password"]
22
+
23
+ puts "Creating compressed backup of #{database} database on #{domain}..."
24
+ run "mysqldump --user=#{username} --password=#{password} #{database} | gzip > ~/#{database}.sql.gz"
25
+
26
+ system "rake porter:db DOMAIN=#{domain} DATABASE=#{database} --trace"
27
+ end
28
+
29
+ task :assets do
30
+ system "rake porter:assets STAGE=#{stage.to_s} DOMAIN=#{domain} APP_DIR=#{deploy_to}"
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+ end
@@ -1,5 +1,6 @@
1
- require 'porter'
2
- require 'rails'
1
+ require "porter"
2
+ require "rails"
3
+
3
4
  module Porter
4
5
  class Railtie < Rails::Railtie
5
6
  railtie_name :porter
@@ -8,4 +9,4 @@ module Porter
8
9
  load "tasks/porter.rake"
9
10
  end
10
11
  end
11
- end
12
+ end
@@ -1,3 +1,3 @@
1
1
  module Porter
2
- VERSION = "1.0.2"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -1,75 +1,73 @@
1
- CONFIG = YAML::load_file(Rails.root.join('config', 'porter_config.yml'))
2
- DATABASES = YAML::load_file(Rails.root.join('config', 'database.yml'))
3
- STAGES = DATABASES.keys - %w(development test) # you don't need data out of these
4
-
5
1
  namespace :porter do
6
- STAGES.each do |stage|
7
- namespace stage do
8
- task :db => :environment do
9
- if CONFIG[stage]
10
- src_user = CONFIG[stage]['user']
11
- src_domain = CONFIG[stage]['domain']
12
- else
13
- puts "Please tell config/porter_config.yml about the '#{stage}' server."
14
- return
15
- end
16
-
17
- src_db = ActiveRecord::Base.configurations[stage]
18
- dest_db = ActiveRecord::Base.configurations[Rails.env]
19
- dest_root = Rails.root
20
-
21
- app = src_db['database'].split('_').first
22
- root = Rails.root
23
-
24
- puts "Retrieving latest compressed database backup from #{stage} server..."
25
- system "scp #{src_user}@#{src_domain}:~/#{src_db['database']}.sql.gz #{root}"
26
-
27
- puts "Decompressing database backup..."
28
- system "gunzip #{root}/#{src_db['database']}.sql.gz"
29
-
30
- # Drop the database if it exists
31
- begin
32
- ActiveRecord::Base.establish_connection(dest_db)
33
- ActiveRecord::Base.connection # Should raise Mysql::Error if db doesn't exist
34
- puts "Dropping database: " + dest_db['database']
35
- Rake::Task['db:drop'].execute
36
- rescue Mysql::Error => e
37
- raise e unless e.message =~ /Unknown database/
38
- end
39
-
40
- puts "Creating database: " + dest_db['database']
41
- Rake::Task['db:create'].execute
42
-
43
- puts "Restoring database from backup..."
44
- mysql_version = `which mysql`.empty? ? 'mysql5' : 'mysql'
45
- cmd = [mysql_version]
46
- cmd << "-u #{dest_db['username']}"
47
- cmd << "--password=#{dest_db['password']}" unless dest_db['password'].blank?
48
- cmd << dest_db['database']
49
- cmd << "< #{root}/#{src_db['database']}.sql"
50
- system cmd.join(' ') # Run the mysql import
51
-
52
- puts "Removing database backup file..."
53
- system "rm #{root}/#{src_db['database']}.sql"
54
-
55
- puts "Database reload complete"
56
- end
57
2
 
58
- task :assets => :environment do
59
- root = Rails.root
60
- user = CONFIG[stage]['user']
61
- domain = CONFIG[stage]['domain']
62
- app_dir = CONFIG[stage]['app_dir']
63
- asset_dirs = CONFIG[stage]['asset_dirs'].blank? ? '' : CONFIG[stage]['asset_dirs'].gsub(/,/,'').split(' ').map { |i| i.strip }
64
- rsync_options = CONFIG[stage]['rsync_options']
65
-
66
- asset_dirs.each do |d|
67
- puts "Synchronizing assets in #{d}..."
68
- system "rsync #{rsync_options} #{user}@#{domain}:#{app_dir}/#{d}/ #{d}"
69
- end
70
-
71
- puts "Asset synchronization complete"
3
+ task :db => :environment do
4
+ domain = ENV["DOMAIN"]
5
+ user = ENV["AS"] || ENV["USER"]
6
+ source_database = ENV["DATABASE"]
7
+
8
+ destintation_database_config = ActiveRecord::Base.configurations[Rails.env]
9
+ destintation_database = destintation_database_config["database"]
10
+ destintation_database_username = destintation_database_config["username"]
11
+ destintation_database_password = destintation_database_config["password"]
12
+
13
+ root = Rails.root
14
+
15
+ puts "Connecting to #{domain} as #{user}..."
16
+
17
+ puts "Retrieving database backup from #{domain}..."
18
+ system "scp #{user}@#{domain}:~/#{source_database}.sql.gz #{root}"
19
+
20
+ puts "Decompressing database backup..."
21
+ system "gunzip #{root}/#{source_database}.sql.gz"
22
+
23
+ # Drop the database if it exists
24
+ begin
25
+ ActiveRecord::Base.establish_connection(destintation_database_config)
26
+ ActiveRecord::Base.connection # Should raise Mysql::Error if db doesn't exist
27
+ puts "Dropping database: " + destintation_database
28
+ Rake::Task["db:drop"].execute
29
+ rescue Mysql2::Error => e
30
+ raise e unless e.message =~ /Unknown database/
31
+ end
32
+
33
+ puts "Creating database: " + destintation_database
34
+ Rake::Task["db:create"].execute
35
+
36
+ puts "Restoring database from backup..."
37
+ mysql_version = `which mysql`.empty? ? "mysql5" : "mysql"
38
+ cmd = [mysql_version]
39
+ cmd << "-u #{destintation_database_username}"
40
+ cmd << "--password=#{destintation_database_password}" unless destintation_database_password.blank?
41
+ cmd << destintation_database
42
+ cmd << "< #{root}/#{source_database}.sql"
43
+ system cmd.join(' ') # Run the mysql import
44
+
45
+ puts "Removing database backup file..."
46
+ system "rm #{root}/#{source_database}.sql"
47
+
48
+ puts "Database reload complete"
49
+ end
50
+
51
+ task :assets => :environment do
52
+ stage = ENV["STAGE"]
53
+ domain = ENV["DOMAIN"]
54
+ user = ENV["AS"] || ENV["USER"]
55
+ app_dir = ENV["APP_DIR"]+"/current"
56
+ config = YAML::load_file(Rails.root.join("config", "porter_config.yml"))
57
+ rsync_options = config[stage]["rsync_options"]
58
+
59
+ unless config[stage]["asset_dirs"].blank?
60
+ asset_dirs = config[stage]["asset_dirs"].gsub(/,/,' ').split(' ').map { |i| i.strip }
61
+
62
+ puts "Connecting to #{domain} as #{user}..."
63
+
64
+ asset_dirs.each do |d|
65
+ puts "Synchronizing assets in #{d}..."
66
+ system "rsync #{rsync_options} #{user}@#{domain}:#{app_dir}/#{d}/ #{d}"
72
67
  end
73
68
  end
69
+
70
+ puts "Asset synchronization complete"
74
71
  end
75
- end
72
+
73
+ end
data/porter.gemspec CHANGED
@@ -12,7 +12,9 @@ Gem::Specification.new do |s|
12
12
  s.summary = %q{Capistrano and Rake tasks for cloning production and/or staging databases and assets to development.}
13
13
  s.description = %q{Capistrano and Rake tasks for cloning production and/or staging databases and assets to development.}
14
14
 
15
- s.rubyforge_project = "porter"
15
+ s.add_runtime_dependency "capistrano", ">= 2.5.0"
16
+ s.add_runtime_dependency "capistrano-ext", ">= 1.2.0"
17
+ s.add_runtime_dependency "rake", ">= 0.8.7"
16
18
 
17
19
  s.files = `git ls-files`.split("\n")
18
20
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
metadata CHANGED
@@ -1,79 +1,95 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: porter
3
- version: !ruby/object:Gem::Version
4
- hash: 19
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
5
  prerelease:
6
- segments:
7
- - 1
8
- - 0
9
- - 2
10
- version: 1.0.2
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Kenny Johnston
14
9
  - Robert Bousquet
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
-
19
- date: 2011-08-18 00:00:00 Z
20
- dependencies: []
21
-
22
- description: Capistrano and Rake tasks for cloning production and/or staging databases and assets to development.
23
- email:
13
+ date: 2011-12-07 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: capistrano
17
+ requirement: &2223799140 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 2.5.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2223799140
26
+ - !ruby/object:Gem::Dependency
27
+ name: capistrano-ext
28
+ requirement: &2223798140 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *2223798140
37
+ - !ruby/object:Gem::Dependency
38
+ name: rake
39
+ requirement: &2223797360 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: 0.8.7
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *2223797360
48
+ description: Capistrano and Rake tasks for cloning production and/or staging databases
49
+ and assets to development.
50
+ email:
24
51
  - kjohnston.ca@gmail.com
25
52
  executables: []
26
-
27
53
  extensions: []
28
-
29
54
  extra_rdoc_files: []
30
-
31
- files:
55
+ files:
32
56
  - .gitignore
33
57
  - Gemfile
58
+ - Gemfile.lock
59
+ - README.md
34
60
  - Rakefile
35
- - Readme.textile
36
61
  - lib/generators/porter/porter_generator.rb
37
62
  - lib/generators/porter/templates/INSTALL
38
63
  - lib/generators/porter/templates/porter_config.yml
39
64
  - lib/porter.rb
65
+ - lib/porter/capistrano.rb
40
66
  - lib/porter/railtie.rb
41
- - lib/porter/recipes/porter.rb
42
67
  - lib/porter/version.rb
43
68
  - lib/tasks/porter.rake
44
69
  - porter.gemspec
45
70
  homepage: http://github.com/kjohnston/porter
46
71
  licenses: []
47
-
48
72
  post_install_message:
49
73
  rdoc_options: []
50
-
51
- require_paths:
74
+ require_paths:
52
75
  - lib
53
- required_ruby_version: !ruby/object:Gem::Requirement
76
+ required_ruby_version: !ruby/object:Gem::Requirement
54
77
  none: false
55
- requirements:
56
- - - ">="
57
- - !ruby/object:Gem::Version
58
- hash: 3
59
- segments:
60
- - 0
61
- version: "0"
62
- required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ! '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
83
  none: false
64
- requirements:
65
- - - ">="
66
- - !ruby/object:Gem::Version
67
- hash: 3
68
- segments:
69
- - 0
70
- version: "0"
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
71
88
  requirements: []
72
-
73
- rubyforge_project: porter
74
- rubygems_version: 1.8.6
89
+ rubyforge_project:
90
+ rubygems_version: 1.8.10
75
91
  signing_key:
76
92
  specification_version: 3
77
- summary: Capistrano and Rake tasks for cloning production and/or staging databases and assets to development.
93
+ summary: Capistrano and Rake tasks for cloning production and/or staging databases
94
+ and assets to development.
78
95
  test_files: []
79
-
data/Readme.textile DELETED
@@ -1,58 +0,0 @@
1
- h1. Porter Gem
2
-
3
- The Porter gem is comprised of Capistrano and Rake tasks that make cloning your production and/or staging server data down to your development environment a cinch.
4
-
5
- h2. Overview
6
-
7
- * A mysqldump command is remotely issued (via Capistrano) to the remote server (production or staging environment), saving the result as a compressed (gz) file
8
- * The database backup file from the server is retrieved (via scp) and decompressed
9
- * The development database is dropped, recreated, and restored from the backup
10
- * Assets stored in directories you define are rysnc'd down to your local application directory
11
- * Separate rake tasks are included for restoring the db and re-syncing the assets without re-dumping the remote db
12
-
13
- h2. Dependencies
14
-
15
- * Capistrano (and a config/deploy.rb file)
16
- * Rake
17
- * A Rails app
18
- * rsync (locally and remotely)
19
-
20
- h2. Installation
21
-
22
- * Add gem 'porter' to your Gemfile
23
- * Run: bundle install
24
- * Run: rails g porter
25
- * Add require 'porter' to your config/deploy.rb
26
- * See the generated config/porter_config.yml - it's pretty straight-forward
27
-
28
- h2. Usage
29
-
30
- * cap porter:[stage] (creates the remote db backup file then calls the two rake tasks below)
31
- * rake porter:[stage]:db (if you've already got a db backup on the remote server and want to restore from it again)
32
- * rake porter:[stage]:assets (rsync the assets down from the remote server again)
33
-
34
- Note: [stage] is most likely going to be 'production' unless your app has a staging or demo environment and you want to pull from there instead.
35
-
36
- h2. License
37
-
38
- The MIT License
39
-
40
- Copyright (c) 2010-2011 Kenny Johnston
41
-
42
- Permission is hereby granted, free of charge, to any person obtaining a copy
43
- of this software and associated documentation files (the "Software"), to deal
44
- in the Software without restriction, including without limitation the rights
45
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
46
- copies of the Software, and to permit persons to whom the Software is
47
- furnished to do so, subject to the following conditions:
48
-
49
- The above copyright notice and this permission notice shall be included in
50
- all copies or substantial portions of the Software.
51
-
52
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
54
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
55
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
56
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
58
- THE SOFTWARE.
@@ -1,26 +0,0 @@
1
- if defined?(Capistrano)
2
- Capistrano::Configuration.instance.load do
3
- namespace :porter do
4
- CONFIG = YAML::load_file('config/porter_config.yml')
5
- DATABASES = YAML::load_file('config/database.yml')
6
- STAGES = DATABASES.keys - %w(development test) # you don't need data out of these
7
- STAGES.each do |stage|
8
- # task names for each of your other stages: production, staging, etc.
9
- # cap porter:production, cap porter:staging, etc.
10
- task stage do
11
- src_db = DATABASES[stage]
12
- db = src_db['database']
13
- user = src_db['username']
14
- pass = src_db['password']
15
-
16
- domain = CONFIG[stage]['domain']
17
- server domain, :porter
18
-
19
- run "mysqldump --user=#{user} --password=#{pass} #{db} | gzip > ~/#{db}.sql.gz", :roles => :porter
20
- system "rake porter:#{stage}:db"
21
- system "rake porter:#{stage}:assets"
22
- end
23
- end
24
- end
25
- end
26
- end