ey-deploy 0.2.4.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +66 -0
  3. data/Rakefile +63 -0
  4. data/TODO +4 -0
  5. data/bin/eysd +10 -0
  6. data/lib/ey-deploy.rb +16 -0
  7. data/lib/ey-deploy/cli.rb +58 -0
  8. data/lib/ey-deploy/compatibility.rb +24 -0
  9. data/lib/ey-deploy/configuration.rb +111 -0
  10. data/lib/ey-deploy/deploy.rb +158 -0
  11. data/lib/ey-deploy/server.rb +84 -0
  12. data/lib/ey-deploy/strategies/git.rb +43 -0
  13. data/lib/ey-deploy/task.rb +42 -0
  14. data/lib/ey-deploy/version.rb +3 -0
  15. data/lib/vendor/thor/CHANGELOG.rdoc +89 -0
  16. data/lib/vendor/thor/LICENSE +20 -0
  17. data/lib/vendor/thor/README.rdoc +297 -0
  18. data/lib/vendor/thor/Thorfile +69 -0
  19. data/lib/vendor/thor/bin/rake2thor +86 -0
  20. data/lib/vendor/thor/bin/thor +6 -0
  21. data/lib/vendor/thor/lib/thor.rb +244 -0
  22. data/lib/vendor/thor/lib/thor/actions.rb +275 -0
  23. data/lib/vendor/thor/lib/thor/actions/create_file.rb +103 -0
  24. data/lib/vendor/thor/lib/thor/actions/directory.rb +91 -0
  25. data/lib/vendor/thor/lib/thor/actions/empty_directory.rb +134 -0
  26. data/lib/vendor/thor/lib/thor/actions/file_manipulation.rb +223 -0
  27. data/lib/vendor/thor/lib/thor/actions/inject_into_file.rb +104 -0
  28. data/lib/vendor/thor/lib/thor/base.rb +540 -0
  29. data/lib/vendor/thor/lib/thor/core_ext/file_binary_read.rb +9 -0
  30. data/lib/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  31. data/lib/vendor/thor/lib/thor/core_ext/ordered_hash.rb +100 -0
  32. data/lib/vendor/thor/lib/thor/error.rb +30 -0
  33. data/lib/vendor/thor/lib/thor/group.rb +271 -0
  34. data/lib/vendor/thor/lib/thor/invocation.rb +180 -0
  35. data/lib/vendor/thor/lib/thor/parser.rb +4 -0
  36. data/lib/vendor/thor/lib/thor/parser/argument.rb +67 -0
  37. data/lib/vendor/thor/lib/thor/parser/arguments.rb +150 -0
  38. data/lib/vendor/thor/lib/thor/parser/option.rb +128 -0
  39. data/lib/vendor/thor/lib/thor/parser/options.rb +169 -0
  40. data/lib/vendor/thor/lib/thor/rake_compat.rb +66 -0
  41. data/lib/vendor/thor/lib/thor/runner.rb +314 -0
  42. data/lib/vendor/thor/lib/thor/shell.rb +83 -0
  43. data/lib/vendor/thor/lib/thor/shell/basic.rb +239 -0
  44. data/lib/vendor/thor/lib/thor/shell/color.rb +108 -0
  45. data/lib/vendor/thor/lib/thor/task.rb +102 -0
  46. data/lib/vendor/thor/lib/thor/util.rb +230 -0
  47. data/lib/vendor/thor/lib/thor/version.rb +3 -0
  48. data/lib/vendor/thor/thor.gemspec +120 -0
  49. data/spec/ey-deploy_spec.rb +7 -0
  50. data/spec/spec_helper.rb +4 -0
  51. metadata +114 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Engine Yard, Inc
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,66 @@
1
+ == ey-deploy
2
+
3
+ We've been listening to your feedback here on the Engine Yard Cloud and we've heard that the current web deploy is not optimal. People like to see the deploy steps as they happen. not wait until the end to go through the logs to see what went wrong. It is also clear that running the full set of chef recipes every time you deploy is doing a lot of redundant work and taking a lot of time each deploy. So I say down and came up with a new deployment strategy that meets these needs and makes deploying to our cloud a much nicer experience. So today I am releasing a beta of our new git deployment strategy for you to use. This new system is 100% backwards and forwards compatible with the current web deploy. If you have a server already deployed you can start using this new system right on top of it with a few minutes of setup.
4
+
5
+ So here is the steps needed to get a new git push based deploy up and running on your cloud system. Let's assume that you have an environment called 'production' with an ip address of 123.123.123.123 and a unix user called 'deploy' with an application attached called 'railsapp'. In the instructions below please replace these items with the correct info for your own setup.
6
+
7
+
8
+ Once you have a server fully up and running, follow these steps:
9
+
10
+ 1. SSH into each of the servers in your cluster, or just the single server if you have only one and run the following commands:
11
+ $ sudo gem install ey-deploy --source http://gems.engineyard.com
12
+ Successfully installed ey-deploy-0.0.7
13
+ 1 gem installed
14
+ $ sudo ey-deploy-install
15
+ engineyard git hooks installed
16
+
17
+ Now back on your local machine,
18
+
19
+ cd railsapp
20
+ git remote add production deploy@123.123.123.123:/data/railsapp/shared/cached-copy
21
+
22
+ # NOTE make sure to replace 'deploy' with the username you created for this env
23
+ # NOTE also make sure to change the ip address to the address of your app master
24
+ # NOTE also make sure to replace 'railsapp' in the path with the name of your own application
25
+
26
+ If you have only one server then you can go ahead and deploy new code like this:
27
+ $ git commit -m "made some changes"
28
+ $ git push production master
29
+
30
+ If you have a cluster of servers you need to setup an ssh keypair named 'internal' for them to use to talk to each other.
31
+
32
+ $ cd ~/.ssh
33
+ $ ssh-keygen -t rsa
34
+ Generating public/private rsa key pair.
35
+ Enter file in which to save the key (/Users/ez/.ssh/id_rsa): internal
36
+ Enter passphrase (empty for no passphrase):
37
+ Enter same passphrase again:
38
+ Your identification has been saved in /Users/ez/.ssh/internal.
39
+ Your public key has been saved in /Users/ez/.ssh/foo.pub.
40
+ The key fingerprint is:
41
+ 79:40:8a:18:84:ff:96:39:c7:3a:3d:f2:e9:20:a1:ea ez@ezra-zygmuntowiczs-macbook-pro.local
42
+ The key's randomart image is:
43
+ +--[ RSA 2048]----+
44
+ | oo . |
45
+ |. o . o |
46
+ | .. . . . |
47
+ | . o |
48
+ | .. + S . |
49
+ | . .* o . |
50
+ |. ...= |
51
+ |. .+.o. |
52
+ |oE =+. |
53
+ +-----------------+
54
+
55
+ Now you need to put the ssh keys in place on your servers. Run the following command once for each server in your cluster.
56
+
57
+ $ cd ~/.ssh
58
+ # do this for each server in your cluster
59
+ $ cat internal.pub | ssh deploy@server "cat >> ~/.ssh/authorized_keys && chmod 0600 ~/.ssh/authorized_keys"
60
+ $ cat internal | ssh deploy@server "cat > ~/.ssh/internal && chmod 0600 ~/.ssh/internal"
61
+
62
+
63
+ Once you have those keys in place you can start deploying to your cluster via git push. A few things to keep in mind with this new strategy. Your cluster does not run a git server, so you will still keep the canonical git repo on github or on your own git server somewhere. You can push any branch you want but you will always push to master on the far end as that is the branch that will get deployed on the server. But pushing another branch form your local repo to the remote master will work fine.
64
+
65
+
66
+ Thats it! you are now deploying with git directly to your instances. Please give this a try and give me some feedback! I'm hoping to hear from you if you use this new deploy strategy. You can reach me by responding to this post or email me at ez+git@engineyard.com.
data/Rakefile ADDED
@@ -0,0 +1,63 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems/specification'
4
+ require 'date'
5
+ require 'spec/rake/spectask'
6
+ require File.expand_path("lib/ey-deploy/version", File.dirname(__FILE__))
7
+
8
+ GEM = "ey-deploy"
9
+ GEM_VERSION = EY::VERSION
10
+ AUTHOR = "EY Cloud Team"
11
+ EMAIL = "cloud@engineyard.com"
12
+ HOMEPAGE = "http://engineyard.com"
13
+ SUMMARY = "A gem that deploys ruby applications on EY Cloud instances"
14
+
15
+ spec = Gem::Specification.new do |s|
16
+ s.name = GEM
17
+ s.version = GEM_VERSION
18
+ s.platform = Gem::Platform::RUBY
19
+ s.has_rdoc = true
20
+ s.extra_rdoc_files = ["README.rdoc", "LICENSE", 'TODO']
21
+ s.summary = SUMMARY
22
+ s.description = s.summary
23
+ s.author = AUTHOR
24
+ s.email = EMAIL
25
+ s.homepage = HOMEPAGE
26
+ s.bindir = "bin"
27
+ s.executables = %w(eysd)
28
+
29
+ bundle = Bundler::Definition.from_gemfile('Gemfile')
30
+ bundle.dependencies.each do |dep|
31
+ next unless dep.groups.include?(:runtime)
32
+ s.add_dependency(dep.name, dep.version_requirements.to_s)
33
+ end
34
+
35
+ s.require_path = 'lib'
36
+ s.autorequire = GEM
37
+ s.files = %w(LICENSE README.rdoc Rakefile TODO) + Dir.glob("{lib,spec}/**/*")
38
+ end
39
+
40
+ task :default => :spec
41
+
42
+ desc "Run specs"
43
+ Spec::Rake::SpecTask.new do |t|
44
+ t.spec_files = FileList['spec/**/*_spec.rb']
45
+ t.spec_opts = %w(-fs --color)
46
+ end
47
+
48
+
49
+ Rake::GemPackageTask.new(spec) do |pkg|
50
+ pkg.gem_spec = spec
51
+ end
52
+
53
+ desc "install the gem locally"
54
+ task :install => [:package] do
55
+ sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
56
+ end
57
+
58
+ desc "create a gemspec file"
59
+ task :make_spec do
60
+ File.open("#{GEM}.gemspec", "w") do |file|
61
+ file.puts spec.to_ruby
62
+ end
63
+ end
data/TODO ADDED
@@ -0,0 +1,4 @@
1
+ TODO:
2
+ Fix LICENSE with your name
3
+ Fix Rakefile with your name and contact info
4
+ Add your code to lib/<%= name %>.rb
data/bin/eysd ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ begin
3
+ require 'rubygems'
4
+ rescue LoadError
5
+ end
6
+
7
+ $LOAD_PATH.push(File.expand_path("../lib", File.dirname(__FILE__)))
8
+ require 'ey-deploy'
9
+
10
+ EY::CLI.start
data/lib/ey-deploy.rb ADDED
@@ -0,0 +1,16 @@
1
+ $LOAD_PATH.push(File.expand_path("ey-deploy", File.dirname(__FILE__)))
2
+
3
+ require 'version'
4
+ require 'compatibility'
5
+ require 'strategies/git'
6
+ require 'task'
7
+ require 'server'
8
+ require 'deploy'
9
+ require 'cli'
10
+ require 'configuration'
11
+
12
+ module EY
13
+ def self.node
14
+ @node ||= JSON.parse(`sudo cat /etc/chef/dna.json`)
15
+ end
16
+ end
@@ -0,0 +1,58 @@
1
+ $:.unshift File.expand_path('../vendor/thor/lib', File.dirname(__FILE__))
2
+
3
+ require 'thor'
4
+
5
+ module EY
6
+ class CLI < Thor
7
+ method_option :migrate, :type => :string,
8
+ :desc => "Run migrations with this deploy",
9
+ :aliases => ["-m"]
10
+
11
+ method_option :branch, :type => :string,
12
+ :desc => "Branch to deploy from, defaults to master",
13
+ :aliases => ["-b"]
14
+
15
+ method_option :repo, :type => :string,
16
+ :desc => "Remote repo to deploy",
17
+ :aliases => ["-r"]
18
+
19
+ method_option :app, :type => :string,
20
+ :required => true,
21
+ :desc => "Application to deploy",
22
+ :aliases => ["-a"]
23
+
24
+ method_option :config, :type => :string,
25
+ :desc => "Additional configuration"
26
+
27
+ desc "deploy", "Deploy code from /data/<app>"
28
+ def deploy(default_task=:deploy)
29
+ EY::Deploy.run(options.merge("default_task" => default_task))
30
+ end
31
+
32
+
33
+ desc "check", "Check whether the client gem is compatible with the server gem"
34
+ def check(client_version, server_requirement)
35
+ compat = EY::Compatibility.new(client_version, server_requirement)
36
+ return if compat.compatible?
37
+
38
+ if compat.server_newer?
39
+ puts "Server library is newer than supported by the engineyard gem"
40
+ puts "Please upgrade the engineyard gem"
41
+ exit(1)
42
+ end
43
+
44
+ system("gem install ey-deploy -v '#{server_requirement}' > /dev/null 2>&1")
45
+ case $?.exitstatus
46
+ when 2
47
+ puts "Incompatible server component detected"
48
+ puts "Please contact us at http://cloud-support.engineyard.com"
49
+ exit 2
50
+ when 0
51
+ puts "Upgraded server component"
52
+ exit
53
+ else
54
+ exit 3
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,24 @@
1
+ module EY
2
+ class Compatibility
3
+ attr_reader :server_version, :client_version, :server_required
4
+
5
+ def initialize(client_version, server_required)
6
+ require 'rubygems'
7
+ @client_version = Gem::Version.new(client_version)
8
+ @server_required = Gem::Requirement.new(server_required)
9
+ @server_version = Gem::Version.new(EY::VERSION)
10
+ end
11
+
12
+ def server_required_version
13
+ server_required.requirements.first.last
14
+ end
15
+
16
+ def compatible?
17
+ server_required.satisfied_by?(server_version)
18
+ end
19
+
20
+ def server_newer?
21
+ server_version > server_required_version
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,111 @@
1
+ require 'json'
2
+
3
+ module EY
4
+ class Deploy::Configuration
5
+ DEFAULT_CONFIG = {
6
+ "migrate" => "rake db:migrate",
7
+ "branch" => "master",
8
+ "copy_exclude" => ".git",
9
+ "strategy" => "Git",
10
+ }
11
+
12
+ attr_reader :configuration
13
+ alias :c :configuration
14
+
15
+ def initialize(opts={})
16
+ config = JSON.parse(opts["config"] || "{}")
17
+ @configuration = DEFAULT_CONFIG.merge(config).merge(opts)
18
+ end
19
+
20
+ # Delegate to the configuration objects
21
+ def method_missing(meth, *args, &blk)
22
+ c.key?(meth.to_s) ? c[meth.to_s] : super
23
+ end
24
+ def respond_to?(meth)
25
+ c.key?(meth.to_s) ? true : super
26
+ end
27
+
28
+ def repository_cache
29
+ configuration['repository_cache'] || File.join(deploy_to, "/shared/cached-copy")
30
+ end
31
+
32
+ def repo
33
+ configuration['repo'] || EY.node["applications"][app]["repository_name"]
34
+ end
35
+
36
+ def deploy_to
37
+ configuration['deploy_to'] || "/data/#{app}"
38
+ end
39
+
40
+ def migrate?
41
+ !!configuration['migrate']
42
+ end
43
+
44
+ def migration_command
45
+ configuration['migrate'] == "migrate" ? DEFAULT_CONFIG["migrate"] : configuration['migrate']
46
+ end
47
+
48
+ def user
49
+ EY.node['users'].first['username'] || 'nobody'
50
+ end
51
+ alias :group :user
52
+
53
+ def role
54
+ EY.node['instance_role']
55
+ end
56
+
57
+ def copy_exclude
58
+ @copy_exclude ||= Array(configuration.fetch("copy_exclude", []))
59
+ end
60
+
61
+ def stack
62
+ EY.node['environment']['stack']
63
+ end
64
+
65
+ def environment
66
+ EY.node['environment']['framework_env']
67
+ end
68
+
69
+ def latest_release
70
+ all_releases.last
71
+ end
72
+
73
+ def previous_release(current=latest_release)
74
+ index = all_releases.index(current)
75
+ all_releases[index-1]
76
+ end
77
+
78
+ def oldest_release
79
+ all_releases.first
80
+ end
81
+
82
+ def all_releases
83
+ Dir.glob("#{release_dir}/*").sort
84
+ end
85
+
86
+ def framework_envs
87
+ "RAILS_ENV=#{environment} RACK_ENV=#{environment} MERB_ENV=#{environment}"
88
+ end
89
+
90
+ def current_path
91
+ File.join(deploy_to, "current")
92
+ end
93
+
94
+ def shared_path
95
+ File.join(deploy_to, "shared")
96
+ end
97
+
98
+ def release_dir
99
+ File.join(deploy_to, "releases")
100
+ end
101
+
102
+ def release_path
103
+ @release_path ||= File.join(release_dir, Time.now.utc.strftime("%Y%m%d%H%M%S"))
104
+ end
105
+
106
+ def exclusions
107
+ copy_exclude.map { |e| %|--exclude="#{e}"| }.join(' ')
108
+ end
109
+
110
+ end
111
+ end
@@ -0,0 +1,158 @@
1
+ # stolen wholesale from capistrano, thanks Jamis!
2
+ require 'fileutils'
3
+ require 'json'
4
+
5
+ module EY
6
+ class DeployBase < Task
7
+ # default task
8
+ def deploy
9
+ update_repository_cache
10
+ require_custom_tasks
11
+ push_code
12
+
13
+ puts "~> Starting full deploy"
14
+
15
+ copy_repository_cache
16
+ bundle
17
+ symlink_configs
18
+ migrate
19
+ symlink
20
+ restart
21
+ cleanup
22
+
23
+ puts "~> finalizing deploy"
24
+ end
25
+
26
+ # task
27
+ def push_code
28
+ puts "~> Pushing code to all servers"
29
+ EY::Server.all.each do |server|
30
+ server.push_code
31
+ end
32
+ end
33
+
34
+ # task
35
+ def restart
36
+ puts "~> Restarting app servers"
37
+ roles :app_master, :app, :solo do
38
+ restart_command = case c.stack
39
+ when "nginx_unicorn"
40
+ "/etc/init.d/unicorn_#{c.app} restart"
41
+ when "nginx_mongrel"
42
+ "monit restart all -g #{c.app}"
43
+ when "nginx_passenger", "apache_passenger"
44
+ "touch #{c.latest_release}/tmp/restart.txt"
45
+ end
46
+ if restart_command
47
+ puts "~> restarting app: #{c.latest_release}"
48
+ sudo("cd #{c.current_path} && INLINEDIR=/tmp #{c.framework_envs} #{restart_command}")
49
+ end
50
+ callback(:after_restart)
51
+ end
52
+ end
53
+
54
+ # task
55
+ def bundle
56
+ roles :app_master, :app, :solo do
57
+ if File.exist?("#{c.latest_release}/Gemfile")
58
+ puts "~> Gemfile detected, bundling gems"
59
+ run %|cd #{c.latest_release} && bundle install|
60
+ end
61
+ end
62
+ end
63
+
64
+ # task
65
+ def cleanup
66
+ puts "~> cleaning up old releases"
67
+ sudo "ls #{c.release_dir} | head -n -3 | xargs -I{} rm -rf #{c.release_dir}/{}"
68
+ end
69
+
70
+ # task
71
+ def rollback
72
+ puts "~> rolling back to previous release"
73
+ symlink(c.previous_release)
74
+ FileUtils.rm_rf c.latest_release
75
+ puts "~> restarting with previous release"
76
+ restart
77
+ end
78
+
79
+ # task
80
+ def migrate
81
+ roles :app_master, :solo do
82
+ if c.migrate?
83
+ callback(:before_migrate)
84
+ puts "~> migrating"
85
+ cmd = "cd #{c.latest_release} && #{c.framework_envs} #{c.migration_command}"
86
+ puts "~> Migrating: #{cmd}"
87
+ run(cmd)
88
+ end
89
+ end
90
+ end
91
+
92
+ # task
93
+ def copy_repository_cache
94
+ puts "~> copying to #{c.release_path}"
95
+ sudo("mkdir -p #{c.release_path} && rsync -aq #{c.exclusions} #{c.repository_cache}/* #{c.release_path}")
96
+
97
+ puts "~> ensuring proper ownership"
98
+ sudo("chown -R #{c.user}:#{c.group} #{c.deploy_to}")
99
+ end
100
+
101
+ def symlink_configs(release_to_link=c.latest_release)
102
+ puts "~> Symlinking configs"
103
+ sudo [ "chmod -R g+w #{release_to_link}",
104
+ "rm -rf #{release_to_link}/log #{release_to_link}/public/system #{release_to_link}/tmp/pids",
105
+ "mkdir -p #{release_to_link}/tmp",
106
+ "ln -nfs #{c.shared_path}/log #{release_to_link}/log",
107
+ "mkdir -p #{release_to_link}/public",
108
+ "mkdir -p #{release_to_link}/config",
109
+ "ln -nfs #{c.shared_path}/system #{release_to_link}/public/system",
110
+ "ln -nfs #{c.shared_path}/pids #{release_to_link}/tmp/pids",
111
+ "ln -nfs #{c.shared_path}/config/database.yml #{release_to_link}/config/database.yml",
112
+ "chown -R #{c.user}:#{c.group} #{release_to_link}"
113
+ ].join(" && ")
114
+ end
115
+
116
+ # task
117
+ def symlink(release_to_link=c.latest_release)
118
+ callback(:before_symlink)
119
+ puts "~> symlinking code"
120
+ begin
121
+ sudo "rm -f #{c.current_path} && ln -nfs #{release_to_link} #{c.current_path} && chown -R #{c.user}:#{c.group} #{c.current_path}"
122
+ rescue => e
123
+ sudo "rm -f #{c.current_path} && ln -nfs #{c.previous_release(release_to_link)} #{c.current_path} && chown -R #{c.user}:#{c.group} #{c.current_path}"
124
+ sudo "rm -rf #{release_to_link}"
125
+ raise e
126
+ end
127
+ end
128
+
129
+ # before_symlink
130
+ # before_restart
131
+ def callback(what)
132
+ if File.exist?("#{c.latest_release}/deploy/#{what}.rb")
133
+ Dir.chdir(c.latest_release) do
134
+ puts "~> running deploy hook: deploy/#{what}.rb"
135
+ instance_eval(IO.read("#{c.latest_release}/deploy/#{what}.rb"))
136
+ end
137
+ end
138
+ end
139
+
140
+ end
141
+
142
+ class Deploy < DeployBase
143
+ def self.new(opts={})
144
+ # include the correct fetch strategy
145
+ include EY::Strategies.const_get(opts.strategy)::Helpers
146
+ super
147
+ end
148
+
149
+ def self.run(opts={})
150
+ conf = EY::Deploy::Configuration.new(opts)
151
+ EY::Server.config = conf
152
+
153
+ dep = new(conf)
154
+ dep.require_custom_tasks
155
+ dep.send(opts["default_task"])
156
+ end
157
+ end
158
+ end