locarails 1.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.
@@ -0,0 +1,240 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Created on 2008-8-19.
4
+ # Copyright (c) 2008. All rights reserved.
5
+ # Fabio Akita - akitaonrails.com
6
+
7
+ begin
8
+ require 'rubygems'
9
+ rescue LoadError
10
+ # no rubygems to load, so we fail silently
11
+ end
12
+
13
+ require 'ostruct'
14
+ require 'optparse'
15
+ require 'erb'
16
+ require 'highline/import'
17
+
18
+ # configuracoes da sua hospedagem
19
+ class MyOpenStruct < OpenStruct
20
+ def blank?(campo)
21
+ send(campo).nil? || send(campo).empty?
22
+ end
23
+
24
+ def input(campo, message, default_value = nil)
25
+ unless blank?(campo)
26
+ puts "* #{message} > #{message =~ /senha/ ? "********" : send(campo)}"
27
+ return send(campo)
28
+ end
29
+ result = if message =~ /senha/
30
+ ask("* #{message} > ") { |q| q.echo = "*" }
31
+ else
32
+ ask("* #{message} > ")
33
+ end
34
+ send("#{campo}=", (default_value && result.empty?) ? default_value : result)
35
+ end
36
+ end
37
+
38
+ config = MyOpenStruct.new
39
+ mysqlcfg = MyOpenStruct.new
40
+
41
+ # defaults
42
+ config.force = false
43
+ config.mode = 'copy'
44
+
45
+ OptionParser.new do |opts|
46
+ opts.banner = <<-STR
47
+ LocaRails - configurador de Capistrano para projetos Rails
48
+ especifico para hospedagens Linux da Locaweb
49
+
50
+ Uso: #{File.basename($0)} [caminho] [opcoes]
51
+ STR
52
+
53
+ opts.on("--version", "Mostra versao atual do locarails") do
54
+ require 'locarails'
55
+ puts "Locarails v#{Locarails::VERSION::STRING}"
56
+ exit 0
57
+ end
58
+
59
+ opts.on("-h", "--help", "Mostra esta tela de ajuda") do
60
+ puts opts
61
+ exit 0
62
+ end
63
+
64
+ opts.on("-m", "--mode=tipo", "modo de deployment (copy/git)", "Padrao: copy") do |mode|
65
+ config.mode = mode
66
+ unless "copy|git".include?(mode)
67
+ puts "#{mode} nao existe. Escolha copy ou git como --mode."
68
+ exit 0
69
+ end
70
+ end
71
+
72
+ opts.on("-s", "--sshkey=caminho", "local da sua chave privada SSH", "Padrao: ~/.ssh/id_rsa") do |path|
73
+ config.ssh_key_path = path
74
+ unless File.exists?(path)
75
+ puts "Chave inexistente no caminho #{path}."
76
+ exit 0
77
+ end
78
+ end
79
+
80
+ opts.on("-f", "--force", "Sobrescreve seu config/deploy.rb, caso exista.", "Cuidado: voce ira perder sua configuracao anterior") do
81
+ config.force = true
82
+ end
83
+
84
+ opts.on("-u", "--usuario=login", "Usuario da hospedagem Linux") do |usuario|
85
+ config.usuario = usuario
86
+ end
87
+
88
+ opts.on("-a", "--aplicacao=aplicacao", "Nome da sua aplicacao", "O mesmo do apontamento /public_html/aplicacao") do |aplicacao|
89
+ config.app_name = aplicacao
90
+ end
91
+
92
+ opts.on("-d", "--dominio=URL", "Dominio do seu site", "ex. www.seu_dominio.com") do |dominio|
93
+ config.dominio = dominio
94
+ end
95
+
96
+ opts.on("-q", "--banco=banco", "Nome do seu banco de dados") do |db|
97
+ mysqlcfg.db = db
98
+ end
99
+
100
+ opts.on("-l", "--banco-usuario=login", "Login do seu banco de dados MySQL") do |dbuser|
101
+ mysqlcfg.user = dbuser
102
+ end
103
+
104
+ opts.on("-p", "--banco-senha=senha", "Senha do seu banco de dados MySQL") do |dbpass|
105
+ mysqlcfg.pass = dbpass
106
+ end
107
+
108
+ opts.on("-v", "--banco-servidor=servidor", "Servidor do seu banco de dados", "ex. mysql6666.locaweb.com.br") do |dbhost|
109
+ mysqlcfg.host = dbhost
110
+ end
111
+
112
+ opts.on("-b", "--git-branch=branch", "Branch local do seu repositorio Git", "padrao: master") do |gitbranch|
113
+ config.branch = gitbranch
114
+ end
115
+
116
+ opts.on("-r", "--git-remote=remote", "Nome do repositorio remoto gravado no seu .git/config", "padrao: locaweb") do |gitname|
117
+ config.remote_repo = gitname
118
+ end
119
+
120
+ begin
121
+ opts.parse!(ARGV)
122
+ rescue OptionParser::ParseError => e
123
+ warn e.message
124
+ puts opts
125
+ exit 1
126
+ end
127
+ end
128
+
129
+ if ARGV.empty?
130
+ abort "Por favor, especifique o diretorio do seu projeto Rails, e.g. `#{File.basename($0)} .'"
131
+ elsif !File.exists?(ARGV.first)
132
+ abort "`#{ARGV.first}' nao existe. Tente novamente."
133
+ elsif !File.directory?(ARGV.first)
134
+ abort "`#{ARGV.first}' nao eh um diretorio. Tente novamente."
135
+ end
136
+
137
+ # configuracoes locais da sua maquina
138
+ config.bin_path = File.dirname(File.expand_path(__FILE__))
139
+ config.local_path = File.expand_path(ARGV.shift)
140
+ config.app_name ||= config.local_path.split('/').last
141
+
142
+ if !config.force && File.exists?(File.join(config.local_path, 'config/deploy.rb'))
143
+ abort "Voce ja tem capistrano configurado em config/deploy.rb. Configuracao abortada."
144
+ end
145
+
146
+ puts <<-STR
147
+ ========================================================
148
+ Bem Vindos ao configurador de projetos da Locaweb.
149
+
150
+ Vamos configurar seu projeto Rails para melhor se
151
+ Adequar nas nossas hospedagens Linux compartilhada.
152
+
153
+ O comando locarails deve ser executado *dentro* do
154
+ diretorio do seu projeto, na sua maquina local.
155
+
156
+ Para tanto precisaremos de algumas informacoes:
157
+ ========================================================
158
+
159
+ Estrategia de instalacao via: #{config.mode}
160
+
161
+ Garanta que a seguinte pasta contem sua aplicacao Rails:
162
+ #{config.local_path}
163
+
164
+ STR
165
+
166
+ # configuracoes inseridas manualmente pelo usuario
167
+ config.input( :app_name, "Nome da sua aplicacao" )
168
+ config.input( :dominio, "Dominio do seu site (ex. teste.tempsite.ws)" )
169
+ config.input( :usuario, "Seu usuario de hospedagem" )
170
+ mysqlcfg.input( :db, "Nome do seu banco mysql (enter para '#{config.usuario}')", config.usuario )
171
+ mysqlcfg.input( :user, "Seu usuario de mysql (enter para #{mysqlcfg.db})", mysqlcfg.db )
172
+ mysqlcfg.input( :pass, "Sua senha de mysql" )
173
+ mysqlcfg.input( :host, "Seu servidor mysql (ex. mysqlxxxx.locaweb.com.br)" )
174
+ if config.mode == 'git'
175
+ config.input( :branch, "Git branch local (enter para 'master')", 'master' )
176
+ config.input( :remote_repo, "Nome do repositorio remoto (enter para 'locaweb')", 'locaweb' )
177
+ config.remote_git = "#{config.usuario}@#{config.dominio}:~/repo/#{config.app_name}.git"
178
+ end
179
+
180
+ # forca rodar capistrano
181
+ unless File.exists?("#{config.local_path}/Capfile")
182
+ puts "- Executando Capistrano no seu projeto ..."
183
+ begin
184
+ `capify .`
185
+ rescue Exception => e
186
+ puts <<-STR
187
+ ERRO: Voce provavelmente nao tem Capistrano instalado
188
+ Rode: sudo gem install capistrano
189
+
190
+ STR
191
+ end
192
+ end
193
+
194
+ if config.mode == 'git'
195
+ begin
196
+ FileUtils.copy_file("#{config.bin_path}/../templates/.gitignore",
197
+ "#{config.local_path}/.gitignore") unless File.exists?("#{config.local_path}/.gitignore")
198
+ rescue
199
+ puts "Error copying file #{config.bin_path}/../templates/.gitignore"
200
+ end
201
+ end
202
+
203
+ begin
204
+ FileUtils.copy_file("#{config.bin_path}/../templates/locaweb_backup.rb",
205
+ "#{config.local_path}/config/locaweb_backup.rb") unless File.exists?("#{config.local_path}/config/locaweb_backup.rb")
206
+ rescue
207
+ puts "Error copying file #{config.bin_path}/../templates/locaweb_backup.rb"
208
+ end
209
+
210
+ begin
211
+ FileUtils.copy_file("#{config.bin_path}/../templates/ssh_helper.rb",
212
+ "#{config.local_path}/config/ssh_helper.rb") unless File.exists?("#{config.local_path}/config/ssh_helper.rb")
213
+ rescue
214
+ puts "Error copying file #{config.bin_path}/../templates/ssh_helper.rb"
215
+ end
216
+
217
+ File.open("#{config.local_path}/config/deploy.rb", 'w') do |out|
218
+ erb = ERB.new(File.read("#{config.bin_path}/../templates/deploy.rb.erb"))
219
+ buffer = erb.result(config.send(:binding))
220
+ erb = ERB.new(File.read("#{config.bin_path}/../templates/deploy.common.rb.erb"))
221
+ buffer << erb.result(config.send(:binding))
222
+ out.puts buffer
223
+ end
224
+
225
+ File.open("#{config.local_path}/config/database.locaweb.yml", 'w') do |out|
226
+ erb = ERB.new(File.read("#{config.bin_path}/../templates/database.locaweb.yml.erb"))
227
+ out.puts erb.result(mysqlcfg.send(:binding))
228
+ end
229
+
230
+ puts <<-STR
231
+
232
+ # Parabens, voce terminou de configurar sua aplicacao Rails!
233
+ # Execute apenas uma vez 'cap deploy:setup' para configurar os
234
+ diretorios remotamente na sua hospedagem.
235
+ # Em seguida execute 'cap deploy' para transportar sua aplicacao
236
+ para a hospedagem. Sempre que quiser atualizar sua aplicacao
237
+ no servidor apenas execute novamente 'cap deploy'
238
+
239
+ [finalizado!]
240
+ STR
@@ -0,0 +1 @@
1
+ @ruby "C:/ruby/bin/locarails" %*
@@ -0,0 +1,4 @@
1
+ module Locarails
2
+ end
3
+
4
+ require 'locarails/version'
@@ -0,0 +1,24 @@
1
+ module Capistrano
2
+ module Deploy
3
+ module Strategy
4
+ class Base
5
+ protected
6
+ # A wrapper for Kernel#system that logs the command being executed.
7
+ def system(*args)
8
+ cmd = args.join(' ')
9
+ if RUBY_PLATFORM =~ /win32/
10
+ cmd.gsub!('/','\\') # Replace / with \\
11
+ cmd.gsub!(/^cd /,'cd /D ') # Replace cd with cd /D
12
+ cmd.gsub!(/&& cd /,'&& cd /D ') # Replace cd with cd /D
13
+ cmd.gsub!('%%', '/') # Avoid windows command line parameters to be erroneously replaced by backslashes
14
+ logger.trace "executing locally: #{cmd}"
15
+ super(cmd)
16
+ else
17
+ logger.trace "executing locally: #{cmd}"
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,73 @@
1
+ class Capistrano::Deploy::Strategy::Copy
2
+ # Obtains a copy of the source code locally (via the #command method),
3
+ # compresses it to a single file, copies that file to all target
4
+ # servers, and uncompresses it on each of them into the deployment
5
+ # directory.
6
+ def deploy!
7
+ if copy_cache
8
+ if File.exists?(copy_cache)
9
+ logger.debug "refreshing local cache to revision #{revision} at #{copy_cache}"
10
+ system(source.sync(revision, copy_cache))
11
+ else
12
+ logger.debug "preparing local cache at #{copy_cache}"
13
+ system(source.checkout(revision, copy_cache))
14
+ end
15
+
16
+ logger.debug "copying cache to deployment staging area #{destination}"
17
+ Dir.chdir(copy_cache) do
18
+ FileUtils.mkdir_p(destination)
19
+ queue = Dir.glob("*", File::FNM_DOTMATCH)
20
+ while queue.any?
21
+ item = queue.shift
22
+ name = File.basename(item)
23
+
24
+ next if name == "." || name == ".."
25
+ next if copy_exclude.any? { |pattern| File.fnmatch(pattern, item) }
26
+
27
+ if File.symlink?(item)
28
+ FileUtils.ln_s(File.readlink(File.join(copy_cache, item)), File.join(destination, item))
29
+ elsif File.directory?(item)
30
+ queue += Dir.glob("#{item}/*", File::FNM_DOTMATCH)
31
+ FileUtils.mkdir(File.join(destination, item))
32
+ else
33
+ FileUtils.ln(File.join(copy_cache, item), File.join(destination, item))
34
+ end
35
+ end
36
+ end
37
+ else
38
+ logger.debug "getting (via #{copy_strategy}) revision #{revision} to #{destination}"
39
+ system(command)
40
+
41
+ if copy_exclude.any?
42
+ logger.debug "processing exclusions..."
43
+ if copy_exclude.any?
44
+ copy_exclude.each do |pattern|
45
+ delete_list = Dir.glob(File.join(destination, pattern), File::FNM_DOTMATCH)
46
+ # avoid the /.. trap that deletes the parent directories
47
+ delete_list.delete_if { |dir| dir =~ /\/\.\.$/ }
48
+ FileUtils.rm_rf(delete_list.compact)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ File.open(File.join(destination, "REVISION"), "w") { |f| f.puts(revision) }
55
+
56
+ logger.trace "compressing #{destination} to #{filename}"
57
+ # if it is Windows, force gzip using the pure Ruby minitar library
58
+ if Capistrano::Deploy::LocalDependency.on_windows?
59
+ require 'zlib'
60
+ require 'archive/tar/minitar'
61
+ Dir.chdir(tmpdir) { Archive::Tar::Minitar.pack(File.basename(destination), Zlib::GzipWriter.new(File.open(File.basename(filename), 'wb'))) }
62
+ configuration[:copy_compression] = :gzip
63
+ else
64
+ Dir.chdir(tmpdir) { system(compress(File.basename(destination), File.basename(filename)).join(" ")) }
65
+ end
66
+
67
+ upload(filename, remote_filename)
68
+ run "cd #{configuration[:releases_path]} && #{decompress(remote_filename).join(" ")} && rm #{remote_filename}"
69
+ ensure
70
+ FileUtils.rm filename rescue nil
71
+ FileUtils.rm_rf destination rescue nil
72
+ end
73
+ end
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ unless Gem.source_index.find_name('capistrano').select { |g| g.version.to_s =~ /^2\.5/ }.empty?
3
+ puts "Loading temporary fixes for Capistrano 2.5.x"
4
+ require 'capistrano'
5
+ require 'capistrano/recipes/deploy/dependencies'
6
+ require 'capistrano/recipes/deploy/strategy/base'
7
+ require 'capistrano/recipes/deploy/strategy/copy'
8
+ require 'capistrano/recipes/deploy/scm/git'
9
+ require 'capistrano/recipes/deploy/scm/none'
10
+ require 'locarails/base'
11
+ require 'locarails/copy'
12
+ require 'locarails/git'
13
+ require 'locarails/none'
14
+ end
@@ -0,0 +1,39 @@
1
+ class Capistrano::Deploy::SCM::Git
2
+ alias :checkout_old :checkout
3
+ def checkout(revision, destination)
4
+ sub_wrapper(:checkout_old, revision, destination)
5
+ end
6
+
7
+ alias :sync_old :sync
8
+ def sync(revision, destination)
9
+ sub_wrapper(:sync_old, revision, destination)
10
+ end
11
+
12
+ def sub_wrapper(method, revision, destination)
13
+ execute = send(method, revision, destination) # execute original method
14
+ # filter the git URL to force it to a local file:// URL
15
+ execute.collect do |line|
16
+ if line.include?(configuration[:repository])
17
+ line.sub(configuration[:repository], remote_repository)
18
+ else
19
+ line
20
+ end
21
+ end
22
+ end
23
+
24
+ # force the remote git commands to fetch from the local filesystem instead
25
+ # making a round-trip to itself through ssh
26
+ def remote_repository
27
+ url = "#{configuration[:user]}@#{configuration[:domain]}:"
28
+ @remote_repository ||= if configuration[:repository].include?(url)
29
+ tmp = configuration[:repository].sub(url, "file://")
30
+ if tmp.include?("~")
31
+ tmp.sub!("~", "/home/#{configuration[:user]}")
32
+ end
33
+ tmp
34
+ else
35
+ configuration[:repository]
36
+ end
37
+ @remote_repository
38
+ end
39
+ end
@@ -0,0 +1,10 @@
1
+ class Capistrano::Deploy::SCM::None
2
+ # Simply does a copy from the :repository directory to the
3
+ # :destination directory.
4
+ # fix: avoid xcopy parameters to be erroneously replaced by backslashes
5
+ def checkout(revision, destination)
6
+ !Capistrano::Deploy::LocalDependency.on_windows? ? "cp -R #{repository} #{destination}" : "xcopy #{repository} \"#{destination}\" %%S%%I%%Y%%Q%%E"
7
+ end
8
+
9
+ alias_method :export, :checkout
10
+ end
@@ -0,0 +1,9 @@
1
+ module Locarails
2
+ module VERSION #:nodoc:
3
+ MAJOR = 1
4
+ MINOR = 2
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,43 @@
1
+ locarails_gemspec = Gem::Specification.new do |s|
2
+ s.name = "locarails"
3
+ s.version = Locarails::VERSION::STRING
4
+ s.homepage = "http://www.locaweb.com.br/rails"
5
+ s.summary = "Configuracao de Capistrano automatica para hospedagens Linux Locaweb."
6
+ s.authors = ["Fabio Akita"]
7
+ s.date = %q{Time.now.strftime("%Y/%d/%m")}
8
+ s.default_executable = "locarails"
9
+ s.description = "A maneira mais simples para instalar aplicacoes Rails na hospedagem Linux da Locaweb."
10
+ s.email = "fabio.akita@locaweb.com.br"
11
+ s.executables = ["locarails"]
12
+ s.files = Dir.glob("{bin,lib,templates,tasks}/**/*") + ['templates/.gitignore']
13
+ s.has_rdoc = true
14
+ s.require_paths = ["lib"]
15
+
16
+ s.add_runtime_dependency("capistrano", [">= 2.0.0"])
17
+ s.add_runtime_dependency("highline", [">= 0"])
18
+ s.add_runtime_dependency("archive-tar-minitar", [">= 0.5.2"])
19
+ end
20
+
21
+
22
+ Rake::GemPackageTask.new(locarails_gemspec) do |pkg|
23
+ pkg.gem_spec = locarails_gemspec
24
+ end
25
+
26
+ namespace :gem do
27
+ namespace :spec do
28
+ desc "Update locarails.gemspec"
29
+ task :generate do
30
+ File.open("locarails.gemspec", "w") do |f|
31
+ f.puts(locarails_gemspec.to_ruby)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ desc "Generate package and install"
38
+ task :install => :package do
39
+ sh %{sudo gem install --local pkg/locarails-#{Locarails::VERSION}}
40
+ end
41
+
42
+ desc "Remove all generated artifacts"
43
+ task :clean => :clobber_package
@@ -0,0 +1,22 @@
1
+ log/*.log
2
+ log/*.out
3
+ log/*.pid
4
+ tmp/**/*
5
+ .DS_Store
6
+ db/schema.rb
7
+ db/schema.sql
8
+ db/*.sqlite3*
9
+ config/database.yml
10
+ config/database.locaweb.yml
11
+ public/photos/*
12
+ public/upload/*
13
+ public/assets/*
14
+ .project
15
+ .#*
16
+ tmp/.*
17
+ \#*
18
+ *~
19
+ vendor/**/**/doc/*
20
+ rsa_key*
21
+ coverage/
22
+ coverage
@@ -0,0 +1,8 @@
1
+ production:
2
+ adapter: mysql
3
+ encoding: utf8
4
+ database: <%= mysqlcfg.db %>
5
+ username: <%= mysqlcfg.user %>
6
+ password: <%= mysqlcfg.pass %>
7
+ host: <%= mysqlcfg.host %>
8
+ pool: 5
@@ -0,0 +1,136 @@
1
+ # =============================================================================
2
+ # TAREFAS - NAO MEXER A MENOS QUE SAIBA O QUE ESTA FAZENDO
3
+ # =============================================================================
4
+ desc "Garante que o database.yml foi corretamente configurado"
5
+ task :before_symlink do
6
+ on_rollback {}
7
+ run "test -d #{release_path}/tmp || mkdir -m 755 #{release_path}/tmp"
8
+ run "test -d #{release_path}/db || mkdir -m 755 #{release_path}/db"
9
+ run "cp #{deploy_to}/etc/database.yml #{release_path}/config/database.yml"
10
+ run "cd #{release_path} && rake db:migrate RAILS_ENV=production"
11
+ end
12
+
13
+ desc "Garante que as configuracoes estao adequadas"
14
+ task :before_setup do
15
+ ts = Time.now.strftime("%y%m%d%H%M%S")
16
+ <% if config.mode == 'git' %>
17
+ # git folder
18
+ run "test -d #{git_repo} || mkdir -p -m 755 #{git_repo}"
19
+ run "test -d #{git_repo}/.git || cd #{git_repo} && git init"
20
+ git_config = File.join(File.dirname(__FILE__), "../.git/config")
21
+
22
+ has_git = false
23
+ if File.exists?(git_config)
24
+ `git remote rm #{remote_repo}` if File.read(git_config) =~ /\[remote\s+\"#{remote_repo}\"\]/
25
+ `git remote add #{remote_repo} #{repository}`
26
+ output = `git branch`.strip
27
+ `git checkout master && git checkout -b #{branch}` if output !~ /#{branch}/
28
+ `git checkout #{branch}` if output !~ /^\*\s+#{branch}/
29
+ `git push #{remote_repo} #{branch}`
30
+ has_git = true
31
+ end
32
+ <% end %>
33
+
34
+ run "test -d /home/#{user}/rails_app || mkdir -m 755 /home/#{user}/rails_app"
35
+ run "if [ -d #{deploy_to} ]; then mv #{deploy_to} #{deploy_to}-#{ts}.old ; fi"
36
+ run "test -d #{deploy_to} || mkdir -m 755 #{deploy_to}"
37
+ run "test -d #{deploy_to}/etc || mkdir -m 755 #{deploy_to}/etc"
38
+ run "if [ -d #{site_path} ]; then mv #{site_path} #{site_path}-#{ts}.old ; fi"
39
+ run "if [ -h #{site_path} ]; then mv #{site_path} #{site_path}-#{ts}.old ; fi"
40
+ run "ln -s #{deploy_to}/current/public #{public_html}/#{application}"
41
+ upload File.join(File.dirname(__FILE__), "database.locaweb.yml"), "#{deploy_to}/etc/database.yml"
42
+ upload File.join(File.dirname(__FILE__), "locaweb_backup.rb"), "#{deploy_to}/etc/locaweb_backup.rb"
43
+ upload File.join(File.dirname(__FILE__), "ssh_helper.rb"), "#{deploy_to}/etc/ssh_helper.rb"
44
+
45
+ <% if config.mode == 'git' %>
46
+ # ssh keygen
47
+ run "test -f ~/.ssh/id_rsa || ruby #{deploy_to}/etc/ssh_helper.rb /home/#{user}/.ssh/id_rsa #{domain} #{user}"
48
+
49
+ unless has_git
50
+ 2.times { puts "" }
51
+ puts "==============================================================="
52
+ puts "Rode os seguintes comandos depois de criar seu repositorio Git:"
53
+ puts ""
54
+ puts " git remote add #{remote_repo} #{repository}"
55
+ puts " git push #{remote_repo} #{branch}"
56
+ puts "==============================================================="
57
+ 2.times { puts "" }
58
+ end
59
+ <% end %>
60
+ end
61
+
62
+ desc "Prepare the production database before migration"
63
+ task :before_cold do
64
+ end
65
+
66
+ namespace :deploy do
67
+ desc "Pede restart ao servidor Passenger"
68
+ task :restart, :roles => :app do
69
+ run "chmod -R 755 #{release_path}"
70
+ run "touch #{deploy_to}/current/tmp/restart.txt"
71
+ end
72
+ end
73
+
74
+ [:start, :stop].each do |t|
75
+ desc "A tarefa #{t} nao eh necessaria num ambiente com Passenger"
76
+ task t, :roles => :app do ; end
77
+ end
78
+
79
+ namespace :log do
80
+ desc "tail production log files"
81
+ task :tail, :roles => :app do
82
+ run "tail -f #{shared_path}/log/production.log" do |channel, stream, data|
83
+ puts # para uma linha extra
84
+ puts "#{channel[:host]}: #{data}"
85
+ break if stream == :err
86
+ end
87
+ end
88
+ end
89
+
90
+ namespace :db do
91
+ desc "Faz o backup remoto e download do banco de dados MySQL"
92
+ task :backup, :roles => :db do
93
+ backup_rb ||= "#{deploy_to}/etc/locaweb_backup.rb"
94
+ run "if [ -f #{backup_rb} ]; then ruby #{backup_rb} backup #{deploy_to} ; fi"
95
+ get "#{deploy_to}/etc/dump.tar.gz", "dump.tar.gz"
96
+ run "rm #{deploy_to}/etc/dump.tar.gz"
97
+ end
98
+
99
+ desc "Faz o upload e o restore remoto do banco de dados MySQL"
100
+ task :restore, :roles => :db do
101
+ unless File.exists?("dump.tar.gz")
102
+ puts "Backup dump.tar.gz nao encontrado"
103
+ exit 0
104
+ end
105
+ backup_rb ||= "#{deploy_to}/etc/locaweb_backup.rb"
106
+ upload "dump.tar.gz", "#{deploy_to}/etc/dump.tar.gz"
107
+ run "if [ -f #{backup_rb} ]; then ruby #{backup_rb} restore #{deploy_to} ; fi"
108
+ end
109
+
110
+ desc "Apaga todas as tabelas do banco de dados [CUIDADO! OPERACAO SEM VOLTA!]"
111
+ task :drop_all, :roles => :db do
112
+ backup_rb ||= "#{deploy_to}/etc/locaweb_backup.rb"
113
+ run "if [ -f #{backup_rb} ]; then ruby #{backup_rb} drop_all #{deploy_to} ; fi"
114
+ end
115
+ end
116
+
117
+ namespace :ssh do
118
+ desc "Faz upload da sua chave publica"
119
+ task :upload_key, :roles => :app do
120
+ public_key_path = File.expand_path("~/.ssh/id_rsa.pub")
121
+ unless File.exists?(public_key_path)
122
+ puts %{
123
+ Chave publica nao encontrada em #{public_key_path}
124
+ Crie sua chave - sem passphrase - com o comando:
125
+ ssh_keygen -t rsa
126
+ }
127
+ exit 0
128
+ end
129
+ ssh_path = "/home/#{user}/.ssh"
130
+ run "test -d #{ssh_path} || mkdir -m 755 #{ssh_path}"
131
+ upload public_key_path, "#{ssh_path}/../id_rsa.pub"
132
+ run "test -f #{ssh_path}/authorized_keys || touch #{ssh_path}/authorized_keys"
133
+ run "cat #{ssh_path}/../id_rsa.pub >> #{ssh_path}/authorized_keys"
134
+ run "chmod 755 #{ssh_path}/authorized_keys"
135
+ end
136
+ end
@@ -0,0 +1,77 @@
1
+ # =============================================================================
2
+ # Receita de Capistrano 2.x para hospedagem compartilhada Linux
3
+ # utilizando estratégia de cópia sem servidor de versionamento
4
+ # =============================================================================
5
+ #
6
+ # 1. Esta receita é executada na sua maquina local e nao na hospedagem remota
7
+ #
8
+ # 2. O Locarails depende da gem Capistrano
9
+ #
10
+ # 3. A estrategia de deployment padrao eh Copy, que comprime seu projeto e envia
11
+ # para o servidor via SCP, e la eh descomprimido. Esta opcao funciona em
12
+ # qualquer sistema operacional sem mais nenhuma dependencia, incluindo
13
+ # Windows
14
+ #
15
+ # 4. A opcao -m git ativa a receita via Git que eh um repositorio descentralizado
16
+ # muito eficiente e que garante um deployment ainda mais rapido. Eh necessario
17
+ # que seu projeto local esteja em git e voce precisa do Git instalado na sua
18
+ # maquina
19
+ #
20
+ # 5. Ainda nao existe suporte a Subversion
21
+ #
22
+ #
23
+ # Autor: Fabio Akita
24
+ # E-mail: fabio.akita@locaweb.com.br
25
+ # Locaweb Serviços de Internet S/A
26
+ # Todos os direitos reservados
27
+
28
+ # correcao temporaria para capistrano 2.5.0
29
+ require 'locarails/fix'
30
+
31
+ # =============================================================================
32
+ # CONFIGURE OS VALORES DE ACORDO COM SUA HOSPEDAGEM
33
+ # =============================================================================
34
+ set :user, "<%= config.usuario %>"
35
+ set :domain, "<%= config.dominio %>"
36
+ set :application, "<%= config.app_name %>"
37
+ <% if config.mode == 'git' %>
38
+ set :repository, "<%= config.remote_git %>"
39
+ set :remote_repo, '<%= config.remote_repo %>'
40
+ set :branch, '<%= config.branch %>'
41
+ set :git_repo, "/home/#{user}/repo/#{application}.git"
42
+ <% else %>
43
+ set :repository, "<%= config.local_path %>"
44
+ <% end %>
45
+ <% if config.ssh_key_path %>
46
+ ssh_options[:keys] = File.expand_path("<%= config.ssh_key_path %>") # apenas descomente se tiver chave
47
+ <% end %>
48
+
49
+ # =============================================================================
50
+ # NAO MEXER DAQUI PARA BAIXO
51
+ # =============================================================================
52
+ role :web, domain
53
+ role :app, domain
54
+ role :db, domain
55
+
56
+ set :deploy_to, "/home/#{user}/rails_app/#{application}"
57
+ set :public_html, "/home/#{user}/public_html"
58
+ set :site_path, "#{public_html}/#{application}"
59
+ set :runner, nil
60
+ set :use_sudo, false
61
+ set :no_release, true
62
+
63
+ <% if config.mode == 'git' %>
64
+ set :scm, :git
65
+ set :deploy_via, :remote_cache
66
+ set :git_shallow_clone, 1
67
+ set :remote, user
68
+ set :scm_verbose, true
69
+ <% else %>
70
+ set :scm, :none
71
+ set :deploy_via, :copy
72
+ <% end %>
73
+ set :copy_exclude, %w(.git/* .svn/* log/* tmp/* .gitignore)
74
+ set :keep_releases, 5
75
+
76
+ ssh_options[:username] = user
77
+ ssh_options[:paranoid] = false
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby -wKU
2
+ require 'yaml'
3
+ require 'erb'
4
+
5
+ operation, deploy_to = ARGV
6
+ cfg = YAML::load(ERB.new(IO.read("#{deploy_to}/etc/database.yml")).result)
7
+ exit 0 unless cfg['production'] # sai se nao encontrar o arquivo de banco
8
+ prd = cfg['production']
9
+ mysql_opts = "-u #{prd['username']} -p#{prd['password']} -h #{prd['host']} #{prd['database']}"
10
+ mysql_opts_no_data = "-u #{prd['username']} -p#{prd['password']} -h #{prd['host']} --add-drop-table --no-data #{prd['database']}"
11
+
12
+ commands = []
13
+
14
+ case operation
15
+ when 'backup'
16
+ commands << "mysqldump #{mysql_opts} > #{deploy_to}/etc/dump.sql"
17
+ commands << "cd #{deploy_to}/etc && tar cvfz dump.tar.gz dump.sql"
18
+ commands << "rm #{deploy_to}/etc/dump.sql"
19
+ when 'restore'
20
+ commands << "cd #{deploy_to}/etc && if [ -f dump.tar.gz ]; then tar xvfz dump.tar.gz dump.sql ; fi"
21
+ commands << "if [ -f #{deploy_to}/etc/dump.sql ]; then mysql -u #{mysql_opts} < #{deploy_to}/etc/dump.sql && rm #{deploy_to}/etc/dump.sql ; fi"
22
+ when 'drop_all'
23
+ commands << "mysqldump #{mysql_opts_no_data} | grep ^DROP | mysql #{mysql_opts}"
24
+ end
25
+
26
+ commands.each do |cmd|
27
+ puts "executando: #{cmd.gsub(prd['password'], '*****')}"
28
+ `#{cmd}`
29
+ end
30
+ puts "operacao #{operation} finalizada."
@@ -0,0 +1,319 @@
1
+ require 'rubygems'
2
+ gem "net-ssh", ">= 1.1.3"
3
+ require 'base64'
4
+ require 'net/ssh'
5
+
6
+ #--
7
+ # =============================================================================
8
+ # Copyright (c) 2004,2005 Jamis Buck (jamis@37signals.com)
9
+ # All rights reserved.
10
+ #
11
+ # This source file is distributed as part of the Net::SSH Secure Shell Client
12
+ # library for Ruby. This file (and the library as a whole) may be used only as
13
+ # allowed by either the BSD license, or the Ruby license (or, by association
14
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
15
+ # distribution for the texts of these licenses.
16
+ # -----------------------------------------------------------------------------
17
+ # net-ssh website : http://net-ssh.rubyforge.org
18
+ # project website: http://rubyforge.org/projects/net-ssh
19
+ # =============================================================================
20
+ #++
21
+
22
+ module Net
23
+ module SSH
24
+
25
+ module Util
26
+
27
+ # The abstract ancestor module of both ReaderBufferImpl and
28
+ # WriterBufferImpl. It defines the common interface for both submodules.
29
+ module BufferBase
30
+
31
+ # exposes the content of the buffer
32
+ attr_reader :content
33
+
34
+ # the length of the buffer's content.
35
+ def length
36
+ @content.length
37
+ end
38
+
39
+ # returns a copy of the buffer's content.
40
+ def to_s
41
+ ( @content || "" ).dup
42
+ end
43
+
44
+ # Compares the contents of the two buffers.
45
+ def ==( buffer )
46
+ to_s == buffer.to_s
47
+ end
48
+
49
+ # Resets the buffer, making it empty.
50
+ def clear!
51
+ @content = ""
52
+ end
53
+
54
+ def init_BufferBase( content="" )
55
+ @content = content
56
+ end
57
+ private :init_BufferBase
58
+
59
+ end
60
+
61
+ # A convenience module for representing a string of encoded data. It
62
+ # provides an interface for easily reading and decoding the buffer.
63
+ module ReaderBufferImpl
64
+
65
+ # the current position of the pointer in the buffer
66
+ attr_reader :position
67
+
68
+ # used by derived modules and classes to perform any
69
+ # reader-buffer-specific initialization.
70
+ def init_ReaderBufferImpl
71
+ @position = 0
72
+ end
73
+ private :init_ReaderBufferImpl
74
+
75
+ # Appends the given text to the end of the buffer.
76
+ def append( text )
77
+ @content << text
78
+ end
79
+
80
+ # Returns all text from the current pointer to the end of the buffer as
81
+ # a new buffer as the same class as the receiver.
82
+ def remainder_as_buffer
83
+ self.class.new( @content[ @position..-1 ] )
84
+ end
85
+
86
+ # Reads +count+ bytes from the buffer. If +count+ is +nil+, this will
87
+ # return all remaining text in the buffer. This method will increment
88
+ # the pointer.
89
+ def read( count = nil )
90
+ count = length - @position unless count
91
+ return nil if @position + count > length
92
+
93
+ @position += count
94
+ @content[ @position-count, count ]
95
+ end
96
+
97
+ # Return the next 8 bytes as a 64-bit integer (in network byte order).
98
+ def read_int64
99
+ hi = read_long
100
+ lo = read_long
101
+ return ( hi << 32 ) + lo
102
+ end
103
+
104
+ # Return the next four bytes as a long integer (in network byte order).
105
+ def read_long
106
+ b = read( 4 ) or return nil
107
+ b.unpack( "N" ).first
108
+ end
109
+
110
+ # Read the next two bytes as a short integer (in network byte order).
111
+ def read_short
112
+ b = read( 2 ) or return nil
113
+ b.unpack( "n" ).first
114
+ end
115
+
116
+ # Read and return the next byte in the buffer.
117
+ def read_byte
118
+ b = read( 1 ) or return nil
119
+ b[0]
120
+ end
121
+
122
+ # Read and return an SSH2-encoded string. The string starts with a long
123
+ # integer that describes the number of bytes remaining in the string.
124
+ def read_string
125
+ length = read_long or return nil
126
+ read( length )
127
+ end
128
+
129
+ # Read a single byte and convert it into a boolean, using 'C' rules
130
+ # (i.e., zero is false, non-zero is true).
131
+ def read_bool
132
+ b = read( 1 ) or return nil
133
+ b[0] != 0
134
+ end
135
+
136
+ # Resets the pointer to the start of the buffer.
137
+ def reset!
138
+ @position = 0
139
+ end
140
+
141
+ # Returns true if the pointer is at the end of the buffer.
142
+ def eof?
143
+ @position >= length
144
+ end
145
+
146
+ # Resets the buffer, making it empty.
147
+ def clear!
148
+ @content = ""
149
+ @position = 0
150
+ end
151
+
152
+ end # ReaderBufferImpl
153
+
154
+ # A convenience module for writing a string of encoded data. It provides
155
+ # an interface for easily writing and encoding data.
156
+ module WriterBufferImpl
157
+
158
+ def init_WriterBufferImpl
159
+ # nothing
160
+ end
161
+ private :init_WriterBufferImpl
162
+
163
+ # Writes the given data literally into the string.
164
+ def write( *data )
165
+ @content << data.join
166
+ end
167
+
168
+ # Writes each argument to the buffer as a network-byte-order-encoded
169
+ # 64-bit integer (8 bytes).
170
+ def write_int64( *n )
171
+ n.each do |i|
172
+ hi = ( i >> 32 ) & 0xFFFFFFFF
173
+ lo = i & 0xFFFFFFFF
174
+ @content << [ hi, lo ].pack( "N2" )
175
+ end
176
+ end
177
+
178
+ # Writes each argument to the buffer as a network-byte-order-encoded
179
+ # long (4-byte) integer.
180
+ def write_long( *n )
181
+ @content << n.pack( "N*" )
182
+ end
183
+
184
+ # Writes each argument to the buffer as a network-byte-order-encoded
185
+ # short (2-byte) integer.
186
+ def write_short( *n )
187
+ @content << n.pack( "n*" )
188
+ end
189
+
190
+ # Writes each argument to the buffer as a byte.
191
+ def write_byte( *n )
192
+ @content << n.map { |c| c.chr }.join
193
+ end
194
+
195
+ # Writes each argument to the buffer as an SSH2-encoded string. Each
196
+ # string is prefixed by its length, encoded as a 4-byte long integer.
197
+ def write_string( *text )
198
+ text.each do |string|
199
+ write_long( string.length )
200
+ write( string )
201
+ end
202
+ end
203
+
204
+ # Writes each argument to the buffer as a (C-style) boolean, with 1
205
+ # meaning true, and 0 meaning false.
206
+ def write_bool( *b )
207
+ @content << b.map { |v| ( v ? 1 : 0 ).chr }.join
208
+ end
209
+
210
+ # Writes each argument to the buffer as a bignum (SSH2-style). No
211
+ # checking is done to ensure that the arguments are, in fact, bignums.
212
+ def write_bignum( *n )
213
+ @content << n.map { |b| b.to_ssh }.join
214
+ end
215
+
216
+ # Writes the given arguments to the buffer as SSH2-encoded keys.
217
+ def write_key( *key )
218
+ key.each do |k|
219
+ write_string( k.ssh_type )
220
+
221
+ case k.ssh_type
222
+ when "ssh-dss"
223
+ write_bignum( k.p )
224
+ write_bignum( k.q )
225
+ write_bignum( k.g )
226
+ write_bignum( k.pub_key )
227
+
228
+ when "ssh-rsa"
229
+ write_bignum( k.e )
230
+ write_bignum( k.n )
231
+
232
+ else
233
+ raise NotImplementedError,
234
+ "unsupported key type '#{k.ssh_type}'"
235
+ end
236
+ end
237
+ end
238
+
239
+ end # class WriterBufferImpl
240
+
241
+ # A convenience class for a read-only buffer.
242
+ class ReaderBuffer
243
+ include BufferBase
244
+ include ReaderBufferImpl
245
+
246
+ def initialize( content )
247
+ init_BufferBase( content )
248
+ init_ReaderBufferImpl
249
+ end
250
+ end
251
+
252
+ # A convenience class for a write-only buffer.
253
+ class WriterBuffer
254
+ include BufferBase
255
+ include WriterBufferImpl
256
+
257
+ def initialize( content="" )
258
+ init_BufferBase( content )
259
+ init_WriterBufferImpl
260
+ end
261
+ end
262
+
263
+ # A convenience class for a read/write buffer.
264
+ class Buffer
265
+ include BufferBase
266
+ include ReaderBufferImpl
267
+ include WriterBufferImpl
268
+
269
+ def initialize( content="" )
270
+ init_BufferBase( content )
271
+ init_ReaderBufferImpl
272
+ init_WriterBufferImpl
273
+ end
274
+ end
275
+
276
+ end # module Util
277
+
278
+ end # module SSH
279
+ end # module Net
280
+
281
+ class SSHHelper
282
+ def self.generate_keys(filename)
283
+ authorized_file = "#{File.dirname(filename)}/authorized_keys"
284
+
285
+ private_key = OpenSSL::PKey::RSA.new(2048)
286
+ public_pem = export_ssh_pubkey( private_key )
287
+
288
+ File.delete( filename ) if File.exists?( filename )
289
+ File.open( filename, "w" ) { |file| file.write private_key.export }
290
+ File.delete( "#{filename}.pub" ) if File.exists?("#{filename}.pub")
291
+ File.open( "#{filename}.pub", "w" ) { |file| file.write public_pem }
292
+ File.open( authorized_file, 'w') { |file| file.write public_pem + "\n"}
293
+
294
+ FileUtils.chmod 0755, authorized_file
295
+ FileUtils.chmod 0600, filename
296
+ end
297
+
298
+ def self.test_connection(hostname, username)
299
+ # will create known_host
300
+ Net::SSH.start(hostname, username) { |ssh| puts ssh.exec!('hostname') }
301
+ end
302
+
303
+ private
304
+ def self.export_ssh_pubkey( key )
305
+ s = key.ssh_type + " "
306
+
307
+ writer = Net::SSH::Util::WriterBuffer.new
308
+ writer.write_key key
309
+ s << Base64.encode64( writer.to_s ).strip.gsub( /[\n\r\t ]/, "" )
310
+ s << " #{ENV['USER']}@#{ENV['HOSTNAME']}"
311
+
312
+ s
313
+ end
314
+ end
315
+
316
+ if ARGV && ARGV.size == 3
317
+ SSHHelper.generate_keys(ARGV[0])
318
+ SSHHelper.test_connection(ARGV[1], ARGV[2])
319
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: locarails
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Fabio Akita
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-22 00:00:00 -03:00
13
+ default_executable: locarails
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: capistrano
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.0.0
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: highline
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: archive-tar-minitar
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.5.2
44
+ version:
45
+ description: A maneira mais simples para instalar aplicacoes Rails na hospedagem Linux da Locaweb.
46
+ email: fabio.akita@locaweb.com.br
47
+ executables:
48
+ - locarails
49
+ extensions: []
50
+
51
+ extra_rdoc_files: []
52
+
53
+ files:
54
+ - bin/locarails
55
+ - bin/locarails.cmd
56
+ - lib/locarails/base.rb
57
+ - lib/locarails/copy.rb
58
+ - lib/locarails/fix.rb
59
+ - lib/locarails/git.rb
60
+ - lib/locarails/none.rb
61
+ - lib/locarails/version.rb
62
+ - lib/locarails.rb
63
+ - templates/database.locaweb.yml.erb
64
+ - templates/deploy.common.rb.erb
65
+ - templates/deploy.rb.erb
66
+ - templates/locaweb_backup.rb
67
+ - templates/ssh_helper.rb
68
+ - tasks/gems.rake
69
+ - templates/.gitignore
70
+ has_rdoc: true
71
+ homepage: http://www.locaweb.com.br/rails
72
+ licenses: []
73
+
74
+ post_install_message:
75
+ rdoc_options: []
76
+
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: "0"
84
+ version:
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "0"
90
+ version:
91
+ requirements: []
92
+
93
+ rubyforge_project:
94
+ rubygems_version: 1.3.5
95
+ signing_key:
96
+ specification_version: 3
97
+ summary: Configuracao de Capistrano automatica para hospedagens Linux Locaweb.
98
+ test_files: []
99
+