shuttle-deploy 0.2.0.beta4 → 0.2.0.beta5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NTdhYWM4MjI3ZmUyZjE5Mzc4YTJjNjFjYjA2ODViZWE3YWVlZTllZg==
4
+ NjM4NmQ3ZGZhOTQwNGNmMzkxYzM4ZjNiZTM3MjUwMzNhMTY2NWFhZQ==
5
5
  data.tar.gz: !binary |-
6
- MzUxMzk0ZDlhMGYyYWNjYmI2YjdkMmM5NzNkN2I2MmM5YWRjOTI2MQ==
6
+ NzYyNTBlODY1NmE2ZTNmYjFmZmM0MDY1MzU4NzQzM2UwZmY0N2JjZg==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- NzVkZTFlNzgxMGI1ZjNmMDQ5ZmVjYjRiNzVmNGYwMWU2NDBmYmJkNzllZDA4
10
- ZTBhYmUwMjQ3YjZlOGEzMGMxODVmMWY2MzAwMjQ3NWU3NzU5ZjJiNjZiZTJi
11
- ZjllNTIxYzBkN2I0NDJiODM1NGEzODI3NDM2NmNhZTBiZGQ2MmY=
9
+ N2IzN2ZiZTdlNzg4ZWUyMjgzM2Q3NWYzYjZjZjllYTBiOGEwZDJkMTExMjRj
10
+ MGZiN2NmY2FhZGQ3MmUzYmY5Y2RiN2ZlNDYzODM4NGQ2YTk0MjRjNjIyYjBh
11
+ YWI2YzljNzYwMDUzMjYwODg4ZGI1ZDhmOTIxNmU0NzJhZDAyMzE=
12
12
  data.tar.gz: !binary |-
13
- YmY3NGUwNDUyM2NkYWQ1ZjkwMWQ4ZjIyOWFjMWFkMDFmYmQ4OTU0ZTZkMzAy
14
- YzVmNTdmYTA4MDVkYmYzNzhkZDJmY2QxZWFmMjgwYjM1OTNhNGJkZmJkODcz
15
- ZTIyM2Y2ZTAyODBhNWI0MDgyZmRlMTRmY2M0YTlmNWY4YTg2MDM=
13
+ OTA3YzJjNTc3NDZjYzQ0ZDg2ZmUwOWFjYzUyMTUzZGMwOTRlZDJiNTJiOTZk
14
+ Y2FkMzRmMmIxYmY4YTg0YmY1Yzk3ZWY0MzU4NWFiMzM2ZGIwY2UyYWUyMmM4
15
+ NjZhMTc0YTQ3M2ZhYTNiOTUwYzA3Yzg0MDYyZmM4NDQ1YWE2ZGU=
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Shuttle
1
+ # Shuttle ![Build Status](https://magnum-ci.com/status/dea40dc3b6055d6a628a444149e2fead.png)
2
2
 
3
3
  Shuttle is a minimalistic application deployment tool designed for small applications
4
4
  and one-server deployments. Configuration is stored as YAML-encoded file, no need to use ruby code.
@@ -88,7 +88,62 @@ target:
88
88
  ### WordPress Strategy
89
89
 
90
90
  This strategy is designed to deploy wordpress sites developed as a separate theme.
