engineyard 0.4.0 → 0.5.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/lib/engineyard.rb +1 -1
- data/lib/engineyard/api.rb +12 -1
- data/lib/engineyard/cli.rb +116 -48
- data/lib/engineyard/cli/recipes.rb +37 -7
- data/lib/engineyard/cli/ui.rb +8 -0
- data/lib/engineyard/cli/web.rb +41 -0
- data/lib/engineyard/error.rb +8 -1
- data/lib/engineyard/model/environment.rb +32 -6
- data/lib/engineyard/model/instance.rb +39 -20
- data/lib/engineyard/repo.rb +7 -3
- data/lib/engineyard/thor.rb +55 -2
- data/spec/engineyard/api_spec.rb +2 -2
- data/spec/engineyard/cli/api_spec.rb +1 -1
- data/spec/engineyard/model/environment_spec.rb +8 -6
- data/spec/ey/deploy_spec.rb +46 -81
- data/spec/ey/ey_spec.rb +2 -2
- data/spec/ey/list_environments_spec.rb +1 -1
- data/spec/ey/logs_spec.rb +11 -21
- data/spec/ey/rebuild_spec.rb +8 -33
- data/spec/ey/recipes/apply_spec.rb +8 -33
- data/spec/ey/recipes/download_spec.rb +29 -0
- data/spec/ey/recipes/upload_spec.rb +8 -25
- data/spec/ey/rollback_spec.rb +10 -40
- data/spec/ey/ssh_spec.rb +17 -34
- data/spec/ey/web/disable_spec.rb +18 -0
- data/spec/ey/web/enable_spec.rb +18 -0
- data/spec/spec_helper.rb +7 -3
- data/spec/support/fake_awsm.ru +18 -0
- data/spec/support/helpers.rb +13 -0
- data/spec/support/shared_behavior.rb +132 -0
- metadata +8 -3
@@ -3,7 +3,7 @@ require 'escape'
|
|
3
3
|
module EY
|
4
4
|
module Model
|
5
5
|
class Instance < ApiStruct.new(:id, :role, :status, :amazon_id, :public_hostname, :environment)
|
6
|
-
EYSD_VERSION = "~>0.4.
|
6
|
+
EYSD_VERSION = "~>0.4.1"
|
7
7
|
CHECK_SCRIPT = <<-SCRIPT
|
8
8
|
require "rubygems"
|
9
9
|
requirement = Gem::Requirement.new("#{EYSD_VERSION}")
|
@@ -29,7 +29,8 @@ exit(17) # required_version < current_version
|
|
29
29
|
|
30
30
|
alias :hostname :public_hostname
|
31
31
|
|
32
|
-
|
32
|
+
|
33
|
+
def deploy(app, ref, migration_command=nil, extra_configuration=nil)
|
33
34
|
deploy_cmd = [eysd_path, 'deploy', '--app', app.name, '--branch', ref]
|
34
35
|
|
35
36
|
if extra_configuration
|
@@ -43,18 +44,42 @@ exit(17) # required_version < current_version
|
|
43
44
|
ssh Escape.shell_command(deploy_cmd)
|
44
45
|
end
|
45
46
|
|
46
|
-
def
|
47
|
+
def rollback(app, extra_configuration=nil)
|
48
|
+
deploy_cmd = [eysd_path, 'deploy', 'rollback', '--app', app.name]
|
49
|
+
|
50
|
+
if extra_configuration
|
51
|
+
deploy_cmd << '--config' << extra_configuration.to_json
|
52
|
+
end
|
53
|
+
|
54
|
+
ssh Escape.shell_command(deploy_cmd)
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def put_up_maintenance_page(app)
|
59
|
+
ssh Escape.shell_command([
|
60
|
+
eysd_path, 'deploy', 'enable_maintenance_page', '--app', app.name
|
61
|
+
])
|
62
|
+
end
|
63
|
+
|
64
|
+
def take_down_maintenance_page(app)
|
65
|
+
ssh Escape.shell_command([
|
66
|
+
eysd_path, 'deploy', 'disable_maintenance_page', '--app', app.name
|
67
|
+
])
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
def ensure_eysd_present
|
47
72
|
case ey_deploy_check
|
48
73
|
when :ssh_failed
|
49
74
|
raise EnvironmentError, "SSH connection to #{hostname} failed"
|
50
75
|
when :eysd_missing
|
51
76
|
yield :installing if block_given?
|
52
|
-
install_ey_deploy
|
77
|
+
install_ey_deploy
|
53
78
|
when :too_new
|
54
79
|
raise EnvironmentError, "server-side component too new; please upgrade your copy of the engineyard gem."
|
55
80
|
when :too_old
|
56
81
|
yield :upgrading if block_given?
|
57
|
-
upgrade_ey_deploy
|
82
|
+
upgrade_ey_deploy
|
58
83
|
when :ok
|
59
84
|
# no action needed
|
60
85
|
else
|
@@ -66,26 +91,20 @@ exit(17) # required_version < current_version
|
|
66
91
|
require 'base64'
|
67
92
|
encoded_script = Base64.encode64(CHECK_SCRIPT).gsub(/\n/, '')
|
68
93
|
ssh "#{ruby_path} -r base64 -e \"eval Base64.decode64(ARGV[0])\" #{encoded_script}", false
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
ssh(Escape.shell_command(['sudo', gem_path, 'install', 'ey-deploy', '-v', EYSD_VERSION]))
|
74
|
-
end
|
75
|
-
|
76
|
-
def rollback!(app, extra_configuration=nil)
|
77
|
-
deploy_cmd = [eysd_path, 'deploy', 'rollback', '--app', app.name]
|
78
|
-
|
79
|
-
if extra_configuration
|
80
|
-
deploy_cmd << '--config' << extra_configuration.to_json
|
94
|
+
if ENV["NO_SSH"]
|
95
|
+
:ok
|
96
|
+
else
|
97
|
+
EXIT_STATUS[$?.exitstatus]
|
81
98
|
end
|
99
|
+
end
|
82
100
|
|
83
|
-
|
101
|
+
def install_ey_deploy
|
102
|
+
ssh(Escape.shell_command(['sudo', gem_path, 'install', 'ey-deploy', '--no-rdoc', '--no-ri', '-v', EYSD_VERSION]))
|
84
103
|
end
|
85
104
|
|
86
|
-
def upgrade_ey_deploy
|
105
|
+
def upgrade_ey_deploy
|
87
106
|
ssh "sudo #{gem_path} uninstall -a -x ey-deploy"
|
88
|
-
install_ey_deploy
|
107
|
+
install_ey_deploy
|
89
108
|
end
|
90
109
|
|
91
110
|
private
|
data/lib/engineyard/repo.rb
CHANGED
@@ -6,9 +6,13 @@ module EY
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def current_branch
|
9
|
-
|
10
|
-
|
11
|
-
head
|
9
|
+
if File.directory?(File.join(@path, ".git"))
|
10
|
+
head = File.read(File.join(@path, ".git/HEAD")).chomp
|
11
|
+
if head.gsub!("ref: refs/heads/", "")
|
12
|
+
head
|
13
|
+
else
|
14
|
+
nil
|
15
|
+
end
|
12
16
|
else
|
13
17
|
nil
|
14
18
|
end
|
data/lib/engineyard/thor.rb
CHANGED
@@ -9,17 +9,56 @@ module EY
|
|
9
9
|
end
|
10
10
|
|
11
11
|
no_tasks do
|
12
|
-
def
|
13
|
-
@@
|
12
|
+
def self.subcommands
|
13
|
+
@@subcommands ||= {}
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.subcommand(subcommand, subcommand_class)
|
17
|
+
subcommand = subcommand.to_s
|
18
|
+
subcommands[subcommand] = subcommand_class
|
19
|
+
subcommand_class.subcommand_help subcommand
|
17
20
|
define_method(subcommand) { |*_| subcommand_class.start(subcommand_args) }
|
18
21
|
end
|
22
|
+
|
23
|
+
def self.subcommand_help(cmd)
|
24
|
+
desc "help #{cmd} [SUBCOMMAND]", "Describe all subcommands or one specific subcommand."
|
25
|
+
|
26
|
+
class_eval <<-RUBY
|
27
|
+
def help(*args)
|
28
|
+
super
|
29
|
+
if args.empty?
|
30
|
+
banner = "See '" + self.class.send(:banner_base) + " help #{cmd} [SUBCOMMAND]' "
|
31
|
+
text = "for more information on a specific subcommand."
|
32
|
+
EY.ui.say banner + text
|
33
|
+
end
|
34
|
+
end
|
35
|
+
RUBY
|
36
|
+
end
|
37
|
+
|
38
|
+
def subcommand_args
|
39
|
+
@@original_args[1..-1]
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.printable_tasks(all=true)
|
43
|
+
(all ? all_tasks : tasks).map do |_, task|
|
44
|
+
item = []
|
45
|
+
item << banner(task)
|
46
|
+
item << (task.description ? "# #{task.description.gsub(/\n.*/,'')}" : "")
|
47
|
+
item
|
48
|
+
end
|
49
|
+
end
|
19
50
|
end
|
20
51
|
|
21
52
|
protected
|
22
53
|
|
54
|
+
def self.handle_no_task_error(task)
|
55
|
+
if self.banner_base == "thor"
|
56
|
+
raise UndefinedTaskError, "Could not find command #{task.inspect} in #{namespace.inspect} namespace."
|
57
|
+
else
|
58
|
+
raise UndefinedTaskError, "Could not find command #{task.inspect}."
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
23
62
|
def self.exit_on_failure?
|
24
63
|
true
|
25
64
|
end
|
@@ -32,6 +71,20 @@ module EY
|
|
32
71
|
@repo ||= EY::Repo.new
|
33
72
|
end
|
34
73
|
|
74
|
+
def loudly_check_eysd(environment)
|
75
|
+
environment.ensure_eysd_present do |action|
|
76
|
+
case action
|
77
|
+
when :installing
|
78
|
+
EY.ui.warn "Instance does not have server-side component installed"
|
79
|
+
EY.ui.info "Installing server-side component..."
|
80
|
+
when :upgrading
|
81
|
+
EY.ui.info "Upgrading server-side component..."
|
82
|
+
else
|
83
|
+
# nothing slow is happening, so there's nothing to say
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
35
88
|
# if an app is supplied, it is used as a constraint for implied environment lookup
|
36
89
|
def fetch_environment(env_name, app = nil)
|
37
90
|
env_name ||= EY.config.default_environment
|
data/spec/engineyard/api_spec.rb
CHANGED
@@ -8,7 +8,7 @@ describe EY::API do
|
|
8
8
|
|
9
9
|
context "fetching the token from EY cloud" do
|
10
10
|
before(:each) do
|
11
|
-
FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/authenticate", :body => %|{"api_token": "asdf"}
|
11
|
+
FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/authenticate", :body => %|{"api_token": "asdf"}|, :content_type => 'application/json')
|
12
12
|
@token = EY::API.fetch_token("a@b.com", "foo")
|
13
13
|
end
|
14
14
|
|
@@ -46,7 +46,7 @@ describe EY::API do
|
|
46
46
|
end
|
47
47
|
|
48
48
|
it "raises InvalidCredentials when the credentials are invalid" do
|
49
|
-
FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/authenticate", :status => 401)
|
49
|
+
FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/authenticate", :status => 401, :content_type => 'application/json')
|
50
50
|
|
51
51
|
lambda {
|
52
52
|
EY::API.fetch_token("a@b.com", "foo")
|
@@ -20,7 +20,7 @@ describe EY::CLI::API do
|
|
20
20
|
|
21
21
|
context "without saved api token" do
|
22
22
|
before(:each) do
|
23
|
-
FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/authenticate", :body => %|{"api_token": "asdf"}
|
23
|
+
FakeWeb.register_uri(:post, "https://cloud.engineyard.com/api/v2/authenticate", :body => %|{"api_token": "asdf"}|, :content_type => 'application/json')
|
24
24
|
|
25
25
|
capture_stdio("\n\n") do
|
26
26
|
@token = EY::CLI::API.new
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe "EY::Model::Environment#rebuild" do
|
4
|
-
|
4
|
+
given "it has an api"
|
5
5
|
|
6
6
|
it "hits the rebuild action in the API" do
|
7
7
|
env = EY::Model::Environment.from_hash({
|
@@ -22,7 +22,7 @@ describe "EY::Model::Environment#rebuild" do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
describe "EY::Model::Environment#run_custom_recipes" do
|
25
|
-
|
25
|
+
given "it has an api"
|
26
26
|
|
27
27
|
it "hits the rebuild action in the API" do
|
28
28
|
env = EY::Model::Environment.from_hash({
|
@@ -33,7 +33,8 @@ describe "EY::Model::Environment#run_custom_recipes" do
|
|
33
33
|
FakeWeb.register_uri(
|
34
34
|
:put,
|
35
35
|
"https://cloud.engineyard.com/api/v2/environments/#{env.id}/run_custom_recipes",
|
36
|
-
:body => ''
|
36
|
+
:body => '',
|
37
|
+
:content_type => 'application/json'
|
37
38
|
)
|
38
39
|
|
39
40
|
env.run_custom_recipes
|
@@ -56,7 +57,7 @@ describe "EY::Model::Environment.from_array" do
|
|
56
57
|
end
|
57
58
|
|
58
59
|
describe "EY::Model::Environment#instances" do
|
59
|
-
|
60
|
+
given "it has an api"
|
60
61
|
|
61
62
|
it "returns instances" do
|
62
63
|
env = EY::Model::Environment.from_hash({
|
@@ -72,8 +73,9 @@ describe "EY::Model::Environment#instances" do
|
|
72
73
|
}
|
73
74
|
FakeWeb.register_uri(:get,
|
74
75
|
"https://cloud.engineyard.com/api/v2/environments/#{env.id}/instances",
|
75
|
-
:body => {"instances" => [instance_data]}.to_json
|
76
|
-
|
76
|
+
:body => {"instances" => [instance_data]}.to_json,
|
77
|
+
:content_type => 'application/json'
|
78
|
+
)
|
77
79
|
|
78
80
|
env.should have(1).instances
|
79
81
|
env.instances.first.should == EY::Model::Instance.from_hash(instance_data.merge(:environment => env))
|
data/spec/ey/deploy_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe "ey deploy without an eyrc file" do
|
4
4
|
|
5
|
-
|
5
|
+
given "integration without an eyrc file"
|
6
6
|
|
7
7
|
before(:each) do
|
8
8
|
FileUtils.rm_rf(ENV['EYRC'])
|
@@ -22,8 +22,27 @@ describe "ey deploy without an eyrc file" do
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
|
25
26
|
describe "ey deploy" do
|
26
|
-
|
27
|
+
given "integration"
|
28
|
+
|
29
|
+
def command_to_run(options)
|
30
|
+
cmd = "deploy"
|
31
|
+
cmd << " -e #{options[:env]}" if options[:env]
|
32
|
+
cmd
|
33
|
+
end
|
34
|
+
|
35
|
+
def verify_ran(scenario)
|
36
|
+
@out.should match(/Running deploy for '#{scenario[:environment]}'/)
|
37
|
+
end
|
38
|
+
|
39
|
+
# common behavior
|
40
|
+
it_should_behave_like "it takes an environment name"
|
41
|
+
it_should_behave_like "it invokes eysd"
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "ey deploy" do
|
45
|
+
given "integration"
|
27
46
|
|
28
47
|
context "with invalid input" do
|
29
48
|
it "complains when there is no app" do
|
@@ -32,15 +51,9 @@ describe "ey deploy" do
|
|
32
51
|
@err.should include(%|no application configured|)
|
33
52
|
end
|
34
53
|
|
35
|
-
it "complains when you specify a nonexistent environment" do
|
36
|
-
api_scenario "one app, one environment"
|
37
|
-
ey "deploy typo-happens-here master", :expect_failure => true
|
38
|
-
@err.should match(/no environment named 'typo-happens-here'/i)
|
39
|
-
end
|
40
|
-
|
41
54
|
it "complains when the specified environment does not contain the app" do
|
42
55
|
api_scenario "one app, one environment, not linked"
|
43
|
-
ey "deploy giblets master", :expect_failure => true
|
56
|
+
ey "deploy -e giblets -r master", :expect_failure => true
|
44
57
|
@err.should match(/does not run this application/i)
|
45
58
|
end
|
46
59
|
|
@@ -52,19 +65,12 @@ describe "ey deploy" do
|
|
52
65
|
|
53
66
|
it "complains when the app master is in a non-running state" do
|
54
67
|
api_scenario "one app, one environment, app master red"
|
55
|
-
ey "deploy giblets master", :expect_failure => true
|
68
|
+
ey "deploy --environment giblets --ref master", :expect_failure => true
|
56
69
|
@err.should_not match(/No running instances/i)
|
57
70
|
@err.should match(/running.*\(green\)/)
|
58
71
|
end
|
59
72
|
end
|
60
73
|
|
61
|
-
it "runs when environment is known" do
|
62
|
-
api_scenario "one app, one environment"
|
63
|
-
ey "deploy", :hide_err => true
|
64
|
-
@out.should match(/running deploy/i)
|
65
|
-
@err.should be_empty
|
66
|
-
end
|
67
|
-
|
68
74
|
context "migration command" do
|
69
75
|
before(:each) do
|
70
76
|
api_scenario "one app, one environment"
|
@@ -86,11 +92,6 @@ describe "ey deploy" do
|
|
86
92
|
@ssh_commands.last.should =~ /eysd deploy/
|
87
93
|
@ssh_commands.last.should_not =~ /--migrate/
|
88
94
|
end
|
89
|
-
|
90
|
-
it "can be disabled with --no-migrate in the middle of the command line" do
|
91
|
-
ey "deploy --no-migrate giblets master"
|
92
|
-
@ssh_commands.last.should_not =~ /--migrate/
|
93
|
-
end
|
94
95
|
end
|
95
96
|
|
96
97
|
context "choosing something to deploy" do
|
@@ -120,14 +121,24 @@ describe "ey deploy" do
|
|
120
121
|
end
|
121
122
|
|
122
123
|
it "deploys another branch if given" do
|
123
|
-
ey "deploy
|
124
|
+
ey "deploy --ref master"
|
124
125
|
@ssh_commands.last.should =~ /--branch master/
|
125
126
|
end
|
126
127
|
|
127
128
|
it "deploys a tag if given" do
|
128
|
-
ey "deploy
|
129
|
+
ey "deploy --ref v1"
|
129
130
|
@ssh_commands.last.should =~ /--branch v1/
|
130
131
|
end
|
132
|
+
|
133
|
+
it "allows using --branch to specify a branch" do
|
134
|
+
ey "deploy --branch master"
|
135
|
+
@ssh_commands.last.should match(/--branch master/)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "allows using --tag to specify the tag" do
|
139
|
+
ey "deploy --tag v1"
|
140
|
+
@ssh_commands.last.should match(/--branch v1/)
|
141
|
+
end
|
131
142
|
end
|
132
143
|
|
133
144
|
context "when there is extra configuration" do
|
@@ -160,12 +171,12 @@ describe "ey deploy" do
|
|
160
171
|
end
|
161
172
|
|
162
173
|
it "complains about a non-default branch without --force" do
|
163
|
-
ey "deploy
|
174
|
+
ey "deploy -r current-branch", :expect_failure => true
|
164
175
|
@err.should =~ /deploy branch is set to "master"/
|
165
176
|
end
|
166
177
|
|
167
178
|
it "deploys a non-default branch with --force" do
|
168
|
-
ey "deploy
|
179
|
+
ey "deploy -r current-branch --force"
|
169
180
|
@ssh_commands.last.should =~ /--branch current-branch/
|
170
181
|
end
|
171
182
|
end
|
@@ -176,72 +187,26 @@ describe "ey deploy" do
|
|
176
187
|
api_scenario "one app, many similarly-named environments"
|
177
188
|
end
|
178
189
|
|
179
|
-
it "lets you choose by unambiguous substring" do
|
180
|
-
ey "deploy prod"
|
181
|
-
@out.should match(/Running deploy for 'railsapp_production'/)
|
182
|
-
end
|
183
|
-
|
184
190
|
it "lets you choose by complete name even if the complete name is ambiguous" do
|
185
|
-
ey "deploy railsapp_staging"
|
191
|
+
ey "deploy --environment railsapp_staging"
|
186
192
|
@out.should match(/Running deploy for 'railsapp_staging'/)
|
187
193
|
end
|
188
|
-
|
189
|
-
it "complains when given an ambiguous substring" do
|
190
|
-
# NB: there's railsapp_staging and railsapp_staging_2
|
191
|
-
ey "deploy staging", :hide_err => true, :expect_failure => true
|
192
|
-
@err.should match(/'staging' is ambiguous/)
|
193
|
-
end
|
194
194
|
end
|
195
195
|
|
196
|
-
context "
|
196
|
+
context "specifying the application" do
|
197
197
|
before(:all) do
|
198
198
|
api_scenario "one app, one environment"
|
199
|
+
Dir.chdir(File.expand_path("~"))
|
199
200
|
end
|
200
201
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
after(:each) do
|
206
|
-
ENV['NO_SSH'] = "true"
|
207
|
-
end
|
208
|
-
|
209
|
-
def exiting_ssh(exit_code)
|
210
|
-
"#!/usr/bin/env ruby\n exit!(#{exit_code}) if ARGV.to_s =~ /Base64.decode64/"
|
211
|
-
end
|
212
|
-
|
213
|
-
it "raises an error if SSH fails" do
|
214
|
-
ey "deploy", :prepend_to_path => {'ssh' => exiting_ssh(255)}, :expect_failure => true
|
215
|
-
@err.should =~ /SSH connection to \S+ failed/
|
216
|
-
end
|
217
|
-
|
218
|
-
it "installs ey-deploy if it's missing" do
|
219
|
-
ey "deploy", :prepend_to_path => {'ssh' => exiting_ssh(104)}
|
220
|
-
|
221
|
-
gem_install_command = @ssh_commands.find do |command|
|
222
|
-
command =~ /gem install ey-deploy/
|
223
|
-
end
|
224
|
-
gem_install_command.should =~ %r{/usr/local/ey_resin/ruby/bin/gem install}
|
225
|
-
end
|
226
|
-
|
227
|
-
it "upgrades ey-deploy if it's too old" do
|
228
|
-
ey "deploy", :prepend_to_path => {'ssh' => exiting_ssh(70)}
|
229
|
-
@ssh_commands.should have_command_like(/gem uninstall -a -x ey-deploy/)
|
230
|
-
@ssh_commands.should have_command_like(/gem install ey-deploy/)
|
231
|
-
end
|
232
|
-
|
233
|
-
it "raises an error if ey-deploy is too new" do
|
234
|
-
ey "deploy", :prepend_to_path => {'ssh' => exiting_ssh(17)}, :expect_failure => true
|
235
|
-
@ssh_commands.should_not have_command_like(/gem install ey-deploy/)
|
236
|
-
@ssh_commands.should_not have_command_like(/eysd deploy/)
|
237
|
-
@err.should match(/too new/i)
|
202
|
+
it "allows you to specify an app when not in a directory" do
|
203
|
+
ey "deploy --app rails232app --ref master"
|
204
|
+
@ssh_commands.last.should match(/deploy --app rails232app --branch master --migrate 'rake db:migrate'/)
|
238
205
|
end
|
239
206
|
|
240
|
-
it "
|
241
|
-
ey "deploy", :
|
242
|
-
@
|
243
|
-
@ssh_commands.should_not have_command_like(/gem uninstall.* ey-deploy/)
|
244
|
-
@ssh_commands.should have_command_like(/eysd deploy/)
|
207
|
+
it "requires that you specify a ref when specifying the application" do
|
208
|
+
ey "deploy --app rails232app", :expect_failure => true
|
209
|
+
@err.should match(/you must also specify the ref to deploy/)
|
245
210
|
end
|
246
211
|
end
|
247
212
|
end
|