如何使用 Capistrano 有条件地清理版本?
How do I conditionally cleanup releases using Capistrano?
我知道我可以使用 keep_releases
来保留特定 数量 的版本,但我有一系列具有指向它们的符号链接的版本。例如,我有:
http://www.example.com/version/1.0.0
这是某个版本的符号链接,比如 /var/www/example.com/releases/2019050101
。我还有一系列我称之为 "transient" 的版本,它们使用 /current/
链接。当部署其中一个 'transient' 版本时,/current
符号链接将被覆盖到最新版本。这意味着有些版本没有指向它们的符号链接。
我想做的是指定 Capistrano 只保留 keep_releases
个 transient 版本。换句话说,应该始终保留从根目录建立符号链接的所有版本。
有人可以帮我用 Capistrano 方法来完成这个吗?
我最终使用了以下配方,它主要是 the cleanup recipe in the Capistrano source 的副本,除了一些额外的逻辑来确定和跳过符号链接目录:
desc "Clean up old releases"
task :cleanup do
on release_roles :all do |host|
releases = capture(:ls, "-x", releases_path).split
kept_paths = []
within release_path.parent.parent do
root_path = release_path.parent.parent
links = capture(:ls, "-l", "|", "grep", "^l").split("\n")
links.each { |x|
next_link_target = x.split("->")[1]
next_link_target = next_link_target.gsub("/build", "")
target_components = next_link_target.split("/")
next_link_target = target_components[target_components.size - 1]
kept_paths.push(next_link_target)
}
end
valid, invalid = releases.partition { |e| /^\d{14}$/ =~ e }
warn t(:skip_cleanup, host: host.to_s) if invalid.any?
valid, invalid = valid.partition { |v|
split_path = v.split("/")
!kept_paths.include? split_path[split_path.size - 1]
}
if invalid.any?
info "Skipping cleanup of releases: #{invalid} because they are symlinked in the root directory"
end
if valid.count >= fetch(:keep_releases)
info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: valid.count)
directories = (valid - valid.last(fetch(:keep_releases))).map do |release|
releases_path.join(release).to_s
end
if test("[ -d #{current_path} ]")
current_release = capture(:readlink, current_path).to_s
if directories.include?(current_release)
warn t(:wont_delete_current_release, host: host.to_s)
directories.delete(current_release)
end
else
debug t(:no_current_release, host: host.to_s)
end
if directories.any?
execute :rm, "-rf", *directories
else
info t(:no_old_releases, host: host.to_s, keep_releases: fetch(:keep_releases))
end
end
end
end
我知道我可以使用 keep_releases
来保留特定 数量 的版本,但我有一系列具有指向它们的符号链接的版本。例如,我有:
http://www.example.com/version/1.0.0
这是某个版本的符号链接,比如 /var/www/example.com/releases/2019050101
。我还有一系列我称之为 "transient" 的版本,它们使用 /current/
链接。当部署其中一个 'transient' 版本时,/current
符号链接将被覆盖到最新版本。这意味着有些版本没有指向它们的符号链接。
我想做的是指定 Capistrano 只保留 keep_releases
个 transient 版本。换句话说,应该始终保留从根目录建立符号链接的所有版本。
有人可以帮我用 Capistrano 方法来完成这个吗?
我最终使用了以下配方,它主要是 the cleanup recipe in the Capistrano source 的副本,除了一些额外的逻辑来确定和跳过符号链接目录:
desc "Clean up old releases"
task :cleanup do
on release_roles :all do |host|
releases = capture(:ls, "-x", releases_path).split
kept_paths = []
within release_path.parent.parent do
root_path = release_path.parent.parent
links = capture(:ls, "-l", "|", "grep", "^l").split("\n")
links.each { |x|
next_link_target = x.split("->")[1]
next_link_target = next_link_target.gsub("/build", "")
target_components = next_link_target.split("/")
next_link_target = target_components[target_components.size - 1]
kept_paths.push(next_link_target)
}
end
valid, invalid = releases.partition { |e| /^\d{14}$/ =~ e }
warn t(:skip_cleanup, host: host.to_s) if invalid.any?
valid, invalid = valid.partition { |v|
split_path = v.split("/")
!kept_paths.include? split_path[split_path.size - 1]
}
if invalid.any?
info "Skipping cleanup of releases: #{invalid} because they are symlinked in the root directory"
end
if valid.count >= fetch(:keep_releases)
info t(:keeping_releases, host: host.to_s, keep_releases: fetch(:keep_releases), releases: valid.count)
directories = (valid - valid.last(fetch(:keep_releases))).map do |release|
releases_path.join(release).to_s
end
if test("[ -d #{current_path} ]")
current_release = capture(:readlink, current_path).to_s
if directories.include?(current_release)
warn t(:wont_delete_current_release, host: host.to_s)
directories.delete(current_release)
end
else
debug t(:no_current_release, host: host.to_s)
end
if directories.any?
execute :rm, "-rf", *directories
else
info t(:no_old_releases, host: host.to_s, keep_releases: fetch(:keep_releases))
end
end
end
end