blazing 0.0.16 → 0.1.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/.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
|