91
- It requires `subversion` installed on the server (will be automatically installed).
91
+ It requires `subversion` installed on the server (will be automatically installed).
92
+
93
+ Define strategy:
94
+
95
+ ```
96
+ app:
97
+ strategy: wordpress
98
+ ```
99
+
100
+ Wordpress applications are configured and deployed with `wp` cli utility. On a clean setup
101
+ shuttle will attempt to install wp-cli and wordpress core first. CLI is installed from
102
+ main github repository and latest stable tag. Wordpress core will install latest version.
103
+ To specify required versions, use wordpress section:
104
+
105
+ ```
106
+ wordpress:
107
+ core: 3.5.1
108
+ cli: 0.9.1
109
+ ```
110
+
111
+ Then, you'll need to define theme and wp related options:
112
+
113
+ ```
114
+ wordpress:
115
+ theme: my-theme
116
+ site:
117
+ title: "Site Title"
118
+ url: "http://sample-site.com"
119
+ admin_name: "admin"
120
+ admin_email: "admin@admin.com"
121
+ admin_password: "password"
122
+ ```
123
+
124
+ Database options:
125
+
126
+ ```
127
+ wordpress:
128
+ mysql:
129
+ host: 127.0.0.1
130
+ user: mysql-user
131
+ password: mysql-password
132
+ database: mysql-database
133
+ ```
134
+
135
+ You can also provide a list of required plugins:
136
+
137
+ ```
138
+ wordpress:
139
+ plugins:
140
+ - acf
141
+ - acf: git://github.com/elliotcondon/acf.git
142
+ - acf: http://my-site.com/acf.zip
143
+ - acf: http://my-site.com/acf.tar.gz
144
+ ```
145
+
146
+ For more detailed example, check `examples/wordpress.yml`
92
147
 
93
148
  ### Rails Strategy
94
149
 
data/bin/shuttle CHANGED
@@ -4,57 +4,6 @@ lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
4
  $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
5
 
6
6
  require 'rubygems'
7
- require 'optparse'
8
7
  require 'shuttle'
9
8
 
10
- config_name = Dir.pwd.split('/').last + ".yml"
11
-
12
- options = {
13
- :path => File.join(ENV['HOME'], '.shuttle', config_name),
14
- :target => 'production',
15
- :log => false
16
- }
17
-
18
- optparse = OptionParser.new do |opts|
19
- opts.on('-v', '--version', 'Show version') do
20
- puts "Shuttle version #{Shuttle::VERSION}"
21
- exit 0
22
- end
23
-
24
- opts.on('-e', '--environment NAME', 'Deployment target environment') do |v|
25
- options[:target] = v
26
- end
27
-
28
- opts.on('-d', '--debug', 'Enable debugging') do
29
- options[:log] = true
30
- end
31
-
32
- opts.on('-f', '--file PATH', 'Configuration file path') do |v|
33
- options[:path] = v
34
- end
35
- end
36
-
37
- begin
38
- optparse.parse!
39
- rescue OptionParser::ParseError => e
40
- puts "Error: #{e.message}"
41
- exit 1
42
- end
43
-
44
- case ARGV.size
45
- when 2
46
- options[:target] = ARGV.shift
47
- command = ARGV.shift
48
- when 1
49
- command = ARGV.shift
50
- else
51
- puts "Command required"
52
- exit 1
53
- end
54
-
55
- begin
56
- runner = Shuttle::Runner.new(options)
57
- runner.execute(command.dup)
58
- rescue Shuttle::ConfigError => err
59
- puts "Error: #{err.message}."
60
- end
9
+ Shuttle::CLI.new.run
@@ -1,32 +1,47 @@
1
1
  app:
2
+ # name of the app
2
3
  name: sample-site
3
4
  strategy: wordpress
5
+ # source repository containing your theme
4
6
  git: git@github.com/username/sample-site.git
7
+ # svn: https://some-svn-repo.com/sample-site
5
8
  branch: production
6
9
 
10
+ # Where to deploy
7
11
  target:
12
+ # host name or ip
8
13
  host: sample-site.com
14
+ # Credentials for user that'll run deploy
9
15
  user: deployer
10
16
  password: password
17
+ # Deploy path
11
18
  deploy_to: /home/deployer/www
12
19
 
13
20
  wordpress:
21
+ # Core version
14
22
  core: 3.5.1
23
+ # wp-cli version. See wp-cli.org
15
24
  cli: 0.9.1
16
- theme: theme_name
25
+ # Theme name for source repo, should match theme slug
26
+ theme: sample-site
27
+ # Basic WP settings
17
28
  site:
18
29
  title: "Site Title"
19
30
  url: "http://sample-site.com"
