Skip to content

Commit

Permalink
Add archive source fetching strategy
Browse files Browse the repository at this point in the history
- grab file and unzip in source cache dir
- accept flags for git and archive for uri
- shasum written to `REVISION`
- add basic vagrant box for testing
  • Loading branch information
jhsu authored and martinemde committed Aug 2, 2013
1 parent 295d87c commit 6bee2ef
Show file tree
Hide file tree
Showing 24 changed files with 551 additions and 165 deletions.
1 change: 1 addition & 0 deletions ChangeLog.md
Expand Up @@ -3,6 +3,7 @@
## NEXT

* Abort rollbacks if unexpected files are found in the /data/app/releases/ directory because they disrupt the ability to find the previous and latest releases.
* Accepts flags for git and archive strategies (`--git` and `--archive`) that are passed a uri

## v2.2.1 (2013-07-29)

Expand Down
10 changes: 10 additions & 0 deletions Vagrantfile
@@ -0,0 +1,10 @@
Vagrant.configure("2") do |config|
config.vm.box = "opscode-ubuntu-12.04"
config.vm.box_url = "https://opscode-vm.s3.amazonaws.com/vagrant/opscode_ubuntu-12.04_provisionerless.box"

config.ssh.max_tries = 15
config.ssh.timeout = 120

config.vm.provision :shell, :path => "bootstrap.sh"
config.vm.define "boxi"
end
6 changes: 6 additions & 0 deletions bootstrap.sh
@@ -0,0 +1,6 @@
#!/usr/bin/env bash

apt-get update
apt-get install -y ruby1.9.3 unzip curl

mkdir -p /data/serverside && chown vagrant:vagrant /data/serverside
13 changes: 13 additions & 0 deletions deploy.sh
@@ -0,0 +1,13 @@
#!/usr/bin/env bash

engineyard-serverside deploy --verbose \
--account-name serverside-testing \
--app serverside \
--config '{"deployed_by":"The Mothership"}' \
--environment-name production \
--framework-env production \
--instances localhost \
--instance-roles localhost:solo \
--archive https://github.com/engineyard/todo/archive/master.zip
# --ref master \
# --git https://github.com/engineyard/todo.git
3 changes: 3 additions & 0 deletions install.sh
@@ -0,0 +1,3 @@
#!/usr/bin/env bash

rm *.gem && gem build engineyard-serverside.gemspec && sudo gem install *.gem
7 changes: 6 additions & 1 deletion lib/engineyard-serverside.rb
Expand Up @@ -19,10 +19,15 @@

require 'escape'
require 'multi_json'
require 'uri'

require 'engineyard-serverside/version'
require 'engineyard-serverside/about'
require 'engineyard-serverside/strategies/git'

require 'engineyard-serverside/strategy'
require 'engineyard-serverside/strategy/git'
require 'engineyard-serverside/strategy/archive'

require 'engineyard-serverside/task'
require 'engineyard-serverside/server'
require 'engineyard-serverside/deploy'
Expand Down
11 changes: 11 additions & 0 deletions lib/engineyard-serverside/cli.rb
Expand Up @@ -23,6 +23,17 @@ class CLI < Thor
method_option :repo, :type => :string,
:desc => "Remote repo to deploy",
:aliases => ["-r"]


# Archive strategy
method_option :archive, :type => :string,
:desc => "Remote URI for archive to download and unzip"

# Git strategy
method_option :git, :type => :string,
:desc => "Remote git repo to deploy"


account_app_env_options
config_option
framework_env_option
Expand Down
27 changes: 25 additions & 2 deletions lib/engineyard-serverside/configuration.rb
Expand Up @@ -55,6 +55,8 @@ def self.def_required_option(name, key=nil)
def_required_option :instance_roles
def_required_option :instance_names

def_option :git, nil
def_option :archive, nil
def_option :repo, nil
def_option :migrate, nil
def_option :precompile_assets, 'detect'
Expand Down Expand Up @@ -180,8 +182,29 @@ def node
EY::Serverside.node
end

def strategy_class
EY::Serverside::Strategies.const_get(strategy)
# Infer the deploy strategy to use based on flag or
# default to specified strategy.
#
# Returns a strategy object.
def source_cache_strategy(shell)
if git
load_strategy(EY::Serverside::Strategy::Git, shell, git)
elsif archive
load_strategy(EY::Serverside::Strategy::Archive, shell, archive)
else # repo is allowed to be nil
load_strategy(EY::Serverside::Strategy.for(strategy), shell, repo)
end
end

def load_strategy(klass, shell, uri)
klass.new(
shell,
:verbose => verbose,
:repository_cache => paths.repository_cache,
:app => app,
:uri => uri,
:ref => branch
)
end

def paths
Expand Down
32 changes: 16 additions & 16 deletions lib/engineyard-serverside/deploy.rb
Expand Up @@ -66,13 +66,17 @@ def gc_repository_cache
end

