Capistrano::Twingly

Capistrano 3 tasks used for Twingly's Ruby deployment

Installation

Add this line to your application's Gemfile:

gem 'capistrano-twingly', github: 'twingly/capistrano-twingly'

And then execute:

$ bundle

Usage

If you want to require all dependencies (capistrano, capistrano-bundler, capistrano-chruby) and all task helpers, it is possible to do so with one line:

# Capfile
require 'capistrano/twingly'

See below if you want to selectively require tasks. In any case, you need to set variables and specify tasks as demonstrated below.

Deploy current git branch

# Capfile
require 'capistrano/twingly/current_git_branch'

# config/deploy/production.rb
set :branch, Twingly::Git.current_branch

Nginx tasks

# Capfile
require 'capistrano/twingly/nginx'

# config/deploy.rb
set :app_name, 'contest-bamba'
set :server_names, %w(bamba.bloggportalen.se) # Optional
set :use_https, true # Optional

namespace :deploy do
  after :finishing, 'deploy:nginx:generate_config'
  after :finishing, 'deploy:nginx:upload_config'
  after :finishing, 'deploy:nginx:enable_config'
  after :finishing, 'deploy:nginx:reload'
end

Upstart

# Capfile
require 'capistrano/twingly/upstart'

# config/deploy.rb
set :procfile_contents, -> {
  contents = ''
  contents << "web: "
  contents << "chruby-exec #{fetch(:chruby_ruby)} -- "
  contents << "bundle exec "
  contents << "puma "
  contents << "-b unix:///tmp/#{fetch(:app_name)}.sock "
  contents << "-e #{fetch(:stage)}"
}

namespace :deploy do
  desc 'Start application'
  task :start do
    invoke 'deploy:export_upstart'
    on roles(:app) do
      sudo :start, fetch(:application)
    end
  end

  desc 'Restart application'
  task :restart do
    invoke 'deploy:export_upstart'
    on roles(:app) do
      execute "sudo restart #{fetch(:application)} || sudo start #{fetch(:application)}"
    end
  end

  desc 'Stop application'
  task :stop do
    on roles(:app) do
      sudo :stop, fetch(:application)
    end
  end

  after :stop, 'deploy:disable_autostart'
  after :start, 'deploy:enable_autostart'
  after :restart, 'deploy:enable_autostart'
end

It's also possible to use a different Procfile for each host by setting procfile_contents to a Hash:

# config/deploy.rb
set :procfile_contents, -> {
  servers = fetch(:servers_from_srv_record)

  servers.each_with_object({}) do |hostname, procfiles_by_host|
    contents = "web: CURRENT_HOST=#{hostname} bundle exec puma"

    procfiles_by_host[hostname] = contents
  end
}

Tag deploys in Git

# Capfile
require 'capistrano/twingly/tag_deploy_in_git'

# config/deploy.rb
namespace :deploy do
  after :finishing, 'deploy:push_deploy_tag'
end

Fetch servers from SRV record

# Capfile
require 'capistrano/twingly/servers_from_srv_record'

# config/deploy/production.rb
fetch(:servers_from_srv_record).each do |hostname|
  server hostname, user: 'deploy', roles: %w{app}
end

Release workflow

  • Update the examples in this README if needed.

  • Bump the version in capistrano-twingly.gemspec in a commit, no need to push (the release task does that).

  • Build and publish the gem. This will create the proper tag in git, push the commit and tag and upload to RubyGems.

    bundle exec rake release
    
    • If you are not logged in as twingly with ruby gems, the rake task will fail and tell you to set credentials via gem push, do that and run the release task again. It will be okay.
  • Update the changelog with GitHub Changelog Generator (gem install github_changelog_generator if you don't have it, set CHANGELOG_GITHUB_TOKEN to a personal access token to avoid rate limiting by GitHub). This command will update CHANGELOG.md, commit and push manually.

    github_changelog_generator
    

Note about CHANGELOG.md

The changelog is incorrect for some old versions, where the version was increased before the pull request was merged. This is due to how github_changelog_generator works.