Capistrano (as of version 3.19.1) still defaults to deploying the master
branch, even though GitHub, GitLab and BitBucket have all changed their default branch name to main
.
The simplest fix for this is to add a line to config/deploy.rb
which sets the branch to main
:
# config/deploy.rb
set :branch, "main"
You can easily override that branch setting on a per-environment basis. For example, if you want to always deploy the currently checked-out (HEAD
) branch when deploying to staging
, override the :branch
setting in config/deploy/staging.rb
. The current branch can be obtained with git rev-parse --abbrev-ref HEAD
so the command becomes:
# config/deploy/staging.rb
set :branch, `git rev-parse --abbrev-ref HEAD`.chomp
Setting a global default and then overriding it per-environment is probably sufficient 95+% of the time, but what if you ever want to do something different?
If it’s a one-off thing, you could edit the local copy of config/deploy.rb
or config/deploy/<env>.rb
and deploy. As long as you don’t commit and push the changes to Git, Capistrano on your machine will use the branch you set, and everyone else will happily keep using the original setting from Git.
However, I found a better way (on StackOverflow) that doesn’t rely on you having to remember not to commit your changes. We will set up a workflow that gives us:
First the code, then the explanation (lightly modified from my project’s README).
# config/deploy.rb
# config valid for current version and patch releases of Capistrano
lock "~> 3.19.1"
def branch_name(default_branch)
branch = ENV.fetch('BRANCH', default_branch)
if branch == '.'
`git rev-parse --abbrev-ref HEAD`.chomp
else
branch
end
end
# Uncomment one of these to set an app-wide default for all environments
# set :branch, "main"
# set :branch, branch_name("main")
set :application, "my_app"
# etc, etc
# config/deploy/production.rb
server "<hostname>", user: "deploy", roles: %w[app db web]
set :branch, branch_name("main")
# config/deploy/staging.rb
server "<hostname>", user: "deploy", roles: %w[app db web]
set :branch, branch_name(".")
And here’s the relevant section from my project’s README.md
:
Capistrano is used for deployment. By default the main
branch will be deployed in production (more info in next section), so make sure all code has been committed (and pushed), then run:
> cap production deploy
A typical deployment takes less than 30 seconds and will finish with:
00:19 deploy:log_revision
01 echo "Branch main (at a087b4c40d8ef0031a0b90773c8511d8e873fa59) deployed as release 20240921040843 b…
✔ 01 deploy@<hostname> 0.067s
The last five releases are kept on the server (in theory allowing for easy rollback) but in practice it’s generally safer to revert the changes and deploy a new release (reference).
The default branch has been set to “main” in config/deploy/production.rb
(using set :branch, branch_name("main")
), but you can override it by setting the BRANCH
environment variable when running Capistrano:
> BRANCH=my-new-feature cap production deploy
Set the variable to .
to deploy the current branch (a bit like the current working directory on *nix systems):
> BRANCH=. cap production deploy
The .
shortcut also works in deploy files. We default to using the current branch in staging using:
# config/deploy/staging.rb
set :branch, branch_name(".")
P.S. On a bigger team you might not want to make it so easy to deploy a different branch to production. In that case, don’t include the banch_name
method in production.rb
:
# config/deploy/production.rb
server "<hostname>", user: "deploy", roles: %w[app db web]
set :branch, "main"
P.P.S. I deliberately commented out set :branch
from config/deploy.rb
. That way if I forget to set the branch for a new environment, Capistrano will attempt to use master
and the deploy will fail. If you want new environments to default to something else, uncomment one of the set :branch
lines in config/deploy.rb