blazing 0.0.16 → 0.1.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.rvmrc +1 -1
- data/Gemfile +0 -10
- data/Gemfile.lock +53 -44
- data/Guardfile +8 -0
- data/README.md +23 -99
- data/Rakefile +21 -4
- data/bin/blazing +23 -5
- data/blazing.gemspec +19 -8
- data/features/help_banner.feature +13 -0
- data/features/step_definitions/blazing_steps.rb +1 -0
- data/features/support/env.rb +9 -0
- data/lib/blazing.rb +4 -13
- data/lib/blazing/config.rb +38 -73
- data/lib/blazing/dsl_setter.rb +20 -0
- data/lib/blazing/recipe.rb +5 -78
- data/lib/blazing/runner.rb +44 -2
- data/lib/blazing/shell.rb +7 -0
- data/lib/blazing/target.rb +44 -134
- data/lib/blazing/templates/config.erb +21 -0
- data/lib/blazing/templates/hook.erb +43 -0
- data/lib/blazing/version.rb +1 -1
- data/spec/blazing/config_spec.rb +104 -48
- data/spec/blazing/integration/init_spec.rb +8 -37
- data/spec/blazing/integration/setup_local_spec.rb +27 -0
- data/spec/blazing/integration/setup_remote_spec.rb +32 -0
- data/spec/blazing/integration/update_spec.rb +38 -0
- data/spec/blazing/recipe_spec.rb +5 -66
- data/spec/blazing/runner_spec.rb +41 -6
- data/spec/blazing/target_spec.rb +26 -99
- data/spec/spec_helper.rb +18 -12
- data/spec/support/{config.rb → empty_config.rb} +0 -0
- metadata +170 -97
- data/TODO +0 -3
- data/lib/blazing/base.rb +0 -41
- data/lib/blazing/bootstrap.rb +0 -27
- data/lib/blazing/cli/base.rb +0 -64
- data/lib/blazing/cli/create.rb +0 -32
- data/lib/blazing/cli/hook.rb +0 -22
- data/lib/blazing/cli/templates/blazing.tt +0 -7
- data/lib/blazing/cli/templates/post-hook.tt +0 -25
- data/lib/blazing/core_ext/object.rb +0 -8
- data/lib/blazing/logger.rb +0 -31
- data/lib/blazing/recipes/bundler_recipe.rb +0 -20
- data/lib/blazing/recipes/rvm_recipe.rb +0 -11
- data/spec/blazing/binary_spec.rb +0 -11
- data/spec/blazing/cli/base_spec.rb +0 -94
- data/spec/blazing/cli/create_spec.rb +0 -27
- data/spec/blazing/cli/hook_spec.rb +0 -16
- data/spec/blazing/logger_spec.rb +0 -50
- data/spec/blazing/recipes/bundler_recipe_spec.rb +0 -32
- data/spec/blazing/recipes/passenger_recipe_spec.rb +0 -6
- data/spec/blazing/recipes/rvm_recipe_spec.rb +0 -11
- data/spec/blazing/remote_spec.rb +0 -136
data/lib/blazing.rb
CHANGED
@@ -1,18 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require 'thor/group'
|
3
|
-
require 'blazing'
|
4
|
-
require 'blazing/config'
|
5
|
-
require 'blazing/runner'
|
6
|
-
require 'blazing/logger'
|
7
|
-
require 'blazing/target'
|
8
|
-
require 'blazing/recipe'
|
9
|
-
require 'blazing/cli/base'
|
10
|
-
require 'blazing/cli/create'
|
11
|
-
require 'blazing/cli/hook'
|
1
|
+
require "blazing/version"
|
12
2
|
|
13
3
|
module Blazing
|
14
4
|
|
15
|
-
|
16
|
-
|
5
|
+
TEMPLATE_ROOT = File.expand_path(File.dirname(__FILE__) + File.join('/', 'blazing', 'templates'))
|
6
|
+
DEFAULT_CONFIG_LOCATION = 'config/blazing.rb'
|
7
|
+
TMP_HOOK = '/tmp/post-receive'
|
17
8
|
|
18
9
|
end
|
data/lib/blazing/config.rb
CHANGED
@@ -1,90 +1,55 @@
|
|
1
|
-
require 'blazing'
|
2
1
|
require 'blazing/target'
|
2
|
+
require 'blazing/recipe'
|
3
|
+
require 'blazing/dsl_setter'
|
3
4
|
|
4
|
-
|
5
|
-
class Config
|
5
|
+
class Blazing::Config
|
6
6
|
|
7
|
-
|
7
|
+
extend Blazing::DSLSetter
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def read(&block)
|
13
|
-
config = Blazing::Config.new
|
14
|
-
config.instance_eval(&block)
|
9
|
+
attr_reader :file
|
10
|
+
attr_accessor :targets
|
11
|
+
dsl_setter :repository, :rvm, :rake
|
15
12
|
|
16
|
-
|
17
|
-
end
|
13
|
+
class << self
|
18
14
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
def parse
|
23
|
-
read do
|
24
|
-
instance_eval(File.read(Blazing::CONFIGURATION_FILE))
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
#
|
29
|
-
# DSL Setter helper method
|
30
|
-
#
|
31
|
-
def dsl_setter(*names)
|
32
|
-
names.each do |name|
|
33
|
-
class_eval <<-EVAL
|
34
|
-
def #{name}(value = nil)
|
35
|
-
if value
|
36
|
-
instance_variable_set("@#{name}", value)
|
37
|
-
else
|
38
|
-
instance_variable_get("@#{name}")
|
39
|
-
end
|
40
|
-
end
|
41
|
-
EVAL
|
42
|
-
end
|
43
|
-
end
|
15
|
+
def parse(configuration_file = nil)
|
16
|
+
config = self.new(configuration_file)
|
17
|
+
config.instance_eval(File.read(config.file))
|
44
18
|
|
19
|
+
config
|
45
20
|
end
|
46
21
|
|
47
|
-
|
48
|
-
attr_accessor :targets, :recipes
|
22
|
+
end
|
49
23
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
24
|
+
def initialize(configuration_file = nil)
|
25
|
+
@file = configuration_file || Blazing::DEFAULT_CONFIG_LOCATION
|
26
|
+
@targets = []
|
27
|
+
@recipes = []
|
28
|
+
end
|
54
29
|
|
55
|
-
|
56
|
-
|
57
|
-
|
30
|
+
def target(name, location, options = {})
|
31
|
+
raise "Name already taken" if targets.find { |t| t.name == name }
|
32
|
+
targets << Blazing::Target.new(name, location, self, options)
|
33
|
+
end
|
58
34
|
|
59
|
-
|
60
|
-
|
35
|
+
def recipes(recipes = nil)
|
36
|
+
if recipes.kind_of? Symbol
|
37
|
+
@recipes << Blazing::Recipe.init_by_name(recipes)
|
38
|
+
elsif recipes.kind_of? Array
|
39
|
+
@recipes = recipes.map { |r| Blazing::Recipe.init_by_name(r) }
|
40
|
+
else
|
41
|
+
@recipes
|
61
42
|
end
|
43
|
+
end
|
62
44
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
if target_name
|
71
|
-
active_target = targets.find {|target| target.name == target_name }
|
72
|
-
end
|
73
|
-
|
74
|
-
if active_target.nil? && targets.size == 1
|
75
|
-
active_target = targets.first
|
76
|
-
end
|
77
|
-
|
78
|
-
if active_target.nil?
|
79
|
-
active_target = targets.find {|target| target.default }
|
80
|
-
end
|
81
|
-
|
82
|
-
if active_target.nil?
|
83
|
-
raise 'no target specified and no default targets found'
|
84
|
-
end
|
85
|
-
|
86
|
-
active_target
|
45
|
+
def default_target
|
46
|
+
if @targets.size > 1
|
47
|
+
default = @targets.find { |t| t.options[:default] == true }
|
48
|
+
raise 'could not find default target' unless default
|
49
|
+
default
|
50
|
+
else
|
51
|
+
@targets.first
|
87
52
|
end
|
88
|
-
|
89
53
|
end
|
54
|
+
|
90
55
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Blazing::DSLSetter
|
2
|
+
|
3
|
+
#
|
4
|
+
# DSL Setter helper method
|
5
|
+
#
|
6
|
+
def dsl_setter(*names)
|
7
|
+
names.each do |name|
|
8
|
+
class_eval <<-EVAL
|
9
|
+
def #{name}(value = nil)
|
10
|
+
if value
|
11
|
+
instance_variable_set("@#{name}", value)
|
12
|
+
else
|
13
|
+
instance_variable_get("@#{name}")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
EVAL
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/lib/blazing/recipe.rb
CHANGED
@@ -1,86 +1,13 @@
|
|
1
1
|
require 'active_support/inflector'
|
2
|
-
require 'blazing'
|
3
|
-
# require 'blazing/logger'
|
4
2
|
|
5
|
-
|
6
|
-
class Recipe
|
3
|
+
class Blazing::Recipe
|
7
4
|
|
5
|
+
class << self
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
attr_accessor :name, :options
|
12
|
-
|
13
|
-
def initialize(name, options = {})
|
14
|
-
@name = name.to_s
|
15
|
-
@options = options
|
16
|
-
@logger = options[:_logger] ||= Blazing::Logger.new
|
17
|
-
@runner = Blazing::Runner.new
|
18
|
-
end
|
19
|
-
|
20
|
-
def recipe_class
|
21
|
-
# TODO: Unify naming conventions
|
22
|
-
# Gem Recipe Naming Convention
|
23
|
-
('Blazing::' + @name.to_s.gsub('_','/').camelize).constantize
|
24
|
-
rescue NameError
|
25
|
-
begin
|
26
|
-
# Builtin Recipe Naming Convention
|
27
|
-
('Blazing::' + (@name.to_s + '_recipe').camelize).constantize
|
28
|
-
rescue NameError
|
29
|
-
@logger.log :error, "unable to load #{@name} recipe"
|
30
|
-
return nil
|
31
|
-
end
|
7
|
+
def init_by_name(name)
|
8
|
+
"Blazing::Recipe::#{name.to_s.camelize}".constantize.new
|
32
9
|
end
|
33
10
|
|
34
|
-
def run
|
35
|
-
raise 'run method must be implemented in recipe'
|
36
|
-
end
|
37
|
-
|
38
|
-
class << self
|
39
|
-
|
40
|
-
def new_recipe_by_name(name, options = {})
|
41
|
-
load_builtin_recipes
|
42
|
-
load_gem_recipes
|
43
|
-
new(name, options).recipe_class.new(name, options)
|
44
|
-
end
|
45
|
-
|
46
|
-
def load_builtin_recipes
|
47
|
-
dir = File.join(File.dirname(__FILE__), "/recipes")
|
48
|
-
$LOAD_PATH.unshift(dir)
|
49
|
-
Dir[File.join(dir, "*.rb")].each { |file| load File.basename(file) }
|
50
|
-
end
|
51
|
-
|
52
|
-
def load_gem_recipes
|
53
|
-
# TODO: I'm sure there is a better way to do this...
|
54
|
-
gems = open('Gemfile').grep(/blazing-/).map { |l| l.match(/(blazing-.*)\'\,/)[1] }
|
55
|
-
gems.each do |gem|
|
56
|
-
gem_lib_path = $:.find { |p| p.include? gem }
|
57
|
-
recipes_path = File.join(gem_lib_path, gem, 'recipes')
|
58
|
-
recipes = Dir.entries(recipes_path).delete_if { |r| r == '.' || r == '..' }
|
59
|
-
recipes.each { |recipe| require File.join(gem, 'recipes', recipe) }
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def load_local_recipes
|
64
|
-
#TODO: Implement
|
65
|
-
end
|
66
|
-
|
67
|
-
#
|
68
|
-
# Return the list of available recipes based
|
69
|
-
# on class hierarchy
|
70
|
-
#
|
71
|
-
def list
|
72
|
-
descendants = []
|
73
|
-
|
74
|
-
load_builtin_recipes
|
75
|
-
load_gem_recipes
|
76
|
-
|
77
|
-
ObjectSpace.each_object(Class) do |k|
|
78
|
-
descendants.unshift k if k < self
|
79
|
-
end
|
80
|
-
descendants.uniq!
|
81
|
-
descendants
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
11
|
end
|
12
|
+
|
86
13
|
end
|
data/lib/blazing/runner.rb
CHANGED
@@ -1,7 +1,49 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'methadone'
|
3
|
+
|
1
4
|
class Blazing::Runner
|
2
5
|
|
3
|
-
|
4
|
-
|
6
|
+
include Methadone::CLILogging
|
7
|
+
|
8
|
+
def initialize(config = nil, target = nil)
|
9
|
+
if config
|
10
|
+
@config = config
|
11
|
+
@target = @config.targets.find { |t| t.name == target.to_s } || @config.default_target
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def exec(command)
|
16
|
+
command_method = "#{command.gsub(':', '_')}_command"
|
17
|
+
raise "Unknown Command: #{command}" unless self.respond_to? command_method
|
18
|
+
self.send command_method
|
19
|
+
end
|
20
|
+
|
21
|
+
def init_command
|
22
|
+
info("Creating an example config file in #{Blazing::DEFAULT_CONFIG_LOCATION}")
|
23
|
+
info("Customize it to your needs")
|
24
|
+
|
25
|
+
Dir.mkdir 'config' unless Dir.exists? 'config'
|
26
|
+
configuration_file = ERB.new(File.read("#{Blazing::TEMPLATE_ROOT}/config.erb")).result
|
27
|
+
|
28
|
+
File.open(Blazing::DEFAULT_CONFIG_LOCATION,"wb") do |f|
|
29
|
+
f.puts configuration_file
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def setup_local_command
|
34
|
+
repository = Grit::Repo.new(Dir.pwd)
|
35
|
+
@config.targets.each do |target|
|
36
|
+
info("Adding new remote #{target.name} pointing to #{target.location}")
|
37
|
+
repository.config["remote.#{target.name}.url"] = target.location
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup_remote_command
|
42
|
+
@config.default_target.setup
|
43
|
+
end
|
44
|
+
|
45
|
+
def update_command
|
46
|
+
@config.default_target.update
|
5
47
|
end
|
6
48
|
|
7
49
|
end
|
data/lib/blazing/target.rb
CHANGED
@@ -1,151 +1,61 @@
|
|
1
|
-
require 'blazing'
|
2
|
-
require 'blazing/core_ext/object'
|
3
|
-
require 'blazing/config'
|
4
|
-
require 'blazing/bootstrap'
|
1
|
+
require 'blazing/shell'
|
5
2
|
|
6
|
-
|
7
|
-
class Target
|
3
|
+
class Blazing::Target
|
8
4
|
|
9
|
-
|
5
|
+
attr_accessor :name, :location, :options
|
10
6
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
target = config.find_target(name)
|
19
|
-
runner = Blazing::Runner.new
|
20
|
-
# TODO: Use a Wrapper to Net::SSH
|
21
|
-
target.clone_repository
|
22
|
-
target.setup_post_receive_hook
|
23
|
-
setup target.name
|
24
|
-
end
|
25
|
-
|
26
|
-
def deploy(name)
|
27
|
-
target = config.find_target(name)
|
28
|
-
runner = Blazing::Runner.new
|
29
|
-
deploy_command = "git push #{name}"
|
30
|
-
deploy_command += " #{target.branch}:#{target.branch}" if target.branch
|
31
|
-
|
32
|
-
# TODO: checkout branch if we pushed to a branch which is not checked out
|
33
|
-
runner.run deploy_command
|
34
|
-
end
|
35
|
-
|
36
|
-
def setup(name)
|
37
|
-
if name
|
38
|
-
config.find_target(name).add_target_as_remote
|
39
|
-
else
|
40
|
-
config.targets.each do |target|
|
41
|
-
target.add_target_as_remote
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def post_receive(name)
|
47
|
-
target = config.find_target(name)
|
48
|
-
target.set_git_dir
|
49
|
-
target.reset_head!
|
50
|
-
@recipes.delete_if { |recipe| recipe.name == 'rvm' }
|
51
|
-
target.run_recipes
|
52
|
-
end
|
53
|
-
|
54
|
-
def config
|
55
|
-
Blazing::Config.parse
|
56
|
-
end
|
57
|
-
|
58
|
-
def runner
|
59
|
-
Blazing::Runner.new
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
def initialize(name, options = {})
|
65
|
-
@name = name.to_s
|
66
|
-
@logger = options[:_logger] ||= Blazing::Logger.new
|
67
|
-
@runner = options[:_runner] ||= Blazing::Runner.new
|
68
|
-
@hook = options[:_hook] ||= Blazing::CLI::Hook
|
69
|
-
|
70
|
-
@config = options[:config] || Blazing::Config.parse
|
71
|
-
|
72
|
-
@repository = @config.repository
|
73
|
-
create_accessors_from_config(options)
|
74
|
-
load_recipes
|
75
|
-
end
|
76
|
-
|
77
|
-
def create_accessors_from_config(options)
|
78
|
-
assign_settings(options)
|
79
|
-
parse_deploy_to_string unless @deploy_to.blank?
|
80
|
-
ensure_mandatory_settings
|
81
|
-
end
|
7
|
+
def initialize(name, location, config, options = {})
|
8
|
+
@name = name
|
9
|
+
@location = location
|
10
|
+
@config = config
|
11
|
+
@options = options
|
12
|
+
@shell = Blazing::Shell.new
|
13
|
+
end
|
82
14
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
88
|
-
end
|
15
|
+
def setup
|
16
|
+
@shell.run "ssh #{user}@#{host} '#{clone_repository} && #{setup_repository}'"
|
17
|
+
self.update
|
18
|
+
end
|
89
19
|
|
90
|
-
|
91
|
-
|
92
|
-
@host = @deploy_to.scan(/@(.*):/).join
|
93
|
-
@user = @deploy_to.scan(/(.*)@/).join
|
94
|
-
@path = @deploy_to.scan(/:(.*)/).join
|
95
|
-
end
|
20
|
+
def update
|
21
|
+
hook = ERB.new(File.read("#{Blazing::TEMPLATE_ROOT}/hook.erb")).result(binding)
|
96
22
|
|
97
|
-
|
98
|
-
|
99
|
-
[:host, :user, :path].each do |option|
|
100
|
-
raise "#{option} can't be blank!" if instance_variable_get("@#{option}").blank?
|
101
|
-
end
|
23
|
+
File.open(Blazing::TMP_HOOK, "wb") do |f|
|
24
|
+
f.puts hook
|
102
25
|
end
|
103
26
|
|
104
|
-
|
105
|
-
|
106
|
-
|
27
|
+
copy_hook
|
28
|
+
@shell.run "ssh #{user}@#{host} #{make_hook_executable}"
|
29
|
+
end
|
107
30
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
end
|
31
|
+
def path
|
32
|
+
@location.match(/:(.*)$/)[1]
|
33
|
+
end
|
112
34
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
@rvm_recipe = @recipes.find { |recipe| recipe.name == 'rvm' }
|
118
|
-
@recipes.delete_if { |recipe| recipe.name == 'rvm' }
|
119
|
-
if @rvm_recipe
|
120
|
-
@rvm_recipe.options[:rvm_string]
|
121
|
-
else
|
122
|
-
'none'
|
123
|
-
end
|
124
|
-
end
|
35
|
+
def host
|
36
|
+
host = @location.match(/@(.*):/)
|
37
|
+
host[1] unless host.nil?
|
38
|
+
end
|
125
39
|
|
126
|
-
|
40
|
+
def user
|
41
|
+
user = @location.match(/(.*)@/)
|
42
|
+
user[1] unless user.nil?
|
43
|
+
end
|
127
44
|
|
128
|
-
|
129
|
-
|
130
|
-
|
45
|
+
def clone_repository
|
46
|
+
"git clone #{@config.repository} #{path}"
|
47
|
+
end
|
131
48
|
|
132
|
-
|
133
|
-
|
134
|
-
|
49
|
+
def copy_hook
|
50
|
+
@shell.run "scp #{Blazing::TMP_HOOK} #{user}@#{host}:#{path}/.git/hooks/post-receive"
|
51
|
+
end
|
135
52
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
recipe.run
|
140
|
-
end
|
141
|
-
end
|
53
|
+
def make_hook_executable
|
54
|
+
"chmod +x #{path}/.git/hooks/post-receive"
|
55
|
+
end
|
142
56
|
|
143
|
-
|
144
|
-
|
145
|
-
if bundler
|
146
|
-
bundler.run
|
147
|
-
@recipes.delete_if { |r| r.name == 'bundler' }
|
148
|
-
end
|
149
|
-
end
|
57
|
+
def setup_repository
|
58
|
+
"cd #{path} && git config receive.denyCurrentBranch ignore"
|
150
59
|
end
|
60
|
+
|
151
61
|
end
|