engineyard-serverside 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +19 -0
- data/bin/engineyard-serverside +10 -0
- data/lib/engineyard-serverside.rb +49 -0
- data/lib/engineyard-serverside/bundle_installer.rb +4 -0
- data/lib/engineyard-serverside/cli.rb +146 -0
- data/lib/engineyard-serverside/configuration.rb +130 -0
- data/lib/engineyard-serverside/default_maintenance_page.html +29 -0
- data/lib/engineyard-serverside/deploy.rb +321 -0
- data/lib/engineyard-serverside/deploy_hook.rb +80 -0
- data/lib/engineyard-serverside/lockfile_parser.rb +55 -0
- data/lib/engineyard-serverside/logged_output.rb +78 -0
- data/lib/engineyard-serverside/server.rb +70 -0
- data/lib/engineyard-serverside/strategies/git.rb +136 -0
- data/lib/engineyard-serverside/task.rb +62 -0
- data/lib/engineyard-serverside/version.rb +3 -0
- data/lib/vendor/dataflow/HISTORY +52 -0
- data/lib/vendor/dataflow/LICENSE +19 -0
- data/lib/vendor/dataflow/README.textile +290 -0
- data/lib/vendor/dataflow/Rakefile +36 -0
- data/lib/vendor/dataflow/dataflow.rb +120 -0
- data/lib/vendor/dataflow/dataflow/actor.rb +22 -0
- data/lib/vendor/dataflow/dataflow/equality.rb +28 -0
- data/lib/vendor/dataflow/dataflow/future_queue.rb +24 -0
- data/lib/vendor/dataflow/dataflow/port.rb +54 -0
- data/lib/vendor/dataflow/examples/barrier.rb +9 -0
- data/lib/vendor/dataflow/examples/data_driven.rb +17 -0
- data/lib/vendor/dataflow/examples/dataflow_http_gets.rb +13 -0
- data/lib/vendor/dataflow/examples/flow.rb +20 -0
- data/lib/vendor/dataflow/examples/future_http_gets.rb +12 -0
- data/lib/vendor/dataflow/examples/future_queue.rb +11 -0
- data/lib/vendor/dataflow/examples/instance_variables.rb +15 -0
- data/lib/vendor/dataflow/examples/laziness.rb +9 -0
- data/lib/vendor/dataflow/examples/local_variables.rb +11 -0
- data/lib/vendor/dataflow/examples/messages.rb +26 -0
- data/lib/vendor/dataflow/examples/port_http_gets.rb +13 -0
- data/lib/vendor/dataflow/examples/port_send.rb +10 -0
- data/lib/vendor/dataflow/examples/ring.rb +21 -0
- data/lib/vendor/dataflow/spec/actor_spec.rb +28 -0
- data/lib/vendor/dataflow/spec/anonymous_variables_spec.rb +21 -0
- data/lib/vendor/dataflow/spec/barrier_spec.rb +25 -0
- data/lib/vendor/dataflow/spec/by_need_spec.rb +55 -0
- data/lib/vendor/dataflow/spec/dataflow_spec.rb +151 -0
- data/lib/vendor/dataflow/spec/equality_spec.rb +40 -0
- data/lib/vendor/dataflow/spec/flow_spec.rb +25 -0
- data/lib/vendor/dataflow/spec/forker_spec.rb +28 -0
- data/lib/vendor/dataflow/spec/future_queue_spec.rb +31 -0
- data/lib/vendor/dataflow/spec/inspect_spec.rb +19 -0
- data/lib/vendor/dataflow/spec/need_later_spec.rb +12 -0
- data/lib/vendor/dataflow/spec/port_spec.rb +26 -0
- data/lib/vendor/dataflow/spec/spec.opts +1 -0
- data/lib/vendor/dataflow/spec/spec_helper.rb +10 -0
- data/lib/vendor/escape/Readme +21 -0
- data/lib/vendor/escape/doc_include/template/qualitysmith.rb +631 -0
- data/lib/vendor/escape/lib/escape.rb +247 -0
- data/lib/vendor/json_pure/CHANGES +166 -0
- data/lib/vendor/json_pure/COPYING +58 -0
- data/lib/vendor/json_pure/GPL +340 -0
- data/lib/vendor/json_pure/README +358 -0
- data/lib/vendor/json_pure/Rakefile +292 -0
- data/lib/vendor/json_pure/TODO +1 -0
- data/lib/vendor/json_pure/VERSION +1 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkComparison.log +52 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast-autocorrelation.dat +1000 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_fast.dat +1001 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty-autocorrelation.dat +900 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_pretty.dat +901 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe-autocorrelation.dat +1000 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt#generator_safe.dat +1001 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkExt.log +261 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast-autocorrelation.dat +1000 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_fast.dat +1001 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty-autocorrelation.dat +1000 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_pretty.dat +1001 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe-autocorrelation.dat +1000 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure#generator_safe.dat +1001 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkPure.log +262 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator-autocorrelation.dat +1000 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails#generator.dat +1001 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/GeneratorBenchmarkRails.log +82 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkComparison.log +34 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser-autocorrelation.dat +900 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt#parser.dat +901 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkExt.log +81 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser-autocorrelation.dat +1000 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure#parser.dat +1001 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkPure.log +82 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser-autocorrelation.dat +1000 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails#parser.dat +1001 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkRails.log +82 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser-autocorrelation.dat +1000 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML#parser.dat +1001 -0
- data/lib/vendor/json_pure/benchmarks/data-p4-3GHz-ruby18/ParserBenchmarkYAML.log +82 -0
- data/lib/vendor/json_pure/benchmarks/generator2_benchmark.rb +222 -0
- data/lib/vendor/json_pure/benchmarks/generator_benchmark.rb +224 -0
- data/lib/vendor/json_pure/benchmarks/ohai.json +1216 -0
- data/lib/vendor/json_pure/benchmarks/ohai.ruby +1 -0
- data/lib/vendor/json_pure/benchmarks/parser2_benchmark.rb +251 -0
- data/lib/vendor/json_pure/benchmarks/parser_benchmark.rb +259 -0
- data/lib/vendor/json_pure/bin/edit_json.rb +9 -0
- data/lib/vendor/json_pure/bin/prettify_json.rb +75 -0
- data/lib/vendor/json_pure/data/example.json +1 -0
- data/lib/vendor/json_pure/data/index.html +38 -0
- data/lib/vendor/json_pure/data/prototype.js +4184 -0
- data/lib/vendor/json_pure/ext/json/ext/generator/extconf.rb +16 -0
- data/lib/vendor/json_pure/ext/json/ext/generator/generator.c +1323 -0
- data/lib/vendor/json_pure/ext/json/ext/generator/generator.h +170 -0
- data/lib/vendor/json_pure/ext/json/ext/parser/extconf.rb +15 -0
- data/lib/vendor/json_pure/ext/json/ext/parser/parser.c +1935 -0
- data/lib/vendor/json_pure/ext/json/ext/parser/parser.h +71 -0
- data/lib/vendor/json_pure/ext/json/ext/parser/parser.rl +792 -0
- data/lib/vendor/json_pure/install.rb +26 -0
- data/lib/vendor/json_pure/lib/json.rb +10 -0
- data/lib/vendor/json_pure/lib/json/Array.xpm +21 -0
- data/lib/vendor/json_pure/lib/json/FalseClass.xpm +21 -0
- data/lib/vendor/json_pure/lib/json/Hash.xpm +21 -0
- data/lib/vendor/json_pure/lib/json/Key.xpm +73 -0
- data/lib/vendor/json_pure/lib/json/NilClass.xpm +21 -0
- data/lib/vendor/json_pure/lib/json/Numeric.xpm +28 -0
- data/lib/vendor/json_pure/lib/json/String.xpm +96 -0
- data/lib/vendor/json_pure/lib/json/TrueClass.xpm +21 -0
- data/lib/vendor/json_pure/lib/json/add/core.rb +148 -0
- data/lib/vendor/json_pure/lib/json/add/rails.rb +58 -0
- data/lib/vendor/json_pure/lib/json/common.rb +397 -0
- data/lib/vendor/json_pure/lib/json/editor.rb +1371 -0
- data/lib/vendor/json_pure/lib/json/ext.rb +15 -0
- data/lib/vendor/json_pure/lib/json/json.xpm +1499 -0
- data/lib/vendor/json_pure/lib/json/pure.rb +77 -0
- data/lib/vendor/json_pure/lib/json/pure/generator.rb +452 -0
- data/lib/vendor/json_pure/lib/json/pure/parser.rb +307 -0
- data/lib/vendor/json_pure/lib/json/version.rb +8 -0
- data/lib/vendor/json_pure/tests/fixtures/fail1.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail10.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail11.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail12.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail13.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail14.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail18.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail19.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail2.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail20.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail21.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail22.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail23.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail24.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail25.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail27.json +2 -0
- data/lib/vendor/json_pure/tests/fixtures/fail28.json +2 -0
- data/lib/vendor/json_pure/tests/fixtures/fail3.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail4.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail5.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail6.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail7.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail8.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/fail9.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/pass1.json +56 -0
- data/lib/vendor/json_pure/tests/fixtures/pass15.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/pass16.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/pass17.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/pass2.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/pass26.json +1 -0
- data/lib/vendor/json_pure/tests/fixtures/pass3.json +6 -0
- data/lib/vendor/json_pure/tests/test_json.rb +361 -0
- data/lib/vendor/json_pure/tests/test_json_addition.rb +162 -0
- data/lib/vendor/json_pure/tests/test_json_encoding.rb +68 -0
- data/lib/vendor/json_pure/tests/test_json_fixtures.rb +34 -0
- data/lib/vendor/json_pure/tests/test_json_generate.rb +122 -0
- data/lib/vendor/json_pure/tests/test_json_rails.rb +144 -0
- data/lib/vendor/json_pure/tests/test_json_unicode.rb +76 -0
- data/lib/vendor/json_pure/tools/fuzz.rb +139 -0
- data/lib/vendor/json_pure/tools/server.rb +61 -0
- data/lib/vendor/open4/lib/open4.rb +403 -0
- data/lib/vendor/thor/CHANGELOG.rdoc +89 -0
- data/lib/vendor/thor/LICENSE +20 -0
- data/lib/vendor/thor/README.rdoc +297 -0
- data/lib/vendor/thor/Thorfile +69 -0
- data/lib/vendor/thor/bin/rake2thor +86 -0
- data/lib/vendor/thor/bin/thor +6 -0
- data/lib/vendor/thor/lib/thor.rb +244 -0
- data/lib/vendor/thor/lib/thor/actions.rb +275 -0
- data/lib/vendor/thor/lib/thor/actions/create_file.rb +103 -0
- data/lib/vendor/thor/lib/thor/actions/directory.rb +91 -0
- data/lib/vendor/thor/lib/thor/actions/empty_directory.rb +134 -0
- data/lib/vendor/thor/lib/thor/actions/file_manipulation.rb +223 -0
- data/lib/vendor/thor/lib/thor/actions/inject_into_file.rb +104 -0
- data/lib/vendor/thor/lib/thor/base.rb +540 -0
- data/lib/vendor/thor/lib/thor/core_ext/file_binary_read.rb +9 -0
- data/lib/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
- data/lib/vendor/thor/lib/thor/core_ext/ordered_hash.rb +100 -0
- data/lib/vendor/thor/lib/thor/error.rb +30 -0
- data/lib/vendor/thor/lib/thor/group.rb +271 -0
- data/lib/vendor/thor/lib/thor/invocation.rb +180 -0
- data/lib/vendor/thor/lib/thor/parser.rb +4 -0
- data/lib/vendor/thor/lib/thor/parser/argument.rb +67 -0
- data/lib/vendor/thor/lib/thor/parser/arguments.rb +150 -0
- data/lib/vendor/thor/lib/thor/parser/option.rb +128 -0
- data/lib/vendor/thor/lib/thor/parser/options.rb +169 -0
- data/lib/vendor/thor/lib/thor/rake_compat.rb +66 -0
- data/lib/vendor/thor/lib/thor/runner.rb +314 -0
- data/lib/vendor/thor/lib/thor/shell.rb +83 -0
- data/lib/vendor/thor/lib/thor/shell/basic.rb +239 -0
- data/lib/vendor/thor/lib/thor/shell/color.rb +108 -0
- data/lib/vendor/thor/lib/thor/task.rb +102 -0
- data/lib/vendor/thor/lib/thor/util.rb +230 -0
- data/lib/vendor/thor/lib/thor/version.rb +3 -0
- data/lib/vendor/thor/thor.gemspec +120 -0
- data/spec/custom_deploy_spec.rb +95 -0
- data/spec/deploy_hook_spec.rb +211 -0
- data/spec/fixtures/gitrepo.tar.gz +0 -0
- data/spec/fixtures/gitrepo/foo +0 -0
- data/spec/fixtures/invalid_hook.rb +1 -0
- data/spec/fixtures/valid_hook.rb +1 -0
- data/spec/git_strategy_spec.rb +22 -0
- data/spec/lockfile_parser_spec.rb +30 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/support/lockfiles/0.9-no-bundler +111 -0
- data/spec/support/lockfiles/0.9-with-bundler +117 -0
- data/spec/support/lockfiles/1.0-no-bundler +54 -0
- data/spec/support/lockfiles/1.0.0.rc.1-with-bundler +162 -0
- data/spec/support/lockfiles/not-a-lockfile +10 -0
- metadata +279 -0
data/LICENSE
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2010 Engine Yard, Inc
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
|
11
|
+
all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
+
THE SOFTWARE.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
$LOAD_PATH.push(File.expand_path("engineyard-serverside", File.dirname(__FILE__)))
|
|
2
|
+
$LOAD_PATH.unshift File.expand_path('vendor/thor/lib', File.dirname(__FILE__))
|
|
3
|
+
$LOAD_PATH.unshift File.expand_path('vendor/open4/lib', File.dirname(__FILE__))
|
|
4
|
+
$LOAD_PATH.unshift File.expand_path('vendor/escape/lib', File.dirname(__FILE__))
|
|
5
|
+
$LOAD_PATH.unshift File.expand_path('vendor/json_pure/lib', File.dirname(__FILE__))
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path('vendor/dataflow', File.dirname(__FILE__))
|
|
7
|
+
|
|
8
|
+
require 'escape'
|
|
9
|
+
require 'json'
|
|
10
|
+
require 'dataflow'
|
|
11
|
+
|
|
12
|
+
require 'version'
|
|
13
|
+
require 'strategies/git'
|
|
14
|
+
require 'task'
|
|
15
|
+
require 'server'
|
|
16
|
+
require 'deploy'
|
|
17
|
+
require 'deploy_hook'
|
|
18
|
+
require 'lockfile_parser'
|
|
19
|
+
require 'bundle_installer'
|
|
20
|
+
require 'cli'
|
|
21
|
+
require 'configuration'
|
|
22
|
+
|
|
23
|
+
module EY
|
|
24
|
+
def self.node
|
|
25
|
+
@node ||= deep_indifferentize(JSON.parse(dna_json))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.dna_json
|
|
29
|
+
@dna_json ||= `sudo cat /etc/chef/dna.json`
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
RemoteFailure = Class.new StandardError
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
def self.deep_indifferentize(thing)
|
|
36
|
+
if thing.kind_of?(Hash)
|
|
37
|
+
indifferent_hash = Thor::CoreExt::HashWithIndifferentAccess.new
|
|
38
|
+
thing.each do |k, v|
|
|
39
|
+
indifferent_hash[k] = deep_indifferentize(v)
|
|
40
|
+
end
|
|
41
|
+
indifferent_hash
|
|
42
|
+
elsif thing.kind_of?(Array)
|
|
43
|
+
thing.map {|x| deep_indifferentize(x)}
|
|
44
|
+
else
|
|
45
|
+
thing
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
require 'thor'
|
|
2
|
+
|
|
3
|
+
module EY
|
|
4
|
+
class CLI < Thor
|
|
5
|
+
include Dataflow
|
|
6
|
+
|
|
7
|
+
def self.start(*)
|
|
8
|
+
super
|
|
9
|
+
rescue RemoteFailure
|
|
10
|
+
exit(1)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
method_option :migrate, :type => :string,
|
|
14
|
+
:desc => "Run migrations with this deploy",
|
|
15
|
+
:aliases => ["-m"]
|
|
16
|
+
|
|
17
|
+
method_option :branch, :type => :string,
|
|
18
|
+
:desc => "Git ref to deploy, defaults to master. May be a branch, a tag, or a SHA",
|
|
19
|
+
:aliases => %w[-b --ref --tag]
|
|
20
|
+
|
|
21
|
+
method_option :repo, :type => :string,
|
|
22
|
+
:desc => "Remote repo to deploy",
|
|
23
|
+
:aliases => ["-r"]
|
|
24
|
+
|
|
25
|
+
method_option :app, :type => :string,
|
|
26
|
+
:required => true,
|
|
27
|
+
:desc => "Application to deploy",
|
|
28
|
+
:aliases => ["-a"]
|
|
29
|
+
|
|
30
|
+
method_option :framework_env, :type => :string,
|
|
31
|
+
:required => true,
|
|
32
|
+
:desc => "Ruby web framework environment",
|
|
33
|
+
:aliases => ["-e"]
|
|
34
|
+
|
|
35
|
+
method_option :config, :type => :string,
|
|
36
|
+
:desc => "Additional configuration"
|
|
37
|
+
|
|
38
|
+
method_option :stack, :type => :string,
|
|
39
|
+
:desc => "Web stack (so we can restart it correctly)"
|
|
40
|
+
|
|
41
|
+
method_option :instances, :type => :array,
|
|
42
|
+
:desc => "Instances in cluster"
|
|
43
|
+
|
|
44
|
+
method_option :verbose, :type => :boolean,
|
|
45
|
+
:default => false,
|
|
46
|
+
:desc => "Verbose output",
|
|
47
|
+
:aliases => ["-v"]
|
|
48
|
+
|
|
49
|
+
desc "deploy", "Deploy code from /data/<app>"
|
|
50
|
+
def deploy(default_task=:deploy)
|
|
51
|
+
EY::Server.all = parse_instances(options[:instances])
|
|
52
|
+
EY::LoggedOutput.verbose = options[:verbose]
|
|
53
|
+
EY::LoggedOutput.logfile = File.join(ENV['HOME'], "#{options[:app]}-deploy.log")
|
|
54
|
+
|
|
55
|
+
invoke :propagate
|
|
56
|
+
EY::Deploy.run(options.merge("default_task" => default_task))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
method_option :app, :type => :string,
|
|
60
|
+
:required => true,
|
|
61
|
+
:desc => "Which application's hooks to run",
|
|
62
|
+
:aliases => ["-a"]
|
|
63
|
+
|
|
64
|
+
method_option :release_path, :type => :string,
|
|
65
|
+
:desc => "Value for #release_path in hooks (mostly for internal coordination)",
|
|
66
|
+
:aliases => ["-r"]
|
|
67
|
+
|
|
68
|
+
method_option :current_role, :type => :string,
|
|
69
|
+
:desc => "Value for #current_role in hooks"
|
|
70
|
+
|
|
71
|
+
method_option :framework_env, :type => :string,
|
|
72
|
+
:required => true,
|
|
73
|
+
:desc => "Ruby web framework environment",
|
|
74
|
+
:aliases => ["-e"]
|
|
75
|
+
|
|
76
|
+
method_option :config, :type => :string,
|
|
77
|
+
:desc => "Additional configuration"
|
|
78
|
+
|
|
79
|
+
method_option :current_name, :type => :string,
|
|
80
|
+
:desc => "Value for #current_name in hooks"
|
|
81
|
+
|
|
82
|
+
desc "hook [NAME]", "Run a particular deploy hook"
|
|
83
|
+
def hook(hook_name)
|
|
84
|
+
EY::DeployHook.new(options).run(hook_name)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
desc "install_bundler [VERSION]", "Make sure VERSION of bundler is installed (in system ruby)"
|
|
88
|
+
def install_bundler(version)
|
|
89
|
+
egrep_escaped_version = version.gsub(/\./, '\.')
|
|
90
|
+
# the grep "bundler " is so that gems like bundler08 don't get
|
|
91
|
+
# their versions considered too
|
|
92
|
+
#
|
|
93
|
+
# the [,$] is to stop us from looking for e.g. 0.9.2, seeing
|
|
94
|
+
# 0.9.22, and mistakenly thinking 0.9.2 is there
|
|
95
|
+
has_bundler_cmd = "gem list bundler | grep \"bundler \" | egrep -q '#{egrep_escaped_version}[,)]'"
|
|
96
|
+
|
|
97
|
+
unless system(has_bundler_cmd)
|
|
98
|
+
system("gem install bundler -q --no-rdoc --no-ri -v '#{version}'")
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
desc "propagate", "Propagate the engineyard-serverside gem to the other instances in the cluster. This will install exactly version #{VERSION} and remove other versions if found."
|
|
103
|
+
def propagate
|
|
104
|
+
config = EY::Deploy::Configuration.new
|
|
105
|
+
gem_filename = "engineyard-serverside-#{VERSION}.gem"
|
|
106
|
+
local_gem_file = File.join(Gem.dir, 'cache', gem_filename)
|
|
107
|
+
remote_gem_file = File.join(Dir.tmpdir, gem_filename)
|
|
108
|
+
gem_binary = File.join(Gem.default_bindir, 'gem')
|
|
109
|
+
|
|
110
|
+
EY::Server.config = config
|
|
111
|
+
|
|
112
|
+
barrier(*(EY::Server.all.find_all do |server|
|
|
113
|
+
!server.local? # of course this machine has it
|
|
114
|
+
end.map do |server|
|
|
115
|
+
need_later do
|
|
116
|
+
egrep_escaped_version = VERSION.gsub(/\./, '\.')
|
|
117
|
+
# the [,)] is to stop us from looking for e.g. 0.5.1, seeing
|
|
118
|
+
# 0.5.11, and mistakenly thinking 0.5.1 is there
|
|
119
|
+
has_gem_cmd = "#{gem_binary} list engineyard-serverside | grep \"engineyard-serverside\" | egrep -q '#{egrep_escaped_version}[,)]'"
|
|
120
|
+
|
|
121
|
+
if !server.run(has_gem_cmd) # doesn't have this exact version
|
|
122
|
+
puts "~> Installing engineyard-serverside on #{server.hostname}"
|
|
123
|
+
|
|
124
|
+
system(Escape.shell_command([
|
|
125
|
+
'scp', '-i', "#{ENV['HOME']}/.ssh/internal",
|
|
126
|
+
"-o", "StrictHostKeyChecking=no",
|
|
127
|
+
local_gem_file,
|
|
128
|
+
"#{config.user}@#{server.hostname}:#{remote_gem_file}",
|
|
129
|
+
]))
|
|
130
|
+
server.run("sudo #{gem_binary} install --no-rdoc --no-ri '#{remote_gem_file}'")
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end))
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
def parse_instances(instance_strings)
|
|
139
|
+
instance_strings.map do |s|
|
|
140
|
+
tuple = s.split(/,/)
|
|
141
|
+
{:hostname => tuple[0], :role => tuple[1], :name => tuple[2]}
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'thor'
|
|
3
|
+
|
|
4
|
+
module EY
|
|
5
|
+
class Deploy::Configuration
|
|
6
|
+
DEFAULT_CONFIG = Thor::CoreExt::HashWithIndifferentAccess.new({
|
|
7
|
+
"branch" => "master",
|
|
8
|
+
"strategy" => "Git",
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
attr_reader :configuration
|
|
12
|
+
alias :c :configuration
|
|
13
|
+
|
|
14
|
+
attr_writer :release_path
|
|
15
|
+
|
|
16
|
+
def initialize(opts={})
|
|
17
|
+
@release_path = opts[:release_path]
|
|
18
|
+
config = JSON.parse(opts["config"] || "{}")
|
|
19
|
+
@configuration = DEFAULT_CONFIG.merge(config).merge(opts)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Delegate to the configuration objects
|
|
23
|
+
def method_missing(meth, *args, &blk)
|
|
24
|
+
c.key?(meth.to_s) ? c[meth.to_s] : super
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def respond_to?(meth, include_private=false)
|
|
28
|
+
c.key?(meth.to_s) ? true : super
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def [](key)
|
|
32
|
+
if respond_to?(key.to_sym)
|
|
33
|
+
send(key.to_sym)
|
|
34
|
+
else
|
|
35
|
+
c[key]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def has_key?(key)
|
|
40
|
+
if respond_to?(key.to_sym)
|
|
41
|
+
true
|
|
42
|
+
else
|
|
43
|
+
c.has_key?(key)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def node
|
|
48
|
+
EY.node
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def revision
|
|
52
|
+
IO.read(File.join(latest_release, 'REVISION'))
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def repository_cache
|
|
56
|
+
configuration['repository_cache'] || File.join(deploy_to, "/shared/cached-copy")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def deploy_to
|
|
60
|
+
configuration['deploy_to'] || "/data/#{app}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def migrate?
|
|
64
|
+
!!configuration['migrate']
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def migration_command
|
|
68
|
+
configuration['migrate'] == "migrate" ? DEFAULT_CONFIG["migrate"] : configuration['migrate']
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def user
|
|
72
|
+
ENV['USER']
|
|
73
|
+
end
|
|
74
|
+
alias :group :user
|
|
75
|
+
|
|
76
|
+
def role
|
|
77
|
+
node['instance_role']
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def copy_exclude
|
|
81
|
+
@copy_exclude ||= Array(configuration.fetch("copy_exclude", []))
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def environment
|
|
85
|
+
configuration['framework_env']
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def latest_release
|
|
89
|
+
all_releases.last
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def previous_release(current=latest_release)
|
|
93
|
+
index = all_releases.index(current)
|
|
94
|
+
all_releases[index-1]
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def oldest_release
|
|
98
|
+
all_releases.first
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def all_releases
|
|
102
|
+
Dir.glob("#{release_dir}/*").sort
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def framework_envs
|
|
106
|
+
"RAILS_ENV=#{environment} RACK_ENV=#{environment} MERB_ENV=#{environment}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def current_path
|
|
110
|
+
File.join(deploy_to, "current")
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def shared_path
|
|
114
|
+
File.join(deploy_to, "shared")
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def release_dir
|
|
118
|
+
File.join(deploy_to, "releases")
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def release_path
|
|
122
|
+
@release_path ||= File.join(release_dir, Time.now.utc.strftime("%Y%m%d%H%M%S"))
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def exclusions
|
|
126
|
+
copy_exclude.map { |e| %|--exclude="#{e}"| }.join(' ')
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<!DOCTYPE html >
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>Undergoing Maintenance</title>
|
|
5
|
+
|
|
6
|
+
<style type="text/css">
|
|
7
|
+
body{font-size: 75%;font-family: Helvetica,Arial,sans-serif;color:#333;background:#FDFDFD;}
|
|
8
|
+
.container{font-size:1.1em;width:700px;text-align:center;margin:80px auto;}
|
|
9
|
+
.message{background:#FFF;border:1px solid #EEE;padding:30px;}
|
|
10
|
+
h1{margin:0 0 0.5em;font-weight:normal;}
|
|
11
|
+
p{margin:0;line-height:1.75em;}
|
|
12
|
+
.foot{color:#999;margin-top:30px}
|
|
13
|
+
.foot a{color:#666;text-decoration:none}
|
|
14
|
+
</style>
|
|
15
|
+
</head>
|
|
16
|
+
|
|
17
|
+
<body>
|
|
18
|
+
<div class="container">
|
|
19
|
+
<div class="message">
|
|
20
|
+
<h1>This site is currently undergoing some maintenance.</h1>
|
|
21
|
+
<p>Customize this maintenance page by updating the file located at: /public/maintenance.html</p>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="foot">
|
|
24
|
+
Hosted by <a href="http://www.engineyard.com">Engine Yard</a>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</body>
|
|
28
|
+
|
|
29
|
+
</html>
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# stolen wholesale from capistrano, thanks Jamis!
|
|
2
|
+
require 'base64'
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'json'
|
|
5
|
+
|
|
6
|
+
module EY
|
|
7
|
+
class DeployBase < Task
|
|
8
|
+
include LoggedOutput
|
|
9
|
+
|
|
10
|
+
# default task
|
|
11
|
+
def deploy
|
|
12
|
+
debug "Starting deploy at #{Time.now.asctime}"
|
|
13
|
+
update_repository_cache
|
|
14
|
+
require_custom_tasks
|
|
15
|
+
push_code
|
|
16
|
+
|
|
17
|
+
info "~> Starting full deploy"
|
|
18
|
+
copy_repository_cache
|
|
19
|
+
|
|
20
|
+
with_failed_release_cleanup do
|
|
21
|
+
create_revision_file
|
|
22
|
+
bundle
|
|
23
|
+
symlink_configs
|
|
24
|
+
conditionally_enable_maintenance_page
|
|
25
|
+
run_with_callbacks(:migrate)
|
|
26
|
+
callback(:before_symlink)
|
|
27
|
+
symlink
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
callback(:after_symlink)
|
|
31
|
+
run_with_callbacks(:restart)
|
|
32
|
+
disable_maintenance_page
|
|
33
|
+
|
|
34
|
+
cleanup_old_releases
|
|
35
|
+
debug "Finished deploy at #{Time.now.asctime}"
|
|
36
|
+
rescue Exception
|
|
37
|
+
debug "Finished failing to deploy at #{Time.now.asctime}"
|
|
38
|
+
puts_deploy_failure
|
|
39
|
+
raise
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def enable_maintenance_page
|
|
43
|
+
maintenance_page_candidates = [
|
|
44
|
+
"public/maintenance.html.custom",
|
|
45
|
+
"public/maintenance.html.tmp",
|
|
46
|
+
"public/maintenance.html",
|
|
47
|
+
"public/system/maintenance.html.default",
|
|
48
|
+
].map do |file|
|
|
49
|
+
File.join(c.latest_release, file)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# this one is guaranteed to exist
|
|
53
|
+
maintenance_page_candidates << File.expand_path(
|
|
54
|
+
"default_maintenance_page.html",
|
|
55
|
+
File.dirname(__FILE__)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# put in the maintenance page
|
|
59
|
+
maintenance_file = maintenance_page_candidates.detect do |file|
|
|
60
|
+
File.exists?(file)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
@maintenance_up = true
|
|
64
|
+
roles :app_master, :app, :solo do
|
|
65
|
+
visible_maint_page = File.join(c.shared_path, "system", "maintenance.html")
|
|
66
|
+
run "cp '#{maintenance_file}' '#{visible_maint_page}'"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def conditionally_enable_maintenance_page
|
|
71
|
+
if c.migrate? || c.stack == "nginx_mongrel"
|
|
72
|
+
enable_maintenance_page
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def disable_maintenance_page
|
|
77
|
+
@maintenance_up = false
|
|
78
|
+
roles :app_master, :app, :solo do
|
|
79
|
+
run "rm -f #{File.join(c.shared_path, "system", "maintenance.html")}"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def run_with_callbacks(task, *args)
|
|
84
|
+
callback(:"before_#{task}")
|
|
85
|
+
send(task, *args)
|
|
86
|
+
callback(:"after_#{task}")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# task
|
|
90
|
+
def push_code
|
|
91
|
+
info "~> Pushing code to all servers"
|
|
92
|
+
barrier *(EY::Server.all.map do |server|
|
|
93
|
+
need_later { server.push_code }
|
|
94
|
+
end)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# task
|
|
98
|
+
def restart
|
|
99
|
+
@restart_failed = true
|
|
100
|
+
info "~> Restarting app servers"
|
|
101
|
+
roles :app_master, :app, :solo do
|
|
102
|
+
restart_command = case c.stack
|
|
103
|
+
when "nginx_unicorn"
|
|
104
|
+
pidfile = "/var/run/engineyard/unicorn_#{c.app}.pid"
|
|
105
|
+
condition = "[ -e #{pidfile} ] && [ ! -d /proc/`cat #{pidfile}` ]"
|
|
106
|
+
run("if #{condition}; then rm -f #{pidfile}; fi")
|
|
107
|
+
run("/engineyard/bin/app_#{c.app} deploy")
|
|
108
|
+
when "nginx_mongrel"
|
|
109
|
+
sudo("monit restart all -g #{c.app}")
|
|
110
|
+
when "nginx_passenger"
|
|
111
|
+
run("touch #{c.current_path}/tmp/restart.txt")
|
|
112
|
+
else
|
|
113
|
+
raise "Unknown stack #{c.stack}; restart failed!"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
@restart_failed = false
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# task
|
|
120
|
+
def bundle
|
|
121
|
+
if File.exist?("#{c.release_path}/Gemfile")
|
|
122
|
+
info "~> Gemfile detected, bundling gems"
|
|
123
|
+
lockfile = File.join(c.release_path, "Gemfile.lock")
|
|
124
|
+
|
|
125
|
+
bundler_installer = if File.exist?(lockfile)
|
|
126
|
+
get_bundler_installer(lockfile)
|
|
127
|
+
else
|
|
128
|
+
warn_about_missing_lockfile
|
|
129
|
+
BundleInstaller.new(DEFAULT_09_BUNDLER, "--without=development --without=test")
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
sudo "#{$0} _#{VERSION}_ install_bundler #{bundler_installer.version}"
|
|
133
|
+
|
|
134
|
+
run "cd #{c.release_path} && bundle _#{bundler_installer.version}_ install #{bundler_installer.options}"
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# task
|
|
139
|
+
def cleanup_old_releases
|
|
140
|
+
@cleanup_failed = true
|
|
141
|
+
info "~> Cleaning up old releases"
|
|
142
|
+
sudo "ls #{c.release_dir} | head -n -3 | xargs -I{} rm -rf #{c.release_dir}/{}"
|
|
143
|
+
@cleanup_failed = false
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# task
|
|
147
|
+
def rollback
|
|
148
|
+
if c.all_releases.size > 1
|
|
149
|
+
c.release_path = c.previous_release
|
|
150
|
+
|
|
151
|
+
revision = File.read(File.join(c.release_path, 'REVISION')).strip
|
|
152
|
+
info "~> Rolling back to previous release: #{short_log_message(revision)}"
|
|
153
|
+
|
|
154
|
+
run_with_callbacks(:symlink, c.previous_release)
|
|
155
|
+
cleanup_current_release
|
|
156
|
+
bundle
|
|
157
|
+
info "~> Restarting with previous release"
|
|
158
|
+
with_maintenance_page { run_with_callbacks(:restart) }
|
|
159
|
+
else
|
|
160
|
+
info "~> Already at oldest release, nothing to roll back to"
|
|
161
|
+
exit(1)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# task
|
|
166
|
+
def migrate
|
|
167
|
+
return unless c.migrate?
|
|
168
|
+
@migrations_reached = true
|
|
169
|
+
roles :app_master, :solo do
|
|
170
|
+
cmd = "cd #{c.release_path} && #{c.framework_envs} #{c.migration_command}"
|
|
171
|
+
info "~> Migrating: #{cmd}"
|
|
172
|
+
run(cmd)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# task
|
|
177
|
+
def copy_repository_cache
|
|
178
|
+
info "~> Copying to #{c.release_path}"
|
|
179
|
+
run("mkdir -p #{c.release_path} && rsync -aq #{c.exclusions} #{c.repository_cache}/ #{c.release_path}")
|
|
180
|
+
|
|
181
|
+
info "~> Ensuring proper ownership"
|
|
182
|
+
sudo("chown -R #{c.user}:#{c.group} #{c.deploy_to}")
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def create_revision_file
|
|
186
|
+
run create_revision_file_command
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def symlink_configs(release_to_link=c.release_path)
|
|
190
|
+
info "~> Symlinking configs"
|
|
191
|
+
[ "chmod -R g+w #{release_to_link}",
|
|
192
|
+
"rm -rf #{release_to_link}/log #{release_to_link}/public/system #{release_to_link}/tmp/pids",
|
|
193
|
+
"mkdir -p #{release_to_link}/tmp",
|
|
194
|
+
"ln -nfs #{c.shared_path}/log #{release_to_link}/log",
|
|
195
|
+
"mkdir -p #{release_to_link}/public",
|
|
196
|
+
"mkdir -p #{release_to_link}/config",
|
|
197
|
+
"ln -nfs #{c.shared_path}/system #{release_to_link}/public/system",
|
|
198
|
+
"ln -nfs #{c.shared_path}/pids #{release_to_link}/tmp/pids",
|
|
199
|
+
"ln -nfs #{c.shared_path}/config/database.yml #{release_to_link}/config/database.yml",
|
|
200
|
+
"ln -nfs #{c.shared_path}/config/mongrel_cluster.yml #{release_to_link}/config/mongrel_cluster.yml",
|
|
201
|
+
].each do |cmd|
|
|
202
|
+
run cmd
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
sudo "chown -R #{c.user}:#{c.group} #{release_to_link}"
|
|
206
|
+
run "if [ -f \"#{c.shared_path}/config/newrelic.yml\" ]; then ln -nfs #{c.shared_path}/config/newrelic.yml #{release_to_link}/config/newrelic.yml; fi"
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# task
|
|
210
|
+
def symlink(release_to_link=c.release_path)
|
|
211
|
+
info "~> Symlinking code"
|
|
212
|
+
run "rm -f #{c.current_path} && ln -nfs #{release_to_link} #{c.current_path} && chown -R #{c.user}:#{c.group} #{c.current_path}"
|
|
213
|
+
@symlink_changed = true
|
|
214
|
+
rescue Exception
|
|
215
|
+
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}"
|
|
216
|
+
@symlink_changed = false
|
|
217
|
+
raise
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def callback(what)
|
|
221
|
+
@callbacks_reached ||= true
|
|
222
|
+
if File.exist?("#{c.release_path}/deploy/#{what}.rb")
|
|
223
|
+
eydeploy_path = $0 # invoke others just like we were invoked
|
|
224
|
+
run "#{eydeploy_path} _#{VERSION}_ hook '#{what}' --app '#{config.app}' --release-path #{config.release_path}" do |server, cmd|
|
|
225
|
+
cmd << " --framework-env '#{c.environment}'"
|
|
226
|
+
cmd << " --current-role '#{server.role}'"
|
|
227
|
+
cmd << " --current-name '#{server.name}'" if server.name
|
|
228
|
+
cmd << " --config '#{c[:config]}'" if c.has_key?(:config)
|
|
229
|
+
cmd
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
protected
|
|
235
|
+
|
|
236
|
+
def puts_deploy_failure
|
|
237
|
+
if @cleanup_failed
|
|
238
|
+
info "~> [Relax] Your site is running new code, but cleaning up old deploys failed"
|
|
239
|
+
elsif @maintenance_up
|
|
240
|
+
info "~> [Attention] Maintenance page still up, consider the following before removing:"
|
|
241
|
+
info " * any deploy hooks ran, be careful if they were destructive" if @callbacks_reached
|
|
242
|
+
info " * any migrations ran, be careful if they were destructive" if @migrations_reached
|
|
243
|
+
if @symlink_changed
|
|
244
|
+
info " * your new code is symlinked as current"
|
|
245
|
+
else
|
|
246
|
+
info " * your old code is still symlinked as current"
|
|
247
|
+
end
|
|
248
|
+
info " * application servers failed to restart" if @restart_failed
|
|
249
|
+
else
|
|
250
|
+
info "~> [Relax] Your site is still running old code and nothing destructive could have occurred"
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def with_maintenance_page
|
|
255
|
+
conditionally_enable_maintenance_page
|
|
256
|
+
yield if block_given?
|
|
257
|
+
disable_maintenance_page
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def with_failed_release_cleanup
|
|
261
|
+
yield
|
|
262
|
+
rescue Exception
|
|
263
|
+
cleanup_current_release
|
|
264
|
+
raise
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def cleanup_current_release
|
|
268
|
+
sudo "rm -rf #{c.release_path}"
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
DEFAULT_09_BUNDLER = '0.9.26'
|
|
272
|
+
DEFAULT_10_BUNDLER = '1.0.0.rc.3'
|
|
273
|
+
|
|
274
|
+
def warn_about_missing_lockfile
|
|
275
|
+
info "!>"
|
|
276
|
+
info "!> WARNING: Gemfile.lock is missing!"
|
|
277
|
+
info "!> You can get different gems in production than what you tested with."
|
|
278
|
+
info "!> You can get different gems on every deployment even if your Gemfile hasn't changed."
|
|
279
|
+
info "!> Deploying may take a long time."
|
|
280
|
+
info "!>"
|
|
281
|
+
info "!> Fix this by running \"git add Gemfile.lock; git commit\" and deploying again."
|
|
282
|
+
info "!> If you don't have a Gemfile.lock, run \"bundle lock\" to create one."
|
|
283
|
+
info "!>"
|
|
284
|
+
info "!> This deployment will use bundler #{DEFAULT_09_BUNDLER} to run 'bundle install'."
|
|
285
|
+
info "!>"
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def get_bundler_installer(lockfile)
|
|
289
|
+
parser = LockfileParser.new(File.read(lockfile))
|
|
290
|
+
case parser.lockfile_version
|
|
291
|
+
when :bundler09
|
|
292
|
+
BundleInstaller.new(
|
|
293
|
+
parser.bundler_version || DEFAULT_09_BUNDLER,
|
|
294
|
+
"--without=development --without=test")
|
|
295
|
+
when :bundler10
|
|
296
|
+
BundleInstaller.new(
|
|
297
|
+
parser.bundler_version || DEFAULT_10_BUNDLER,
|
|
298
|
+
"--deployment --path #{c.shared_path}/bundled_gems --without development test"
|
|
299
|
+
)
|
|
300
|
+
else
|
|
301
|
+
raise "Unknown lockfile version #{parser.lockfile_version}"
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
public :get_bundler_installer
|
|
305
|
+
|
|
306
|
+
end # DeployBase
|
|
307
|
+
|
|
308
|
+
class Deploy < DeployBase
|
|
309
|
+
def self.new(opts={})
|
|
310
|
+
# include the correct fetch strategy
|
|
311
|
+
include EY::Strategies.const_get(opts.strategy)::Helpers
|
|
312
|
+
super
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def self.run(opts={})
|
|
316
|
+
conf = EY::Deploy::Configuration.new(opts)
|
|
317
|
+
EY::Server.config = conf
|
|
318
|
+
new(conf).send(opts["default_task"])
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
end
|