Class: CachedDeploy

Inherits:
Object
  • Object
show all
Defined in:
lib/chef-deploy/cached_deploy.rb

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ CachedDeploy

:repository_cache :shared_path :repository :release_path :copy_exclude :revision :user :group



193
194
195
196
# File 'lib/chef-deploy/cached_deploy.rb', line 193

def initialize(opts={})
  @configuration = opts
  @configuration[:shared_path] = "#{@configuration[:deploy_to]}/shared"
end

Instance Method Details

#all_releasesObject



83
84
85
# File 'lib/chef-deploy/cached_deploy.rb', line 83

def all_releases
  `ls #{release_dir}`.split("\n").sort.map{|r| File.join(release_dir, r)}
end

#callback(what) ⇒ Object

before_symlink before_restart



61
62
63
64
65
66
67
68
# File 'lib/chef-deploy/cached_deploy.rb', line 61

def callback(what)
  if File.exist?("#{latest_release}/deploy/#{what}.rb")
    Dir.chdir(latest_release) do
      Chef::Log.info "running deploy hook: #{latest_release}/deploy/#{what}.rb"
      instance_eval(IO.read("#{latest_release}/deploy/#{what}.rb"))
    end
  end
end

#check_current_revision_and_noop_if_same(newrev) ⇒ Object



53
54
55
56
57
# File 'lib/chef-deploy/cached_deploy.rb', line 53

def check_current_revision_and_noop_if_same(newrev)
  IO.read("#{latest_release}/REVISION").chomp == newrev
rescue
  false
end

#chef_run(cmd) ⇒ Object



173
174
175
# File 'lib/chef-deploy/cached_deploy.rb', line 173

def chef_run(cmd)
  Chef::Mixin::Command.run_command(:command => cmd)
end

#cleanupObject



87
88
89
90
91
# File 'lib/chef-deploy/cached_deploy.rb', line 87

def cleanup
  while all_releases.size >= 5
    FileUtils.rm_rf oldest_release
  end
end

#configurationObject



198
199
200
# File 'lib/chef-deploy/cached_deploy.rb', line 198

def configuration
  @configuration
end

#current_pathObject



122
123
124
# File 'lib/chef-deploy/cached_deploy.rb', line 122

def current_path
  "#{@configuration[:deploy_to]}/current"
end

#deployObject

Executes the SCM command for this strategy and writes the REVISION mark file to each host.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/chef-deploy/cached_deploy.rb', line 9

def deploy
  @configuration[:release_path] = "#{@configuration[:deploy_to]}/releases/#{Time.now.utc.strftime("%Y%m%d%H%M%S")}"
  if @configuration[:revision] == ''
     @configuration[:revision] = source.query_revision(@configuration[:branch]) {|cmd| run_with_result "#{cmd}"}
  end
  
  if check_current_revision_and_noop_if_same(@configuration[:revision])
    Chef::Log.info "Revision is already deployed, running migrations if there are any"
    callback(:before_migrate)
    migrate
    callback(:before_symlink)
    symlink
    return
  end
  
  Chef::Log.info "ensuring proper ownership"
  chef_run(fix_ownership_command(user, group, @configuration[:deploy_to]))
  
  Chef::Log.info "deploying branch: #{@configuration[:branch]} rev: #{@configuration[:revision]}"
  Chef::Log.info "updating the cached checkout"
  chef_run(update_repository_cache)
  Chef::Log.info "copying the cached version to #{release_path}"
  chef_run(copy_repository_cache)
  install_gems
  
  chef_run(fix_ownership_command(user, group, @configuration[:deploy_to]))
  
  callback(:before_migrate)
  migrate
  callback(:before_symlink)
  symlink
  callback(:before_restart)
  restart
  callback(:after_restart)
  cleanup
end

#fix_ownership_command(user, group, path) ⇒ Object



101
102
103
# File 'lib/chef-deploy/cached_deploy.rb', line 101

def fix_ownership_command(user, group, path)
  "find -L #{path} \\( ! -group #{group} -o ! -user #{user} \\) -exec chown #{user}:#{group} \\{\\} \\;"
end

#groupObject



118
119
120
# File 'lib/chef-deploy/cached_deploy.rb', line 118

def group
  @configuration[:group] || user
end

#latest_releaseObject



70
71
72
# File 'lib/chef-deploy/cached_deploy.rb', line 70

def latest_release
  all_releases.last
end

#migrateObject



105
106
107
108
109
110
111
112
# File 'lib/chef-deploy/cached_deploy.rb', line 105