20
31
  admin_name: "admin"
21
32
  admin_email: "admin@admin.com"
22
33
  admin_password: "password"
34
+ # MySQL config
23
35
  mysql:
24
36
  host: 127.0.0.1
25
37
  user: mysql-user
26
38
  password: mysql-password
27
39
  database: mysql-dadtabase
40
+ # Plugins that you need for the site
28
41
  plugins:
42
+ # Grab a plugin from any git/svn repo
29
43
  - advanced-custom-fields: git://github.com/elliotcondon/acf.git
44
+ # Install directly from wp plugins repo
30
45
  - be-subpages-widget
31
46
  - contact-form-7
32
47
  - contact-form-7-to-database-extension
@@ -0,0 +1,108 @@
1
+ require 'optparse'
2
+
3
+ module Shuttle
4
+ class CLI
5
+ attr_reader :options, :command
6
+ attr_reader :path
7
+
8
+ def initialize(path=nil)
9
+ @path = File.expand_path(path || Dir.pwd)
10
+ @options = default_options
11
+ end
12
+
13
+ def run
14
+ parse_options
15
+ parse_command
16
+ find_config
17
+
18
+ begin
19
+ runner = Shuttle::Runner.new(@options)
20
+ runner.execute(@command.dup)
21
+ rescue Shuttle::ConfigError => err
22
+ terminate(err.message)
23
+ end
24
+ end
25
+
26
+ def terminate(message, status=1)
27
+ STDERR.puts(message)
28
+ exit(status)
29
+ end
30
+
31
+ def default_options
32
+ {
33
+ :path => nil,
34
+ :target => 'production',
35
+ :log => false
36
+ }
37
+ end
38
+
39
+ def parse_options
40
+ parser = OptionParser.new do |opts|
41
+ opts.on('-v', '--version', 'Show version') do
42
+ puts "Shuttle version #{Shuttle::VERSION}"
43
+ exit 0
44
+ end
45
+
46
+ opts.on('-e', '--environment NAME', 'Deployment target environment') do |v|
47
+ @options[:target] = v
48
+ end
49
+
50
+ opts.on('-d', '--debug', 'Enable debugging') do
51
+ @options[:log] = true
52
+ end
53
+
54
+ opts.on('-f', '--file PATH', 'Configuration file path') do |v|
55
+ @options[:path] = v
56
+ end
57
+ end
58
+
59
+ begin
60
+ parser.parse!
61
+ rescue OptionParser::ParseError => e
62
+ terminate(e.message)
63
+ end
64
+ end
65
+
66
+ def parse_command
67
+ case ARGV.size
68
+ when 0
69
+ terminate("Command required")
70
+ when 1
71
+ @command = ARGV.shift
72
+ when 2
73
+ @options[:target] = ARGV.shift
74
+ @command = ARGV.shift
75
+ else
76
+ terminate("Maximum of 2 arguments allowed")
77
+ end
78
+ end
79
+
80
+ def find_config
81
+ lookup_files.each { |path| break if try_config(path) }
82
+
83
+ if @options[:path].nil?
84
+ terminate("Please provide config with -f option.")
85
+ end
86
+ end
87
+
88
+ def try_config(path)
89
+ if File.exists?(path)
90
+ @options[:path] = path
91
+ true
92
+ else
93
+ false
94
+ end
95
+ end
96
+
97
+ private
98
+
99
+ def lookup_files
100
+ [
101
+ "#{@path}/shuttle.yml",
102
+ "#{@path}/config/deploy.yml",
103
+ "#{@path}/config/deploy/#{options[:target]}.yml",
104
+ "#{ENV['HOME']}/.shuttle/#{File.basename(Dir.pwd)}.yml"
105
+ ]
106
+ end
107
+ end
108
+ end
@@ -10,6 +10,29 @@ module Shuttle
10
10
  def cli_install
11
11
  log "Installing WordPress CLI"
12
12
 
