blazing 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,3 +2,6 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in blazing.gemspec
4
4
  gemspec
5
+
6
+ gem 'rspec'
7
+ gem 'ruby-debug19'
@@ -0,0 +1,42 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ blazing (0.0.1)
5
+ thor (>= 0.14.6)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ archive-tar-minitar (0.5.2)
11
+ columnize (0.3.2)
12
+ diff-lcs (1.1.2)
13
+ linecache19 (0.5.11)
14
+ ruby_core_source (>= 0.1.4)
15
+ rspec (2.4.0)
16
+ rspec-core (~> 2.4.0)
17
+ rspec-expectations (~> 2.4.0)
18
+ rspec-mocks (~> 2.4.0)
19
+ rspec-core (2.4.0)
20
+ rspec-expectations (2.4.0)
21
+ diff-lcs (~> 1.1.2)
22
+ rspec-mocks (2.4.0)
23
+ ruby-debug-base19 (0.11.24)
24
+ columnize (>= 0.3.1)
25
+ linecache19 (>= 0.5.11)
26
+ ruby_core_source (>= 0.1.4)
27
+ ruby-debug19 (0.11.6)
28
+ columnize (>= 0.3.1)
29
+ linecache19 (>= 0.5.11)
30
+ ruby-debug-base19 (>= 0.11.19)
31
+ ruby_core_source (0.1.4)
32
+ archive-tar-minitar (>= 0.5.2)
33
+ thor (0.14.6)
34
+
35
+ PLATFORMS
36
+ ruby
37
+
38
+ DEPENDENCIES
39
+ blazing!
40
+ rspec
41
+ ruby-debug19
42
+ thor (>= 0.14.6)
data/README CHANGED
@@ -6,6 +6,26 @@ Top Design goals, ideas:
6
6
 
7
7
  - deploy is just a push to another remote. all that must be done is triggered by pre and post receveie git hooks.
8
8
  - initial setup done by ruby script
9
- - the stuff that gets executed is defined in recipes, which are handled kind of like chef recipes with vendor branches
9
+ - extensible recipe system, so you can plug in and out what you need and easily roll your own recipes
10
10
 
11
- Also, I just wanted to play around with instance_eval and such :-)
11
+ == Usage
12
+
13
+ Setup a project with
14
+
15
+ blazing init
16
+
17
+ Then edit your config/blazing.rb file.
18
+
19
+ If you are ready to do your first deploy, run
20
+
21
+ blazing setup <target_name>
22
+
23
+ Afterwards you can just deploy with
24
+
25
+ blazing deploy <target_name>
26
+
27
+ Or just use
28
+
29
+ git push <target_name>
30
+
31
+ which does basically the same
data/TODO CHANGED
@@ -6,6 +6,4 @@ o customizable and modular
6
6
  o multistage
7
7
  o sync fs and db flavours
8
8
 
9
- o recipes should live in git submodules
10
-
11
-
9
+ o recipes should/can live in git submodules
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'rubygems'
4
3
  require 'thor'
4
+ require 'thor/group'
5
5
  require 'blazing'
6
- require 'blazing/cli'
6
+ require 'blazing/cli/base'
7
7
 
8
- Blazing::CLI.start
8
+ Blazing::CLI::Base.start
@@ -8,16 +8,14 @@ Gem::Specification.new do |s|
8
8
  s.platform = Gem::Platform::RUBY
9
9
  s.authors = ["Felipe Kaufmann"]
10
10
  s.email = ["felipekaufmann@gmail.com"]
11
- s.homepage = ""
11
+ s.homepage = "https://github.com/effkay/blazing"
12
12
  s.summary = %q{blazing fast deployment}
13
- s.description = %q{git push style deployments for the masses}
14
-
15
- s.rubyforge_project = "blazing"
16
-
13
+ s.description = %q{git push deployent utility, ready to be extended by your own recipes}
17
14
  s.files = `git ls-files`.split("\n")
18
15
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
16
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
17
  s.require_paths = ["lib"]