def migrate
  if @configuration[:migrate]
    chef_run "ln -nfs #{shared_path}/config/database.yml #{latest_release}/config/database.yml"
    Chef::Log.info "Migrating: cd #{latest_release} && sudo -u #{user} RAILS_ENV=#{@configuration[:environment]} RACK_ENV=#{@configuration[:environment]} MERB_ENV=#{@configuration[:environment]} #{@configuration[:migration_command]}"
    chef_run(fix_ownership_command(user, group, latest_release))
    chef_run("cd #{latest_release} && sudo -u #{user} RAILS_ENV=#{@configuration[:environment]} RACK_ENV=#{@configuration[:environment]} MERB_ENV=#{@configuration[:environment]} #{@configuration[:migration_command]}")
  end
end

#nodeObject



138
139
140
# File 'lib/chef-deploy/cached_deploy.rb', line 138

def node
  @configuration[:node]
end

#oldest_releaseObject



79
80
81
# File 'lib/chef-deploy/cached_deploy.rb', line 79

def oldest_release
  all_releases.first
end

#previous_release(current = latest_release) ⇒ Object



74
75
76
77
# File 'lib/chef-deploy/cached_deploy.rb', line 74

def previous_release(current=latest_release)
  index = all_releases.index(current)
  all_releases[index-1]
end

#release_dirObject



130
131
132
# File 'lib/chef-deploy/cached_deploy.rb', line 130

def release_dir
  "#{@configuration[:deploy_to]}/releases"
end

#release_pathObject



134
135
136
# File 'lib/chef-deploy/cached_deploy.rb', line 134

def release_path
  @configuration[:release_path]
end

#restartObject



46
47
48
49
50
51
# File 'lib/chef-deploy/cached_deploy.rb', line 46

def restart
  unless @configuration[:restart_command].empty?
    Chef::Log.info "restarting app: #{latest_release}"
    chef_run("cd #{current_path} && sudo -u #{user} RAILS_ENV=#{@configuration[:environment]} RACK_ENV=#{@configuration[:environment]} MERB_ENV=#{@configuration[:environment]} #{@configuration[:restart_command]}")
  end
end

#rollbackObject



93
94
95
96
97
98
99
# File 'lib/chef-deploy/cached_deploy.rb', line 93

def rollback
  Chef::Log.info "rolling back to previous release"
  symlink(previous_release)
  FileUtils.rm_rf latest_release
  Chef::Log.info "restarting with previous release"
  restart
end

#run(cmd) ⇒ Object



177
178
179
# File 'lib/chef-deploy/cached_deploy.rb', line 177

def run(cmd)
  Chef::Mixin::Command.run_command(:command => cmd, :user => user)
end

#run_with_result(cmd) ⇒ Object

Raises:



167
168
169
170
171
# File 'lib/chef-deploy/cached_deploy.rb', line 167

def run_with_result(cmd)
  res = `#{cmd} 2>&1`
  raise(ChefDeployFailure, res) unless $? == 0
  res
end

#shared_pathObject



126
127
128
# File 'lib/chef-deploy/cached_deploy.rb', line 126

def shared_path
  configuration[:shared_path]
end

#sourceObject



202
203
204
205
206
207
208
209
# File 'lib/chef-deploy/cached_deploy.rb', line 202

def source
  @source ||= case configuration[:scm]
  when 'git'
    Git.new configuration
  when 'svn'
    Subversion.new configuration
  end
end

#sudo(cmd) ⇒ Object



181
182
183
# File 'lib/chef-deploy/cached_deploy.rb', line 181

def sudo(cmd)
  Chef::Mixin::Command.run_command(:command => cmd)
end


142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/chef-deploy/cached_deploy.rb', line 142

def symlink(release_to_link=latest_release)
  Chef::Log.info "symlinking and finishing deploy"
  symlink = false
  begin
    chef_run [ "find #{release_to_link} ! -perm /g+w -exec chmod g+w \\{\\} \\;",
          "rm -rf #{release_to_link}/log #{release_to_link}/public/system #{release_to_link}/tmp/pids",
          "mkdir -p #{release_to_link}/tmp",
          "ln -nfs #{shared_path}/log #{release_to_link}/log",
          "mkdir -p #{release_to_link}/public",
          "mkdir -p #{release_to_link}/config",
          "ln -nfs #{shared_path}/system #{release_to_link}/public/system",
          "ln -nfs #{shared_path}/pids #{release_to_link}/tmp/pids",
          "ln -nfs #{shared_path}/config/database.yml #{release_to_link}/config/database.yml",
          fix_ownership_command(user, group, release_to_link)
        ].join(" && ")

    symlink = true
    chef_run "rm -f #{current_path} && ln -nfs #{release_to_link} #{current_path} && #{fix_ownership_command(user, group, current_path)}"
  rescue => e
    chef_run "rm -f #{current_path} && ln -nfs #{previous_release(release_to_link)} #{current_path} && #{fix_ownership_command(user, group, current_path)}" if symlink
    chef_run "rm -rf #{release_to_link}"
    raise e
  end
end

#userObject



114
115
116
# File 'lib/chef-deploy/cached_deploy.rb', line 114

def user
  @configuration[:user] || 'nobody'
end