Posted about 2 years ago. Visible to the public.

Upgrading from Capistrano 2 to 3

Capistrano 3 is a major rework of the framework and requires several adjustments to your deploy configuration files. The biggest change is that they moved away from their custom DSL and use Rake instead. For connecting with and operating on the servers, they bring a new gem SSHKit which does the heavy lifting. It's SSHKit's DSL that is used anywhere inside the Rake tasks. See #Resources at the bottom for examples.

Step 1: Upgrade guide

For migration from 2 to 3, follow this tutorial: Capistrano 3 Upgrade Guide.

Step 2: More changes

  • There is no :user setting any more. Set the deploy user directly as an option to the server directive. Also, the roles syntax has become more ruby'esque, and the first server will by default be the primary one:

    Copy
    server 'staging.example.com', user: <user here>, roles: %w(app web db)
  • The organization of Capistrano files has changed. It seems the deploy.rb and deploy/*.rb files are only meant for configuration, i.e. many calls to set :<variable>, <value>. Custom tasks should live in lib/capistrano/tasks/*.rake.

  • The deploy:restart task is not automatically run any more! If you need it to run, add an after hook:

    Copy
    after 'deploy:published', 'deploy:restart'
  • To run code on the servers, you need to use execute instead of run. Caution: When a command passed to execute contains white space, it is run in the home directory instead of the directory you might have specified with within(...) do. I would call that a bug, but the core team disagrees. Basically, execute and capture commands behave like Ruby's system etc. methods. Just call them with separate arguments, e.g. execute :dumple, '--fail-gently'.

  • Hooks have changed:

    Copy
    deploy:update_code -> deploy:updating
  • Invocation of other tasks has changed:

    Copy
    # old: namespace.task # new: invoke 'namespace:task'
  • shared/system is now shared/public/system! See this card. This is already handled for our own projects.

Configuration that is not needed any more

set :copy_exclude, ['.git']
The .git repository is excluded from the current directory on the server, but its contents live in the repo directory on the server.
set :allow_sudo, false
Capistrano does no sudo any more.

Error messages

When trying to deploy with Capistrano 3 using your old Capistrano 2 config files, you'll get many error messages that are giving no hint about what really is wrong. The solution to most of them is to strictly hold to the new task syntax.

undefined method `instance' for Capistrano::Configuration:Class
undefined local variable or method `ssh_options' for main:Object
Use the new syntax instead:
Copy
set :ssh_options, { ... }
wrong number of arguments (1 for 2)
undefined method `tail' for nil:NilClass
You need to wrap your task body in a on ... do ... end block, e.g.
Copy
task :dump do on primary roles :db do # <-- this # perform dump end end
undefined method `map' for :roles:Symbol
You're still using the old task ..., roles: ... syntax, which is not supported any more. Capistrano tasks are Rake tasks now, so you need to specify the roles as shown above (on roles(...) do ... end).
Don't know how to build task 'deploy:update_code'/'deploy:setup'/etc
These error messages may originate from before/after hooks. The Capistrano hooks and deploy tasks have change significantly. See the docs for what to hook on.

I didn't need to require capistrano/rvm or similar.

Resources

makandra has been working exclusively with Ruby on Rails since 2007. Our laser focus on a single technology has made us a leader in this space.

Author of this card:

Avatar
Dominik Schöler
Last edit:
over 1 year ago
by Dominik Schöler
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Dominik Schöler to makandropedia