13
+ rev, tag = cli_checkout_code
14
+
15
+ res = ssh.run("cd #{CLI_PATH} && sudo utils/dev-build")
16
+
17
+ if res.failure?
18
+ error "Unable to build cli: #{res.output}"
19
+ end
20
+
21
+ if cli_installed?
22
+ log "WordPress CLI (#{tag}) installed"
23
+ else
24
+ error "Wordpress CLI installation failed"
25
+ end
26
+ end
27
+
28
+ # Checkout a proper wp-cli revision. By default it'll install
29
+ # latest available tag from git. That's considered a stable version.
30
+ # To install latest code, set `cli` option in config:
31
+ #
32
+ # wordpress:
33
+ # cli: master
34
+ #
35
+ def cli_checkout_code
13
36
  ssh.run("sudo git clone --recursive --quiet #{CLI_GIT} #{CLI_PATH}")
14
37
 
15
38
  if config.wordpress.cli.nil?
@@ -17,17 +40,22 @@ module Shuttle
17
40
  tag = tags.first
18
41
  rev = ssh.capture("cd #{CLI_PATH} && git rev-parse #{tag}").strip
19
42
  else
20
- tag = rev = config.wordpress.cli
43
+ tag = config.wordpress.cli
44
+
45
+ if tag =~ /^[\d\.]+$/ # version def
46
+ tag = "v#{tag}" unless tag =~ /v[\d]+/
47
+ end
48
+
49
+ rev = tag
21
50
  end
22
51
 
23
- ssh.run("cd #{CLI_PATH} && sudo git checkout #{rev}")
24
- ssh.run("cd #{CLI_PATH} && sudo utils/dev-build")
25
-
26
- if cli_installed?
27
- log "WordPress CLI (#{tag}) installed"
28
- else
29
- error "Unable to install WordPress CLI"
52
+ res = ssh.run("cd #{CLI_PATH} && sudo git checkout #{rev}")
53
+
54
+ if res.failure?
55
+ error "Unable to checkout revision #{rev}: #{res.output}"
30
56
  end
57
+
58
+ #rev, tag
31
59
  end
32
60
 
33
61
  def cli_uninstall
@@ -24,15 +24,20 @@ module Shuttle
24
24
  cli_install
25
25
  else
26
26
  version = ssh.capture("cd #{core_path} && wp --version")
27
- version.gsub!('wp-cli', '').strip!
27
+ version.gsub!('wp-cli', '').to_s.strip!
28
28
  log "WordPress CLI version: #{version}"
29
29
  end
30
30
 
31
31
  if !core_installed?
32
32
  core_install
33
33
  else
34
- version = ssh.capture("cd #{core_path} && wp core version")
35
- log "WordPress core version: #{version}"
34
+ res = ssh.run("cd #{core_path} && wp core version")
35
+
36
+ if res.success?
37
+ log "WordPress core version: #{res.output}"
38
+ else
39
+ error "Unable to detect WordPress core version: #{res.output}"
40
+ end
36
41
  end
37
42
 
38
43
  check_config
@@ -12,7 +12,9 @@ module Shuttle
12
12
  end
13
13
 
14
14
  def error(message)
15
- log("ERROR: #{message}", 'error')
15
+ log("ERROR: #{message}", "error")
16
+ log("Release v#{version} aborted", "error")
17
+
16
18
  raise DeployError, message
17
19
  end
18
20
 
@@ -0,0 +1,33 @@
1
+ module Shuttle
2
+ class Hook
3
+ def initialize(deploy)
4
+ @deploy = deploy
5
+ end
6
+
7
+ def run(commands, allow_failures=false)
8
+ [commands].flatten.compact.uniq.each do |cmd|
9
+ execute(cmd, allow_failures)
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def execute(cmd, allow_failures)
16
+ @deploy.log %{Executing "#{cmd.strip}"}
17
+
18
+ command = cmd
19
+
20
+ if @deploy.ssh.directory_exists?(@deploy.release_path)
21
+ command = "cd #{@deploy.release_path} && #{command}"
22
+ end
23
+
24
+ result = @deploy.ssh.run(command)
25
+
26
+ if result.failure? && allow_failures == false
27
+ @deploy.error("Failed: #{result.output}")
28
+ else
29
+ @deploy.stream_output(result.output)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -18,7 +18,11 @@ module Shuttle
18
18
  end