21
18
 
19
+ # TODO: better to use ~ ?
22
20
  s.add_dependency "thor", ">= 0.14.6"
23
21
  end
@@ -0,0 +1,8 @@
1
+ module Blazing
2
+ 'blazing/base'
3
+ 'blazing/cli'
4
+ 'blazing/version'
5
+ 'blazing/config'
6
+ 'blazing/remote'
7
+ 'blazing/remote'
8
+ end
@@ -1,5 +1,5 @@
1
- require 'blazing/cli'
2
1
  require 'blazing/config'
2
+ require 'blazing/cli'
3
3
 
4
4
  module Blazing::Base
5
5
 
@@ -1,4 +1,5 @@
1
1
  require 'blazing/config'
2
+ require 'blazing/config/helper'
2
3
 
3
4
  class Blazing::CLI < Thor
4
5
 
@@ -15,30 +16,26 @@ class Blazing::CLI < Thor
15
16
 
16
17
  desc 'setup TARGET', 'bootstrap or update blazing setup on remote host and do a first deploy'
17
18
  def setup(target = nil)
18
-
19
- # Load config file
20
- config = Blazing::Config.read do |blazing|
21
- blazing.instance_eval(File.read blazing.file)
22
- end
23
-
24
- # Check if target can be found in config file
25
- if target
26
- target = config.targets.find { |t| t.name == target.to_sym }
27
- end
28
-
29
- target = target || config.determine_target
19
+
20
+ target = Blazing::Config::Helper.find_target(target)
30
21
 
31
22
  if target
32
23
  say "[BLAZING] -- SETTING UP #{ target.location }", :yellow
33
- invoke 'blazing:target:setup:setup_repository', [target]
24
+ invoke 'blazing:remote:setup:setup_repository', [target]
34
25
  else
35
- say 'no target specified and no default found in config', :red
26
+ say 'no remote specified and no default found in config', :red
36
27
  end
37
28
 
38
29
  end
39
30
 
40
31
  desc 'deploy TARGET', 'deploy project with blazing'
41
- def deploy
32
+ def deploy(target=nil)
33
+
34
+ target = Blazing::Config::Helper.find_target(target)
35
+
36
+ # TODO: optional: specify branch
37
+ `git push #{ target.name } master`
38
+
42
39
  # TODO: check if deployed setup is still uptodate, if not, run setup
43
40
  # tag and push
44
41
  end
