billy_the_tool 0.1.2 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +59 -11
- data/lib/billy/commands/command.rb +1 -5
- data/lib/billy/commands/config.rb +15 -8
- data/lib/billy/commands/eat.rb +8 -10
- data/lib/billy/commands/hello.rb +13 -37
- data/lib/billy/commands/my.rb +36 -0
- data/lib/billy/commands/walk.rb +31 -79
- data/lib/billy/commands.rb +1 -1
- data/lib/billy/config.rb +4 -3
- data/lib/billy/session.rb +3 -3
- data/lib/billy/util/scm/git.rb +74 -0
- data/lib/billy/util/scm/scm.rb +30 -0
- data/lib/billy/util/ssh.rb +32 -0
- data/lib/billy/util/ui.rb +42 -0
- data/lib/billy.rb +6 -2
- metadata +53 -46
data/README.md
CHANGED
@@ -1,28 +1,76 @@
|
|
1
1
|
# Billy the tool
|
2
2
|
|
3
|
-
##
|
3
|
+
## Intro
|
4
4
|
|
5
|
-
|
5
|
+
Billy is very simple deploy application built on top of [capistrano](https://github.com/capistrano/capistrano). This tool may be useful for designers and html programmers to simplify roll out process on staging server.
|
6
|
+
|
7
|
+
Deploy model undermeans single staging server and deploying from `master` branch only.
|
8
|
+
|
9
|
+
## Install
|
10
|
+
|
11
|
+
Billy distributes as [ruby gem](http://rubygems.org/gems/billy_the_tool), requires ruby 1.8.7+ and superuser privileges in case of global system installation (not [rvm](https://rvm.io/)).
|
12
|
+
|
13
|
+
Open your terminal ( on MacOS: ⌘ + Space, then type `terminal` in search bar ). When terminal window is opened:
|
14
|
+
|
15
|
+
```
|
16
|
+
sudo gem install billy_the_tool --no-rdoc
|
17
|
+
```
|
18
|
+
If everything is ok this command will ask you to provide superuser password and then install billy on your system.
|
19
|
+
|
20
|
+
## Setup
|
6
21
|
* billy hello
|
7
|
-
* billy eat {
|
22
|
+
* billy eat {url_to_billy_config_or_local_file}
|
23
|
+
|
24
|
+
`billy hello` will check all the system requirements and will give some helpful info. Billy will great you if all the requirements are satisfied And prompt to install otherwise.
|
8
25
|
|
9
|
-
|
10
|
-
* billy walk {app_name}
|
26
|
+
`billy eat {url_to_billy_config_or_local_file}` will parse config file with specified path and save it to current folder. `url_to_billy_config_or_local_file` could be local file path or remote file url. Spaeking of deploy process billy will check both current and home folders while looking for config file. Billy stores it's settings in file named `.billyrc`.
|
11
27
|
|
12
|
-
|
28
|
+
### Sample config file
|
13
29
|
|
14
30
|
```
|
15
|
-
deploy_to: /var/
|
31
|
+
deploy_to: /var/www/
|
16
32
|
user: user
|
17
|
-
server:
|
33
|
+
server: staging.server.com
|
18
34
|
```
|
19
35
|
|
36
|
+
### Get current config
|
37
|
+
|
38
|
+
```bash
|
39
|
+
billy my config
|
40
|
+
```
|
41
|
+
|
42
|
+
This command will return config settings from current folder if there wis .billyrc file, home settings from ~/.billyrc otherwise.
|
43
|
+
|
44
|
+
### GIT dependency
|
45
|
+
Billy hopes to find git repository inside your project with existing remote. You haven't say billy where your remote is. It checks for `.git/config` file and grabs all the remotes inside.
|
46
|
+
|
47
|
+
After config file is set up and you have pushed all the changes you've done Billy is ready to deploy.
|
48
|
+
|
20
49
|
## Usage
|
21
50
|
|
51
|
+
Here I will show how to download remote config file to my local folder and then deploy some project_name to staging server:
|
52
|
+
|
22
53
|
```bash
|
23
54
|
cd ~
|
24
|
-
billy eat http://
|
55
|
+
billy eat http://staging.server.com/billy.cfg
|
25
56
|
cd project_name
|
26
57
|
billy walk project_name
|
27
|
-
open http://
|
28
|
-
```
|
58
|
+
open http://staging.server.com/project_name/index.html
|
59
|
+
```
|
60
|
+
|
61
|
+
### SSH keys management
|
62
|
+
|
63
|
+
Authorization uses ssh keys only, no password auth.
|
64
|
+
|
65
|
+
Auth process:
|
66
|
+
deployer → ssh → staging server → ssh → git remote repository
|
67
|
+
|
68
|
+
This scheme requires deployer publick key to be placed on staging server and staging server publick key on remote git server.
|
69
|
+
|
70
|
+
### Get my ssh key
|
71
|
+
|
72
|
+
```bash
|
73
|
+
billy my key
|
74
|
+
```
|
75
|
+
|
76
|
+
This command will return one of your ssh keys, id_rsa.pub by default
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'billy/commands'
|
2
2
|
|
3
|
-
|
3
|
+
module Billy
|
4
4
|
class Commands
|
5
5
|
class Command
|
6
6
|
|
@@ -13,10 +13,6 @@ class Billy
|
|
13
13
|
def initialize
|
14
14
|
end
|
15
15
|
|
16
|
-
def get_confirmation
|
17
|
-
gets.chomp.downcase == "y"
|
18
|
-
end
|
19
|
-
|
20
16
|
class << self
|
21
17
|
|
22
18
|
attr_accessor :_instance
|
@@ -1,21 +1,28 @@
|
|
1
|
+
require 'colorize'
|
1
2
|
require 'billy/commands/command'
|
3
|
+
require 'billy/util/ui'
|
2
4
|
|
3
|
-
|
5
|
+
module Billy
|
4
6
|
class Commands
|
5
7
|
class Config < Command
|
6
8
|
|
7
9
|
def proceed!( arguments = nil )
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
else
|
10
|
+
%w(. ~).each do |f|
|
11
|
+
dir = File.expand_path( f )
|
12
|
+
next unless Billy::Config.config_exists?( dir )
|
13
|
+
Billy::Util::UI.inform "Config loaded from file: #{dir}/#{Billy::Config::BILLYRC}"
|
13
14
|
Billy::Config.load!( dir )
|
14
|
-
|
15
|
+
Billy::Util::UI.inform "Current Billy settings:"
|
15
16
|
Billy::Config.settings.each_pair do |k, v|
|
16
|
-
|
17
|
+
yellow_k = "#{k}".magenta
|
18
|
+
Billy::Util::UI.inform "#{yellow_k}:\t\t#{v.green}"
|
17
19
|
end
|
20
|
+
return
|
18
21
|
end
|
22
|
+
|
23
|
+
Billy::Util::UI.err "Billy config file could not be found here. Say Billy hello."
|
24
|
+
exit 1
|
25
|
+
|
19
26
|
end
|
20
27
|
|
21
28
|
end
|
data/lib/billy/commands/eat.rb
CHANGED
@@ -2,7 +2,7 @@ require 'uri'
|
|
2
2
|
require 'net/http'
|
3
3
|
require 'billy/commands/command'
|
4
4
|
|
5
|
-
|
5
|
+
module Billy
|
6
6
|
class Commands
|
7
7
|
class Eat < Command
|
8
8
|
|
@@ -10,14 +10,14 @@ class Billy
|
|
10
10
|
( path = arguments.shift ) unless arguments.nil?
|
11
11
|
begin
|
12
12
|
if path.nil? || path.empty?
|
13
|
-
raise "No config path given. \nYou have to provide some settings path, e.g. in your local filesystem or direct link to blob file in repository etc
|
13
|
+
raise "No config path given. \nYou have to provide some settings path, e.g. in your local filesystem or direct link to blob file in repository etc."
|
14
14
|
elsif uri?( path ) && ( result = load_remote_config( path ) ).nil?
|
15
15
|
raise "Remote config file could not be loaded"
|
16
16
|
elsif file?( path ) && ( !File.exists?( path ) || ( result = File.read( path ) ).nil? )
|
17
17
|
raise "Config File not found: #{path}"
|
18
18
|
end
|
19
19
|
rescue Exception => e
|
20
|
-
|
20
|
+
Billy::Util::UI.err e.message
|
21
21
|
exit 1
|
22
22
|
end
|
23
23
|
eat_config( result )
|
@@ -29,18 +29,16 @@ class Billy
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def save_config
|
32
|
-
|
32
|
+
Billy::Util::UI.inform "Parsed config data:"
|
33
33
|
Billy::Config.settings.each_pair do |k, v|
|
34
|
-
|
34
|
+
Billy::Util::UI.inform "#{k}: #{v}"
|
35
35
|
end
|
36
|
-
|
37
|
-
|
38
|
-
if !confirm
|
39
|
-
print "Billy didn't save config file. Skipping\n"
|
36
|
+
if !Billy::Util::UI.confirm? "Save this settings?(y/n): "
|
37
|
+
Billy::Util::UI.inform "Billy didn't save config file. Skipping."
|
40
38
|
exit 1
|
41
39
|
end
|
42
40
|
Billy::Config.save
|
43
|
-
|
41
|
+
Billy::Util::UI.succ "Billy saved config file to #{Billy::Config::BILLYRC}"
|
44
42
|
end
|
45
43
|
|
46
44
|
def uri?( str )
|
data/lib/billy/commands/hello.rb
CHANGED
@@ -1,28 +1,25 @@
|
|
1
1
|
require 'billy/commands/command'
|
2
2
|
|
3
|
-
|
3
|
+
module Billy
|
4
4
|
class Commands
|
5
5
|
class Hello < Command
|
6
6
|
|
7
7
|
def proceed!( arguments = nil )
|
8
8
|
billy_say_hello
|
9
|
-
path = get_init_path( arguments )
|
10
|
-
config = Billy::Config.instance
|
11
|
-
config.save!( path, true )
|
12
9
|
if !ssh_command_exists?
|
13
10
|
suggest_install_ssh
|
14
11
|
exit 1
|
15
12
|
end
|
16
13
|
offer_ssh_keygen unless ssh_key_exists?
|
17
|
-
|
14
|
+
Billy::Util::UI.succ "All done!"
|
18
15
|
end
|
19
16
|
|
20
17
|
def billy_say_hello
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
Billy::Util::UI.inform "Hi! I'm Billy, simple deploy tool."
|
19
|
+
Billy::Util::UI.inform "Usage:"
|
20
|
+
Billy::Util::UI.inform " * billy hello (path) -- init billy in {path} folder. Inites in current if no one given."
|
21
|
+
Billy::Util::UI.inform " * billy eat {cfg_path} -- parse and save billy config in current folder. {cfg_path} here means remote file url or local one."
|
22
|
+
Billy::Util::UI.inform " * billy walk {application_name} -- deploy HEAD version in repository to remote server."
|
26
23
|
end
|
27
24
|
|
28
25
|
def ssh_command_exists?
|
@@ -34,44 +31,23 @@ class Billy
|
|
34
31
|
end
|
35
32
|
|
36
33
|
def ssh_key_exists?
|
37
|
-
|
38
|
-
res = true
|
39
|
-
res &= File.exists?( ssh_root_path )
|
40
|
-
res &= File.directory?( ssh_root_path )
|
41
|
-
res &= Dir[ ssh_root_path + "/*.pub" ].any?
|
42
|
-
res
|
34
|
+
Billy::Util::Ssh.get_pub_key.nil?
|
43
35
|
end
|
44
36
|
|
45
37
|
def suggest_install_ssh
|
46
|
-
|
38
|
+
Billy::Util::UI.err "Billy wants you to install ssh command. Please do it first."
|
47
39
|
end
|
48
40
|
|
49
41
|
def offer_ssh_keygen
|
50
|
-
|
51
|
-
|
52
|
-
if !confirm
|
53
|
-
print "Ssh key should be generated before we continue. Please generate it.\n"
|
42
|
+
if !Billy::Util::UI.confirm? "Billy did not find your ssh key. Would you like to create it now?(y/n): "
|
43
|
+
Billy::Util::UI.err "Ssh key should be generated before we continue. Please generate it."
|
54
44
|
exit 1
|
55
45
|
end
|
56
46
|
enc_type = 'rsa'
|
57
|
-
|
47
|
+
Billy::Util::UI.inform "Billy creates ssh keys for you..."
|
58
48
|
system "ssh-keygen -t #{enc_type} -N '' -f ~/.ssh/id_#{enc_type}"
|
59
|
-
print "All done!"
|
60
|
-
end
|
61
|
-
|
62
|
-
def get_init_path( arguments )
|
63
|
-
( path = arguments.shift ) unless arguments.nil?
|
64
|
-
if path.nil? || path.empty?
|
65
|
-
print "Billy will be inited in current directory. Proceed?(y/n): "
|
66
|
-
confirm = get_confirmation
|
67
|
-
if !confirm
|
68
|
-
print "Billy has nothing to do. Bye-bye."
|
69
|
-
end
|
70
|
-
path = Dir.pwd
|
71
|
-
end
|
72
|
-
File.expand_path( path )
|
73
49
|
end
|
74
|
-
|
50
|
+
|
75
51
|
end
|
76
52
|
end
|
77
53
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'billy/commands/command'
|
2
|
+
|
3
|
+
module Billy
|
4
|
+
class Commands
|
5
|
+
class My < Command
|
6
|
+
|
7
|
+
def proceed!( arguments = nil )
|
8
|
+
if arguments.length < 1
|
9
|
+
Billy::Util::UI.err 'Please provide Billy more info what do you need?'
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
sub_cmd = arguments.shift.downcase.to_sym rescue nil
|
13
|
+
case sub_cmd
|
14
|
+
when :key
|
15
|
+
res = Billy::Util::Ssh.get_pub_key
|
16
|
+
if res.nil?
|
17
|
+
Billy::Util::UI.err "Billy could not find your ssh key. Say billy hello."
|
18
|
+
exit 1
|
19
|
+
else
|
20
|
+
Billy::Util::UI.inform "Billy found an ssh key:"
|
21
|
+
Billy::Util::UI.succ res
|
22
|
+
Billy::Util::UI.inform "Copy and add it to your deployment server."
|
23
|
+
end
|
24
|
+
when :config
|
25
|
+
Billy::Commands::Config.instance.proceed!( arguments )
|
26
|
+
else
|
27
|
+
Billy::Util::UI.err "Billy doesn't know #{sub_cmd} command."
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Billy::Commands::My.register_self!
|
data/lib/billy/commands/walk.rb
CHANGED
@@ -1,34 +1,39 @@
|
|
1
1
|
require 'billy/commands/command'
|
2
2
|
require 'capistrano'
|
3
3
|
|
4
|
-
|
4
|
+
module Billy
|
5
5
|
class Commands
|
6
6
|
class Walk < Command
|
7
7
|
|
8
|
-
GIT_PATH = ".git"
|
9
|
-
|
10
8
|
def proceed!( arguments = nil )
|
11
9
|
|
12
10
|
if !Billy::Config.load
|
13
|
-
|
11
|
+
Billy::Util::UI.inform "Billy config could not be found. Say Billy hello."
|
14
12
|
exit 1
|
15
13
|
end
|
16
14
|
|
17
15
|
destination = ( arguments.shift rescue nil ) || Billy::Config.instance.destination
|
18
16
|
|
19
17
|
if destination.nil?
|
20
|
-
|
21
|
-
|
18
|
+
Billy::Util::UI.err "Billy doesn't know where to walk."
|
19
|
+
Billy::Util::UI.err "You have to provide deploy folder, e.g.: billy walk my_super_project."
|
22
20
|
exit 1
|
23
21
|
end
|
24
22
|
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
begin
|
24
|
+
cap = prepare_capistrano( destination )
|
25
|
+
%w(deploy:setup deploy).each do |command|
|
26
|
+
cap.find_and_execute_task(command, :before => :start, :after => :finish)
|
27
|
+
end
|
28
|
+
cap.trigger( :exit )
|
29
|
+
Billy::Util::UI.succ 'Billy has successfully deployed project!'
|
30
|
+
Billy::Util::UI.succ "Check http://#{Billy::Config.instance.server}/#{cap.application}/"
|
31
|
+
rescue Exception => e
|
32
|
+
Billy::Util::UI.err "Billy could not complete task: #{e.message}"
|
33
|
+
exit 1
|
28
34
|
end
|
29
|
-
cap.trigger( :exit )
|
30
35
|
|
31
|
-
|
36
|
+
Billy::Util::UI.succ "All done! Billy is a clever boy!"
|
32
37
|
end
|
33
38
|
|
34
39
|
def prepare_capistrano( destination )
|
@@ -40,22 +45,26 @@ class Billy
|
|
40
45
|
config = Billy::Config.instance
|
41
46
|
|
42
47
|
if config.deploy_to.nil?
|
43
|
-
|
48
|
+
Billy::Util::UI.err "Billy doesn't know remote deploy path. Please provide it in config under deploy_to key."
|
44
49
|
exit 1
|
45
50
|
end
|
46
|
-
|
47
|
-
cap.set :scm, "git"
|
48
|
-
cap.set :use_sudo, false
|
49
|
-
cap.set :deploy_via, :remote_cache
|
50
|
-
cap.set :application, destination
|
51
51
|
cap.set :deploy_to, File.join( config.deploy_to, destination )
|
52
|
-
cap.
|
53
|
-
cap.set :user, config.user
|
52
|
+
cap.set :normalize_asset_timestamps, false
|
54
53
|
|
55
|
-
|
54
|
+
reject_keys = [ :deploy_to, :server ]
|
56
55
|
|
57
|
-
|
58
|
-
|
56
|
+
{
|
57
|
+
:scm => :git,
|
58
|
+
:use_sudo => false,
|
59
|
+
:deploy_via => :remote_cache,
|
60
|
+
:application => destination
|
61
|
+
}.merge( config.storage.reject{ |k, v| reject_keys.include?( k.to_sym ) } ).each_pair do |k, v|
|
62
|
+
cap.set k, v
|
63
|
+
end
|
64
|
+
|
65
|
+
Billy::Util::Scm.configure!( cap, config )
|
66
|
+
|
67
|
+
cap.server config.server, :app, :web, :db, :primary => true
|
59
68
|
|
60
69
|
cap.namespace :deploy do
|
61
70
|
cap.task :start, :roles => :app do; end
|
@@ -65,63 +74,6 @@ class Billy
|
|
65
74
|
|
66
75
|
cap
|
67
76
|
end
|
68
|
-
|
69
|
-
def get_repository_path
|
70
|
-
if !local_repository_exists?
|
71
|
-
print "Git repository was not created. Do you want Billy to create it now?\n"
|
72
|
-
confirm = get_confirmation
|
73
|
-
if !confirm
|
74
|
-
print "Billy could not proceed without git repository.\n"
|
75
|
-
exit 1
|
76
|
-
else
|
77
|
-
print "Creating git repository.\n"
|
78
|
-
init_git_repository
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
config = get_git_config
|
83
|
-
|
84
|
-
if !remote_repository_exists?( config )
|
85
|
-
print "Billy could not find remote repository for your project.\n"
|
86
|
-
print "Please add some remote, e.g. git remote add git@github.com:myUsername/myProject.git.\n"
|
87
|
-
exit 1
|
88
|
-
end
|
89
|
-
|
90
|
-
idx = 1
|
91
|
-
i = 0
|
92
|
-
|
93
|
-
match_data = get_remotes( config )
|
94
|
-
|
95
|
-
if match_data.length > 1
|
96
|
-
print "Billy found several remotes in repository. Choose one to deploy from:"
|
97
|
-
match_data.each do |remote|
|
98
|
-
i += 1
|
99
|
-
print "#{i}: #{remote[0]}\t\t#{remote[1]}\n"
|
100
|
-
end
|
101
|
-
while ( idx = gets.chomp.to_i ) > match_data.length; end
|
102
|
-
end
|
103
|
-
match_data[ idx - 1 ][ 1 ]
|
104
|
-
end
|
105
|
-
|
106
|
-
def get_git_config
|
107
|
-
File.read( File.expand_path( GIT_PATH + "/config" ) )
|
108
|
-
end
|
109
|
-
|
110
|
-
def local_repository_exists?
|
111
|
-
File.exists?( File.expand_path( GIT_PATH ) )
|
112
|
-
end
|
113
|
-
|
114
|
-
def remote_repository_exists?( config )
|
115
|
-
get_remotes( config ).any?
|
116
|
-
end
|
117
|
-
|
118
|
-
def get_remotes( config )
|
119
|
-
config.gsub( /\n/, ';' ).scan /\[remote\s+\"([^"]+)\"\][^\[]+url\s*=\s*([^;]+)/
|
120
|
-
end
|
121
|
-
|
122
|
-
def init_git_repository
|
123
|
-
system "git init ."
|
124
|
-
end
|
125
77
|
|
126
78
|
end
|
127
79
|
end
|
data/lib/billy/commands.rb
CHANGED
data/lib/billy/config.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
|
1
|
+
module Billy
|
2
2
|
class Config
|
3
3
|
|
4
4
|
BILLYRC = '.billyrc'
|
5
|
+
SEPARATOR_PATTERN = /:\s*/
|
5
6
|
SEPARATOR = ': '
|
6
7
|
|
7
8
|
attr_accessor :storage
|
@@ -26,7 +27,7 @@ class Billy
|
|
26
27
|
self.storage.each_pair do |k, v|
|
27
28
|
res.push "#{k}#{SEPARATOR}#{v}"
|
28
29
|
end
|
29
|
-
}.push(
|
30
|
+
}.push( '' ).join( "\n" )
|
30
31
|
end
|
31
32
|
|
32
33
|
def load
|
@@ -84,7 +85,7 @@ class Billy
|
|
84
85
|
clear
|
85
86
|
string_config.each_line do |line|
|
86
87
|
next unless !line.empty?
|
87
|
-
items = line.split(
|
88
|
+
items = line.split( SEPARATOR_PATTERN )
|
88
89
|
k = items.shift
|
89
90
|
v = items.join( SEPARATOR ).strip
|
90
91
|
( self.storage[ k.to_s ] = v ) unless k.nil? || k.empty? || v.nil? || v.empty?
|
data/lib/billy/session.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
module Billy
|
2
2
|
class Session
|
3
3
|
class << self
|
4
4
|
|
@@ -7,7 +7,7 @@ class Billy
|
|
7
7
|
command = ARGV.shift
|
8
8
|
arguments = ARGV
|
9
9
|
if command.nil?
|
10
|
-
|
10
|
+
Billy::Util::UI.succ "Billy has nothing to do. Yay!"
|
11
11
|
exit 0
|
12
12
|
end
|
13
13
|
status = proceed_command!( command, arguments )
|
@@ -17,7 +17,7 @@ class Billy
|
|
17
17
|
def proceed_command!( command_name, arguments )
|
18
18
|
cmd = Billy::Commands.pool[ command_name.to_s ]
|
19
19
|
if cmd.nil?
|
20
|
-
|
20
|
+
Billy::Util::UI.err "Billy doesn't know this command: #{command_name}. Say billy hello."
|
21
21
|
return 1
|
22
22
|
end
|
23
23
|
cmd.proceed!( arguments )
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'billy/util/scm/scm'
|
2
|
+
|
3
|
+
module Billy
|
4
|
+
module Util
|
5
|
+
class Git < Scm
|
6
|
+
|
7
|
+
GIT_PATH = ".git"
|
8
|
+
|
9
|
+
def configure!( cap, config )
|
10
|
+
cap.set :scm, :git
|
11
|
+
cap.set :repository, config.repository || get_repository_path
|
12
|
+
cap.set :branch, config.branch || 'master'
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_config
|
16
|
+
File.read( File.expand_path( GIT_PATH + "/config" ) )
|
17
|
+
end
|
18
|
+
|
19
|
+
def local_repository_exists?
|
20
|
+
File.exists?( File.expand_path( GIT_PATH ) )
|
21
|
+
end
|
22
|
+
|
23
|
+
def remote_repository_exists?( config )
|
24
|
+
get_remotes( config ).any?
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_remotes( config )
|
28
|
+
config.gsub( /\n/, ';' ).scan /\[remote\s+\"([^"]+)\"\][^\[]+url\s*=\s*([^;]+)/
|
29
|
+
end
|
30
|
+
|
31
|
+
def init_repository
|
32
|
+
system "git init ."
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_repository_path
|
36
|
+
if !local_repository_exists?
|
37
|
+
if !Billy::Util::UI.confirm?( "Git repository was not created. Do you want Billy to create it now?" )
|
38
|
+
Billy::Util::UI.err "Billy could not proceed without git repository."
|
39
|
+
exit 1
|
40
|
+
else
|
41
|
+
Billy::Util::UI.inform "Creating git repository."
|
42
|
+
init_git_repository
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
config = get_config
|
47
|
+
|
48
|
+
if !remote_repository_exists?( config )
|
49
|
+
Billy::Util::UI.err "Billy could not find remote repository for your project."
|
50
|
+
Billy::Util::UI.err "Please add some remote, e.g. git remote add git@github.com:myUsername/myProject.git."
|
51
|
+
exit 1
|
52
|
+
end
|
53
|
+
|
54
|
+
idx = 1
|
55
|
+
i = 0
|
56
|
+
|
57
|
+
match_data = get_remotes( config )
|
58
|
+
|
59
|
+
if match_data.length > 1
|
60
|
+
Billy::Util::UI.inform "Billy found several remotes in repository. Choose one to deploy from:"
|
61
|
+
match_data.each do |remote|
|
62
|
+
i += 1
|
63
|
+
Billy::Util::UI.inform "#{i}: #{remote[0]}\t\t#{remote[1]}"
|
64
|
+
end
|
65
|
+
while ( idx = Billy::Util::UI.input.to_i ) > match_data.length; end
|
66
|
+
end
|
67
|
+
match_data[ idx - 1 ][ 1 ]
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
Billy::Util::Git.register_self!
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'billy/util/ui'
|
2
|
+
|
3
|
+
module Billy
|
4
|
+
module Util
|
5
|
+
class Scm
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
attr_accessor :pool
|
10
|
+
|
11
|
+
def register_self!
|
12
|
+
Billy::Util::Scm.register_scm( self.new )
|
13
|
+
end
|
14
|
+
|
15
|
+
def register_scm( scm )
|
16
|
+
key = scm.class.to_s.split( "::" ).last.downcase.to_sym
|
17
|
+
( self.pool ||= {} )[ key ] = scm
|
18
|
+
end
|
19
|
+
|
20
|
+
def configure!( cap, config )
|
21
|
+
scm = ( config.scm || :git ).to_sym
|
22
|
+
raise "#{scm} handler is unknown." if !self.pool.has_key?( scm )
|
23
|
+
pool[ scm ].configure!( cap, config )
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Billy
|
2
|
+
module Util
|
3
|
+
module Ssh
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def ssh_root_path
|
7
|
+
File.expand_path( "~/.ssh" )
|
8
|
+
end
|
9
|
+
|
10
|
+
def ssh_folder_exists?
|
11
|
+
File.exists?( ssh_root_path ) && File.directory?( ssh_root_path )
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_pub_key( type = :id_rsa )
|
15
|
+
keys = pub_keys
|
16
|
+
return nil unless !keys.nil? && keys.any?
|
17
|
+
keys[ type ]
|
18
|
+
end
|
19
|
+
|
20
|
+
def pub_keys
|
21
|
+
return nil unless ssh_folder_exists?
|
22
|
+
res = Hash.new
|
23
|
+
Dir[ ssh_root_path + '/*.pub' ].each do |f|
|
24
|
+
key = File.basename( f, '.pub' ).to_sym
|
25
|
+
res[ key ] = File.read( f )
|
26
|
+
end
|
27
|
+
res
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
|
3
|
+
module Billy
|
4
|
+
module Util
|
5
|
+
class UI
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
def red( text )
|
10
|
+
text.red
|
11
|
+
end
|
12
|
+
|
13
|
+
def green( text )
|
14
|
+
text.green
|
15
|
+
end
|
16
|
+
|
17
|
+
def input
|
18
|
+
gets.chomp.downcase
|
19
|
+
end
|
20
|
+
|
21
|
+
def confirm?( msg = nil )
|
22
|
+
inform( msg ) if !msg.nil?
|
23
|
+
input == "y"
|
24
|
+
end
|
25
|
+
|
26
|
+
def inform( msg )
|
27
|
+
puts "#{msg.to_s}\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
def succ( msg )
|
31
|
+
inform green msg
|
32
|
+
end
|
33
|
+
|
34
|
+
def err( msg )
|
35
|
+
inform red msg
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/billy.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
-
$:.unshift File.dirname(__FILE__)
|
1
|
+
$:.unshift File.dirname( __FILE__ )
|
2
2
|
|
3
|
-
|
3
|
+
module Billy
|
4
4
|
require 'billy/session'
|
5
|
+
require 'billy/util/ui'
|
5
6
|
require 'billy/commands'
|
6
7
|
require 'billy/config'
|
8
|
+
require 'billy/util/ssh'
|
9
|
+
require 'billy/util/scm/scm'
|
10
|
+
require 'billy/util/scm/git'
|
7
11
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: billy_the_tool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
- 1
|
9
8
|
- 2
|
10
|
-
|
9
|
+
- 2
|
10
|
+
version: 0.2.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- 4pcbr
|
@@ -15,10 +15,11 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-12-03 00:00:00 +04:00
|
19
|
+
default_executable: billy
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
|
-
|
22
|
+
type: :runtime
|
22
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
23
24
|
none: false
|
24
25
|
requirements:
|
@@ -30,12 +31,28 @@ dependencies:
|
|
30
31
|
- 13
|
31
32
|
- 5
|
32
33
|
version: 2.13.5
|
33
|
-
type: :runtime
|
34
|
-
name: capistrano
|
35
34
|
version_requirements: *id001
|
36
|
-
|
35
|
+
name: capistrano
|
37
36
|
prerelease: false
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
type: :runtime
|
38
39
|
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 27
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
- 5
|
48
|
+
- 8
|
49
|
+
version: 0.5.8
|
50
|
+
version_requirements: *id002
|
51
|
+
name: colorize
|
52
|
+
prerelease: false
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
type: :development
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
39
56
|
none: false
|
40
57
|
requirements:
|
41
58
|
- - ">="
|
@@ -44,12 +61,12 @@ dependencies:
|
|
44
61
|
segments:
|
45
62
|
- 0
|
46
63
|
version: "0"
|
47
|
-
|
64
|
+
version_requirements: *id003
|
48
65
|
name: shoulda
|
49
|
-
version_requirements: *id002
|
50
|
-
- !ruby/object:Gem::Dependency
|
51
66
|
prerelease: false
|
52
|
-
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
type: :development
|
69
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
53
70
|
none: false
|
54
71
|
requirements:
|
55
72
|
- - ~>
|
@@ -59,12 +76,12 @@ dependencies:
|
|
59
76
|
- 3
|
60
77
|
- 12
|
61
78
|
version: "3.12"
|
62
|
-
|
79
|
+
version_requirements: *id004
|
63
80
|
name: rdoc
|
64
|
-
version_requirements: *id003
|
65
|
-
- !ruby/object:Gem::Dependency
|
66
81
|
prerelease: false
|
67
|
-
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
type: :development
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
68
85
|
none: false
|
69
86
|
requirements:
|
70
87
|
- - ~>
|
@@ -75,12 +92,12 @@ dependencies:
|
|
75
92
|
- 2
|
76
93
|
- 2
|
77
94
|
version: 1.2.2
|
78
|
-
|
95
|
+
version_requirements: *id005
|
79
96
|
name: bundler
|
80
|
-
version_requirements: *id004
|
81
|
-
- !ruby/object:Gem::Dependency
|
82
97
|
prerelease: false
|
83
|
-
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
type: :development
|
100
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
84
101
|
none: false
|
85
102
|
requirements:
|
86
103
|
- - ~>
|
@@ -91,12 +108,12 @@ dependencies:
|
|
91
108
|
- 8
|
92
109
|
- 4
|
93
110
|
version: 1.8.4
|
94
|
-
|
111
|
+
version_requirements: *id006
|
95
112
|
name: jeweler
|
96
|
-
version_requirements: *id005
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
113
|
prerelease: false
|
99
|
-
|
114
|
+
- !ruby/object:Gem::Dependency
|
115
|
+
type: :development
|
116
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
100
117
|
none: false
|
101
118
|
requirements:
|
102
119
|
- - ">="
|
@@ -105,12 +122,12 @@ dependencies:
|
|
105
122
|
segments:
|
106
123
|
- 0
|
107
124
|
version: "0"
|
108
|
-
|
125
|
+
version_requirements: *id007
|
109
126
|
name: rcov
|
110
|
-
version_requirements: *id006
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
127
|
prerelease: false
|
113
|
-
|
128
|
+
- !ruby/object:Gem::Dependency
|
129
|
+
type: :development
|
130
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
114
131
|
none: false
|
115
132
|
requirements:
|
116
133
|
- - ~>
|
@@ -121,25 +138,9 @@ dependencies:
|
|
121
138
|
- 12
|
122
139
|
- 0
|
123
140
|
version: 2.12.0
|
124
|
-
|
141
|
+
version_requirements: *id008
|
125
142
|
name: rspec
|
126
|
-
version_requirements: *id007
|
127
|
-
- !ruby/object:Gem::Dependency
|
128
143
|
prerelease: false
|
129
|
-
requirement: &id008 !ruby/object:Gem::Requirement
|
130
|
-
none: false
|
131
|
-
requirements:
|
132
|
-
- - ~>
|
133
|
-
- !ruby/object:Gem::Version
|
134
|
-
hash: 49
|
135
|
-
segments:
|
136
|
-
- 2
|
137
|
-
- 13
|
138
|
-
- 5
|
139
|
-
version: 2.13.5
|
140
|
-
type: :runtime
|
141
|
-
name: capistrano
|
142
|
-
version_requirements: *id008
|
143
144
|
description: Billy is simplified deploy system based on top of capistrano
|
144
145
|
email: me@4pcbr.com
|
145
146
|
executables:
|
@@ -157,11 +158,17 @@ files:
|
|
157
158
|
- lib/billy/commands/config.rb
|
158
159
|
- lib/billy/commands/eat.rb
|
159
160
|
- lib/billy/commands/hello.rb
|
161
|
+
- lib/billy/commands/my.rb
|
160
162
|
- lib/billy/commands/walk.rb
|
161
163
|
- lib/billy/config.rb
|
162
164
|
- lib/billy/session.rb
|
165
|
+
- lib/billy/util/scm/git.rb
|
166
|
+
- lib/billy/util/scm/scm.rb
|
167
|
+
- lib/billy/util/ssh.rb
|
168
|
+
- lib/billy/util/ui.rb
|
163
169
|
- LICENSE.txt
|
164
170
|
- README.md
|
171
|
+
has_rdoc: true
|
165
172
|
homepage: http://github.com/AltSpace/billy
|
166
173
|
licenses:
|
167
174
|
- MIT
|
@@ -191,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
191
198
|
requirements: []
|
192
199
|
|
193
200
|
rubyforge_project:
|
194
|
-
rubygems_version: 1.
|
201
|
+
rubygems_version: 1.6.1
|
195
202
|
signing_key:
|
196
203
|
specification_version: 3
|
197
204
|
summary: Billy the tool
|