19
19
 
20
20
  def load_config
21
- data = File.read(config_path)
21
+ data = File.read(config_path).strip
22
+
23
+ if data.empty?
24
+ raise ConfigError, "Configuration file is empty"
25
+ end
22
26
 
23
27
  if config_path =~ /\.toml$/
24
28
  parse_toml_data(data)
@@ -129,7 +133,9 @@ module Shuttle
129
133
  exit_code = 1
130
134
  rescue Exception => err
131
135
  integration.cleanup_release
132
- integration.log("ERROR: #{err.message}", 'error')
136
+ integration.log("Shuttle ERROR: #{err.message}", 'error')
137
+ integration.log(err.backtrace.join("\n"), 'error')
138
+
133
139
  exit_code = 1
134
140
  ensure
135
141
  integration.release_lock
@@ -150,7 +156,7 @@ module Shuttle
150
156
 
151
157
  ssh.close
152
158
  rescue Net::SSH::AuthenticationFailed
153
- STDERR.puts "Authentication failed"
159
+ STDERR.puts "SSH Authentication failed"
154
160
  exit 1
155
161
  end
156
162
  end
@@ -26,6 +26,8 @@ module Shuttle
26
26
  end
27
27
 
28
28
  def rollback
29
+ execute_hook(:before_rollback)
30
+
29
31
  if last_version == 0
30
32
  error "There are no releases to rollback to"
31
33
  end
@@ -41,11 +43,15 @@ module Shuttle
41
43
  error "Unable to create symlink to current path"
42
44
  end
43
45
 
44
- ssh.run("echo #{version} > #{version_path}")
46
+ ssh.run("echo #{release} > #{version_path}")
47
+ ssh.run("rm -rf #{deploy_path}/releases/#{last_version}")
48
+
45
49
  log "Rolled back to release v#{release}"
46
50
  else
47
51
  error "There are no older releases"
48
52
  end
53
+
54
+ execute_hook(:after_rollback)
49
55
  end
50
56
 
51
57
  def update_code
@@ -270,19 +276,7 @@ module Shuttle
270
276
  end
271
277
 
272
278
  def execute_commands(commands=[], allow_failures=false)
273
- commands.flatten.compact.uniq.each do |cmd|
274
- log %{Executing "#{cmd.strip}"}
275
- command = cmd
276
- command = "cd #{release_path} && #{command}" if ssh.directory_exists?(release_path)
277
-
278
- result = ssh.run(command)
279
-
280
- if result.failure? && allow_failures == false
281
- error "Failed: #{result.output}"
282
- else
283
- stream_output(result.output)
284
- end
285
- end
279
+ Shuttle::Hook.new(self).run(commands, allow_failures)
286
280
  end
287
281
  end
288
282
  end
@@ -1,3 +1,3 @@
1
1
  module Shuttle
2
- VERSION = '0.2.0.beta4'
2
+ VERSION = '0.2.0.beta5'
3
3
  end
data/lib/shuttle.rb CHANGED
@@ -13,6 +13,7 @@ require 'shuttle/version'
13
13
  require 'shuttle/errors'
14
14
 
15
15
  module Shuttle
16
+ autoload :CLI, 'shuttle/cli'
16
17
  autoload :Session, 'shuttle/session'
17
18
  autoload :Runner, 'shuttle/runner'
18
19
  autoload :Deploy, 'shuttle/deploy'
@@ -20,6 +21,7 @@ module Shuttle
20
21
  autoload :Helpers, 'shuttle/helpers'
21
22
  autoload :PathHelpers, 'shuttle/path_helpers'
