zendesk/samson

Rails 6 causing DATABASE_URL cannot be empty error for rake db:migrate?

SamFleming opened this issue · 5 comments

A little background here, I'm running Samson in Kubernetes, and every so often update the version of Samson and usually log into the pod after upgrading to run migrations. This has worked for the past few years without much issue. All the environment variables are correctly configured, and Samson has been working great.

However, after upgrading from v2784 (old I know 🤦‍♂) to v3071, I tried running bin/rake db:migrate and was met with the following error:

user@samson:/app# bin/rake db:migrate
rake aborted!
Database URL cannot be empty
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/connection_adapters/connection_specification.rb:39:in `initialize'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations/url_config.rb:64:in `new'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations/url_config.rb:64:in `build_url_hash'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations/url_config.rb:69:in `build_config'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations/url_config.rb:36:in `initialize'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:172:in `new'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:172:in `build_db_config_from_hash'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:150:in `build_db_config_from_raw_config'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:126:in `block in build_configs'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:122:in `each'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:122:in `flat_map'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:122:in `build_configs'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:18:in `initialize'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/tasks/database_tasks.rb:159:in `new'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/tasks/database_tasks.rb:159:in `for_each'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/railties/databases.rake:28:in `block (2 levels) in <top (required)>'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/railties/databases.rake:23:in `block in <top (required)>'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/railties/databases.rake:7:in `<top (required)>'
/usr/local/bundle/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:319:in `load'
/usr/local/bundle/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:319:in `block in load'
/usr/local/bundle/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:291:in `load_dependency'
/usr/local/bundle/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:319:in `load'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/railtie.rb:49:in `block in <class:Railtie>'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:246:in `instance_exec'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:246:in `block in run_tasks_blocks'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:255:in `each'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:255:in `each_registered_block'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:246:in `run_tasks_blocks'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/application.rb:509:in `block in run_tasks_blocks'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/engine/railties.rb:15:in `each'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/engine/railties.rb:15:in `each'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/application.rb:509:in `run_tasks_blocks'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/engine.rb:459:in `load_tasks'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:190:in `public_send'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:190:in `method_missing'
/app/Rakefile:11:in `<top (required)>'
(See full trace by running task with --trace)

Looking through releases I can see that in v3052 rails was updated to v6. Running the same migrate command in version v3051, the database is migrated, all is hunky-dory. No errors 👍

Apologies, but I don't really know too much about rails, but some Googling brings up this issue rails/rails#36610 – could this be related?

can you post your DATABASE_URL and config ? (make sure to remove passwords)
... I'd guess the url is empty ?
... does doing a unset DATABASE_URL before running rake help ?

This is my database.yml

<%
  uri = URI(ENV['DATABASE_URL'] || 'mysql://root@192.168.99.100:8306')
  uri.scheme = 'mysql2'
%>

production:
  <% uri.path = "/samson" %>
  url: "<%= uri %>"
  pool: <%= ENV['RAILS_MAX_THREADS'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>
  adapter: mysql2

development:
  <% uri.path = "/samson" %>
  url: "<%= uri %>"
  password: "123"
  adapter: mysql2

My DATABASE_URL env is mysql://samson@db:3306

Just to clarify. The exact same environment variables and database.yml work on v3051, but not on v3071

... does doing a unset DATABASE_URL before running rake help ?
Unfortunately this doesn't change anything.

user@samson:/app# echo $DATABASE_URL
mysql://samson@db:3306
user@samson:/app# unset DATABASE_URL
user@samson:/app# echo $DATABASE_URL

user@samson:/app# bin/rake
rake aborted!
Database URL cannot be empty
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/connection_adapters/connection_specification.rb:39:in `initialize'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations/url_config.rb:64:in `new'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations/url_config.rb:64:in `build_url_hash'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations/url_config.rb:69:in `build_config'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations/url_config.rb:36:in `initialize'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:172:in `new'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:172:in `build_db_config_from_hash'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:150:in `build_db_config_from_raw_config'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:126:in `block in build_configs'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:122:in `each'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:122:in `flat_map'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:122:in `build_configs'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:18:in `initialize'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/tasks/database_tasks.rb:159:in `new'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/tasks/database_tasks.rb:159:in `for_each'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/railties/databases.rake:28:in `block (2 levels) in <top (required)>'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/railties/databases.rake:23:in `block in <top (required)>'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/railties/databases.rake:7:in `<top (required)>'
/usr/local/bundle/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:319:in `load'
/usr/local/bundle/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:319:in `block in load'
/usr/local/bundle/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:291:in `load_dependency'
/usr/local/bundle/gems/activesupport-6.0.1/lib/active_support/dependencies.rb:319:in `load'
/usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/railtie.rb:49:in `block in <class:Railtie>'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:246:in `instance_exec'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:246:in `block in run_tasks_blocks'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:255:in `each'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:255:in `each_registered_block'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:246:in `run_tasks_blocks'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/application.rb:509:in `block in run_tasks_blocks'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/engine/railties.rb:15:in `each'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/engine/railties.rb:15:in `each'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/application.rb:509:in `run_tasks_blocks'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/engine.rb:459:in `load_tasks'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:190:in `public_send'
/usr/local/bundle/gems/railties-6.0.1/lib/rails/railtie.rb:190:in `method_missing'
/app/Rakefile:11:in `<top (required)>'
(See full trace by running task with --trace)

from activerecords code it looks like it reads the url attribute from the config correctly, just that it is empty ... add RAILS_ENV=production to make sure it picks up the right env

then open up /usr/local/bundle/gems/activerecord-6.0.1/lib/active_record/database_configurations.rb:172
and add p env_name, spec_name, config

Similar issue was reproduced in my environment.

I gave the url value in config.yml as an immediate value and db:migrate succeeded.

production:
  adapter: postgresql
  url: postgres://postgres:mysecretpassword@127.0.0.1:5432/postgres
#  url: "<%= ENV['DATABASE_URL'] %>"

This issue does not seem to occur with rails serve and any other tasks/commands. So, temporarily rewriting config.yml only for db:migrate task can be used as a workaround solution.

alternative could be doing the rails 7 upgrade and seeing if that magically fixes it ...