trooper 0.6.0.alpha1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README.md +96 -0
- data/Rakefile +44 -0
- data/bin/trooper +9 -0
- data/lib/trooper/action.rb +56 -0
- data/lib/trooper/actions/clone_repository_action.rb +31 -0
- data/lib/trooper/actions/install_gems_action.rb +31 -0
- data/lib/trooper/actions/migrate_database_action.rb +31 -0
- data/lib/trooper/actions/restart_server_action.rb +33 -0
- data/lib/trooper/actions/rollback_migrate_action.rb +31 -0
- data/lib/trooper/actions/setup_database_action.rb +31 -0
- data/lib/trooper/actions/update_repository_action.rb +33 -0
- data/lib/trooper/arsenal.rb +51 -0
- data/lib/trooper/cli.rb +67 -0
- data/lib/trooper/config/action.rb +34 -0
- data/lib/trooper/config/environment.rb +36 -0
- data/lib/trooper/config/strategy.rb +14 -0
- data/lib/trooper/configuration.rb +88 -0
- data/lib/trooper/dsl/bundler.rb +26 -0
- data/lib/trooper/dsl/folders.rb +24 -0
- data/lib/trooper/dsl/rake.rb +11 -0
- data/lib/trooper/logger.rb +86 -0
- data/lib/trooper/runner.rb +57 -0
- data/lib/trooper/strategy.rb +104 -0
- data/lib/trooper/template/troopfile.rb +34 -0
- data/lib/trooper/version.rb +9 -0
- data/lib/trooper.rb +29 -0
- metadata +220 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 Richard Adams
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
# Trooper [](http://travis-ci.org/madwire/trooper)
|
2
|
+
|
3
|
+
Trooper is designed to give you the flexibility to deploy your code to any server in any way you like.
|
4
|
+
You design your deployment strategy to best fit your application and its needs.
|
5
|
+
Trooper comes with some built in actions that you can use in your own strategies or come up with entirely new ones.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
1. Super easy! `gem install trooper` or add it to your Gemfile `gem 'trooper'`
|
10
|
+
2. Pop into your terminal and run `=> trooper init`
|
11
|
+
3. Start building you deployment strategy :)
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
`=> trooper deploy -e staging` or `=> trooper update`
|
16
|
+
|
17
|
+
#### Define your own strategies and actions
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
action :restart_server, 'Restarting the server' do
|
21
|
+
run 'touch tmp/restart.txt'
|
22
|
+
run "echo 'Restarted'"
|
23
|
+
end
|
24
|
+
|
25
|
+
strategy :restart, 'Restart application' do
|
26
|
+
actions :restart_server
|
27
|
+
end
|
28
|
+
|
29
|
+
strategy :update, 'Update the code base on the server' do
|
30
|
+
actions :update_repository, :install_gems
|
31
|
+
call :restart # call another strategy
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
#### Example Troopfile
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
user 'my_user'
|
39
|
+
hosts 'production1.example.com', 'production2.example.com'
|
40
|
+
repository 'git@git.foo.co.uk:bar.git'
|
41
|
+
path "/fullpath/to/data/folder"
|
42
|
+
|
43
|
+
set :my_value => 'something'
|
44
|
+
|
45
|
+
env :stage do
|
46
|
+
hosts 'stage.example.com',
|
47
|
+
set :my_value => 'something_else'
|
48
|
+
|
49
|
+
action :restart do
|
50
|
+
run 'touch tmp/restert.txt'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
action :restart do
|
55
|
+
run 'touch tmp/restert.txt'
|
56
|
+
run "echo 'Restarted'"
|
57
|
+
end
|
58
|
+
|
59
|
+
strategy :update, 'Update the code base on the server' do
|
60
|
+
actions :update_repository, :install_gems
|
61
|
+
call :restart
|
62
|
+
end
|
63
|
+
|
64
|
+
strategy :deploy, 'Full deployment to the server' do
|
65
|
+
call :update
|
66
|
+
actions :migrate_database
|
67
|
+
call :restart
|
68
|
+
end
|
69
|
+
|
70
|
+
strategy :restart, 'Restart application' do
|
71
|
+
actions :restart
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
## LICENSE
|
76
|
+
|
77
|
+
Copyright 2011 Richard Adams
|
78
|
+
|
79
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
80
|
+
a copy of this software and associated documentation files (the
|
81
|
+
"Software"), to deal in the Software without restriction, including
|
82
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
83
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
84
|
+
permit persons to whom the Software is furnished to do so, subject to
|
85
|
+
the following conditions:
|
86
|
+
|
87
|
+
The above copyright notice and this permission notice shall be
|
88
|
+
included in all copies or substantial portions of the Software.
|
89
|
+
|
90
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
91
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
92
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
93
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
94
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
95
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
96
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'rdoc/task'
|
10
|
+
require 'sdoc'
|
11
|
+
rescue LoadError
|
12
|
+
require 'rdoc/rdoc'
|
13
|
+
require 'rake/rdoctask'
|
14
|
+
RDoc::Task = Rake::RDocTask
|
15
|
+
end
|
16
|
+
|
17
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
18
|
+
rdoc.rdoc_dir = 'rdoc'
|
19
|
+
rdoc.title = 'Trooper'
|
20
|
+
rdoc.options << '--line-numbers'
|
21
|
+
rdoc.options << '-f' << 'sdoc'
|
22
|
+
rdoc.options << '-c' << 'utf-8'
|
23
|
+
rdoc.options << '-t' << 'rails'
|
24
|
+
#rdoc.options << '-g' # SDoc flag, link methods to GitHub
|
25
|
+
rdoc.rdoc_files.include('README.md')
|
26
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
Bundler::GemHelper.install_tasks
|
31
|
+
|
32
|
+
|
33
|
+
ENV["COVERAGE"] = "true"
|
34
|
+
|
35
|
+
require 'rspec/core'
|
36
|
+
require 'rspec/core/rake_task'
|
37
|
+
|
38
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
39
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'Default: Run all specs.'
|
43
|
+
task :default => :spec
|
44
|
+
|
data/bin/trooper
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'trooper/dsl/folders'
|
2
|
+
require 'trooper/dsl/rake'
|
3
|
+
require 'trooper/dsl/bundler'
|
4
|
+
|
5
|
+
module Trooper
|
6
|
+
class Action
|
7
|
+
include Trooper::DSL::Folders
|
8
|
+
include Trooper::DSL::Rake
|
9
|
+
include Trooper::DSL::Bundler
|
10
|
+
|
11
|
+
attr_reader :name, :description, :config, :block
|
12
|
+
attr_accessor :commands
|
13
|
+
|
14
|
+
# expects a name, description and a block
|
15
|
+
# Action.new(:my_action, 'Does great things') { run 'touch file' }
|
16
|
+
def initialize(name, description, &block)
|
17
|
+
@name, @description, @config = name, description, {}
|
18
|
+
@commands, @block = [], block
|
19
|
+
end
|
20
|
+
|
21
|
+
# eval's the block passed on initialize and returns the command array
|
22
|
+
def call(configuration)
|
23
|
+
@config = configuration
|
24
|
+
eval_block(&block)
|
25
|
+
commands
|
26
|
+
end
|
27
|
+
alias :execute :call
|
28
|
+
|
29
|
+
# validates the action
|
30
|
+
def ok?
|
31
|
+
true
|
32
|
+
end
|
33
|
+
|
34
|
+
# run is the base run command used by the dsl
|
35
|
+
def run(command)
|
36
|
+
commands << command if command != ''
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(method_sym, *arguments, &block) # :nodoc:
|
40
|
+
config[method_sym] || super
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def eval_block(&block) # :nodoc:
|
46
|
+
if block_given?
|
47
|
+
if block.arity == 1
|
48
|
+
block.call self
|
49
|
+
else
|
50
|
+
instance_eval &block
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'trooper/action'
|
2
|
+
|
3
|
+
module Trooper
|
4
|
+
module Actions
|
5
|
+
|
6
|
+
class CloneRepositoryAction < Action
|
7
|
+
|
8
|
+
def initialize(config = {})
|
9
|
+
@name = :clone_repository
|
10
|
+
@description = "Cloning repository as 'application'"
|
11
|
+
@config = config
|
12
|
+
@commands = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(configuration)
|
16
|
+
@config = configuration
|
17
|
+
build_commands
|
18
|
+
commands
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def build_commands
|
24
|
+
cd path
|
25
|
+
run "git clone #{repository} application"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'trooper/action'
|
2
|
+
|
3
|
+
module Trooper
|
4
|
+
module Actions
|
5
|
+
|
6
|
+
class InstallGemsAction < Action
|
7
|
+
|
8
|
+
def initialize(config = {})
|
9
|
+
@name = :install_gems
|
10
|
+
@description = "Installing Gems with Bundler"
|
11
|
+
@config = config
|
12
|
+
@commands = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(configuration)
|
16
|
+
@config = configuration
|
17
|
+
build_commands
|
18
|
+
commands
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def build_commands
|
24
|
+
cd application_path
|
25
|
+
bundle_install
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'trooper/action'
|
2
|
+
|
3
|
+
module Trooper
|
4
|
+
module Actions
|
5
|
+
|
6
|
+
class MigrateDatabaseAction < Action
|
7
|
+
|
8
|
+
def initialize(config = {})
|
9
|
+
@name = :migrate_database
|
10
|
+
@description = "Migrating database"
|
11
|
+
@config = config
|
12
|
+
@commands = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(configuration)
|
16
|
+
@config = configuration
|
17
|
+
build_commands
|
18
|
+
commands
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def build_commands
|
24
|
+
cd application_path
|
25
|
+
rake "db:migrate RAILS_ENV=#{environment}"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'trooper/action'
|
2
|
+
|
3
|
+
module Trooper
|
4
|
+
module Actions
|
5
|
+
|
6
|
+
class RestartServerAction < Action
|
7
|
+
|
8
|
+
def initialize(config = {})
|
9
|
+
@name = :restart_server
|
10
|
+
@description = "Restart server"
|
11
|
+
@config = config
|
12
|
+
@commands = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(configuration)
|
16
|
+
@config = configuration
|
17
|
+
build_commands
|
18
|
+
commands
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def build_commands
|
24
|
+
cd application_path
|
25
|
+
create_folder 'tmp'
|
26
|
+
run 'touch tmp/restart.txt'
|
27
|
+
run 'echo "Server restarted!"'
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'trooper/action'
|
2
|
+
|
3
|
+
module Trooper
|
4
|
+
module Actions
|
5
|
+
|
6
|
+
class RollbackMigrateAction < Action
|
7
|
+
|
8
|
+
def initialize(config = {})
|
9
|
+
@name = :rollback_migrate
|
10
|
+
@description = "Rollback database"
|
11
|
+
@config = config
|
12
|
+
@commands = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(configuration)
|
16
|
+
@config = configuration
|
17
|
+
build_commands
|
18
|
+
commands
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def build_commands
|
24
|
+
cd application_path
|
25
|
+
rake "db:rollback RAILS_ENV=#{environment}"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'trooper/action'
|
2
|
+
|
3
|
+
module Trooper
|
4
|
+
module Actions
|
5
|
+
|
6
|
+
class SetupDatabaseAction < Action
|
7
|
+
|
8
|
+
def initialize(config = {})
|
9
|
+
@name = :setup_database
|
10
|
+
@description = "Setting up database"
|
11
|
+
@config = config
|
12
|
+
@commands = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(configuration)
|
16
|
+
@config = configuration
|
17
|
+
build_commands
|
18
|
+
commands
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def build_commands
|
24
|
+
cd application_path
|
25
|
+
rake "db:setup RAILS_ENV=#{environment}"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'trooper/action'
|
2
|
+
|
3
|
+
module Trooper
|
4
|
+
module Actions
|
5
|
+
|
6
|
+
class UpdateRepositoryAction < Action
|
7
|
+
|
8
|
+
def initialize(config = {})
|
9
|
+
@name = :update_repository
|
10
|
+
@description = "Updating repository"
|
11
|
+
@config = config
|
12
|
+
@commands = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(configuration)
|
16
|
+
@config = configuration
|
17
|
+
build_commands
|
18
|
+
commands
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def build_commands
|
24
|
+
cd application_path
|
25
|
+
run "git checkout #{branch} -q"
|
26
|
+
run "git pull origin #{branch} -q"
|
27
|
+
run "git gc --aggressive"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Trooper
|
2
|
+
|
3
|
+
class Arsenal < Array
|
4
|
+
|
5
|
+
# find an arsenal by its name
|
6
|
+
def find_by_name(name)
|
7
|
+
detect { |weapon| weapon.name == name }
|
8
|
+
end
|
9
|
+
alias :[] :find_by_name
|
10
|
+
|
11
|
+
# add a weapon to the arsenal
|
12
|
+
def add(weapon)
|
13
|
+
if weapon.ok?
|
14
|
+
remove weapon.name
|
15
|
+
self << weapon
|
16
|
+
end
|
17
|
+
weapon
|
18
|
+
end
|
19
|
+
|
20
|
+
# remove a weapon from the arsenal
|
21
|
+
def remove(name)
|
22
|
+
self.delete_if {|w| w.name == name}
|
23
|
+
end
|
24
|
+
|
25
|
+
# clears arsenal
|
26
|
+
def clear!
|
27
|
+
self.clear
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
|
32
|
+
# returns the strategies arsenal
|
33
|
+
def strategies
|
34
|
+
@strategies ||= new
|
35
|
+
end
|
36
|
+
|
37
|
+
# returns the strategies arsenal
|
38
|
+
def actions
|
39
|
+
@actions ||= new
|
40
|
+
end
|
41
|
+
|
42
|
+
# clears all default arsenal
|
43
|
+
def reset!
|
44
|
+
@strategies, @actions = nil
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
data/lib/trooper/cli.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'trooper/configuration'
|
3
|
+
|
4
|
+
module Trooper
|
5
|
+
class CLI
|
6
|
+
|
7
|
+
def self.start(argv = ARGV)
|
8
|
+
cli = self.new(argv)
|
9
|
+
cli.execute
|
10
|
+
cli
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :command, :options, :argv
|
14
|
+
attr_accessor :config
|
15
|
+
|
16
|
+
def initialize(argv)
|
17
|
+
@argv = argv
|
18
|
+
@options = { :environment => :production }
|
19
|
+
|
20
|
+
@command = option_parser.parse!(@argv)[0]
|
21
|
+
raise CliArgumentError, "You didnt pass an action" if @command == nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def execute
|
25
|
+
case command.to_sym
|
26
|
+
when :init
|
27
|
+
Configuration.init
|
28
|
+
else
|
29
|
+
config = Configuration.new(options)
|
30
|
+
config.execute action
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def option_parser
|
37
|
+
@option_parser ||= ::OptionParser.new do |op|
|
38
|
+
op.banner = 'Usage: trooper <command> [options]'
|
39
|
+
op.separator ''
|
40
|
+
|
41
|
+
op.on "-d", "--debug", "Debuy" do
|
42
|
+
@options[:debug] = true
|
43
|
+
end
|
44
|
+
|
45
|
+
op.on "-e", "--env ENV", "Environment" do |e|
|
46
|
+
@options[:environment] = e.to_sym
|
47
|
+
end
|
48
|
+
|
49
|
+
op.on "-f", "--file TROOPFILE", "Load a different Troopfile" do |f|
|
50
|
+
@options[:file_name] = f || 'Troopfile'
|
51
|
+
end
|
52
|
+
|
53
|
+
op.on_tail "-h", "--help", "Help" do
|
54
|
+
puts @option_parser
|
55
|
+
exit
|
56
|
+
end
|
57
|
+
|
58
|
+
op.on_tail "-v", "--version", "Show version" do
|
59
|
+
puts "Trooper v#{Trooper::Version::STRING}"
|
60
|
+
exit
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'trooper/action'
|
2
|
+
|
3
|
+
require 'trooper/actions/clone_repository_action'
|
4
|
+
require 'trooper/actions/install_gems_action'
|
5
|
+
require 'trooper/actions/migrate_database_action'
|
6
|
+
require 'trooper/actions/restart_server_action'
|
7
|
+
require 'trooper/actions/rollback_migrate_action'
|
8
|
+
require 'trooper/actions/setup_database_action'
|
9
|
+
require 'trooper/actions/update_repository_action'
|
10
|
+
|
11
|
+
module Trooper
|
12
|
+
module Config
|
13
|
+
module Action
|
14
|
+
|
15
|
+
DEFAULT_ACTIONS = [Actions::CloneRepositoryAction, Actions::InstallGemsAction,
|
16
|
+
Actions::MigrateDatabaseAction, Actions::RestartServerAction,
|
17
|
+
Actions::RollbackMigrateAction, Actions::SetupDatabaseAction,
|
18
|
+
Actions::UpdateRepositoryAction]
|
19
|
+
|
20
|
+
def action(name, description = "No Description", &block)
|
21
|
+
action = Trooper::Action.new name, description, &block
|
22
|
+
Trooper::Arsenal.actions.add action
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def load_default_actions!
|
27
|
+
DEFAULT_ACTIONS.each do |klass|
|
28
|
+
Trooper::Arsenal.actions.add klass.new
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Trooper
|
2
|
+
module Config
|
3
|
+
module Environment
|
4
|
+
|
5
|
+
def load_environment!
|
6
|
+
instance_variable = instance_variable_get("@#{self[:environment].to_s}_configuration")
|
7
|
+
unless instance_variable.nil?
|
8
|
+
instance_eval(&instance_variable)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def env(environment_name, &block)
|
13
|
+
instance_variable_set "@#{environment_name.to_s}_configuration", block
|
14
|
+
end
|
15
|
+
|
16
|
+
def user(arg)
|
17
|
+
set :user => arg
|
18
|
+
end
|
19
|
+
|
20
|
+
def hosts(*arg)
|
21
|
+
set :hosts => [*arg]
|
22
|
+
end
|
23
|
+
|
24
|
+
def repository(arg)
|
25
|
+
set :repository => arg
|
26
|
+
end
|
27
|
+
|
28
|
+
def path(arg)
|
29
|
+
set :application_path => "#{arg}/application"
|
30
|
+
set :trooper_path => "#{arg}/trooper"
|
31
|
+
set :path => arg
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'trooper/strategy'
|
2
|
+
|
3
|
+
module Trooper
|
4
|
+
module Config
|
5
|
+
module Strategy
|
6
|
+
|
7
|
+
def strategy(name, description = "No Description", &block)
|
8
|
+
strategy = Trooper::Strategy.new name, description, self, &block
|
9
|
+
Trooper::Arsenal.strategies.add strategy
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'trooper/arsenal'
|
4
|
+
|
5
|
+
require 'trooper/config/environment'
|
6
|
+
require 'trooper/config/strategy'
|
7
|
+
require 'trooper/config/action'
|
8
|
+
|
9
|
+
module Trooper
|
10
|
+
class Configuration < Hash
|
11
|
+
FILE_NAME = "Troopfile"
|
12
|
+
|
13
|
+
include Trooper::Config::Environment
|
14
|
+
include Trooper::Config::Strategy
|
15
|
+
include Trooper::Config::Action
|
16
|
+
|
17
|
+
def self.init
|
18
|
+
gem_dir = File.dirname(__FILE__)
|
19
|
+
|
20
|
+
if RUBY_VERSION == /1.8/
|
21
|
+
require 'ftools'
|
22
|
+
File.copy("#{gem_dir}/template/troopfile.rb", "./Troopfile")
|
23
|
+
else
|
24
|
+
require 'fileutils'
|
25
|
+
::FileUtils.copy("#{gem_dir}/template/troopfile.rb", "./Troopfile")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# initialize a new configuration object, will parse the given troopfile.
|
30
|
+
# Configuration.new({:my_override => 'settings'})
|
31
|
+
def initialize(options = {})
|
32
|
+
@loaded = false
|
33
|
+
@file_name = options[:file_name] || FILE_NAME
|
34
|
+
self[:environment] = options[:environment] || :production
|
35
|
+
|
36
|
+
load_default_actions!
|
37
|
+
load_troopfile! options
|
38
|
+
end
|
39
|
+
|
40
|
+
# returns a terminal friendly version of the configuration
|
41
|
+
def to_s
|
42
|
+
self.map {|k,v| "#{k}: #{v}" }.join("\n")
|
43
|
+
end
|
44
|
+
|
45
|
+
# will find and execute the strategy name passed
|
46
|
+
# @config.execute(:my_strategy_name)
|
47
|
+
def execute(strategy_name)
|
48
|
+
Arsenal.strategies[strategy_name].execute self
|
49
|
+
end
|
50
|
+
|
51
|
+
# a way to set variables that will be available to all actions
|
52
|
+
# set(:my_variable => 'sdsd') # => available as method in an action
|
53
|
+
def set(hash)
|
54
|
+
self.merge! hash
|
55
|
+
end
|
56
|
+
|
57
|
+
# returns true if the troopfile was loaded
|
58
|
+
def loaded?
|
59
|
+
@loaded
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# loads the troopfile and sets the environment up
|
65
|
+
def load_troopfile!(options)
|
66
|
+
if troopfile?
|
67
|
+
eval troopfile.read
|
68
|
+
@loaded = true
|
69
|
+
|
70
|
+
load_environment!
|
71
|
+
set options
|
72
|
+
else
|
73
|
+
raise Trooper::NoConfigurationFileError, "No Configuration file (#{@file_name}) can be found!"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# returns the troopfile file object
|
78
|
+
def troopfile
|
79
|
+
File.open(@file_name)
|
80
|
+
end
|
81
|
+
|
82
|
+
# returns true if the troopfile exists
|
83
|
+
def troopfile?
|
84
|
+
File.exists?(@file_name)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Trooper
|
2
|
+
module DSL
|
3
|
+
module Bundler
|
4
|
+
|
5
|
+
def bundle_exec(command)
|
6
|
+
use_bundle = using_bundler? ? "bundle exec " : ""
|
7
|
+
run use_bundle + command
|
8
|
+
end
|
9
|
+
|
10
|
+
def bundle_install
|
11
|
+
run "bundle install --path #{trooper_path}/bundle --deployment --without development test" if using_bundler?
|
12
|
+
end
|
13
|
+
|
14
|
+
def rake(command)
|
15
|
+
bundle_exec "rake #{command}"
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def using_bundler?
|
21
|
+
File.exists? "Gemfile"
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Trooper
|
2
|
+
module DSL
|
3
|
+
module Folders
|
4
|
+
|
5
|
+
def cd(path)
|
6
|
+
run "cd #{path}"
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_folder(path)
|
10
|
+
run "mkdir -p #{path}"
|
11
|
+
end
|
12
|
+
alias :mkdir :create_folder
|
13
|
+
|
14
|
+
def delete_folder(path)
|
15
|
+
run "rm -rf #{path}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_folders(*folders)
|
19
|
+
folders.each { |folder| create_folder folder }
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
module Trooper
|
6
|
+
|
7
|
+
class Logger < ::Logger
|
8
|
+
ACTION = 6
|
9
|
+
SUCCESS = 7
|
10
|
+
|
11
|
+
# DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN < ACTION < SUCCESS
|
12
|
+
LABELS = %w(DEBUG INFO WARN ERROR FATAL ANY ACTION SUCCESS)
|
13
|
+
|
14
|
+
def action(progname = nil, &block)
|
15
|
+
add(ACTION, nil, progname, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def success(progname = nil, &block)
|
19
|
+
add(SUCCESS, nil, progname, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def format_severity(severity)
|
25
|
+
LABELS[severity] || 'ANY'
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
class LogFormat
|
32
|
+
|
33
|
+
COLOURS = {
|
34
|
+
:black => 30,
|
35
|
+
:red => 31,
|
36
|
+
:green => 32,
|
37
|
+
:yellow => 33,
|
38
|
+
:blue => 34,
|
39
|
+
:magenta => 35,
|
40
|
+
:cyan => 36,
|
41
|
+
:white => 37
|
42
|
+
}
|
43
|
+
|
44
|
+
def call(severity, datetime, progname, message)
|
45
|
+
# DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN < ACTION < SUCCESS
|
46
|
+
case severity
|
47
|
+
when "DEBUG"
|
48
|
+
colour("#{progname} => [#{severity}] #{message}\n", :yellow)
|
49
|
+
when "WARN"
|
50
|
+
colour("#{progname} => [#{severity}] #{message}\n", :yellow)
|
51
|
+
when "ACTION"
|
52
|
+
colour("#{progname} => [#{severity}] #{message}\n", :magenta)
|
53
|
+
when "SUCCESS"
|
54
|
+
colour("#{progname} => [#{severity}] #{message}\n", :green)
|
55
|
+
when "ERROR", "FATAL"
|
56
|
+
colour("#{progname} => [#{severity}] #{message}\n", :red)
|
57
|
+
else
|
58
|
+
"#{progname} => [#{severity}] #{message}\n"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def colour(msg, clr = :black)
|
65
|
+
"\e[#{COLOURS[clr]}m#{msg}\e[0m"
|
66
|
+
end
|
67
|
+
|
68
|
+
def underline
|
69
|
+
"\e[4m"
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def self.logger
|
76
|
+
@logger ||= begin
|
77
|
+
logger = Logger.new($stdout)
|
78
|
+
logger.level = ::Logger::DEBUG
|
79
|
+
logger.progname = 'Trooper'
|
80
|
+
logger.formatter = LogFormat.new
|
81
|
+
logger
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "net/ssh"
|
4
|
+
|
5
|
+
module Trooper
|
6
|
+
class Runner
|
7
|
+
|
8
|
+
attr_reader :host, :user, :connection
|
9
|
+
|
10
|
+
# pass the host, user and any net/ssh config options
|
11
|
+
# Runner.new('my.example.com', 'admin', :forward_agent => false)
|
12
|
+
def initialize(host, user, options = { :forward_agent => true })
|
13
|
+
@host = host
|
14
|
+
@user = user
|
15
|
+
@connection = Net::SSH.start(host, user, options)
|
16
|
+
end
|
17
|
+
|
18
|
+
# returns user@host as a string
|
19
|
+
def to_s
|
20
|
+
"#{user}@#{host}"
|
21
|
+
end
|
22
|
+
|
23
|
+
# execute a set of commands via net/ssh, returns and array or raises an exception
|
24
|
+
# runner.execute(['cd to/path', 'touch file']) # => ['cd to/path && touch file', :stdout, '']
|
25
|
+
# runner.execute('cat file') # => ['cat file', :stdout, 'file content']
|
26
|
+
def execute(command, options = {})
|
27
|
+
commands = parse command
|
28
|
+
Trooper.logger.debug commands
|
29
|
+
connection.exec! commands do |ch, stream, data|
|
30
|
+
raise Trooper::StdError, "#{data}\n[ERROR INFO] #{commands}" if stream == :stderr
|
31
|
+
ch.wait
|
32
|
+
return [commands, stream, data]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# close net/ssh connection
|
37
|
+
def close
|
38
|
+
connection.close
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# parse command, expects a string or array
|
44
|
+
# parse(['cd to/path', 'touch file']) # => 'cd to/path && touch file'
|
45
|
+
def parse(command)
|
46
|
+
case command.class.name.downcase.to_sym #Array => :array
|
47
|
+
when :array
|
48
|
+
command.compact.join(' && ')
|
49
|
+
when :string
|
50
|
+
command.chomp
|
51
|
+
else
|
52
|
+
raise Trooper::MalformedCommandError, "Command Not a String or Array: #{command.inspect}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'trooper/runner'
|
2
|
+
|
3
|
+
module Trooper
|
4
|
+
class Strategy
|
5
|
+
|
6
|
+
attr_reader :name, :description, :config, :run_list
|
7
|
+
|
8
|
+
def initialize(name, description, config = {}, &block)
|
9
|
+
@name, @description, @config = name, description, config
|
10
|
+
@run_list = []
|
11
|
+
eval_block(&block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute(config = {})
|
15
|
+
@config = config
|
16
|
+
Trooper.logger.debug "Configuration\n#{config}"
|
17
|
+
successful = nil
|
18
|
+
|
19
|
+
runners.each do |runner|
|
20
|
+
begin
|
21
|
+
Trooper.logger.info "\e[4mRunning on #{runner}\n"
|
22
|
+
|
23
|
+
run_list.each do |item, name|
|
24
|
+
self.send("#{item}_execute", runner, name)
|
25
|
+
end
|
26
|
+
|
27
|
+
successful = true
|
28
|
+
Trooper.logger.success "\e[4mAll Actions Completed\n"
|
29
|
+
rescue Exception => e
|
30
|
+
Trooper.logger.error "#{e.class.to_s} : #{e.message}\n\n#{e.backtrace.join("\n")}"
|
31
|
+
|
32
|
+
successful = false
|
33
|
+
break #stop commands running on other servers
|
34
|
+
ensure
|
35
|
+
runner.close
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
successful
|
40
|
+
end
|
41
|
+
|
42
|
+
def ok?
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def call(strategy_name)
|
47
|
+
if Arsenal.strategies[strategy_name]
|
48
|
+
Arsenal.strategies[strategy_name].run_list.each do |action|
|
49
|
+
@run_list << action
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def actions(*action_names)
|
55
|
+
[*action_names].each do |name|
|
56
|
+
@run_list << [:action, name]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def method_missing(method_sym, *arguments, &block)
|
61
|
+
config[method_sym] || super
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def eval_block(&block)
|
67
|
+
if block_given?
|
68
|
+
if block.arity == 1
|
69
|
+
block.call self
|
70
|
+
else
|
71
|
+
instance_eval &block
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def action_execute(runner, name)
|
77
|
+
action = Arsenal.actions[name]
|
78
|
+
|
79
|
+
if action
|
80
|
+
commands = action.execute config
|
81
|
+
Trooper.logger.action action.description
|
82
|
+
runner_execute!(runner, commands)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def runners
|
87
|
+
@runners ||= begin
|
88
|
+
r, h, u = [], (hosts rescue nil), (user rescue nil)
|
89
|
+
h.each {|host| r << Runner.new(host, user) } if h && u; r
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def runner_execute!(runner, commands, options = {})
|
94
|
+
result = runner.execute commands, options
|
95
|
+
if result && result[1] == :stdout
|
96
|
+
Trooper.logger.info "#{result[2]}\n"
|
97
|
+
true
|
98
|
+
else
|
99
|
+
false
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
user 'my_user'
|
2
|
+
hosts 'stage.example.com'
|
3
|
+
repository 'git@git.bar.co.uk:whatever.git'
|
4
|
+
path "/path/to/data/folder"
|
5
|
+
|
6
|
+
set :my_value => 'something'
|
7
|
+
|
8
|
+
env :production do
|
9
|
+
hosts 'production1.example.com', 'production2.example.com'
|
10
|
+
set :my_value => 'something_else'
|
11
|
+
|
12
|
+
action :restart do
|
13
|
+
run 'touch tmp/restert.txt'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
action :restart do
|
18
|
+
run 'touch tmp/restert.txt'
|
19
|
+
end
|
20
|
+
|
21
|
+
strategy :update, 'Update the code base on the server' do
|
22
|
+
actions :update_repository, :install_gems
|
23
|
+
call :restart
|
24
|
+
end
|
25
|
+
|
26
|
+
strategy :deploy, 'Full deployment to the server' do
|
27
|
+
call :update
|
28
|
+
actions :migrate_database
|
29
|
+
call :restart
|
30
|
+
end
|
31
|
+
|
32
|
+
strategy :restart, 'Restart application' do
|
33
|
+
actions :restart
|
34
|
+
end
|
data/lib/trooper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'trooper/version'
|
2
|
+
require 'trooper/logger'
|
3
|
+
|
4
|
+
module Trooper
|
5
|
+
|
6
|
+
# Base class for all Trooper exceptions
|
7
|
+
class TrooperError < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
# When a strategy is not defined
|
11
|
+
class MissingStrategyError < TrooperError
|
12
|
+
end
|
13
|
+
|
14
|
+
# When a CLI argument is missing or badly formed
|
15
|
+
class CliArgumentError < TrooperError
|
16
|
+
end
|
17
|
+
|
18
|
+
# When a command(s) return a stderr stream
|
19
|
+
class StdError < TrooperError
|
20
|
+
end
|
21
|
+
|
22
|
+
# When a command is not formed corrently arrays or strings are exceptal commands
|
23
|
+
class MalformedCommandError < TrooperError
|
24
|
+
end
|
25
|
+
|
26
|
+
class NoConfigurationFileError < TrooperError
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: trooper
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.0.alpha1
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Richard Adams
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-16 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: net-ssh
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.3.0
|
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: 2.3.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '2.8'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '2.8'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: guard-rspec
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0.6'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.6'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rb-fsevent
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: yard
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0.7'
|
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.7'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: pry
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0.9'
|
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: '0.9'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: sdoc
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.3.16
|
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: 0.3.16
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: simplecov
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 0.5.4
|
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.5.4
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: rake
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ~>
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: 0.9.2
|
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.2
|
158
|
+
description: Simple but powerful deployment
|
159
|
+
email:
|
160
|
+
- richard@madwire.co.uk
|
161
|
+
executables: []
|
162
|
+
extensions: []
|
163
|
+
extra_rdoc_files: []
|
164
|
+
files:
|
165
|
+
- bin/trooper
|
166
|
+
- lib/trooper/action.rb
|
167
|
+
- lib/trooper/actions/clone_repository_action.rb
|
168
|
+
- lib/trooper/actions/install_gems_action.rb
|
169
|
+
- lib/trooper/actions/migrate_database_action.rb
|
170
|
+
- lib/trooper/actions/restart_server_action.rb
|
171
|
+
- lib/trooper/actions/rollback_migrate_action.rb
|
172
|
+
- lib/trooper/actions/setup_database_action.rb
|
173
|
+
- lib/trooper/actions/update_repository_action.rb
|
174
|
+
- lib/trooper/arsenal.rb
|
175
|
+
- lib/trooper/cli.rb
|
176
|
+
- lib/trooper/config/action.rb
|
177
|
+
- lib/trooper/config/environment.rb
|
178
|
+
- lib/trooper/config/strategy.rb
|
179
|
+
- lib/trooper/configuration.rb
|
180
|
+
- lib/trooper/dsl/bundler.rb
|
181
|
+
- lib/trooper/dsl/folders.rb
|
182
|
+
- lib/trooper/dsl/rake.rb
|
183
|
+
- lib/trooper/logger.rb
|
184
|
+
- lib/trooper/runner.rb
|
185
|
+
- lib/trooper/strategy.rb
|
186
|
+
- lib/trooper/template/troopfile.rb
|
187
|
+
- lib/trooper/version.rb
|
188
|
+
- lib/trooper.rb
|
189
|
+
- LICENSE
|
190
|
+
- Rakefile
|
191
|
+
- README.md
|
192
|
+
homepage: http://www.madwire.co.uk
|
193
|
+
licenses: []
|
194
|
+
post_install_message:
|
195
|
+
rdoc_options: []
|
196
|
+
require_paths:
|
197
|
+
- lib
|
198
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
199
|
+
none: false
|
200
|
+
requirements:
|
201
|
+
- - ! '>='
|
202
|
+
- !ruby/object:Gem::Version
|
203
|
+
version: '0'
|
204
|
+
segments:
|
205
|
+
- 0
|
206
|
+
hash: 3543094362386461389
|
207
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
208
|
+
none: false
|
209
|
+
requirements:
|
210
|
+
- - ! '>'
|
211
|
+
- !ruby/object:Gem::Version
|
212
|
+
version: 1.3.1
|
213
|
+
requirements: []
|
214
|
+
rubyforge_project:
|
215
|
+
rubygems_version: 1.8.22
|
216
|
+
signing_key:
|
217
|
+
specification_version: 3
|
218
|
+
summary: Deploy like a 'Trooper'
|
219
|
+
test_files: []
|
220
|
+
has_rdoc:
|