22
23
  autoload :Strategy, 'shuttle/strategy'
24
+ autoload :Hook, 'shuttle/hook'
23
25
 
24
26
  autoload :Static, 'shuttle/deployment/static'
25
27
  autoload :Php, 'shuttle/deployment/php'
@@ -30,7 +32,6 @@ module Shuttle
30
32
 
31
33
  module Support
32
34
  autoload :Bundler, 'shuttle/support/bundler'
33
- autoload :Foreman, 'shuttle/support/foreman'
34
35
  autoload :Thin, 'shuttle/support/thin'
35
36
  end
36
37
  end
data/spec/cli_spec.rb ADDED
@@ -0,0 +1,150 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shuttle::CLI do
4
+ let(:cli) { Shuttle::CLI.new }
5
+
6
+ describe '#initialize' do
7
+ it 'assigns current path' do
8
+ Dir.stub(:pwd).and_return('/home/user')
9
+ cli = Shuttle::CLI.new
10
+ expect(cli.path).to eq '/home/user'
11
+ end
12
+
13
+ it 'assigns specified path' do
14
+ cli = Shuttle::CLI.new('/foo/bar')
15
+ expect(cli.path).to eq '/foo/bar'
16
+ end
17
+
18
+ it 'assigns default options' do
19
+ cli = Shuttle::CLI.new
20
+ expect(cli.options).to be_a Hash
21
+ expect(cli.options).not_to be_empty
22
+ end
23
+ end
24
+
25
+ describe '#default_options' do
26
+ let(:opts) { cli.default_options }
27
+
28
+ it 'returns a hash with default options' do
29
+ expect(opts).to be_a Hash
30
+ expect(opts[:path]).to eq nil
31
+ expect(opts[:target]).to eq 'production'
32
+ expect(opts[:log]).to eq false
33
+ end
34
+ end
35
+
36
+ describe '#parse_command' do
37
+ context 'with no arguments' do
38
+ before do
39
+ ARGV.stub(:size).and_return(0)
40
+ cli.should_receive(:terminate).with("Command required")
41
+ end
42
+
43
+ it 'terminates execution with message' do
44
+ cli.parse_command
45
+ end
46
+ end
47
+
48
+ context 'with 1 argument' do
49
+ before do
50
+ ARGV = %w(deploy)
51
+ end
52
+
53
+ it 'sets command' do
54
+ cli.parse_command
55
+ expect(cli.command).to eq 'deploy'
56
+ end
57
+ end
58
+
59
+ context 'with 2 arguments' do
60
+ before do
61
+ ARGV = %w(staging deploy)
62
+ cli.parse_command
63
+ end
64
+
65
+ it 'assigns deployment target' do
66
+ expect(cli.options[:target]).to eq 'staging'
67
+ end
68
+
69
+ it 'assigns command' do
70
+ expect(cli.command).to eq 'deploy'
71
+ end
72
+ end
73
+
74
+ context 'with too many arguments' do
75
+ before do
76
+ ARGV.stub(:size).and_return(3)
77
+ cli.should_receive(:terminate).with("Maximum of 2 arguments allowed")
78
+ end
79
+
80
+ it 'terminates execution with message' do
81
+ cli.parse_command
82
+ end
83
+ end
84
+ end
85
+
86
+ describe '#try_config' do
87
+ it 'does not change path if file does not exist' do
88
+ File.stub(:exists?).and_return(false)
89
+
90
+ expect(cli.try_config('foo/bar')).to eq false
91
+ expect(cli.options[:path]).to eq nil
92
+ end
93
+
94
+ it 'changes config path if file exists' do
95
+ File.stub(:exists?).with('foo/bar').and_return(true)
96
+
97
+ expect(cli.try_config('foo/bar')).to eq true
98
+ expect(cli.options[:path]).to eq 'foo/bar'
99
+ end
100
+ end
101
+
102
+ describe '#find_config' do
103
+ let(:path) { "/tmp" }
104
+ let(:cli) { Shuttle::CLI.new(path) }
105
+
106
+ it 'searches for ./shuttle.yml file' do
107
+ File.should_receive(:exists?).with("/tmp/shuttle.yml").and_return(true)
108
+ cli.find_config
109
+ expect(cli.options[:path]).to eq "/tmp/shuttle.yml"
110
+ end
111
+
112
+ it 'searches for ./config/deploy.yml file' do
113
+ File.should_receive(:exists?).with("/tmp/shuttle.yml").and_return(false)
114
+ File.should_receive(:exists?).with("/tmp/config/deploy.yml").and_return(true)
115
+
116
+ cli.find_config
117
+ expect(cli.options[:path]).to eq "/tmp/config/deploy.yml"
118
+ end
119
+
120
+ it 'searches for ./config/deploy/production.yml' do
121
+ File.should_receive(:exists?).with("/tmp/shuttle.yml").and_return(false)
122
+ File.should_receive(:exists?).with("/tmp/config/deploy.yml").and_return(false)
123
+ File.should_receive(:exists?).with("/tmp/config/deploy/production.yml").and_return(true)
124
+
125
+ cli.find_config
126
+ expect(cli.options[:path]).to eq "/tmp/config/deploy/production.yml"
127
+ end
128
+
129
+ it 'searches foe ~/.shuttle/NAME.yml' do
130
+ ENV['HOME'] = "/tmp"
131
+ File.should_receive(:exists?).with("/tmp/shuttle.yml").and_return(false)
132
+ File.should_receive(:exists?).with("/tmp/config/deploy.yml").and_return(false)
133
+ File.should_receive(:exists?).with("/tmp/config/deploy/production.yml").and_return(false)
134
+ File.should_receive(:exists?).with("/tmp/.shuttle/shuttle.yml").and_return(true)
135
+
136
+ cli.find_config
137
+ expect(cli.options[:path]).to eq '/tmp/.shuttle/shuttle.yml'
138
+ end
139
+
140
+ it 'terminates if no config files found' do
141
+ ENV['HOME'] = "/tmp"
142
+ File.should_receive(:exists?).with("/tmp/shuttle.yml").and_return(false)
143
+ File.should_receive(:exists?).with("/tmp/config/deploy.yml").and_return(false)
144
+ File.should_receive(:exists?).with("/tmp/config/deploy/production.yml").and_return(false)
145
+ File.should_receive(:exists?).with("/tmp/.shuttle/shuttle.yml").and_return(false)
146
+
147
+ expect { cli.find_config }.to raise_error SystemExit
148
+ end
149
+ end
150
+ end
data/spec/helpers_spec.rb CHANGED
@@ -19,8 +19,12 @@ describe Shuttle::Helpers do
19
19
  end