@@ -0,0 +1,73 @@
1
+ require 'thor/group'
2
+ require 'blazing/remote'
3
+
4
+ class Blazing::Config
5
+
6
+ attr_accessor :targets, :file
7
+
8
+ def initialize
9
+ @targets = []
10
+ @file = File.open('config/blazing.rb')
11
+ end
12
+
13
+ def self.read(&block)
14
+ config = Blazing::Config.new
15
+ block.arity < 1 ? config.instance_eval(&block) : block.call(config)
16
+ config.instance_eval(&block)
17
+ return config
18
+ end
19
+
20
+ def remote(name, &block)
21
+ @targets << Blazing::Target.new(name, @repository, &block)
22
+ end
23
+
24
+ def repository(url)
25
+ @repository = url
26
+ end
27
+
28
+ def determine_target
29
+ target = case
30
+ when self.targets.size == 1 && !self.targets.first.location.nil?
31
+ self.targets.first
32
+
33
+ when !self.default.default_target.nil?
34
+ self.targets.find { |t| t.name == self.default.default_target }
35
+
36
+ when self.default && !self.default.hostname.nil?
37
+ self.default
38
+ end
39
+
40
+ return target
41
+ end
42
+
43
+ def default
44
+ self.targets.find { |t| t.name == :blazing}
45
+ end
46
+
47
+ # TODO: Why does thor break when this is put into an external file config folder?
48
+ class Create < Thor::Group
49
+
50
+ desc 'creates a blazing config file'
51
+
52
+ include Thor::Actions
53
+
54
+ argument :username
55
+ argument :hostname
56
+ argument :path
57
+ argument :repository
58
+
59
+ def self.source_root
60
+ File.dirname(__FILE__)
61
+ end
62
+
63
+ def create_blazing_dir
64
+ empty_directory 'config'
65
+ end
66
+
67
+ def create_config_file
68
+ template('templates/blazing.tt', "config/blazing.rb")
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,18 @@
1
+ require 'blazing/config'
2
+
3
+ module Blazing::Config::Helper
4
+
5
+ def self.find_target(target=nil)
6
+ config = Blazing::Config.read do |blazing|
7
+ blazing.instance_eval(File.read blazing.file)
8
+ end
9
+
10
+ # Check if remote can be found in config file
11
+ if target
12
+ target = config.targets.find { |t| t.name == target.to_sym }
13
+ end
14
+
15
+ target = target || config.determine_target
16
+ end
17
+
18
+ end
@@ -0,0 +1,19 @@
1
+ #
2
+ # Stuff that runs on remote machine
3
+ #
4
+ class Blazing::Remote
5
+
6
+ def self.pre_receive(target_name)
7
+ # really needed? probably only for maintenance page, maybe even this can be done post receive
8
+ end
9
+
10
+ def self.post_receive(target_name)
11
+
12
+ target = Blazing::Config::Helper.find_target(target_name)
13
+
14
+ `git reset --hard HEAD`
15
+
16
+ `bundle update`
17
+ end
18
+
19
+ end
@@ -0,0 +1,86 @@
1
+ class Blazing::Target
2
+
3
+ attr_accessor :name, :user, :hostname, :path, :recipes, :target_name, :default_target, :repository
4
+
5
+ def initialize(name, repository, &block)
6
+ @name = name
7
+ @repository = repository
8
+ instance_eval &block
9
+ end
10
+
11
+ def deploy_to(location)
12
+ @user = location.match('(.*)@')[1]
13
+ @hostname = location.match('@(.*):')[1]
14
+ @path = location.match(':(.*)')[1]
15
+ end
16
+
17
+ def location
18
+ # TODO: build this together more carefully, checking for emtpy hostname etc...
19
+ @location ||= "#{ @user }@#{ @hostname }:#{ @path }"
20
+ end
21
+
22
+ # Only used in global remote for setting default remote
23
+ # TODO: extract into other class, inherit
24
+ def set_default_target(target_name)
25
+ @default_target = target_name
26
+ end
27
+
28
+ class Setup < Thor
29
+
30
+ include Thor::Actions
31
+
32
+ def self.source_root
33
+ File.dirname(__FILE__)
34
+ end
35
+
36
+ argument :target
37
+
38
+ desc 'setup:setup_repository TARGET', 'sets up a remote for blazing deployments'
39
+ def setup_repository
40
+
41
+ # TODO: Extract into helper
42
+ # remote_with_condition()
43
+
44
+ command = "if [ -e ~/sites/blazingoverride.ch/ ]; then echo 'repository has been cloned already'; else git clone #{ remote.repository } #{ remote.path } && git config receive.denyCurrentBranch ignore; fi"
45
+ system "ssh #{ remote.user }@#{ remote.hostname } '#{ command }'"
46
+ if $? == 0
47
+ say '--> [ok]', :green
48
+ invoke 'add_pre_receive_hook', remote
49
+ else
50
+ say '--> [FAILED]', :red
51
+ say '[BLAZING] -- ROLLING BACK', :blue
52
+ return
53
+ end
54
+ end
55
+
56
+ desc 'setup:clone_repository TARGET', 'sets up a remote for blazing deployments'
57
+ def add_pre_receive_hook
58
+ say 'adding pre-receive hook'
59
+ pre_hook = "deploy/pre-receive"
60
+ template('templates/pre-hook.tt', pre_hook)
61
+ system "chmod +x #{ pre_hook }"
62
+ system "scp #{ pre_hook } #{ remote.user }@#{ remote.hostname }:#{ remote.path }/.git/hooks/"
63
+ say '--> [ok]', :green
64
+ invoke 'add_post_receive_hook', remote
65
+ end
66
+
67
+ desc 'setup:clone_repository TARGET', 'sets up a remote for blazing deployments'
68
+ def add_post_receive_hook
69
+ say 'adding post-receive hook'
70
+ post_hook = "deploy/post-receive"
71
+ template('templates/post-hook.tt', post_hook)
72
+ system "chmod +x #{ post_hook }"
73
+ system "scp #{ post_hook } #{ remote.user }@#{ remote.hostname }:#{ remote.path }/.git/hooks/"
74
+ say '--> [ok]', :green
75
+ invoke 'add_remote', remote
76
+ end
77
+
78
+ desc 'setup:add_remote TARGET', 'adds a git remote for the given remote'
79
+ def add_remote
80
+ say 'adding remote as remote to repository'
81
+ system "git remote add #{ remote.name } #{ remote.user }@#{ remote.hostname }:#{ remote.path }"
82
+ end
83
+
84
+ end
85
+
86
+ end
@@ -0,0 +1,3 @@
1
+ module Blazing
2
+ VERSION = "0.0.1"
3
+ end
@@ -1,5 +1,19 @@
1
+ require 'thor'
2
+ require 'thor/group'
3
+ require 'blazing'
4
+ require 'blazing/cli/base'
5
+
6
+ require 'blazing/config'
7
+ require 'blazing/logger'
8
+ require 'blazing/target'
9
+ require 'blazing/remote'
10
+ require 'blazing/recipe'
11
+ require 'blazing/object'
12
+ require 'blazing/cli/create'
13
+ require 'blazing/cli/hook'
14
+
1
15
  module Blazing
