Class: Harrison::Deploy
- Inherits:
-
Base
- Object
- Base
- Harrison::Deploy
show all
- Defined in:
- lib/harrison/deploy.rb
Defined Under Namespace
Classes: Phase
Instance Attribute Summary collapse
Attributes inherited from Base
#options
Instance Method Summary
collapse
Methods inherited from Base
#download, #exec, #method_missing, option_helper, #upload
Constructor Details
#initialize(opts = {}) ⇒ Deploy
Returns a new instance of Deploy.
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
# File 'lib/harrison/deploy.rb', line 13
def initialize(opts={})
self.class.option_helper(:hosts)
self.class.option_helper(:env)
self.class.option_helper(:base_dir)
self.class.option_helper(:deploy_via)
self.class.option_helper(:keep)
arg_opts = [
[ :hosts, "List of remote hosts to deploy to. Can also be specified in Harrisonfile.", :type => :strings ],
[ :env, "Environment to deploy to. This can be examined in your Harrisonfile to calculate target hosts.", :type => :string ],
[ :keep, "Number of recent deploys to keep after a successful deploy. (Including the most recent deploy.) Defaults to keeping all deploys forever.", :type => :integer ],
]
super(arg_opts, opts)
self.add_default_phases
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
in the class Harrison::Base
Instance Attribute Details
#artifact ⇒ Object
Returns the value of attribute artifact.
3
4
5
|
# File 'lib/harrison/deploy.rb', line 3
def artifact
@artifact
end
|
#deploy_link ⇒ Object
Returns the value of attribute deploy_link.
6
7
8
|
# File 'lib/harrison/deploy.rb', line 6
def deploy_link
@deploy_link
end
|
#host ⇒ Object
The specific host among –hosts that we are currently working on.
4
5
6
|
# File 'lib/harrison/deploy.rb', line 4
def host
@host
end
|
#phases ⇒ Object
Returns the value of attribute phases.
9
10
11
|
# File 'lib/harrison/deploy.rb', line 9
def phases
@phases
end
|
#release_dir ⇒ Object
Returns the value of attribute release_dir.
5
6
7
|
# File 'lib/harrison/deploy.rb', line 5
def release_dir
@release_dir
end
|
#rollback ⇒ Object
Returns the value of attribute rollback.
8
9
10
|
# File 'lib/harrison/deploy.rb', line 8
def rollback
@rollback
end
|
Instance Method Details
#add_phase(name, &block) ⇒ Object
47
48
49
50
51
|
# File 'lib/harrison/deploy.rb', line 47
def add_phase(name, &block)
@_phases ||= Hash.new
@_phases[name] = Harrison::Deploy::Phase.new(name, &block)
end
|
#cleanup_deploys(limit) ⇒ Object
155
156
157
158
159
160
161
162
163
164
165
166
|
# File 'lib/harrison/deploy.rb', line 155
def cleanup_deploys(limit)
purge_deploys = self.deploys.sort.reverse.slice(limit..-1) || []
if purge_deploys.size > 0
puts "[#{self.host}] Purging #{purge_deploys.size} old deploys. (Keeping #{limit}...)"
purge_deploys.each do |stale_deploy|
remote_exec("cd deploys && rm -f #{stale_deploy}")
end
end
end
|
#cleanup_releases ⇒ Object
168
169
170
171
172
173
174
175
176
177
|
# File 'lib/harrison/deploy.rb', line 168
def cleanup_releases
keep_releases = self.active_releases
self.releases.each do |release|
unless keep_releases.include?(release)
remote_exec("cd releases && rm -rf #{release}")
end
end
end
|
#close(host = nil) ⇒ Object
179
180
181
182
183
184
185
186
187
|
# File 'lib/harrison/deploy.rb', line 179
def close(host=nil)
if host
@_conns[host].close if @_conns && @_conns[host]
elsif @_conns
@_conns.keys.each do |host|
@_conns[host].close unless @_conns[host].closed?
end
end
end
|
#current_symlink ⇒ Object
57
58
59
|
# File 'lib/harrison/deploy.rb', line 57
def current_symlink
"#{self.remote_project_dir}/current"
end
|
#invoke_user_block ⇒ Object
11
|
# File 'lib/harrison/deploy.rb', line 11
alias :invoke_user_block :run
|
#parse(args) ⇒ Object
33
34
35
36
37
38
39
40
41
42
43
44
45
|
# File 'lib/harrison/deploy.rb', line 33
def parse(args)
super
@_argv_hosts = self.hosts.dup if self.hosts
self.rollback = args[0] == 'rollback'
unless self.rollback
self.artifact = args[1] || abort("ERROR: You must specify the artifact to be deployed as an argument to this command.")
end
end
|
#remote_exec(cmd) ⇒ Object
53
54
55
|
# File 'lib/harrison/deploy.rb', line 53
def remote_exec(cmd)
super("cd #{remote_project_dir} && #{cmd}")
end
|
#revert_current_symlink ⇒ Object
69
70
71
72
73
74
|
# File 'lib/harrison/deploy.rb', line 69
def revert_current_symlink
if @_old_current
self.remote_exec("ln -sfn #{@_old_current} #{self.current_symlink}")
end
end
|
#run ⇒ Object
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
# File 'lib/harrison/deploy.rb', line 76
def run
self.hosts = @_argv_hosts if @_argv_hosts
if !self.hosts || self.hosts.empty?
abort("ERROR: You must specify one or more hosts to deploy/rollback on, either in your Harrisonfile or via --hosts.")
end
self.phases ||= [ :upload, :extract, :link, :cleanup ]
self.base_dir ||= '/opt'
if self.rollback
puts "Rolling back \"#{project}\" to previously deployed release on #{hosts.size} hosts...\n\n"
self.host = hosts[0]
last_deploy = self.deploys.sort.reverse[1] || abort("ERROR: No previous deploy to rollback to.")
self.release_dir = remote_exec("cd deploys && readlink -vn #{last_deploy}")
self.phases.delete(:upload)
self.phases.delete(:extract)
self.phases.delete(:cleanup)
else
puts "Deploying #{artifact} for \"#{project}\" onto #{hosts.size} hosts...\n\n"
self.release_dir = "#{remote_project_dir}/releases/" + File.basename(artifact, '.tar.gz')
end
self.deploy_link = "#{remote_project_dir}/deploys/" + Time.new.utc.strftime('%Y-%m-%d_%H%M%S')
progress_stack = []
failed = catch(:failure) do
self.phases.each do |phase_name|
phase = @_phases[phase_name] || abort("ERROR: Could not resolve \"#{phase_name}\" as a deployment phase.")
self.hosts.each do |host|
self.host = host
phase._run(self)
progress_stack << { host: host, phase: phase_name }
end
end
false
end
if failed
print "\n"
progress_stack.reverse.each do |progress|
self.host = progress[:host]
phase = @_phases[progress[:phase]]
catch(:failure) do
phase._fail(self)
end
end
abort "\nDeployment failed, previously completed deployment actions have been reverted."
else
if self.rollback
puts "\nSucessfully rolled back #{project} on #{hosts.join(', ')}."
else
puts "\nSucessfully deployed #{artifact} to #{hosts.join(', ')}."
end
end
end
|
#update_current_symlink ⇒ Object
61
62
63
64
65
66
67
|
# File 'lib/harrison/deploy.rb', line 61
def update_current_symlink
@_old_current = self.remote_exec("if [ -L #{current_symlink} ]; then readlink -vn #{current_symlink}; fi")
@_old_current = nil if @_old_current.empty?
self.remote_exec("ln -sfn #{self.deploy_link} #{self.current_symlink}")
end
|