shuttle-deploy 0.2.0.beta4 → 0.2.0.beta5

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.
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