capistrano-db-tasks 0.2

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 ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ Copyright (c) 2009 Sébastien Gruhier - Xilinus/Maptimize
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
16
+ SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,76 @@
1
+ CapistranoDbTasks
2
+ =================
3
+
4
+ Add database AND assets tasks to capistrano to a Rails project.
5
+
6
+ Currently
7
+
8
+ * It only supports mysql and postgresql (both side remote and local)
9
+ * Synchronize assets remote to local and local to remote
10
+
11
+ Commands mysql, mysqldump (or pg_dump, psql), bzip2 and unbzip2 must be in your PATH
12
+
13
+ Feel free to fork and to add more database support or new tasks.
14
+
15
+ Install
16
+ =======
17
+
18
+ Add it as a gem:
19
+
20
+ ```ruby
21
+ gem "capistrano-db-tasks", require: false
22
+ ```
23
+
24
+ Add to config/deploy.rb:
25
+
26
+ ```ruby
27
+ require 'capistrano-db-tasks'
28
+
29
+ # if you haven't already specified
30
+ set :rails_env, "production"
31
+
32
+ # if you want to remove the dump file after loading
33
+ set :db_local_clean, true
34
+
35
+ # If you want to import assets, you can change default asset dir (default = system)
36
+ # This directory must be in your shared directory on the server
37
+ set :assets_dir, %w(public/assets public/att)
38
+
39
+ # if you want to work on a specific local environment (default = ENV['RAILS_ENV'] || 'development')
40
+ set :locals_rails_env, "production"
41
+ ```
42
+
43
+ Available tasks
44
+ ===============
45
+
46
+ app:local:sync || app:pull # Synchronize your local assets AND database using remote assets and database
47
+ app:remote:sync || app:push # Synchronize your remote assets AND database using local assets and database
48
+
49
+ assets:local:sync || assets:pull # Synchronize your local assets using remote assets
50
+ assets:remote:sync || assets:push # Synchronize your remote assets using local assets
51
+
52
+ db:local:sync || db:pull # Synchronize your local database using remote database data
53
+ db:remote:sync || db:push # Synchronize your remote database using local database data
54
+
55
+ Example
56
+ =======
57
+
58
+ cap db:pull
59
+ cap production db:pull # if you are using capistrano-ext to have multistages
60
+
61
+
62
+ Contributors
63
+ ============
64
+
65
+ * tilsammans (http://github.com/tilsammansee)
66
+ * bigfive (http://github.com/bigfive)
67
+ * jakemauer (http://github.com/jakemauer)
68
+ * tjoneseng (http://github.com/tjoneseng)
69
+
70
+ TODO
71
+ ====
72
+
73
+ * May be change project's name as it's not only database tasks now :)
74
+ * Add tests
75
+
76
+ Copyright (c) 2009 [Sébastien Gruhier - XILINUS], released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'bundler'
5
+ require 'bundler/gem_tasks'
6
+
7
+ desc 'Default: run unit tests.'
8
+ task :default => :test
9
+
10
+ desc 'Test the capistrano_db_tasks plugin.'
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs << 'lib'
13
+ t.libs << 'test'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = true
16
+ end
17
+
18
+ desc 'Generate documentation for the capistrano_db_tasks plugin.'
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'CapistranoDbTasks'
22
+ rdoc.options << '--line-numbers' << '--inline-source'
23
+ rdoc.rdoc_files.include('README')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "capistrano-db-tasks/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "capistrano-db-tasks"
7
+ s.version = CapistranoDbTasks::VERSION
8
+ s.authors = ["Sebastien Gruhier"]
9
+ s.email = ["sebastien.gruhier@xilinus.com"]
10
+ s.homepage = "https://github.com/sgruhier/capistrano-db-tasks"
11
+ s.summary = "A collection of capistrano tasks for syncing assets and databases"
12
+ s.description = "A collection of capistrano tasks for syncing assets and databases"
13
+
14
+ s.rubyforge_project = "capistrano-db-tasks"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "capistrano", "> 2.0.0"
22
+ end
@@ -0,0 +1,23 @@
1
+ module Asset
2
+ extend self
3
+
4
+ def remote_to_local(cap)
5
+ servers = cap.find_servers :roles => :app
6
+ port = cap.port rescue 22
7
+ [cap.assets_dir].flatten.each do |dir|
8
+ system("rsync -a --del -L -K -vv --progress --rsh='ssh -p #{port}' #{cap.user}@#{servers.first}:#{cap.current_path}/#{dir} #{cap.local_assets_dir}")
9
+ end
10
+ end
11
+
12
+ def local_to_remote(cap)
13
+ servers = cap.find_servers :roles => :app
14
+ port = cap.port rescue 22
15
+ [cap.assets_dir].flatten.each do |dir|
16
+ system("rsync -a --del -L -K -vv --progress --rsh='ssh -p #{port}' ./#{dir} #{cap.user}@#{servers.first}:#{cap.current_path}/#{cap.local_assets_dir}")
17
+ end
18
+ end
19
+
20
+ def to_string(cap)
21
+ [cap.assets_dir].flatten.join(" ")
22
+ end
23
+ end
@@ -0,0 +1,141 @@
1
+ module Database
2
+ class Base
3
+ attr_accessor :config, :output_file
4
+ def initialize(cap_instance)
5
+ @cap = cap_instance
6
+ end
7
+
8
+ def mysql?
9
+ @config['adapter'] =~ /^mysql/
10
+ end
11
+
12
+ def postgresql?
13
+ %w(postgresql pg).include? @config['adapter']
14
+ end
15
+
16
+ def credentials
17
+ if mysql?
18
+ " -u #{@config['username']} " + (@config['password'] ? " -p\"#{@config['password']}\" " : '') + (@config['host'] ? " -h #{@config['host']}" : '') + (@config['socket'] ? " -S#{@config['socket']}" : '')
19
+ elsif postgresql?
20
+ " -U #{@config['username']} " + (@config['host'] ? " -h #{@config['host']}" : '')
21
+ end
22
+ end
23
+
24
+ def database
25
+ @config['database']
26
+ end
27
+
28
+ def current_time
29
+ Time.now.strftime("%Y-%m-%d-%H%M%S")
30
+ end
31
+
32
+ def output_file
33
+ @output_file ||= "db/#{database}_#{current_time}.sql.bz2"
34
+ end
35
+
36
+
37
+ private
38
+
39
+ def dump_cmd
40
+ if mysql?
41
+ "mysqldump #{credentials} #{database} --lock-tables=false"
42
+ elsif postgresql?
43
+ "pg_dump #{credentials} -c -O #{database}"
44
+ end
45
+ end
46
+
47
+ def import_cmd(file)
48
+ if mysql?
49
+ "mysql #{credentials} -D #{database} < #{file}"
50
+ elsif postgresql?
51
+ "psql #{credentials} #{database} < #{file}"
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ class Remote < Base
58
+ def initialize(cap_instance)
59
+ super(cap_instance)
60
+ @config = ""
61
+ @cap.run("cat #{@cap.current_path}/config/database.yml") do |c, s, d|
62
+ @config += d
63
+ end
64
+ @config = YAML.load(@config)[@cap.rails_env]
65
+ end
66
+
67
+ def dump
68
+ @cap.run "cd #{@cap.current_path} && #{dump_cmd} | bzip2 - - > #{output_file}"
69
+ self
70
+ end
71
+
72
+ def download(local_file = "#{output_file}")
73
+ remote_file = "#{@cap.current_path}/#{output_file}"
74
+ @cap.get remote_file, local_file
75
+ end
76
+
77
+ # cleanup = true removes the mysqldump file after loading, false leaves it in db/
78
+ def load(file, cleanup)
79
+ unzip_file = File.join(File.dirname(file), File.basename(file, '.bz2'))
80
+ # @cap.run "cd #{@cap.current_path} && bunzip2 -f #{file} && RAILS_ENV=#{@cap.rails_env} bundle exec rake db:drop db:create && #{import_cmd(unzip_file)}"
81
+ @cap.run "cd #{@cap.current_path} && bunzip2 -f #{file} && RAILS_ENV=#{@cap.rails_env} && #{import_cmd(unzip_file)}"
82
+ @cap.run("cd #{@cap.current_path} && rm #{unzip_file}") if cleanup
83
+ end
84
+ end
85
+
86
+ class Local < Base
87
+ def initialize(cap_instance)
88
+ super(cap_instance)
89
+ @config = YAML.load_file(File.join('config', 'database.yml'))[@cap.local_rails_env]
90
+ puts "local #{@config}"
91
+ end
92
+
93
+ # cleanup = true removes the mysqldump file after loading, false leaves it in db/
94
+ def load(file, cleanup)
95
+ unzip_file = File.join(File.dirname(file), File.basename(file, '.bz2'))
96
+ # system("bunzip2 -f #{file} && bundle exec rake db:drop db:create && #{import_cmd(unzip_file)} && bundle exec rake db:migrate")
97
+ system("bunzip2 -f #{file} && #{import_cmd(unzip_file)}")
98
+ File.unlink(unzip_file) if cleanup
99
+ end
100
+
101
+ def dump
102
+ system "#{dump_cmd} | bzip2 - - > #{output_file}"
103
+ self
104
+ end
105
+
106
+ def upload
107
+ remote_file = "#{@cap.current_path}/#{output_file}"
108
+ @cap.upload output_file, remote_file
109
+ end
110
+ end
111
+
112
+
113
+ class << self
114
+ def check(local_db, remote_db)
115
+ unless (local_db.mysql? && remote_db.mysql?) || (local_db.postgresql? && remote_db.postgresql?)
116
+ raise 'Only mysql or postgresql on remote and local server is supported'
117
+ end
118
+ end
119
+
120
+ def remote_to_local(instance)
121
+ local_db = Database::Local.new(instance)
122
+ remote_db = Database::Remote.new(instance)
123
+
124
+ check(local_db, remote_db)
125
+
126
+ remote_db.dump.download
127
+ local_db.load(remote_db.output_file, instance.fetch(:db_local_clean))
128
+ end
129
+
130
+ def local_to_remote(instance)
131
+ local_db = Database::Local.new(instance)
132
+ remote_db = Database::Remote.new(instance)
133
+
134
+ check(local_db, remote_db)
135
+
136
+ local_db.dump.upload
137
+ remote_db.load(local_db.output_file, instance.fetch(:db_local_clean))
138
+ end
139
+ end
140
+
141
+ end
@@ -0,0 +1,115 @@
1
+ if Capistrano::Configuration.instance(false)
2
+
3
+ Capistrano::Configuration.instance(true).load do |instance|
4
+
5
+ require File.expand_path("#{File.dirname(__FILE__)}/util")
6
+ require File.expand_path("#{File.dirname(__FILE__)}/database")
7
+ require File.expand_path("#{File.dirname(__FILE__)}/asset")
8
+
9
+ instance.set :local_rails_env, ENV['RAILS_ENV'] || 'development' unless exists?(:local_rails_env)
10
+ instance.set :rails_env, 'production' unless exists?(:rails_env)
11
+ instance.set :stage, 'production' unless exists?(:stage)
12
+ instance.set :db_local_clean, false unless exists?(:db_local_clean)
13
+ instance.set :assets_dir, 'system' unless exists?(:assets_dir)
14
+ instance.set :local_assets_dir, 'public' unless exists?(:local_assets_dir)
15
+
16
+ namespace :db do
17
+ namespace :remote do
18
+ desc 'Synchronize your remote database using local database data'
19
+ task :sync, :roles => :db do
20
+ if Util.prompt 'Are you sure you want to REPLACE THE REMOTE DATABASE with local database'
21
+ Database.local_to_remote(instance)
22
+ end
23
+ end
24
+ end
25
+
26
+ namespace :local do
27
+ desc 'Synchronize your local database using remote database data'
28
+ task :sync, :roles => :db do
29
+ puts "Local database: #{Database::Local.new(instance).database}"
30
+ if Util.prompt 'Are you sure you want to erase your local database with server database'
31
+ Database.remote_to_local(instance)
32
+ end
33
+ end
34
+ end
35
+
36
+ desc 'Synchronize your local database using remote database data'
37
+ task :pull do
38
+ db.local.sync
39
+ end
40
+
41
+ desc 'Synchronize your remote database using local database data'
42
+ task :push do
43
+ db.remote.sync
44
+ end
45
+ end
46
+
47
+ namespace :assets do
48
+ namespace :remote do
49
+ desc 'Synchronize your remote assets using local assets'
50
+ task :sync, :roles => :app do
51
+ puts "Assets directories: #{assets_dir}"
52
+ if Util.prompt "Are you sure you want to erase your server assets with local assets"
53
+ Asset.local_to_remote(instance)
54
+ end
55
+ end
56
+ end
57
+
58
+ namespace :local do
59
+ desc 'Synchronize your local assets using remote assets'
60
+ task :sync, :roles => :app do
61
+ puts "Assets directories: #{local_assets_dir}"
62
+ if Util.prompt "Are you sure you want to erase your local assets with server assets"
63
+ Asset.remote_to_local(instance)
64
+ end
65
+ end
66
+ end
67
+
68
+ desc 'Synchronize your local assets using remote assets'
69
+ task :pull do
70
+ assets.local.sync
71
+ end
72
+
73
+ desc 'Synchronize your remote assets using local assets'
74
+ task :push do
75
+ assets.remote.sync
76
+ end
77
+ end
78
+
79
+ namespace :app do
80
+ namespace :remote do
81
+ desc 'Synchronize your remote assets AND database using local assets and database'
82
+ task :sync do
83
+ if Util.prompt "Are you sure you want to REPLACE THE REMOTE DATABASE AND your remote assets with local database and assets(#{assets_dir})"
84
+ Database.local_to_remote(instance)
85
+ Asset.local_to_remote(instance)
86
+ end
87
+ end
88
+ end
89
+
90
+ namespace :local do
91
+ desc 'Synchronize your local assets AND database using remote assets and database'
92
+ task :sync do
93
+ puts "Local database : #{Database::Local.new(instance).database}"
94
+ puts "Assets directories : #{local_assets_dir}"
95
+ if Util.prompt "Are you sure you want to erase your local database AND your local assets with server database and assets(#{assets_dir})"
96
+ Database.remote_to_local(instance)
97
+ Asset.remote_to_local(instance)
98
+ end
99
+ end
100
+ end
101
+
102
+ desc 'Synchronize your local assets AND database using remote assets and database'
103
+ task :pull do
104
+ app.local.sync
105
+ end
106
+
107
+ desc 'Synchronize your remote assets AND database using local assets and database'
108
+ task :push do
109
+ app.remote.sync
110
+ end
111
+
112
+ end
113
+ end
114
+
115
+ end
@@ -0,0 +1,10 @@
1
+ module Util
2
+ def self.prompt(msg, prompt = "(y)es, (n)o ")
3
+ answer = Capistrano::CLI.ui.ask("#{msg} #{prompt} ? ") do |q|
4
+ q.overwrite = false
5
+ q.validate = /^y$|^yes$|^n$|^no$/i
6
+ q.responses[:not_valid] = prompt
7
+ end
8
+ (answer =~ /^y$|^yes$/i) == 0
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module CapistranoDbTasks
2
+ VERSION = "0.2"
3
+ end
@@ -0,0 +1,2 @@
1
+ require "capistrano"
2
+ require File.expand_path("#{File.dirname(__FILE__)}/capistrano-db-tasks/dbtasks")
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class CapistranoDbTasksTest < ActiveSupport::TestCase
4
+ # Replace this with your real tests.
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_support/test_case'
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-db-tasks
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.2'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sebastien Gruhier
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: capistrano
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>'
20
+ - !ruby/object:Gem::Version
21
+ version: 2.0.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>'
28
+ - !ruby/object:Gem::Version
29
+ version: 2.0.0
30
+ description: A collection of capistrano tasks for syncing assets and databases
31
+ email:
32
+ - sebastien.gruhier@xilinus.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - Gemfile
38
+ - LICENSE
39
+ - README.markdown
40
+ - Rakefile
41
+ - capistrano-db-tasks.gemspec
42
+ - lib/capistrano-db-tasks.rb
43
+ - lib/capistrano-db-tasks/asset.rb
44
+ - lib/capistrano-db-tasks/database.rb
45
+ - lib/capistrano-db-tasks/dbtasks.rb
46
+ - lib/capistrano-db-tasks/util.rb
47
+ - lib/capistrano-db-tasks/version.rb
48
+ - test/capistrano_db_tasks_test.rb
49
+ - test/test_helper.rb
50
+ homepage: https://github.com/sgruhier/capistrano-db-tasks
51
+ licenses: []
52
+ post_install_message:
53
+ rdoc_options: []
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubyforge_project: capistrano-db-tasks
70
+ rubygems_version: 1.8.23
71
+ signing_key:
72
+ specification_version: 3
73
+ summary: A collection of capistrano tasks for syncing assets and databases
74
+ test_files:
75
+ - test/capistrano_db_tasks_test.rb
76
+ - test/test_helper.rb