Never been to TextSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

« Newer Snippets
Older Snippets »
3 total  XML / RSS feed 

sftp capistrano deployment strategy

// capistrano deployment strategy used when you have sftp access only (no ssh access)

require 'capistrano/recipes/deploy/strategy/base'
require 'fileutils'
require 'tempfile'  # Dir.tmpdir

require 'net/ssh'
require 'net/sftp'
require 'find'

module Capistrano
  module Deploy
    module Strategy

                        # Special Strategy for a special price!
                        # This strategy is created in favor of the sftp only apps, in lack of ssh login support
                        # 
                        # * exports the repository to a local directory
                        # * uploads all the files to the remote server using an sftp script
                        # * renames current directory to a directory with a timestamp of 1 hour ago
                        # * renames the uploaded directory to current
      class SftpCopy < Base
        def deploy!
          logger.debug "getting (via #{copy_strategy}) revision #{revision} to #{destination}"
          system(command)
          File.open(File.join(destination, "REVISION"), "w") { |f| f.puts(revision) }

                                        logger.debug "Connecting to sftp user = #{configuration[:user]}"

                                        Net::SSH.start(configuration[:host], configuration[:user], configuration[:password]) do |ssh|
                                                ssh.sftp.connect do |sftp|
                                                        logger.debug "Creating directory: #{remote_dir}"
                                                        sftp.mkdir remote_dir, :permissions => 0755
                                                        
                                                        logger.debug "Uploading files from #{destination} to #{remote_dir}"
                                                        logger.debug "Why don't you grab a cup of coffee while you wait, i might be busy for some time...\nJust sit back and enjoy the show..."
                                                        Find.find(destination) do |file|
                                                                if File.stat(file).directory?
                                                                        
                                                                        remote_directory = remote_dir + file.sub(destination, '')
                                                                        begin
                                                                                sftp.stat(remote_directory)
                                                                        rescue Net::SFTP::Operations::StatusException => e
                                                                                raise "BOEM" unless e.code == 2
                                                                                sftp.mkdir(remote_directory, :permissions => 0755)
                                                                        end
                                                                else
                                                                        remote_file = remote_dir + file.sub(destination, '')
                                                                        sftp.put_file file, remote_file
                                                                        sftp.setstat(remote_file, :permissions => 0644)
                                                                end
                                                        end
                                                        
                                                        logger.debug "RENAMING DIRECTORIES"
                                                        sftp.rename "#{configuration[:copy_remote_dir]}/current", "#{configuration[:copy_remote_dir]}/#{(Time.now - 1.hour).utc.strftime("%Y%m%d%H%M%S")}"
                                                        sftp.rename "#{remote_dir}", "#{configuration[:copy_remote_dir]}/current"
                                                end
                                        end
        ensure
                                        logger.debug "Remove local export"
          FileUtils.rm_rf destination rescue nil
        end

        def check!
          super.check do |d|
          end
        end

        private

          # Returns the basename of the release_path, which will be used to
          # name the local copy and archive file.
          def destination
            @destination ||= File.join(tmpdir, File.basename(configuration[:release_path]))
          end

          # Returns the value of the :copy_strategy variable, defaulting to
          # :checkout if it has not been set.
          def copy_strategy
            @copy_strategy ||= configuration.fetch(:copy_strategy, :checkout)
          end

          # Should return the command(s) necessary to obtain the source code
          # locally.
          def command
            @command ||= case copy_strategy
            when :checkout
              source.checkout(revision, destination)
            when :export
              source.export(revision, destination)
            end
          end

          # Returns the name of the file that the source code will be
          # compressed to.
          def filename
            @filename ||= File.join(tmpdir, "#{File.basename(destination)}.#{compression_extension}")
          end

          # The directory to which the copy should be checked out
          def tmpdir
            @tmpdir ||= configuration[:copy_dir] || Dir.tmpdir
          end

          # The directory on the remote server to which the archive should be
          # copied
          def remote_dir
            @remote_dir ||= "#{configuration[:copy_remote_dir]}/#{File.basename(configuration[:release_path])}" || "/tmp"
          end
      end

    end
  end
end

Capistrano SFTP recipe

// webistrano recipe used to deploy with sftp access only

desc "Setup the rail environment"
namespace :deploy do
    task :setup do

    end

  task :default do
     update_code
     restart
  end

  task :update_code, :except => { :no_release => true } do
    on_rollback { run "rm -rf #{release_path}; true" }
    strategy.deploy!
  end

  task :symlink, :except => { :no_release => true } do

  end

  task :restart, :roles => :app do
     Net::SSH.start(host, user, password) do |ssh|
        ssh.sftp.connect do |sftp|
            sftp.remove("#{restart_file}")
        end
     end
  end
end


Solaris Capistrano deploy.rb

// capiwhatisit recipe for solaris
// most important thing is overriding some tasks to use GNU ln, since solaris' ln are subtly different

set :application, "awesomeapp"
set :repository, "http://example.com/repos/#{application}/trunk"

role :web, "foo.com"
role :app, "bar.com"
role :db,  "baz.com", :primary => true

set :deploy_to, "/path/to/app"
set :user, "appuser"
set :svn, "/opt/csw/bin/svn"
set :rake, "/opt/csw/bin/rake"
set :mongrel_config, "#{deploy_to}/shared/config/mongrel_cluster.yml"

set :use_sudo, false

desc "The spinner task is used by :cold_deploy to start the application up"
task :spinner, :roles => [:web, :app, :node] do
  run "/opt/csw/bin/mongrel_rails cluster::start -C #{mongrel_config}" # or SMF
end

desc "Restart the Mongrel processes on the app server."
task :restart, :roles => [:web, :app, :node] do
  run "/opt/csw/bin/mongrel_rails cluster::restart -C #{mongrel_config}" # or SMF
end

desc "Symlinks the database.yml into the current release"
task :after_update_code, :roles => [:web, :app, :node] do
    run "/opt/csw/bin/gln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
end

# Run rake migrate after the symlinking has been done, just because I'm a lazy bum
task :after_symlink, :roles => :db do
  backup
  migrate
end

# =====================================================================================
# = Overriding these tasks because we need to use GNU ln and need the full path to it =

desc <<-DESC
Update the 'current' symlink to point to the latest version of
the application's code. Using GNU ln
DESC
task :symlink, :roles => [:app, :db, :web, :node] do
  on_rollback { run "/opt/csw/bin/gln -nfs #{previous_release} #{current_path}" }
  run "/opt/csw/bin/gln -nfs #{current_release} #{current_path}"
end

desc <<-DESC
Rollback the latest checked-out version to the previous one by fixing the
symlinks and deleting the current release from all servers.
DESC
task :rollback_code, :roles => [:app, :db, :web] do
  if releases.length < 2
    raise "could not rollback the code because there is no prior release"
  else
    run <<-CMD
      /opt/csw/bin/gln -nfs #{previous_release} #{current_path} &&
      rm -rf #{current_release}
    CMD
  end
end



« Newer Snippets
Older Snippets »
3 total  XML / RSS feed