2
- 'blazing/base'
3
- 'blazing/cli'
4
- 'blazing/version'
16
+ DIRECTORY = 'config'
17
+ CONFIGURATION_FILE = 'config/blazing.rb'
18
+ LOGGER = Blazing::Logger.new
5
19
  end
@@ -0,0 +1,60 @@
1
+ module Blazing
2
+ module CLI
3
+ class Base < Thor
4
+
5
+ #
6
+ # Configure blazing in current working dir
7
+ #
8
+ desc 'init', 'prepare project for blazing deploys'
9
+ def init
10
+ target = ask "Deployment Target: (ie username@host:/path/to/app)"
11
+ origin = `git remote show origin|grep "Fetch URL"`.split[2]
12
+ if yes? "Get code from here: #{origin} ?"
13
+ repository = origin
14
+ else
15
+ repository = ask "Repository URL: (ie username@host:/path/to/app)"
16
+ end
17
+
18
+ Blazing::CLI::Create.new([repository, target]).invoke_all
19
+ end
20
+
21
+ #
22
+ # Setup target for deployment
23
+ #
24
+ desc 'setup TARGET_NAME', 'setup or update blazing on specified target and deploy'
25
+ def setup(target_name = nil)
26
+ config = Blazing::Config.load
27
+ target = config.find_target(target_name)
28
+ LOGGER.info "setting up target #{target.name}"
29
+ target.setup
30
+
31
+ # TODO: Abstract this into module and load it where we need it. Methods / actions should have
32
+ # a success and failure message
33
+ if $?.exitstatus == 0
34
+ LOGGER.success "successfully set up target #{target.name}"
35
+ else
36
+ LOGGER.error "failed setting up target #{target.name}"
37
+ end
38
+ end
39
+
40
+ #
41
+ # Deploy to target
42
+ #
43
+ desc 'deploy TARGET', 'deploy to TARGET'
44
+ def deploy(target_name = nil)
45
+ config = Blazing::Config.load
46
+ target = config.find_target(target_name)
47
+ LOGGER.info "deploying target #{target.name}"
48
+ target.deploy
49
+
50
+ if $?.exitstatus == 0
51
+ LOGGER.success "successfully deployed target #{target.name}"
52
+ else
53
+ LOGGER.error "failed deploying on target #{target.name}"
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+ end
60
+ end