Deploying To Heroku With Multiple Environments
We’re using Heroku to deploy our application to both a staging and production environment and we’re using the secure credentials for our stripe and sendgrid API keys. However, Heroku requires deployments to use RAILS_ENV=production, which in turn will cause our application to always read from the production encrypted credentials file. We’ve also found that we cannot use the `<%= ENV["MY_KEY"] %>` pattern to access environment variables, as this yml file is read literally and not interpreted (i.e. `Rails.application.credentials.sendgrid.password` will literally print `<%= ENV["SENDGRID_API_KEY"] %>`.
Since our staging and production environments require different keys, does anyone have a recommendation about how we might go about having different credentials for our different Heroku environments?
For those seeking a solution, here's what we came up with...
1. Generate a staging credentials file & master key.
2. In config/environments/production.rb set the value for config.credentials.content_path using an environment variable that you can then configure in the Heroku config vars as follows.
1. Generate a staging credentials file & master key.
2. In config/environments/production.rb set the value for config.credentials.content_path using an environment variable that you can then configure in the Heroku config vars as follows.
config.credentials.content_path = "config/credentials/#{ENV.fetch('RAILS_CREDENTIALS_ENV', "production")}.yml.enc"
Hey
Chris Oliver
I also unfortunately ran into a similar issue, even after doing what you suggested. I'm going to try Gordon's suggestion. Thanks!
My issue, specifically, is that assets didn't finish precompiling when I set
Full stack trace:
I also unfortunately ran into a similar issue, even after doing what you suggested. I'm going to try Gordon's suggestion. Thanks!
My issue, specifically, is that assets didn't finish precompiling when I set
RAILS_ENV=staging
and using my staging RAILS_MASTER_KEY
.Full stack trace:
remote: rake aborted! remote: LoadError: cannot load such file -- uglifier remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:34:in `require' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.3.0/lib/zeitwerk/kernel.rb:23:in `require' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/autoload/uglifier.rb:2:in `<main>' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.4.6/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/zeitwerk-2.3.0/lib/zeitwerk/kernel.rb:23:in `require' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/uglifier_compressor.rb:43:in `initialize' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/uglifier_compressor.rb:26:in `new' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/uglifier_compressor.rb:26:in `instance' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/uglifier_compressor.rb:34:in `cache_key' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:102:in `processor_cache_key' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/cached_environment.rb:49:in `processor_cache_key' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:111:in `block in processors_cache_keys' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:111:in `map' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/processor_utils.rb:111:in `processors_cache_keys' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/processing.rb:165:in `resolve_processors_cache_key_uri' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets.rb:213:in `block in <module:Sprockets>' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/dependencies.rb:68:in `resolve_dependency' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/cached_environment.rb:54:in `resolve_dependency' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/loader.rb:286:in `block in resolve_dependencies' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/loader.rb:286:in `map' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/loader.rb:286:in `resolve_dependencies' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/loader.rb:54:in `block in load' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/loader.rb:329:in `block in fetch_asset_from_dependency_cache' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/loader.rb:325:in `each' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/loader.rb:325:in `each_with_index' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/loader.rb:325:in `fetch_asset_from_dependency_cache' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/loader.rb:43:in `load' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/cached_environment.rb:44:in `load' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/base.rb:81:in `find_asset' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/base.rb:88:in `find_all_linked_assets' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/sprockets-4.0.0/lib/sprockets/manifest.rb:125:in `block (2 levels) in find' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb:24:in `block in execute' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:41:in `block in synchronize' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:41:in `synchronize' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:41:in `synchronize' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb:19:in `execute' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/promise.rb:563:in `block in realize' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:353:in `run_task' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:342:in `block (3 levels) in create_worker' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:325:in `loop' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:325:in `block (2 levels) in create_worker' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:324:in `catch' remote: /tmp/build_d8c3416ca5a47cf7442b834104a1b573/vendor/bundle/ruby/2.7.0/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:324:in `block in create_worker' remote: Tasks: TOP => assets:precompile remote: (See full trace by running task with --trace) remote: remote: ! remote: ! Precompiling assets failed. remote: ! remote: ! Push rejected, failed to compile Ruby app.
Appreciating the discussion above, if a year later! Heroku explains its 12-factor caution against custom environments for staging here: https://devcenter.heroku.com/articles/deploying-to-a-…
Gordon's solution works great and helps limit the concept of staging to the narrow use case of naming a RAILS_CREDENTIALS_ENV. This way we keep the 12 Factor ideal of ENV variables as the main difference between staging and production from the Rails code point of view.
Wonder if the heroku docs should link to the above guide and offer Gordon's snippet as a way to conform to that recommendation when deploying a jumpstart app.
Thanks! C
Gordon's solution works great and helps limit the concept of staging to the narrow use case of naming a RAILS_CREDENTIALS_ENV. This way we keep the 12 Factor ideal of ENV variables as the main difference between staging and production from the Rails code point of view.
Wonder if the heroku docs should link to the above guide and offer Gordon's snippet as a way to conform to that recommendation when deploying a jumpstart app.
Thanks! C
Rails automatically uses environment credentials based upon the RAILS_ENV if the config/credentials/{environment}.yml.enc exists, so no need to add the config lines to change the content path. That's built-in to Rails 6.0 now.
Just make sure you run "rails credentials:edit --environment=staging" to generate the right files.
Just make sure you run "rails credentials:edit --environment=staging" to generate the right files.
Notifications
You’re not receiving notifications from this thread.