20
20
 
21
21
  describe '#error' do
22
+ before { subject.stub(:version).and_return(1) }
23
+
22
24
  it 'prints an error message' do
23
25
  STDOUT.should_receive(:puts).with("\e[1m\e[31m----->\e[0m ERROR: message")
26
+ STDOUT.should_receive(:puts).with("\e[1m\e[31m----->\e[0m Release v1 aborted")
27
+
24
28
  expect { subject.error('message') }.to raise_error Shuttle::DeployError
25
29
  end
26
30
 
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ class Helpers ; include Shuttle::PathHelpers ; end
4
+
5
+ describe Shuttle::PathHelpers do
6
+ let(:target) do
7
+ Hashr.new(:deploy_to => '/tmp')
8
+ end
9
+
10
+ subject { Helpers.new }
11
+ before { subject.stub(:target).and_return(target) }
12
+
13
+ describe '#deploy_path' do
14
+ it 'returns application deployment path' do
15
+ expect(subject.deploy_path).to eq '/tmp'
16
+ end
17
+ end
18
+
19
+ describe '#shared_path' do
20
+ it 'returns shared deployment path' do
21
+ expect(subject.shared_path).to eq '/tmp/shared'
22
+ end
23
+ end
24
+
25
+ describe '#release_path' do
26
+ before { subject.stub(:version).and_return(1) }
27
+
28
+ it 'returns current release path' do
29
+ expect(subject.release_path).to eq '/tmp/releases/1'
30
+ end
31
+ end
32
+
33
+ describe '#current_path' do
34
+ it 'returns current linked release path' do
35
+ expect(subject.current_path).to eq '/tmp/current'
36
+ end
37
+ end
38
+
39
+ describe '#version_path' do
40
+ it 'returns version file path' do
41
+ expect(subject.version_path).to eq '/tmp/version'
42
+ end
43
+ end
44
+
45
+ describe '#scm_path' do
46
+ it 'returns project repository path' do
47
+ expect(subject.scm_path).to eq '/tmp/scm'
48
+ end
49
+ end
50
+ end
data/spec/spec_helper.rb CHANGED
@@ -14,4 +14,8 @@ end
14
14
 
