使用 Capistrano 部署代码时如何替换共享文件?

How to replace a shared file when deploying code with Capistrano?

更新:TL;DR 似乎没有内置的方法来实现这一点,因此自定义任务是一个简单的解决方案。

Capistrano 提供了在所有版本中共享文件和目录的工具。这很方便,甚至可以为不应轻易更改(或必须在各个版本中保持不变)的文件提供一些安全性,例如数据库配置文件。

但是当涉及到 替换 或只是更新这些共享文件之一时,我最终直接在目标机器上手动完成。我想对此进行改进,例如要求 Capistrano 在部署时覆盖部分或所有共享文件。一种具有一定粒度的 --force 标志。

我不知道有任何此类设施,到目前为止我的搜索失败了。任何指针?


正在考虑

这个设施不存在的原因之一(除了我没有找到它!)是它可能比看起来更难。例如,假设我们有一个共享的数据库配置文件,出于安全原因(常见做法),我们将其排除在版本控制之外。当前版本依赖于数据库配置的版本 1。下一个版本需要数据库配置的版本 2。如果部署顺利,一切都很好。在新版本出现一些错误(例如回归)后回滚时会变得更加困难,因为版本 1 必须 然后可用。


这样的自动化很酷也很方便,但也很危险。然而,我手头有实际用例。

一种方法是使用像 Chef 或 Puppet 这样的系统配置工具来部署不同于 Capistrano 的配置文件。

另一种方法是创建自定义任务来执行此操作:https://coderwall.com/p/wgs6gw/copy-local-files-to-remote-server-using-capistrano-3

我个人更改服务器配置的次数不够多,也没有在足够多的服务器上更改过,因此还没有尝试将其自动化。在过去,制作一个 scp 命令将所需的配置文件复制到所有所需的服务器就足够了。

我创建了一个 template 方法来执行此操作。例如,我可以执行这样的任务:

task :create_database_yml do
  on roles(:app, :db) do
    within(shared_path) do
      template "local/path/to/database.yml.erb",
               "config/database.yml",
               :mode => "600"
    end
  end
end

然后我有一个 database.yml.erb 模板,它使用 fetch(:database_password) 之类的东西来填充适当的值。您可以使用 Capistrano 中的 ask 方法来提示输入这些值,这样它们就永远不会被提交。

template的实现可以很简单:你只需要读取文件,通过ERB,然后使用Capistrano的upload!将结果放在服务器。

我的版本可能比您需要的复杂一点,但如果您好奇的话:

https://github.com/mattbrictson/capistrano-mb/blob/7600440ecd3331945d03e059368b75849857f1fb/lib/capistrano/mb/dsl.rb#L104