使用 capistrano 从不同的 git 分支进行部署
Posted
技术标签:
【中文标题】使用 capistrano 从不同的 git 分支进行部署【英文标题】:Using capistrano to deploy from different git branches 【发布时间】:2010-12-04 04:44:08 【问题描述】:我正在使用 capistrano 部署 RoR 应用程序。代码库位于 git 存储库中,分支在开发中被广泛使用。 Capistrano 使用deploy.rb
文件进行设置,其中之一是要部署的分支。
我的问题是这样的:假设我从 master 创建了一个新分支 A。部署文件将引用 master 分支。我对其进行了编辑,因此 A 可以部署到测试环境。我完成了该功能的工作,并将分支 A 合并到 master 中。由于来自A 的deploy.rb
文件更新鲜,因此它被合并,现在master 分支中的deploy.rb
引用A。是时候再次编辑了。
这是很多看似不必要的手动编辑 - 参数应始终与当前分支名称匹配。最重要的是,很容易忘记每次都编辑设置。
自动化这个过程的最佳方法是什么?
编辑:原来是someone already had done exactly what I needed:
今天早上我有机会将一个 git 存储库的分支部署到 一个登台服务器,但不知道怎么做。快速搜索 通过 capistrano 源代码显示我可以使用 set
:branch "branch_name"
在我的部署脚本中。我试过了,它奏效了。 然后我想我需要对我所有的 分支机构。当然,我是一个懒惰的草皮,想知道是否没有 更好的方法。如果你不熟悉 git,git branch 命令的输出 是带有星号的分支列表,表示当前分支 在您的本地计算机上签出。例如:
> git branch * drupal_authentication fragment_caching master
所以,我想,如果我只是解析输出并搜索 分支标记为当前:
set :branch, $1 if `git branch` =~ /\* (\S+)\s/m
现在我可以在本地机器上部署当前的任何分支 来自单个共享的部署脚本。
【问题讨论】:
这是更新后的链接:Deploying branches with Capistrano 【参考方案1】:这适用于 Capistrano >= 3.1:
将此行添加到config/deploy.rb
:
set :branch, ENV['BRANCH'] if ENV['BRANCH']
然后调用 capistrano:
cap production deploy BRANCH=master
此解决方案适用于 Capistrano
# call with cap -s env="<env>" branch="<branchname>" deploy
set :branch, fetch(:branch, "master")
set :env, fetch(:env, "production")
【讨论】:
如果使用mustistage扩展,不需要设置env
,但这对我来说只使用一个分支就可以了
如@lulalala 所述,我需要使用小写 -s 才能获取指定的分支。
@Jani:谢谢,似乎他们在较新的 capistrano 版本中改变了这一点,我相应地编辑了我的答案。
我遇到了与@Jani 完全相反的问题:当使用 fetch(:var_name, 'default') 获取时,我必须大写 -S,否则参数不会传递给 cap它。
option '-s' (--set) 代表'在配方加载后设置一个变量'。选项“S”(--set-before)代表“在加载配方之前设置一个变量。”【参考方案2】:
使用 Capistrano 3.1.0+,这些都不再适合我了。相反,根据他们的评论说明:
ask :branch, proc `git rev-parse --abbrev-ref HEAD`.chomp
但是,您不想使用ask
,否则它会提示您。相反,您应该使用set
。 HEAD
是最顶层的分支;所谓的“边缘”。如果您想要不同的分支,请将HEAD
替换为您的分支名称,例如:master
、staging
等。
以示例结束,在/config/deploy/production.rb
中,您可以包含以下行:
set :branch, proc `git rev-parse --abbrev-ref master`.chomp
...或
set :branch, proc `git rev-parse --abbrev-ref HEAD`.chomp
顺便说一句,HEAD
是默认设置,因此无需在文件中真正声明。在/config/deploy/edge.rb
中使用可能会更好。
在/config/deploy/staging.rb
中,您可以包含以下行:
set :branch, proc `git rev-parse --abbrev-ref staging`.chomp
...或
set :branch, proc `git rev-parse --abbrev-ref test`.chomp
你懂的!
我希望这些示例对 capistrano 的未来用户有所帮助 (^_^)
【讨论】:
git rev-parse --abbrev-ref HEAD
用于找出 HEAD 在哪个分支上。运行git rev-parse --abbrev-ref staging
将(几乎)总是输出staging
。您可以使用set :branch, 'staging'
。【参考方案3】:
我可以确认以下内容在 Cap 3.11.0 13/10/18 和 Cap 2 中仍然有效:
在deploy.rb/stage.rb中:
set :branch, ENV['BRANCH'] || 'develop'
在命令行上:
cap deploy BRANCH=featurex
这为您提供了一个默认分支(对于不同的环境可能会有所不同),并且可以根据需要更改分支。
【讨论】:
【参考方案4】:使用多级,实际上是现在:
cap production deploy -s branch=my-branch
之前的帖子语法在我的环境中不起作用
【讨论】:
-s branch=foo
在配方加载后将 capistrano 变量分支设置为 foo
【参考方案5】:
或者,您可以从具有默认分支和环境的命令行构造它,并且您还可以将参数传递给可以包括环境和要使用的分支的 cap 调用。这可能是一个明确传递的分支,或者您可以有一个参数来指示当前分支,如您列出的链接中所述。
#call with cap -S env="<env>" branch="<branchname>" deploy
...
# Prevents error if not parameter passed, assumes that default 'cap deploy' command
# and should deploy the master branch to the production server
set(:env, ‘production’) unless exists?(:env)
set(:branch, ‘master’) unless exists?(:branch)
if !env.nil? && env == "production"
role :web, "production_ip_address"
else # add more as needed
role :web, "development_ip_address"
end
if !branch.nil? && branch == "current"
set :branch, $1 if `git branch` =~ /\* (\S+)\s/m
elsif !branch.nil?
set :branch, branch
else # add more as needed
set :branch, "master"
end
...
Code example borrowed heavily from here
【讨论】:
我需要使用小写的-s
来获取指定的分支
我遇到了与@lulula 完全相反的问题:当使用 fetch(:var_name, 'default') 获取时,我必须大写 -S,否则参数不会传递给 cap它。【参考方案6】:
如果你使用capistrano-multistage,你只需要运行
cap -s branch=$MY_BRANCH deploy
或
cap -s branch=$MY_BRANCH production deploy
无需进一步编辑您的deploy.rb
。
【讨论】:
应该是branch=
,而不是branch-
。
OptionParser::AmbiguousOption: 模糊选项:-s【参考方案7】:
此命令将不再起作用:
cap deploy -s branch=your_branch
在 capistrano v3+ 中删除了对 -sS
标志的支持。
在这里您可以了解更多信息:link
在几个答案中都提到过,但目前不正确。
什么对我有用:
在deploy.rb
文件中添加
set :branch, ENV['BRANCH'] || :master
然后运行:
BRANCH=your_branch cap deploy
另外请注意,为了成功运行这个命令,你需要在 master 分支上。
【讨论】:
【参考方案8】:此解决方案应适用于所有版本的 Capistrano。
def branch_name(default_branch)
branch = ENV.fetch('BRANCH', default_branch)
if branch == '.'
# current branch
`git rev-parse --abbrev-ref HEAD`.chomp
else
branch
end
end
set :branch, branch_name('master')
用法:
BRANCH=. cap [staging] deploy
# => deploy current branch
BRANCH=master cap [staging] deploy
# => deploy master branch
cap [staging] deploy
# => deploy default branch
【讨论】:
【参考方案9】:我使用的是 3.3.5 版本,并且可以正常工作:
set :branch, 'develop'
【讨论】:
【参考方案10】:一般答案:
如果您的设置文件的内容在不同环境之间进行了修改,则应将该行设置为“模板”(使用字符串表示变量名称,如@BRANCH_NAME@
或@ENV_NAME@
)。
然后您将拥有一个能够读取您的配置文件的(版本化)脚本,并将“@BRANCH_NAME@
”变量替换为您的部署过程所需的适当值。
【讨论】:
参见同类问题:***.com/questions/1429256/…、***.com/questions/487753/…、***.com/questions/6009/…【参考方案11】:对于 capistrano 3 用户:
desc "prompt for branch or tag"
task :git_branch_or_tag do
on roles(:all) do |host|
run_locally do
execute :git, 'tag'
tag_prompt = "Enter a branch or tag name to deploy"
ask(:branch_or_tag, tag_prompt)
tag_branch_target = fetch(:branch_or_tag, 'master')
set(:branch, tag_branch_target)
end
end
end
before 'deploy:updated', :git_branch_or_tag
【讨论】:
【参考方案12】:方法一:为部署设置阶段特定的分支(例如测试、生产)
将branch
配置放入阶段文件而不是“deploy.rb”并设置该阶段的目标分支以进行部署。
对于具有关联分支名称 test
和 production
的两阶段应用程序,配置将如下所示,
# app_root/config/deploy/test.rb
...
set :branch, "test"
...
# app_root/config/deploy/production.rb
...
set :branch, "production"
...
此方法可以从特定阶段的分支进行部署。因此,唯一需要的额外步骤是从基本分支合并或重新构建最新代码。
方法二:直接从任意分支部署(使用标签)
另一种方法是使用标签进行部署。为了使用标签进行部署,请设置 branch
配置。在'deploy.rb'中如下,
set :branch, `git describe --tags $(git rev-list --tags --max-count=1)`.chomp
并且,如果关联的标记模式匹配(例如/.*-test$/
),则将 CI 配置为有条件地部署到不同阶段。
现在,可以从任何分支进行部署,
首先,从任意分支创建一个标签,
git tag -a v0.1.0-test -m "版本 0.1.0-test"
然后,推
git push origin v0.1.0-test
注意:以上方法基于 Capistrano 3。
【讨论】:
【参考方案13】:git rev-parse --abbrev-ref HEAD
将返回您所在的当前分支。
我总是设置gpsh
而不是git push -u origin branch_name
$ which gpsh
gpsh: aliased to git push -u origin `git rev-parse --abbrev-ref HEAD`
【讨论】:
以上是关于使用 capistrano 从不同的 git 分支进行部署的主要内容,如果未能解决你的问题,请参考以下文章