lobstr 0.0.1
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/.gitignore +19 -0
- data/.travis.yml +6 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +59 -0
- data/Rakefile +9 -0
- data/bin/lob +90 -0
- data/lib/lobstr.rb +19 -0
- data/lib/lobstr/base.rb +33 -0
- data/lib/lobstr/config.rb +61 -0
- data/lib/lobstr/deploy.rb +89 -0
- data/lib/lobstr/error.rb +23 -0
- data/lib/lobstr/version.rb +3 -0
- data/lobstr.gemspec +33 -0
- data/spec/lobstr_base_spec.rb +27 -0
- data/spec/lobstr_config_spec.rb +102 -0
- data/spec/lobstr_deploy_spec.rb +84 -0
- data/spec/spec_helper.rb +14 -0
- metadata +228 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Eric Marden
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Lobstr
|
2
|
+
|
3
|
+
[](http://travis-ci.org/xentek/lobstr)
|
4
|
+
|
5
|
+
deployments so easy, even a zoidberg can do it.
|
6
|
+
|
7
|
+

|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'lobstr'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install lobstr
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
````bash
|
26
|
+
$ lob deploy branch@environment
|
27
|
+
````
|
28
|
+
|
29
|
+
Since `deploy` is the default task, Lobstr supports additional syntax to
|
30
|
+
save your typing fingers:
|
31
|
+
|
32
|
+
````bash
|
33
|
+
# without branch or @ (requires task name though), currently defaults to "master"
|
34
|
+
$ lob deploy production
|
35
|
+
|
36
|
+
# without task name, but full branch and environment
|
37
|
+
$ lob branch@environment
|
38
|
+
|
39
|
+
# without task name or environment, currently defaults to "production"
|
40
|
+
$ lob branch@
|
41
|
+
|
42
|
+
# without task name or branch, currently defaults to "master"
|
43
|
+
$ lob @producuction
|
44
|
+
|
45
|
+
# without any input, currently defaults to "master@production"
|
46
|
+
$ lob
|
47
|
+
````
|
48
|
+
|
49
|
+
## Configuration
|
50
|
+
|
51
|
+
*Coming soon*
|
52
|
+
|
53
|
+
## Contributing
|
54
|
+
|
55
|
+
1. Fork it
|
56
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
57
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
58
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
59
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/lob
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'lobstr'
|
5
|
+
|
6
|
+
class Lob < Thor
|
7
|
+
|
8
|
+
|
9
|
+
desc "deploy TARGET", "lobs code at the branch and environment you specify"
|
10
|
+
long_desc "lobs code at the branch and environment you specify, separated by @
|
11
|
+
\n\n
|
12
|
+
Example: lob deploy master@production"
|
13
|
+
def deploy(target='master@production')
|
14
|
+
if File.exist? 'Lobfile'
|
15
|
+
Lobstr.target = target
|
16
|
+
load "Lobfile"
|
17
|
+
else
|
18
|
+
lobstr target do
|
19
|
+
connect do
|
20
|
+
deploy
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
default_task :deploy
|
26
|
+
|
27
|
+
desc "rollback ENVIRONMENT", "rolls the last deployment back"
|
28
|
+
def rollback(environment)
|
29
|
+
lobstr environment do
|
30
|
+
connect do
|
31
|
+
rollback
|
32
|
+
notify(:rollback)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "setup ENVIRONMENT", "runs your setup recipe"
|
38
|
+
method_option :file, :type => :string, :aliases => '-f'
|
39
|
+
def setup(environment)
|
40
|
+
if options['file']
|
41
|
+
if File.exist? options['file']
|
42
|
+
load options['file']
|
43
|
+
else
|
44
|
+
say "#{set_color(options['file'] ,:yellow)} #{set_color('does not exist', :red)}"
|
45
|
+
end
|
46
|
+
else
|
47
|
+
lobstr environment do
|
48
|
+
connect do
|
49
|
+
setup
|
50
|
+
notify(:setup)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "config", "displays current configuration"
|
57
|
+
long_desc "displays current configuration"
|
58
|
+
method_option :init, :type => :boolean, :default => false,
|
59
|
+
:desc => "creates the configurtion file, unless it exists"
|
60
|
+
method_option :reset, :type => :boolean, :default => false,
|
61
|
+
:desc => "removes current configuration file and creates a new one"
|
62
|
+
def config
|
63
|
+
@config = Lobstr::Config.new
|
64
|
+
|
65
|
+
if options['init']
|
66
|
+
say "Created Lobstr Config:", :green if @config.create
|
67
|
+
end
|
68
|
+
|
69
|
+
if options['reset']
|
70
|
+
say "Reset Lobstr Config:", :red if @config.reset
|
71
|
+
end
|
72
|
+
|
73
|
+
say @config.print
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
begin
|
78
|
+
ENV['THOR_DEBUG'] = '1'
|
79
|
+
Lob.start
|
80
|
+
rescue Thor::UndefinedTaskError => e
|
81
|
+
if ARGV[0] =~ /@/
|
82
|
+
Lob.new.invoke(:deploy, ARGV)
|
83
|
+
else
|
84
|
+
Lob.new.say e.message, :red
|
85
|
+
end
|
86
|
+
rescue => e
|
87
|
+
p e
|
88
|
+
p e.backtrace.last
|
89
|
+
Lob.new.say e.message, :on_red
|
90
|
+
end
|
data/lib/lobstr.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'net/ssh'
|
5
|
+
require 'highline/import'
|
6
|
+
require 'lobstr/base'
|
7
|
+
require 'lobstr/config'
|
8
|
+
require 'lobstr/deploy'
|
9
|
+
require 'lobstr/error'
|
10
|
+
require 'lobstr/version'
|
11
|
+
|
12
|
+
module Lobstr
|
13
|
+
class << self ; attr_accessor :target ; end
|
14
|
+
end
|
15
|
+
|
16
|
+
def lobstr(target = nil, config_file = 'config/lobstr.yml', &block)
|
17
|
+
target ||= Lobstr.target
|
18
|
+
Lobstr::Deploy.new(target, config_file, &block)
|
19
|
+
end
|
data/lib/lobstr/base.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'minitest/mock'
|
2
|
+
module Lobstr
|
3
|
+
class Base
|
4
|
+
attr_accessor :branch, :environment, :config, :ssh
|
5
|
+
def parse_target(target)
|
6
|
+
branch,environment = target.split('@', 2)
|
7
|
+
|
8
|
+
if environment.nil? # e.g. production
|
9
|
+
environment = branch
|
10
|
+
branch = 'master'
|
11
|
+
end
|
12
|
+
|
13
|
+
branch = "master" if branch.empty? # e.g. @production
|
14
|
+
environment = "production" if environment.empty? # e.g. master@
|
15
|
+
[branch,environment]
|
16
|
+
end
|
17
|
+
|
18
|
+
def connect(&block)
|
19
|
+
@ssh = ::Net::SSH.start(@config['ssh_host'],
|
20
|
+
@config['ssh_user'],
|
21
|
+
:keys => [@config['ssh_key']])
|
22
|
+
instance_eval(&block) if block_given?
|
23
|
+
end
|
24
|
+
|
25
|
+
def remote_task(cmd)
|
26
|
+
@ssh.exec! cmd
|
27
|
+
end
|
28
|
+
|
29
|
+
def local_task(cmd)
|
30
|
+
`#{cmd}`
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Lobstr
|
2
|
+
class Config
|
3
|
+
attr_accessor :config_file, :config_path
|
4
|
+
|
5
|
+
def initialize(config = 'config/lobstr.yml')
|
6
|
+
@config_file = config
|
7
|
+
@config_path = File.dirname config
|
8
|
+
end
|
9
|
+
|
10
|
+
def template
|
11
|
+
<<-TEMPLATE.gsub!(/^ /,'')
|
12
|
+
lobstr: &defaults
|
13
|
+
app: lobstr
|
14
|
+
repos: git://github.com/xentek/lobstr.git
|
15
|
+
path: ~/lobstr
|
16
|
+
ssh_host: localhost
|
17
|
+
ssh_user: xentek
|
18
|
+
ssh_key: ~/.ssh/id_rsa
|
19
|
+
branch: master
|
20
|
+
environment: production
|
21
|
+
production:
|
22
|
+
<<: *defaults
|
23
|
+
TEMPLATE
|
24
|
+
end
|
25
|
+
|
26
|
+
def create
|
27
|
+
raise Lobstr::Error::ConfigFileExists, @config_file if config_file_exists?
|
28
|
+
Dir.mkdir(@config_path) unless Dir.exist?(@config_path)
|
29
|
+
File.open(@config_file, 'w') {|f| f.write(template) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def reset
|
33
|
+
File.delete(@config_file) if config_file_exists?
|
34
|
+
create
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse(environment = 'production')
|
38
|
+
check_config_file
|
39
|
+
config = YAML.load_file(@config_file)[environment]
|
40
|
+
raise Lobstr::Error::InvalidEnvironment, environment if config.nil?
|
41
|
+
config
|
42
|
+
end
|
43
|
+
|
44
|
+
def print
|
45
|
+
check_config_file
|
46
|
+
File.open(@config_file, 'r').read
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def config_file_exists?
|
52
|
+
File.exist? @config_file
|
53
|
+
end
|
54
|
+
|
55
|
+
def check_config_file
|
56
|
+
unless config_file_exists?
|
57
|
+
raise Lobstr::Error::ConfigFileMissing, @config_file
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Lobstr
|
2
|
+
class Deploy < ::Lobstr::Base
|
3
|
+
def initialize(target, config_file = 'config/lobstr.yml', &block)
|
4
|
+
@branch,@environment = parse_target(target)
|
5
|
+
@config = Lobstr::Config.new(config_file).parse(@environment)
|
6
|
+
if block_given?
|
7
|
+
return instance_eval(&block)
|
8
|
+
else
|
9
|
+
return self
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def deploy
|
14
|
+
connect do
|
15
|
+
update
|
16
|
+
bundle_install
|
17
|
+
notify
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def update
|
22
|
+
remote_task "cd #{@config['path']}"
|
23
|
+
remote_task "git fetch origin"
|
24
|
+
remote_task "git reset --hard #{@branch}"
|
25
|
+
remote_task "cd #{@config['path']}"
|
26
|
+
remote_task 'git reflog delete --rewrite HEAD@{1}'
|
27
|
+
remote_task 'git reflog delete --rewrite HEAD@{1}'
|
28
|
+
end
|
29
|
+
|
30
|
+
def restart(sudo = true)
|
31
|
+
sudoit = (sudo) ? 'sudo' : ''
|
32
|
+
remote_task "#{sudoit} /etc/init.d/#{@config['app']}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def rollback
|
36
|
+
remote_task "cd #{@config['path']}"
|
37
|
+
remote_task "git fetch origin"
|
38
|
+
remote_task "git reset --hard HEAD@{1}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def notify(event = :deployment)
|
42
|
+
"notify of #{event}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def setup(&block)
|
46
|
+
return instance_eval(&block) if block_given?
|
47
|
+
remote_task "git clone #{@config['repos']} #{@config['path']}"
|
48
|
+
bundle_install
|
49
|
+
export_foreman
|
50
|
+
end
|
51
|
+
|
52
|
+
def bundle_install(options = {})
|
53
|
+
if config.has_key? 'bundler'
|
54
|
+
options = @config['bundler'].merge(options)
|
55
|
+
else
|
56
|
+
options = {
|
57
|
+
'deployment' => nil,
|
58
|
+
'path' => 'vendor/bundle',
|
59
|
+
'without' => 'development test'
|
60
|
+
}.merge(options)
|
61
|
+
end
|
62
|
+
options_string = ''
|
63
|
+
options.each { |k,v| options_string += "--#{k} #{v} " }
|
64
|
+
remote_task "bundle install #{options_string}"
|
65
|
+
end
|
66
|
+
|
67
|
+
def export_foreman(format='upstart', location='/etc/init', options={})
|
68
|
+
valid_formats = ['bluepill','inittab','runit','upstart']
|
69
|
+
unless valid_formats.include? format
|
70
|
+
raise Lobstr::Error::InvalidExportFormat
|
71
|
+
end
|
72
|
+
if @config.has_key? 'foreman'
|
73
|
+
options = @config['foreman'].merge(options)
|
74
|
+
else
|
75
|
+
options = {
|
76
|
+
'app' => @config['app'],
|
77
|
+
'log' => "#{@config['path']}/log",
|
78
|
+
'user' => @config['ssh_user'],
|
79
|
+
'procfile' => "#{@config['path']}/Procfile"
|
80
|
+
}.merge(options)
|
81
|
+
end
|
82
|
+
|
83
|
+
options_string = ''
|
84
|
+
options.each { |k,v| options_string += "--#{k} #{v} " }
|
85
|
+
|
86
|
+
remote_task "foreman export #{format} #{location} #{options_string}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/lobstr/error.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Lobstr
|
2
|
+
module Error
|
3
|
+
|
4
|
+
class InvalidEnvironment < StandardError
|
5
|
+
def initialize(environment)
|
6
|
+
super "Invalid Environment: #{environment}. Can't load config."
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class ConfigFileExists < StandardError
|
11
|
+
def initialize(config_file)
|
12
|
+
super "#{config_file} already exists"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class ConfigFileMissing < StandardError
|
17
|
+
def initialize(config_file)
|
18
|
+
super "#{config_file} is missing. try: \n\n$ lob config --init"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lobstr.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'lobstr/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "lobstr"
|
8
|
+
gem.version = Lobstr::VERSION
|
9
|
+
gem.authors = ["Eric Marden"]
|
10
|
+
gem.email = ["eric@xentek.net"]
|
11
|
+
gem.description = %q{deployments so easy, even a zoidberg can do it}
|
12
|
+
gem.summary = gem.description
|
13
|
+
gem.homepage = "https://github.com/xentek/lobstr"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
gem.required_ruby_version = '>= 1.9.2'
|
20
|
+
|
21
|
+
gem.add_runtime_dependency('psych', '~> 1.3') unless RUBY_PLATFORM == 'java'
|
22
|
+
|
23
|
+
gem.add_dependency('thor', '~> 0.16')
|
24
|
+
gem.add_dependency('net-ssh', '~> 2.5')
|
25
|
+
gem.add_dependency('highline', '~> 1.6')
|
26
|
+
|
27
|
+
gem.add_development_dependency('rake', '~> 0.9.2')
|
28
|
+
gem.add_development_dependency('minitest', '~> 3.4')
|
29
|
+
gem.add_development_dependency('ansi', '~> 1.4')
|
30
|
+
gem.add_development_dependency('turn', '~> 0.9')
|
31
|
+
gem.add_development_dependency('pry', '~> 0.9')
|
32
|
+
gem.add_development_dependency('mocha', '~> 0.12')
|
33
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lobstr::Base do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@deploy = Lobstr::Base.new
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "parse_target" do
|
10
|
+
it "can parse deployment target (full): branch@env" do
|
11
|
+
@deploy.parse_target('branch@env').must_equal ['branch','env']
|
12
|
+
end
|
13
|
+
|
14
|
+
it "can parse deployment target (branch only): branch@" do
|
15
|
+
@deploy.parse_target('branch@').must_equal ['branch','production']
|
16
|
+
end
|
17
|
+
|
18
|
+
it "can parse deployment target (env only): @environment" do
|
19
|
+
@deploy.parse_target('@environment').must_equal ['master','environment']
|
20
|
+
end
|
21
|
+
|
22
|
+
it "can parse deployment target (env only) - alt syntax: environment" do
|
23
|
+
@deploy.parse_target('@environment').must_equal ['master','environment']
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lobstr::Config do
|
4
|
+
before do
|
5
|
+
@config_file = 'spec/config/lobstr.yml'
|
6
|
+
@config = Lobstr::Config.new(@config_file)
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
clean_up_config_file @config_file
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "template" do
|
14
|
+
it "has a config template" do
|
15
|
+
@config.create
|
16
|
+
@config.template.wont_equal nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "create" do
|
21
|
+
before do
|
22
|
+
clean_up_config_file @config_file
|
23
|
+
end
|
24
|
+
|
25
|
+
it "can create a config file" do
|
26
|
+
@config.create
|
27
|
+
File.exist?(@config_file).must_equal true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "won't create a config file if it exists already" do
|
31
|
+
@config.create
|
32
|
+
lambda { @config.create }.must_raise Lobstr::Error::ConfigFileExists
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "reset" do
|
37
|
+
it "can reset the configuration" do
|
38
|
+
@config.create
|
39
|
+
@config.reset
|
40
|
+
File.exist?(@config_file).must_equal true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "parse" do
|
45
|
+
before do
|
46
|
+
@config.create
|
47
|
+
end
|
48
|
+
|
49
|
+
it "has a repos" do
|
50
|
+
@config.parse['repos'].must_equal 'git://github.com/xentek/lobstr.git'
|
51
|
+
end
|
52
|
+
|
53
|
+
it "has a path" do
|
54
|
+
@config.parse['path'].must_equal '~/lobstr'
|
55
|
+
end
|
56
|
+
|
57
|
+
it "has an ssh host" do
|
58
|
+
@config.parse['ssh_host'].must_equal 'localhost'
|
59
|
+
end
|
60
|
+
|
61
|
+
it "has an ssh user" do
|
62
|
+
@config.parse['ssh_user'].must_equal 'xentek'
|
63
|
+
end
|
64
|
+
|
65
|
+
it "has an ssh key" do
|
66
|
+
@config.parse['ssh_key'].must_equal '~/.ssh/id_rsa'
|
67
|
+
end
|
68
|
+
|
69
|
+
it "has a branch" do
|
70
|
+
@config.parse['branch'].must_equal 'master'
|
71
|
+
end
|
72
|
+
|
73
|
+
it "has an environment" do
|
74
|
+
@config.parse['environment'].must_equal 'production'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "print" do
|
79
|
+
it "can print the contents of the config file" do
|
80
|
+
@config.create
|
81
|
+
@config.print.wont_equal nil
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "config_file_exists?" do
|
86
|
+
it "will return true if config file exists" do
|
87
|
+
@config.create
|
88
|
+
@config.send(:config_file_exists?).must_equal true
|
89
|
+
end
|
90
|
+
|
91
|
+
it "will return false if config file does not exist" do
|
92
|
+
@config.send(:config_file_exists?).must_equal false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "check_config_file" do
|
97
|
+
it "will throw an error if config file does not exist" do
|
98
|
+
check = lambda { @config.send(:check_config_file) }
|
99
|
+
check.must_raise Lobstr::Error::ConfigFileMissing
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Lobstr::Deploy do
|
4
|
+
|
5
|
+
before do
|
6
|
+
@config_file = 'spec/config/lobstr.yml'
|
7
|
+
@c = Lobstr::Config.new(@config_file)
|
8
|
+
@c.reset
|
9
|
+
@c = @c.parse('lobstr')
|
10
|
+
@deploy = Lobstr::Deploy.new('@lobstr', @config_file)
|
11
|
+
session = mock('Net::SSH::Connection::Session')
|
12
|
+
$-w = nil
|
13
|
+
Net::SSH = mock('Net::SSH')
|
14
|
+
Net::SSH.expects(:start).with(@c['ssh_host'],@c['ssh_user'],{:keys=>[@c['ssh_key']]}).returns(session)
|
15
|
+
$-w = false
|
16
|
+
end
|
17
|
+
|
18
|
+
after do
|
19
|
+
clean_up_config_file @config_file
|
20
|
+
end
|
21
|
+
|
22
|
+
it "can connect" do
|
23
|
+
@deploy.connect do
|
24
|
+
@ssh.expects(:exec!).with('echo "yo"')
|
25
|
+
@ssh.exec! 'echo "yo"'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can set the app up" do
|
30
|
+
@deploy.expects(:bundle_install)
|
31
|
+
@deploy.expects(:foreman_export)
|
32
|
+
@deploy.connect do
|
33
|
+
@ssh.expects(:exec!).with("git clone #{@config['repos']} #{@config['path']}")
|
34
|
+
setup
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "can deploy" do
|
39
|
+
@deploy.expects(:update)
|
40
|
+
@deploy.expects(:bundle_install)
|
41
|
+
@deploy.expects(:notify)
|
42
|
+
@deploy.deploy
|
43
|
+
end
|
44
|
+
|
45
|
+
it "can update" do
|
46
|
+
@deploy.connect do
|
47
|
+
@ssh.expects(:exec!).with("cd #{@config['path']}")
|
48
|
+
@ssh.expects(:exec!).with("git fetch origin")
|
49
|
+
@ssh.expects(:exec!).with("git reset --hard #{@branch}")
|
50
|
+
@ssh.expects(:exec!).with("cd #{@config['path']}")
|
51
|
+
@ssh.expects(:exec!).with("git reflog delete --rewrite HEAD@{1}")
|
52
|
+
@ssh.expects(:exec!).with("git reflog delete --rewrite HEAD@{1}")
|
53
|
+
update
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "can rollback" do
|
58
|
+
@deploy.connect do
|
59
|
+
@ssh.expects(:exec!).with("cd #{@config['path']}")
|
60
|
+
@ssh.expects(:exec!).with("git fetch origin")
|
61
|
+
@ssh.expects(:exec!).with("git reset --hard HEAD@{1}")
|
62
|
+
rollback
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "can notify" do
|
67
|
+
skip "until this method does something, there is nothing to test"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "can install bundled gems" do
|
71
|
+
@deploy.connect do
|
72
|
+
@ssh.expects(:exec!).with('bundle install --deployment --path vendor/bundle --without development test ')
|
73
|
+
bundle_install
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it "can export Procfiles with foreman" do
|
78
|
+
@deploy.connect do
|
79
|
+
@ssh.expects(:exec!).with("foreman export upstart /etc/init --app #{@config['app']} --log #{@config['path']}/log --user #{@config['ssh_user']} --procfile #{@config['path']}/Procfile ")
|
80
|
+
export_foreman
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'lobstr'
|
2
|
+
require "mocha"
|
3
|
+
begin; require 'turn/autorun'; rescue LoadError; end
|
4
|
+
Turn.config do |c|
|
5
|
+
c.natural = true
|
6
|
+
c.ansi = true
|
7
|
+
c.format = :pretty
|
8
|
+
end
|
9
|
+
|
10
|
+
def clean_up_config_file(config_file = 'spec/config/lobstr.yml')
|
11
|
+
config_path = File.dirname config_file
|
12
|
+
File.delete config_file if File.exist? config_file
|
13
|
+
Dir.delete config_path if Dir.exist? config_path
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lobstr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Eric Marden
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: psych
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.3'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: thor
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0.16'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.16'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: net-ssh
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '2.5'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.5'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: highline
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.6'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '1.6'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rake
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 0.9.2
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 0.9.2
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: minitest
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '3.4'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '3.4'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: ansi
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.4'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '1.4'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: turn
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0.9'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0.9'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: pry
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ~>
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0.9'
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ~>
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0.9'
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: mocha
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ~>
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0.12'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ~>
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0.12'
|
174
|
+
description: deployments so easy, even a zoidberg can do it
|
175
|
+
email:
|
176
|
+
- eric@xentek.net
|
177
|
+
executables:
|
178
|
+
- lob
|
179
|
+
extensions: []
|
180
|
+
extra_rdoc_files: []
|
181
|
+
files:
|
182
|
+
- .gitignore
|
183
|
+
- .travis.yml
|
184
|
+
- Gemfile
|
185
|
+
- LICENSE.txt
|
186
|
+
- README.md
|
187
|
+
- Rakefile
|
188
|
+
- bin/lob
|
189
|
+
- lib/lobstr.rb
|
190
|
+
- lib/lobstr/base.rb
|
191
|
+
- lib/lobstr/config.rb
|
192
|
+
- lib/lobstr/deploy.rb
|
193
|
+
- lib/lobstr/error.rb
|
194
|
+
- lib/lobstr/version.rb
|
195
|
+
- lobstr.gemspec
|
196
|
+
- spec/lobstr_base_spec.rb
|
197
|
+
- spec/lobstr_config_spec.rb
|
198
|
+
- spec/lobstr_deploy_spec.rb
|
199
|
+
- spec/spec_helper.rb
|
200
|
+
homepage: https://github.com/xentek/lobstr
|
201
|
+
licenses: []
|
202
|
+
post_install_message:
|
203
|
+
rdoc_options: []
|
204
|
+
require_paths:
|
205
|
+
- lib
|
206
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
207
|
+
none: false
|
208
|
+
requirements:
|
209
|
+
- - ! '>='
|
210
|
+
- !ruby/object:Gem::Version
|
211
|
+
version: 1.9.2
|
212
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
213
|
+
none: false
|
214
|
+
requirements:
|
215
|
+
- - ! '>='
|
216
|
+
- !ruby/object:Gem::Version
|
217
|
+
version: '0'
|
218
|
+
requirements: []
|
219
|
+
rubyforge_project:
|
220
|
+
rubygems_version: 1.8.23
|
221
|
+
signing_key:
|
222
|
+
specification_version: 3
|
223
|
+
summary: deployments so easy, even a zoidberg can do it
|
224
|
+
test_files:
|
225
|
+
- spec/lobstr_base_spec.rb
|
226
|
+
- spec/lobstr_config_spec.rb
|
227
|
+
- spec/lobstr_deploy_spec.rb
|
228
|
+
- spec/spec_helper.rb
|