def create_revision_file_command
strategy.create_revision_file_command(paths.active_release)
strategy.create_revision_file_command(paths.active_revision)
end

def short_log_message(revision)
strategy.short_log_message(revision)
end

def unchanged_diff_between_revisions?(previous_revision, active_revision, asset_dependencies)
strategy.same?(previous_revision, active_revision, asset_dependencies)
end

def check_repository
check_dependencies
end
Expand Down Expand Up @@ -204,10 +208,14 @@ def abort_on_bad_paths_in_release_directory
def rollback
if config.rollback_paths!
begin
shell.status "Rolling back to previous release: #{short_log_message(config.active_revision)}"
abort_on_bad_paths_in_release_directory
rolled_back_release = paths.latest_release

if config.active_revision.exist?
revision = config.active_revision.read
shell.status "Rolling back to previous release: #{short_log_message(revision)}"
else
shell.status "Rolling back to previous release."
end
abort_on_bad_paths_in_release_directory
run_with_callbacks(:symlink)
sudo "rm -rf #{rolled_back_release}"
bundle
Expand Down Expand Up @@ -378,25 +386,17 @@ def callback(what)
end
end

protected

# Use [] to access attributes instead of calling methods so
# that we get nils instead of NoMethodError.
#
# Rollback doesn't know about the repository location (nor
# should it need to), but it would like to use #short_log_message.
def strategy
ensure_git_ssh_wrapper
@strategy ||= config.strategy_class.new(
shell,
:verbose => config.verbose,
:repository_cache => paths.repository_cache.to_s,
:app => config.app,
:repo => config[:repo],
:ref => config[:branch]
)
end
public :strategy
@strategy ||= config.source_cache_strategy(shell)
end

protected

def base_callback_command_for(what)
cmd = [About.binary, 'hook', what.to_s]
Expand Down
3 changes: 3 additions & 0 deletions lib/engineyard-serverside/deprecation.rb
Expand Up @@ -20,6 +20,9 @@ def self.const_missing(const)
when :LockfileParser
EY::Serverside.deprecation_warning("EY::Serverside::LockfileParser has been deprecated. Use EY::Serverside::DependencyManager::Bundler::Lockfile instead.")
EY::Serverside::DependencyManager::Bundler::Lockfile
when :Strategies
EY::Serverside.deprecation_warning("EY::Serverside::Strategies has been deprecated. Use EY::Serverside::Strategy instead.")
EY::Serverside::Strategy
else
super
end
Expand Down
2 changes: 1 addition & 1 deletion lib/engineyard-serverside/rails_assets.rb
Expand Up @@ -75,7 +75,7 @@ def reuse_assets?
asset_strategy.reusable? &&
previous_revision &&
active_revision &&
runner.strategy.same?(previous_revision, active_revision, asset_dependencies)
runner.unchanged_diff_between_revisions?(previous_revision, active_revision, asset_dependencies)
end

def precompile_detected_assets
Expand Down
104 changes: 0 additions & 104 deletions lib/engineyard-serverside/strategies/git.rb

This file was deleted.

76 changes: 76 additions & 0 deletions lib/engineyard-serverside/strategy.rb
@@ -0,0 +1,76 @@
require 'pathname'
require 'engineyard-serverside/spawner'

class EY::Serverside::Strategy
attr_reader :uri, :opts, :source_cache, :ref, :shell
alias repository_cache source_cache

class << self
attr_reader :required_opts
def require_opts(*names)
@required_opts ||= []
@required_opts += names
end

def for(type)
const_get(type)
end
end

def initialize(shell, opts={})
@shell = shell
@opts = opts

if self.class.required_opts && !self.class.required_opts.all? {|name| @opts[name] }
raise ArgumentError,
"Missing required key(s) (#{self.class.required_opts.join(', ')} required)"
end

@ref = @opts[:ref]
@uri = @opts[:uri].to_s if @opts[:uri]
@source_cache = Pathname.new(@opts[:repository_cache]) if @opts[:repository_cache]
end

protected

def in_source_cache(&block)
raise ArgumentError, "Block required" unless block
source_cache.mkpath
Dir.chdir(source_cache, &block)
end

def escape(*shell_commands)
Escape.shell_command(shell_commands)
end

def runner
EY::Serverside::Spawner
end

# Internal: Run a command.
#
# cmd - A string command.
#
# Returns an instance of Spawner.
def run(cmd)
runner.run(cmd, shell, nil)
end

# Internal: Run a command and return the output.
#
# cmd - A string command.
#
# Returns the output of the command.
def run_and_output(cmd)
run(cmd).output
end

# Internal: Run a command and check if it was successful.
#
# cmd - A string command.
#
# Returns success.
def run_and_success?(cmd)
run(cmd).success?
end
end

0 comments on commit 6bee2ef

Please sign in to comment.