15
15
  def fixture(file)
16
16
  File.read(File.join(fixture_path, file))
17
+ end
18
+
19
+ def fake_run(command, output, exit_code=0, duration=0)
20
+ Net::SSH::SessionCommand.new(command, output, exit_code, duration)
17
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shuttle-deploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0.beta4
4
+ version: 0.2.0.beta5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dan Sosedoff
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-03 00:00:00.000000000 Z
11
+ date: 2013-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -170,7 +170,7 @@ files:
170
170
  - examples/static.yml
171
171
  - examples/wordpress.yml
172
172
  - lib/shuttle.rb
173
- - lib/shuttle/config.rb
173
+ - lib/shuttle/cli.rb
174
174
  - lib/shuttle/deploy.rb
175
175
  - lib/shuttle/deployment/nodejs.rb
176
176
  - lib/shuttle/deployment/php.rb
@@ -184,20 +184,22 @@ files:
184
184
  - lib/shuttle/deployment/wordpress/vip.rb
185
185
  - lib/shuttle/errors.rb
186
186
  - lib/shuttle/helpers.rb
187
+ - lib/shuttle/hook.rb
187
188
  - lib/shuttle/path_helpers.rb
188
189
  - lib/shuttle/runner.rb
189
190
  - lib/shuttle/session.rb
190
191
  - lib/shuttle/strategy.rb
191
192
  - lib/shuttle/support/bundler.rb
192
- - lib/shuttle/support/foreman.rb
193
193
  - lib/shuttle/support/thin.rb
194
194
  - lib/shuttle/target.rb
195
195
  - lib/shuttle/version.rb
196
196
  - shuttle-deploy.gemspec
197
+ - spec/cli_spec.rb
197
198
  - spec/deploy_spec.rb
198
199
  - spec/fixtures/.gitkeep
199
200
  - spec/fixtures/static.yml
200
201
  - spec/helpers_spec.rb
202
+ - spec/path_helpers_spec.rb
201
203
  - spec/spec_helper.rb
202
204
  - spec/target_spec.rb
203
205
  homepage: https://github.com/sosedoff/shuttle
@@ -224,10 +226,12 @@ signing_key:
224
226
  specification_version: 4
225
227
  summary: Minimalistic deployment tool
226
228
  test_files:
229
+ - spec/cli_spec.rb
227
230
  - spec/deploy_spec.rb
228
231
  - spec/fixtures/.gitkeep
229
232
  - spec/fixtures/static.yml
230
233
  - spec/helpers_spec.rb
234
+ - spec/path_helpers_spec.rb
231
235
  - spec/spec_helper.rb
232
236
  - spec/target_spec.rb
233
237
  has_rdoc:
@@ -1,5 +0,0 @@
1
- module Shuttle
2
- class Config
3
- # TODO
4
- end
5
- end
@@ -1,7 +0,0 @@
1
- module Shuttle
2
- module Support::Foreman
3
- def foreman_installed?
4
- ssh.run("which foreman").success?
5
- end
6
- end
7
- end