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.repository = repository self.application = application = options[:application] || self.application || File.basename(parse_repository_uri(repository).path.split('/').last,".git") self.deploy_to = deploy_to = options[:deploy_to] || self.deploy_to || "/u/apps/#{application}" self.shared_path = shared_path = File.join(deploy_to, 'shared') self.shared_repository = shared_repository = File.join(shared_path, "#{application}.git") self.release_name = release_name = Time.now.utc.strftime("%Y%m%d%H%M%S") self.releases_path = releases_path = File.join(deploy_to, 'releases') self.release_path = release_path = File.join(releases_path, release_name) self.env = options[:env] || self.env self.rakefile = options[:rakefile] || self.rakefile self.current_path = 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. def share(path, options = {}) symlink "#{shared_path}/#{path}", options.merge(:to => "#{release_path}/#{path}") end protected 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 GIT_REGEXP = %r'^(?:(\w+)@)?((?:\w+.)*\w+):([/~]?[^/].+)$' if uri =~ GIT_REGEXP URI::Generic.new(nil, $1, $2, nil, nil, $3, nil, nil, nil) else URI.parse(uri) end end end end