require 'uri' module Astrovan module Deploy # Deploy an application to the remote servers. # # Options: # * +application+ - a name for the application. If not provided, the application name is taken from the last component of the path to the source repository. # * +deploy_to+ - the path of the directory for application deployment. Defaults to '/u/apps/:application' # # If a block is provided, the block is run to deploy the application in the specified environment. # # If no block is provided, a default deployment recipe is applied. The default recipe is: # * create the deployment, release and shared directories # * update the application from the repository into the release directory # * symlink to the current application # # Due to differences in application environments, no provision is made to restart the application in the default # recipe. def deploy(repository, options = {}) original_environment = self.environment.dup self.environment.merge!(options) self.repository = repository self.application ||= File.basename(parse_repository_uri(repository).path.split('/').last,".git") self.deploy_to ||= "/u/apps/#{application}" self.shared_path = File.join(deploy_to, 'shared') self.shared_repository = File.join(shared_path, "#{application}.git") self.release_name = Time.now.utc.strftime("%Y%m%d%H%M%S") self.releases_path = File.join(deploy_to, 'releases') self.release_path = File.join(releases_path, release_name) self.current_path = File.join(deploy_to, 'current') if block_given? yield else mkdir deploy_to, releases_path, shared_path, options update options end rescue => e # TODO: rollback # rollback raise ensure self.environment.replace original_environment end # Create a symlink from a file or directory in the shared folder into the current release. # # Options: # * +shared_path+ - specify the parent directory of the file or directory to be shared # * +release_path+ - specify the parent directory to contain the shared file or directory def share(path, options = {}) shared_path = options[:shared_path] || self.shared_path release_path = options[:release_path] || self.release_path symlink "#{shared_path}/#{path}", options.merge(:to => "#{release_path}/#{path}") end private #:stopdoc: GIT_URI_REGEXP = %r'^(?:(\w+)@)?((?:\w+.)*\w+):([/~]?[^/].+)$' #:startdoc: def parse_repository_uri(uri) # [user@]host.xz:/path/to/repo.git/ # [user@]host.xz:~user/path/to/repo.git/ # [user@]host.xz:path/to/repo.git if uri =~ GIT_URI_REGEXP URI::Generic.new(nil, $1, $2, nil, nil, $3, nil, nil, nil) else URI.parse(uri) end end end end