-
Notifications
You must be signed in to change notification settings - Fork 12
Description
My database.yml file includes something like this:
production:
<<: *default
database: prod
host: localhost
username: <%= Rails.application.credentials.dig :postgres, :username %>
password: <%= Rails.application.credentials.dig :postgres, :password %>Currently, this gem fails at task cap production postgres:backup:create with:
00:00 postgres:backup:ensure_remote_dirs
01 mkdir -p my_path/shared/postgres_backup
✔ 01 my_user@my_path 0.059s
#<Thread:0x00007ff89c960928@/Users/me/.rvm/gems/ruby-2.5.1/gems/sshkit-1.18.0/lib/sshkit/runners/parallel.rb:10 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
1: from /Users/me/.rvm/gems/ruby-2.5.1/gems/sshkit-1.18.0/lib/sshkit/runners/parallel.rb:11:in `block (2 levels) in execute'
/Users/me/.rvm/gems/ruby-2.5.1/gems/sshkit-1.18.0/lib/sshkit/runners/parallel.rb:15:in `rescue in block (2 levels) in execute': Exception while executing as my_user@my_path: bundle exit status: 1 (SSHKit::Runner::ExecuteError)
bundle stdout: Nothing written
bundle stderr: (erb):28:in `<main>': uninitialized constant Rails (NameError)
from /usr/share/rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/erb.rb:876:in `eval'
from /usr/share/rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/erb.rb:876:in `result'
from -e:16:in `<main>'
#<Thread:0x00007ff89c16d108@/Users/me/.rvm/gems/ruby-2.5.1/gems/sshkit-1.18.0/lib/sshkit/runners/parallel.rb:10 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
1: from /Users/me/.rvm/gems/ruby-2.5.1/gems/sshkit-1.18.0/lib/sshkit/runners/parallel.rb:11:in `block (2 levels) in execute'
/Users/me/.rvm/gems/ruby-2.5.1/gems/sshkit-1.18.0/lib/sshkit/runners/parallel.rb:15:in `rescue in block (2 levels) in execute': Exception while executing as my_user@:my_path Exception while executing as my_user@my_path: bundle exit status: 1 (SSHKit::Runner::ExecuteError)
bundle stdout: Nothing written
bundle stderr: (erb):28:in `<main>': uninitialized constant Rails (NameError)
from /usr/share/rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/erb.rb:876:in `eval'
from /usr/share/rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/erb.rb:876:in `result'
from -e:16:in `<main>'
(Backtrace restricted to imported tasks)
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as my_user@my_path: Exception while executing as my_user@my_path: bundle exit status: 1
bundle stdout: Nothing written
bundle stderr: (erb):28:in `<main>': uninitialized constant Rails (NameError)
from /usr/share/rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/erb.rb:876:in `eval'
from /usr/share/rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/erb.rb:876:in `result'
from -e:16:in `<main>'
Caused by:
SSHKit::Runner::ExecuteError: Exception while executing as my_user@my_path: bundle exit status: 1
bundle stdout: Nothing written
bundle stderr: (erb):28:in `<main>': uninitialized constant Rails (NameError)
from /usr/share/rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/erb.rb:876:in `eval'
from /usr/share/rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/erb.rb:876:in `result'
from -e:16:in `<main>'
Caused by:
SSHKit::Command::Failed: bundle exit status: 1
bundle stdout: Nothing written
bundle stderr: (erb):28:in `<main>': uninitialized constant Rails (NameError)
from /usr/share/rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/erb.rb:876:in `eval'
from /usr/share/rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/erb.rb:876:in `result'
from -e:16:in `<main>'
Tasks: TOP => postgres:backup:create
(See full trace by running task with --trace)I believe the key error here is: uninitialized constant Rails (NameError). When I inspect this gem's lib/capistrano3/tasks/postgres.rb file, line 162 is the culprit:
# Grabs remote database config before creating dump <---- line 152
def grab_remote_database_config
return if fetch(:postgres_remote_database_config)
on roles(fetch(:postgres_role)) do |role|
within release_path do
env = fetch(:postgres_env).to_s.downcase
filename = "#{deploy_to}/current/config/database.yml"
eval_yaml_with_erb = <<-RUBY.strip
#{env_variables_loader_code(env)}
require 'erb'
puts ERB.new(File.read('#{filename}')).result <------- line 162
RUBY
capture_config_cmd = "ruby -e \"#{eval_yaml_with_erb}\""
yaml_content = test('ruby -v') ? capture(capture_config_cmd) : capture(:bundle, :exec, capture_config_cmd)
set :postgres_remote_database_config, database_config_defaults.merge(YAML::load(yaml_content)[env])
end
end
end <------- line 169Because the scope of line 162 has no way to interpret a call to Rails, my database.yml causes this code to fail.
One obvious, easy work around is to use one of the environment gems that this gem supports. Another solution is to update this gem to support calls to Rails -- something like:
cmd = "cd #{current_path} && /home/my_user/.rvm/gems/ruby-2.5.1/wrappers/rails runner -e production 'puts ERB.new(File.read(\"#{filename}\")).result'"
yaml_content = capture(cmd)
loaded = YAML::load(yaml_content)I am not proficient enough with Capistrano's SSHKit DSL to have figured out a cleaner way to call rails runner, but this is nearly exactly my development code at the moment and its working. A similar change would have to be made to def grab_local_database_config
What are your thoughts on whether this gem should support calls to Rails.application.credentials in the database.yml file?