rudy 0.6.8 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.txt +15 -2
- data/README.rdoc +30 -23
- data/Rakefile +5 -5
- data/Rudyfile +87 -66
- data/bin/rudy +120 -167
- data/bin/rudy-ec2 +17 -13
- data/bin/rudy-s3 +6 -4
- data/bin/rudy-sdb +5 -4
- data/lib/annoy.rb +1 -1
- data/lib/console.rb +1 -3
- data/lib/rudy.rb +11 -25
- data/lib/rudy/aws/ec2/instance.rb +1 -1
- data/lib/rudy/aws/ec2/volume.rb +2 -2
- data/lib/rudy/aws/sdb/error.rb +2 -1
- data/lib/rudy/cli.rb +10 -1
- data/lib/rudy/cli/aws/ec2/addresses.rb +1 -1
- data/lib/rudy/cli/aws/ec2/images.rb +3 -1
- data/lib/rudy/cli/aws/ec2/instances.rb +2 -2
- data/lib/rudy/cli/candy.rb +11 -0
- data/lib/rudy/cli/config.rb +25 -44
- data/lib/rudy/cli/machines.rb +30 -10
- data/lib/rudy/cli/routines.rb +67 -19
- data/lib/rudy/config.rb +30 -13
- data/lib/rudy/config/objects.rb +135 -10
- data/lib/rudy/disks.rb +8 -52
- data/lib/rudy/global.rb +9 -5
- data/lib/rudy/guidelines.rb +18 -0
- data/lib/rudy/huxtable.rb +29 -19
- data/lib/rudy/machines.rb +10 -7
- data/lib/rudy/mixins/hash.rb +25 -0
- data/lib/rudy/routines.rb +160 -10
- data/lib/rudy/routines/helper.rb +50 -0
- data/lib/rudy/routines/helpers/diskhelper.rb +44 -18
- data/lib/rudy/routines/helpers/scmhelper.rb +39 -0
- data/lib/rudy/routines/helpers/scripthelper.rb +86 -35
- data/lib/rudy/routines/helpers/userhelper.rb +37 -0
- data/lib/rudy/routines/passthrough.rb +36 -0
- data/lib/rudy/routines/release.rb +38 -22
- data/lib/rudy/routines/shutdown.rb +20 -49
- data/lib/rudy/routines/startup.rb +20 -47
- data/lib/rudy/scm.rb +75 -0
- data/lib/rudy/scm/git.rb +215 -0
- data/lib/rudy/scm/svn.rb +7 -6
- data/lib/rudy/utils.rb +12 -30
- data/lib/storable.rb +4 -1
- data/lib/sysinfo.rb +10 -0
- data/rudy.gemspec +21 -9
- data/test/01_mixins/10_hash_test.rb +25 -0
- data/test/{05_config → 10_config}/00_setup_test.rb +1 -1
- data/test/{05_config → 10_config}/30_machines_test.rb +1 -1
- data/test/15_scm/00_setup_test.rb +20 -0
- data/test/15_scm/20_git_test.rb +61 -0
- data/test/helper.rb +1 -1
- data/vendor/highline-1.5.1/Rakefile +3 -3
- metadata +41 -12
- data/bin/ird +0 -175
@@ -1,34 +1,50 @@
|
|
1
1
|
|
2
|
+
|
2
3
|
module Rudy; module Routines;
|
3
4
|
class Release < Rudy::Routines::Base
|
4
|
-
|
5
|
-
def execute
|
6
|
-
p find_scm(:release)
|
7
|
-
end
|
8
5
|
|
6
|
+
def init(*args)
|
7
|
+
@routine_name = args.first || :release # :release or :rerelease
|
8
|
+
@routine = fetch_routine_config(@routine_name)
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
env, rol, att = @@global.environment, @@global.role
|
11
|
+
def execute()
|
12
|
+
routine_separator(@routine_name)
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
vlist = []
|
15
|
+
|
16
|
+
# Some early version control system failing
|
17
|
+
if Rudy::Routines::SCMHelper.scm?(@routine)
|
18
|
+
vlist = Rudy::Routines::SCMHelper.create_scm_objects(@routine)
|
19
|
+
puts task_separator("CREATING RELEASE TAG#{'S' if vlist.size > 1}")
|
20
|
+
vlist.each do |scm|
|
21
|
+
scm.create_release(Rudy.sysinfo.user)
|
22
|
+
puts scm.liner_note
|
23
|
+
end
|
22
24
|
end
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
|
26
|
+
machines = []
|
27
|
+
generic_machine_runner(:list) do |machine,rbox|
|
28
|
+
vlist.each do |scm|
|
29
|
+
puts task_separator("CREATING REMOTE #{scm.engine.to_s.upcase} CHECKOUT")
|
30
|
+
scm.create_remote_checkout(rbox)
|
31
|
+
end
|
32
|
+
machines << machine
|
27
33
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
34
|
+
|
35
|
+
machines
|
36
|
+
end
|
37
|
+
|
38
|
+
# Called by generic_machine_runner
|
39
|
+
def raise_early_exceptions
|
40
|
+
raise NoRoutine, :release unless @routine
|
41
|
+
rmach = Rudy::Machines.new
|
42
|
+
raise Rudy::PrivateKeyNotFound, root_keypairpath unless has_keypair?(:root)
|
43
|
+
raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
|
44
|
+
raise MachineGroupNotRunning, current_machine_group unless rmach.running?
|
31
45
|
end
|
32
46
|
|
47
|
+
|
48
|
+
|
33
49
|
end
|
34
50
|
end;end
|
@@ -1,62 +1,33 @@
|
|
1
1
|
|
2
2
|
|
3
3
|
module Rudy; module Routines;
|
4
|
-
|
5
4
|
class Shutdown < Rudy::Routines::Base
|
6
5
|
|
6
|
+
def init(*args)
|
7
|
+
@routine = fetch_routine_config(:shutdown)
|
8
|
+
end
|
9
|
+
|
7
10
|
def execute
|
11
|
+
routine_separator(:shutdown)
|
12
|
+
unless @routine
|
13
|
+
STDERR.puts "[this is a generic shutdown routine]"
|
14
|
+
@routine = {}
|
15
|
+
end
|
16
|
+
machines = []
|
17
|
+
generic_machine_runner(:destroy) do |machine,rbox|
|
18
|
+
#puts task_separator("SHUTDOWN")
|
19
|
+
machines << machine
|
20
|
+
end
|
21
|
+
machines
|
22
|
+
end
|
23
|
+
|
24
|
+
# Called by generic_machine_runner
|
25
|
+
def raise_early_exceptions
|
8
26
|
rmach = Rudy::Machines.new
|
9
27
|
raise Rudy::PrivateKeyNotFound, root_keypairpath unless has_keypair?(:root)
|
10
|
-
raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
|
11
28
|
raise MachineGroupNotRunning, current_machine_group unless rmach.running?
|
12
|
-
|
13
|
-
routine = fetch_routine_config(:shutdown)
|
14
|
-
rbox_local = Rye::Box.new('localhost')
|
15
|
-
sconf = fetch_script_config
|
16
|
-
|
17
|
-
# Runs "before_local" scripts of routines config.
|
18
|
-
puts task_separator("BEFORE SCRIPTS (local)")
|
19
|
-
Rudy::Routines::ScriptHelper.before_local(routine, sconf, rbox_local)
|
20
|
-
|
21
|
-
puts
|
22
|
-
|
23
|
-
rmach.destroy do |machine|
|
24
|
-
#rmach.list do |machine|
|
25
|
-
|
26
|
-
print "Waiting for instance..."
|
27
|
-
isup = Rudy::Utils.waiter(3, 120, STDOUT, "it's up!", 0) {
|
28
|
-
inst = machine.get_instance
|
29
|
-
inst && inst.running?
|
30
|
-
}
|
31
|
-
machine.update # Add instance info to machine and save it
|
32
|
-
print "Waiting for SSH daemon..."
|
33
|
-
isup = Rudy::Utils.waiter(2, 60, STDOUT, "it's up!", 0) {
|
34
|
-
Rudy::Utils.service_available?(machine.dns_public, 22)
|
35
|
-
}
|
36
|
-
|
37
|
-
opts = { :keys => root_keypairpath, :user => 'root', :debug => nil }
|
38
|
-
rbox = Rye::Box.new(machine.dns_public, opts)
|
39
|
-
|
40
|
-
# Runs "before" scripts of routines config.
|
41
|
-
puts task_separator("BEFORE SCRIPTS")
|
42
|
-
Rudy::Routines::ScriptHelper.before(routine, sconf, machine, rbox)
|
43
|
-
|
44
|
-
# Runs "disk" portion of routines config
|
45
|
-
puts task_separator("DISK ROUTINES")
|
46
|
-
Rudy::Routines::DiskHelper.execute(routine, machine, rbox)
|
47
|
-
|
48
|
-
puts machine_separator(machine.liner_note)
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
# Runs "after_local" scripts
|
53
|
-
# NOTE: There "after" (remote) scripts are not run b/c the machines
|
54
|
-
# are no longer running.
|
55
|
-
puts task_separator("AFTER SCRIPTS (local)")
|
56
|
-
Rudy::Routines::ScriptHelper.after_local(routine, sconf, rbox_local)
|
57
|
-
|
58
29
|
end
|
59
|
-
|
30
|
+
|
60
31
|
end
|
61
32
|
|
62
33
|
end; end
|
@@ -1,61 +1,34 @@
|
|
1
1
|
|
2
2
|
|
3
3
|
module Rudy; module Routines;
|
4
|
-
|
5
4
|
class Startup < Rudy::Routines::Base
|
5
|
+
|
6
|
+
def init(*args)
|
7
|
+
@routine = fetch_routine_config(:startup)
|
8
|
+
end
|
9
|
+
|
10
|
+
# * +each_mach+ is an optional block which is executed between
|
11
|
+
# disk creation and the after scripts. The will receives two
|
12
|
+
# arguments: instances of Rudy::Machine and Rye::Box.
|
13
|
+
def execute(&each_mach)
|
14
|
+
routine_separator(:startup)
|
15
|
+
unless @routine
|
16
|
+
STDERR.puts "[this is a generic startup routine]"
|
17
|
+
@routine = {}
|
18
|
+
end
|
19
|
+
generic_machine_runner(:create) do |machine,rbox|
|
20
|
+
end
|
21
|
+
end
|
6
22
|
|
7
|
-
|
23
|
+
# Called by generic_machine_runner
|
24
|
+
def raise_early_exceptions
|
8
25
|
rmach = Rudy::Machines.new
|
9
26
|
# There's no keypair check here because Rudy::Machines will attempt
|
10
27
|
# to create one.
|
11
28
|
raise MachineGroupNotDefined, current_machine_group unless known_machine_group?
|
12
29
|
raise MachineGroupAlreadyRunning, current_machine_group if rmach.running?
|
13
|
-
|
14
|
-
routine = fetch_routine_config(:startup)
|
15
|
-
rbox_local = Rye::Box.new('localhost')
|
16
|
-
sconf = fetch_script_config
|
17
|
-
|
18
|
-
# Runs "before_local" scripts of routines config.
|
19
|
-
# NOTE: Does not run "before" scripts b/c there are no remote machines
|
20
|
-
puts task_separator("BEFORE SCRIPTS (local)")
|
21
|
-
Rudy::Routines::ScriptHelper.before_local(routine, sconf, rbox_local)
|
22
|
-
|
23
|
-
rmach.create do |machine|
|
24
|
-
#rmach.list do |machine|
|
25
|
-
puts machine_separator(machine.liner_note)
|
26
|
-
print "Waiting for instance..."
|
27
|
-
isup = Rudy::Utils.waiter(3, 120, STDOUT, "it's up!", 2) {
|
28
|
-
inst = machine.get_instance
|
29
|
-
inst && inst.running?
|
30
|
-
}
|
31
|
-
machine.update # Add instance info to machine and save it
|
32
|
-
print "Waiting for SSH daemon..."
|
33
|
-
isup = Rudy::Utils.waiter(2, 60, STDOUT, "it's up!", 3) {
|
34
|
-
Rudy::Utils.service_available?(machine.dns_public, 22)
|
35
|
-
}
|
36
|
-
|
37
|
-
opts = { :keys => root_keypairpath, :user => 'root', :debug => nil }
|
38
|
-
rbox = Rye::Box.new(machine.dns_public, opts)
|
39
|
-
|
40
|
-
puts task_separator("DISK ROUTINES")
|
41
|
-
# Runs "disk" portion of routines config
|
42
|
-
Rudy::Routines::DiskHelper.execute(routine, machine, rbox)
|
43
|
-
|
44
|
-
puts task_separator("AFTER SCRIPTS")
|
45
|
-
# Runs "after" scripts of routines config
|
46
|
-
Rudy::Routines::ScriptHelper.after(routine, sconf, machine, rbox)
|
47
|
-
|
48
|
-
puts task_separator("INFO")
|
49
|
-
puts "Filesystem on #{machine.name}:"
|
50
|
-
puts " " << rbox.df(:h).join("#{$/} ")
|
51
|
-
end
|
52
|
-
|
53
|
-
puts task_separator("AFTER SCRIPTS (local)")
|
54
|
-
# Runs "after_local" scripts of routines config
|
55
|
-
Rudy::Routines::ScriptHelper.after_local(routine, sconf, rbox_local)
|
56
|
-
|
57
30
|
end
|
58
|
-
|
31
|
+
|
59
32
|
end
|
60
33
|
|
61
34
|
end; end
|
data/lib/rudy/scm.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module Rudy
|
4
|
+
module SCM
|
5
|
+
|
6
|
+
class NotAWorkingCopy < Rudy::Error
|
7
|
+
def message
|
8
|
+
"Not the root directory of a #{@obj} working copy"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
class CannotCreateTag < Rudy::Error
|
12
|
+
def message
|
13
|
+
"There was an unknown problem creating a release tag (#{@obj})"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
class DirtyWorkingCopy < Rudy::Error
|
17
|
+
def message
|
18
|
+
"Please commit local #{@obj} changes"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
class RemoteError < Rudy::Error; end
|
22
|
+
class NoRemoteURI < Rudy::Error; end
|
23
|
+
class TooManyTags < Rudy::Error
|
24
|
+
def message; "Too many tag creation attempts!"; end
|
25
|
+
end
|
26
|
+
class NoRemotePath < Rudy::Error
|
27
|
+
def message
|
28
|
+
"Add a path for #{@obj} in your routines config"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
module ObjectBase
|
34
|
+
|
35
|
+
|
36
|
+
def raise_early_exceptions; raise "override raise_early_exceptions"; end
|
37
|
+
|
38
|
+
# copied from routines/helper.rb
|
39
|
+
def execute_rbox_command(ret=nil, &command)
|
40
|
+
begin
|
41
|
+
ret = command.call
|
42
|
+
puts ' ' << ret.stdout.join("#{$/} ") if !ret.stdout.empty?
|
43
|
+
print_response(ret)
|
44
|
+
rescue Rye::CommandError => ex
|
45
|
+
print_response(ex)
|
46
|
+
exit 12 unless keep_going?
|
47
|
+
rescue Rye::CommandNotFound => ex
|
48
|
+
STDERR.puts " CommandNotFound: #{ex.message}".color(:red)
|
49
|
+
STDERR.puts ex.backtrace
|
50
|
+
exit 12 unless keep_going?
|
51
|
+
end
|
52
|
+
|
53
|
+
ret
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
private
|
58
|
+
def keep_going?
|
59
|
+
Annoy.pose_question(" Keep going?\a ", /yes|y|ya|sure|you bet!/i, STDERR)
|
60
|
+
end
|
61
|
+
|
62
|
+
def print_response(rap)
|
63
|
+
[:stderr].each do |sumpin|
|
64
|
+
next if rap.send(sumpin).empty?
|
65
|
+
STDERR.puts " #{sumpin}: #{rap.send(sumpin).join("#{$/} ")}".color(:red)
|
66
|
+
end
|
67
|
+
STDERR.puts " Exit code: #{rap.exit_code}".color(:red) if rap.exit_code != 0
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
Rudy::Utils.require_glob(RUDY_LIB, 'rudy', 'scm', '*.rb')
|
data/lib/rudy/scm/git.rb
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
|
5
|
+
module Rudy
|
6
|
+
module SCM
|
7
|
+
class GIT
|
8
|
+
require 'grit'
|
9
|
+
include Rudy::SCM::ObjectBase
|
10
|
+
include Grit
|
11
|
+
|
12
|
+
attr_accessor :base_uri
|
13
|
+
attr_accessor :remote
|
14
|
+
attr_accessor :branch
|
15
|
+
attr_reader :repo
|
16
|
+
attr_reader :rbox
|
17
|
+
attr_reader :rtag
|
18
|
+
attr_reader :user
|
19
|
+
attr_reader :pkey
|
20
|
+
|
21
|
+
# * +args+ a hash of params from the git block in the routines config
|
22
|
+
#
|
23
|
+
def initialize(args={})
|
24
|
+
args = {
|
25
|
+
:privatekey => nil,
|
26
|
+
:remote => :origin,
|
27
|
+
:branch => :master,
|
28
|
+
:user => :root,
|
29
|
+
:path => nil
|
30
|
+
}.merge(args)
|
31
|
+
@remote, @branch, @path = args[:remote], args[:branch], args[:path]
|
32
|
+
@user, @pkey = args[:user], args[:privatekey]
|
33
|
+
@repo = Repo.new(Dir.pwd) if GIT.working_copy?
|
34
|
+
end
|
35
|
+
|
36
|
+
def engine; :git; end
|
37
|
+
|
38
|
+
def liner_note
|
39
|
+
"%-40s (git:%s:%s)" % [@rtag, @remote, @branch]
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_release(username=nil, msg=nil)
|
43
|
+
@rtag = find_next_rtag(username)
|
44
|
+
msg ||= 'Another Release by Rudy!'
|
45
|
+
msg.tr!("'", "''")
|
46
|
+
ret = Rye.shell(:git, "tag", @rtag) # Use annotated? -a -m '#{msg}'
|
47
|
+
raise ret.stderr.join($/) if ret.exit_code > 0
|
48
|
+
ret = Rye.shell(:git, "push") if @remote
|
49
|
+
raise ret.stderr.join($/) if ret.exit_code > 0
|
50
|
+
ret = Rye.shell(:git, "push #{@remote} #{rtag}") if @remote
|
51
|
+
raise ret.stderr.join($/) if ret.exit_code > 0
|
52
|
+
@rtag
|
53
|
+
end
|
54
|
+
|
55
|
+
# rel-2009-03-05-user-rev
|
56
|
+
def find_next_rtag(username=nil)
|
57
|
+
now = Time.now
|
58
|
+
mon = now.mon.to_s.rjust(2, '0')
|
59
|
+
day = now.day.to_s.rjust(2, '0')
|
60
|
+
rev = "01"
|
61
|
+
criteria = ['rel', now.year, mon, day, rev]
|
62
|
+
criteria.insert(-2, username) if username
|
63
|
+
rev.succ! while valid_rtag?(criteria.join(Rudy::DELIM)) && rev.to_i < 50
|
64
|
+
raise TooManyTags if rev.to_i >= 50
|
65
|
+
criteria.join(Rudy::DELIM)
|
66
|
+
end
|
67
|
+
|
68
|
+
def delete_rtag(rtag=nil)
|
69
|
+
rtag ||= @rtag
|
70
|
+
ret = execute_rbox_command { Rye.shell(:git, 'tag', :d, rtag) }
|
71
|
+
raise ret.stderr.join($/) if ret.exit_code > 0 # TODO: retest
|
72
|
+
# Equivalent to: "git push origin :tag-name" which deletes a remote tag
|
73
|
+
ret = execute_rbox_command { Rye.shell(:git, "push #{@remote} :#{rtag}") } if @remote
|
74
|
+
raise ret.stderr.join($/) if ret.exit_code > 0
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_remote_checkout(rbox)
|
79
|
+
|
80
|
+
# Make sure the directory above the clone path exists
|
81
|
+
# and that it's owned by the request user.
|
82
|
+
rbox.mkdir(:p, File.dirname(@path))
|
83
|
+
rbox.chown(@user, File.dirname(@path))
|
84
|
+
|
85
|
+
begin
|
86
|
+
original_user = rbox.user
|
87
|
+
rbox.switch_user(@user)
|
88
|
+
|
89
|
+
if @pkey
|
90
|
+
# Try when debugging: ssh -vi path/2/pkey git@github.com
|
91
|
+
key = File.basename(@pkey)
|
92
|
+
homedir = rbox.getenv['HOME']
|
93
|
+
rbox.mkdir(:p, :m, '700', '.ssh') rescue nil # :p says keep quiet if it exists
|
94
|
+
if rbox.file_exists?(".ssh/#{key}")
|
95
|
+
puts " Remote private key #{key} already exists".colour(:red)
|
96
|
+
else
|
97
|
+
rbox.upload(@pkey, ".ssh/#{key}")
|
98
|
+
end
|
99
|
+
|
100
|
+
# NOTE: The following are two attempts at telling git which
|
101
|
+
# private key to use. Both fail. The only thing I could get
|
102
|
+
# to work is modifying the ~/.ssh/config file.
|
103
|
+
#
|
104
|
+
# This runs fine, but "git clone" doesn't care.
|
105
|
+
# git config --global --replace-all http.sslKey /home/delano/.ssh/id_rsa
|
106
|
+
# rbox.git('config', '--global', '--replace-all', 'http.sslKey', "#{homedir}/.ssh/#{key}")
|
107
|
+
|
108
|
+
# "git clone" doesn't care about this either. Note that both these
|
109
|
+
# config attempts come directly from the git-config man page:
|
110
|
+
# http://www.kernel.org/pub/software/scm/git/docs/git-config.html
|
111
|
+
# export GIT_SSL_KEY=/home/delano/.ssh/id_rsa
|
112
|
+
# rbox.setenv("GIT_SSL_KEY", "#{homedir}/.ssh/#{key}")
|
113
|
+
|
114
|
+
if rbox.file_exists?('.ssh/config')
|
115
|
+
rbox.cp('.ssh/config', ".ssh/config-previous")
|
116
|
+
ssh_config = rbox.download('.ssh/config')
|
117
|
+
end
|
118
|
+
|
119
|
+
ssh_config ||= StringIO.new
|
120
|
+
ssh_config.puts $/, "IdentityFile #{homedir}/.ssh/#{key}"
|
121
|
+
puts " Adding IdentityFile #{key} to #{homedir}/.ssh/config"
|
122
|
+
|
123
|
+
rbox.upload(ssh_config, '.ssh/config')
|
124
|
+
rbox.chmod('0600', '.ssh/config')
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
# We need to add the host keys to the user's known_hosts file
|
129
|
+
# to prevent the git commands from failing when it raises the
|
130
|
+
# "Host key verification failed." messsage.
|
131
|
+
if rbox.file_exists?('.ssh/known_hosts')
|
132
|
+
rbox.cp('.ssh/known_hosts', ".ssh/known_hosts-previous")
|
133
|
+
known_hosts = rbox.download('.ssh/known_hosts')
|
134
|
+
end
|
135
|
+
known_hosts ||= StringIO.new
|
136
|
+
remote = get_remote_uri
|
137
|
+
host = URI.parse(remote).host rescue nil
|
138
|
+
host ||= remote.scan(/\A.+?@(.+?)\:/).flatten.first
|
139
|
+
known_hosts.puts $/, Rye.remote_host_keys(host)
|
140
|
+
puts " Adding host key for #{host} to .ssh/known_hosts"
|
141
|
+
|
142
|
+
rbox.upload(known_hosts, '.ssh/known_hosts')
|
143
|
+
rbox.chmod('0600', '.ssh/known_hosts')
|
144
|
+
|
145
|
+
execute_rbox_command {
|
146
|
+
rbox.git('clone', get_remote_uri, @path)
|
147
|
+
}
|
148
|
+
rbox.cd(@path)
|
149
|
+
execute_rbox_command {
|
150
|
+
rbox.git('checkout', :b, @rtag)
|
151
|
+
}
|
152
|
+
rescue Rye::CommandError => ex
|
153
|
+
puts ex.message
|
154
|
+
ensure
|
155
|
+
# Return to the original user and directory
|
156
|
+
rbox.switch_user(original_user)
|
157
|
+
rbox.cd
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
def get_remote_uri
|
164
|
+
ret = Rye.shell(:git, "config", "remote.#{@remote}.url")
|
165
|
+
ret.stdout.first
|
166
|
+
end
|
167
|
+
|
168
|
+
# Check if the given remote is valid.
|
169
|
+
#def has_remote?(remote)
|
170
|
+
# success = false
|
171
|
+
# (@repo.remotes || []).each do |r|
|
172
|
+
# end
|
173
|
+
# success
|
174
|
+
#end
|
175
|
+
|
176
|
+
def valid_rtag?(tag)
|
177
|
+
# git tag -l tagname returns a 0 exit code and stdout is empty
|
178
|
+
# when a tag does not exit. When it does exist, the exit code
|
179
|
+
# is 0 and stdout contains the tagname.
|
180
|
+
ret = Rye.shell(:git, 'tag', :l, tag)
|
181
|
+
# change :l to :d for quick deleting above and return true
|
182
|
+
# OR: just change to :d to always recreate the same tag
|
183
|
+
(ret.exit_code == 0 && ret.stdout.to_s == tag)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Are all local changes committed?
|
187
|
+
def self.clean_working_copy?(path=Dir.pwd)
|
188
|
+
Rye.shell(:git, 'diff').stdout == []
|
189
|
+
end
|
190
|
+
def clean_working_copy?; GIT.clean_working_copy?; end
|
191
|
+
|
192
|
+
def self.working_copy?(path=Dir.pwd)
|
193
|
+
(File.exists?(File.join(path, '.git')))
|
194
|
+
end
|
195
|
+
def working_copy?; GIT.working_copy?; end
|
196
|
+
|
197
|
+
def raise_early_exceptions
|
198
|
+
raise NotAWorkingCopy, :git unless working_copy?
|
199
|
+
#raise DirtyWorkingCopy, :git unless clean_working_copy?
|
200
|
+
raise NoRemoteURI, "remote.#{@remote}.url not set" if get_remote_uri.nil?
|
201
|
+
raise NoRemotePath, :git if @path.nil?
|
202
|
+
raise PrivateKeyNotFound, @pkey if @pkey && !File.exists?(@pkey)
|
203
|
+
find_next_rtag # will raise exception is there's a problem
|
204
|
+
|
205
|
+
# We can't check stuff that requires access to the machine b/c the
|
206
|
+
# machine may not be running yet. These include:
|
207
|
+
# * Remote checkout path already exists
|
208
|
+
# * No git available
|
209
|
+
# ...
|
210
|
+
# If create_remote_checkout should fail, it should print a message
|
211
|
+
# about the release that was created and how to install it manually
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|