laserlemon / figaro

Simple Rails app configuration
MIT License
3.77k stars 287 forks source link

Add support for "staging" environment ? #254

Closed anthony-robin closed 7 years ago

anthony-robin commented 7 years ago

I am using Figaro (version 1.1.1) on my Rails project which contains many environments (development, staging, production). I'm not sure why but the staging key in application.yml is never recognize when deploying to staging environment whereas it works properly for production.

# application.yml

database_name: 'my_database_development'
staging:
  database_name: 'my_database_staging' 
production: 
  database_name: 'my_database_production'
# staging env
Figaro.env.database_name # => 'my_database_development'

# production env
Figaro.env.database_name # => 'my_database_production`

Is there a way to add staging env to be recognized by Figaro or is it a bug from the gem ?

laserlemon commented 7 years ago

Are you sure Rails.env is actually returning "staging" on your staging server?

anthony-robin commented 7 years ago

I use Capistrano to deploy my Rails application and I've set the corresponding deploy environment:

# config/deploy/staging.rb
set :stage, :staging

# config/deploy/production.rb
set :stage, :production

Here is my puma server log on startup:

Puma starting in cluster mode...
    * Version 3.6.0 (ruby 2.2.2-p95), codename: Sleepy Sunday Serenity
    * Min threads: 0, max threads: 16
    * Environment: staging # <= Rails environment ?
    * Process workers: 2
    * Phased restart available

I assume that the Rails.env should match the corresponding capistrano environment used to deploy ? I still don't understand why it works for production but not staging.

Thanks !

laserlemon commented 7 years ago

To be sure, I'd use rails console on staging to see what Rails.env is set to.

anthony-robin commented 7 years ago

rails console on the staging server doesn't work for me (it throws many errors from gem specified in the development group of Gemfile and not available in staging).

So I have to write bundle exec rails console staging in order to make it to work and obviously the Rails.env give me staging.

laserlemon commented 7 years ago

Sounds like you may need to set RAILS_ENV=staging on your server. That may solve these issues.

anthony-robin commented 7 years ago

Thanks but setting RAILS_ENV=staging didn't change anything 😞

I added a htpasswd protection in my staging environment file. That's weird because it's use config defined in application.yml as well (under staging key) and it works.

# application.yml
staging: 
  htpasswd_name: 'my_name'
  htpasswd_password: 'my_password'
# environments/staging.rb
config.middleware.insert_before(::Rack::Runtime, "::Rack::Auth::Basic", 'Staging environment') do |u, p|
  u == Figaro.env.htpasswd_name && p == Figaro.env.htpasswd_password
end

Does the error could come from database.yml file ? Is the file loaded before Rails env is defined ?

# application.yml
database_name: 'my_database_development'
staging:
  database_name: 'my_database_staging' 
production: 
  database_name: 'my_database_production'
# database.yml
staging:
  <<: *default
  database: <%= Figaro.env.database_name %> # => returns 'my_database_development'
laserlemon commented 7 years ago

That's strange but you could be on to something there. I'm afraid I won't be able to help much more without a failing test case. And I even think the Figaro test suite has a test that uses values from application.yml in database.yml. Check it out and keep me posted with what you find!

anthony-robin commented 7 years ago

Thanks for your help and time. I will try to investigate more about that.

anthony-robin commented 7 years ago

Just after replying I finally figured out why it wasn't working:

I was defining two times the staging key in my application.yml and the first properties (from database) where erased by the seconds ones (htpasswd). About the production key, it was working properly because I only defined it once.

To fix it, I had to inherit from the first staging, so my final solution is as follow:

# application.yml
staging: &staging # <= important
  database_name: 'my_database_staging'

...

staging:
  <<: *staging # <= important
  htpasswd_name: 'my_htpasswd_name'
  ...

That was a very vicious bug !