code.eklund.io

space age technobabble for an electromatic boogaloo

Making Capistrano Rake Tasks Work With Envdir

rails, ruby | Comments

Using envdir to manage environment variables for a Ruby app means that rake tasks run via Capistrano can fail or have unexpected output because the ENV hash won’t be populated with what is located in the envdir.

What is envdir?

https://cr.yp.to/daemontools/envdir.html

envdir runs another program with environment modified according to files in a specified directory.

Why not use dotenv?

dotenv isn’t meant for production and envdir integrates nicely with runit. And if that’s how your SRE team wants to manage apps then that’s what you use.

So how can I fix it?

Add to the rake command prefix in SSHKit.

Create a new Capistrano task

1
2
3
4
5
6
7
8
9
# lib/capistrano/tasks/envdir.rake

desc 'Prefix rake tasks with envidr'
namespace :envdir do
  task :prefix_rake do
      SSHKit.config.command_map.prefix[:rake].unshift 'envdir /path/to/env/directory'
    end
  end
end

This will create a new Capistrano task: envdir:prefix_rake. By using unshift we ensure that if the prefix has already been set (for example by capistrano/bundler) that we don’t overwrite what is already there.

Wire it up.

Load the rake task

1
2
3
# Capfile

Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

Inject the new task

1
2
3
# config/deploy.rb

before 'deploy:starting', 'envdir:prefix_rake'

Capistrano will now run rake tasks prefixed. For example, here is how the asset precompilation task will run (assumes capistrano/bundler has been required as part of capitrano/rails)

1
envdir /path/to/env/directory bundle exec rake assets:precompile

Comments