Are there any reasons not to use RAILS_ENV=staging on Heroku? - ruby-on-rails

The Heroku documentation at https://devcenter.heroku.com/articles/deploying-to-a-custom-rails-environment says I shouldn't use a staging.rb file to define my staging environment.
It may be tempting to create another custom environment such as “staging” and create a config/environments/staging.rb and deploy to a Heroku app with RAILS_ENV=staging.
This is not a good practice. Instead we recommend always running in production mode and modifying any behavior by setting your config vars.
I think this is terrible advice and conflicts with well-established Rails best practice. However, I'm not here to argue about best practices. I'm here to ask:
Are there any reasons not to use RAILS_ENV=staging on Heroku?
Is there anything that will break if I create a staging.rb file and set the xxx_ENV config vars like this?
heroku config:add RACK_ENV=staging --remote staging
heroku config:add RAILS_ENV=staging --remote staging

No, there isn't anything that will break if you do this.
However, I do think that Heroku is right here (note that I work at Heroku).
It introduces possible differences between your staging and production environments, when the only thing that changes between them should be configuration variables.
Heroku already provides a secure mean of setting configuration variables, with the config:set command.
Using 2 config files means you have to maintain the same configuration twice, and possible can have issues because you updated the configuration correctly in staging, but incorrectly in production.
As a side note, RACK_ENV should only ever have 3 values: production, development and none. See https://www.hezmatt.org/~mpalmer/blog/2013/10/13/rack_env-its-not-for-you.html

You'll get some warnings from Heroku when you deploy, but I can confirm I did run staging apps, with RAILS_ENV=staging, on Heroku. As long as you set the correct environment variables and Gemfile groups, it should just work.
My guess is that the reason they advise not to use custom environments is that they have some operational tooling that assumes your Rails app runs in production environment, but so far I didn't run into issues.

Related

Setting up staging environment for heroku app

I am coming in late to add some functionality to an already existing app hosted on heroku. The original builder has given me access and I 'heroku git:clone -a app-name' to my local computer.
I've found some conflicting instructions on how to set up a staging environment for this site. I don't want to push to the original site but want a way to try out functionality.
If anyone has had experience with staging and heroku, I'd appreciate any clarification.
You'll need to create a staging.rb file in config/environments. You can copy development.rb or production.rb and adjust whatever values you need.
Heroku will handle configuring the database configuration and such. You can clone an app in Heroku or just create a new one, then set it's RAILS_ENV and RACK_ENV environment variables to staging, and push to it.
Please refer: Heroku - Managing Multiple Environments for an App
You Need to create a second Heroku application that hosts your staging application.
Follow the instructions provided in the link for working with multiple environment in heroku.

Heroku warning deploying to non-production when multiple apps

I have a one codebase multiple websites (for UK, US etc) setup on Heroku with Rails 4. All works, except when I push to Heroku I see this in the terminal:
remote: ###### WARNING:
remote: You are deploying to a non-production environment: "production_uk".
I have these production rails envs:
production
production_uk
production_us
In my gemfile (and also some other files) I have these environments configured so for example I load puma but I was wondering if I should mind this warning? Maybe heroku treats non-production apps with lower priority or something like this?
I even tried to name rack env "production" while keeping rails env "production_uk" but that had no effect.
Thanks in advanceí!
sounds like you are not setting RAILS_ENV to production, heroku I believe warns you if this is not set.
are you using RAILS_ENV to control your country? if so instead use a different variable for that purpose.
It sounds like you are using RAILS_ENV to control which country the server is supporting. This is why heroku is giving you the warning. It expects to see RAILS_ENV='production'.
I would recommend you set up a separate environment variable (i.e. COUNTRY) and use this to control the country specific configuration of your app rather than than RAILS_ENV

Are you using custom rails environments?

ootb rails has the 3 environments
development
test
production
How do you handle your other environments for example staging ?
When I think about what I want from a staging environment I want most of the production settings, but typically server names and other specific values are different from production.
Do you create 1:N environment/*.rb for each custom environment you have? Or do you treat the environments more as like a profile and then use something like application.yml or secrets.yml for running the application with different server configurations?
What has worked well for you in the past and what has not?
It depends if your "staging" environment is a different thing or is actually a variation on the "production" environment as is usually the case.
Normally you just deploy in full production mode, using the production.rb file and everything, to a non-production server. This distinction is irrelevant to rails, and matters only to your deployment script. For example Capistrano would be concerned about this.
The only time you need another environment is if you need a different group of settings for Rails.
In my opinion, when I run the app in an staging environment I want it to have exactly the same settings as in production, because it's when I check if everything is alright before releasing the new code. So I create a environments/staging.rb that actually is a symbolic link to environments/production.rb. To deploy, I use Capistrano, which lets you define the server settings for every environment you want to. I really encourage you to take a look at it if you don't know it, as it makes deploying as easy as running a simple command, and it takes care of uploading the new code, precompiling the assets, restarting the server, etc.
Appropriate any way described above.
In some cases I am using 1:N way because it easy when you have fixed count of deployment environments (for example when I am deploying own pet-project to remote server).
But in other cases I am using default set of environments (for example when I am deploying project to different customers).
Just choose any way appropriate for you and your project.
I use require_relative to create a staging environment that is identical to production, and then override the parts that are different. Typically the only difference is hostnames.
Here's what my environments/staging.rb looks like:
# Staging configuration is identical to production, with some overrides
# for hostname, etc.
require_relative "./production"
Rails.application.configure do
config.action_mailer.default_url_options = {
:host => "staging.example.com",
:protocol => "https"
}
config.action_mailer.asset_host = "https://staging.example.com"
end

Partitioning Heroku Production Database -- Possible?

I'm considering paying the $50/ mo for a production database so I can use PostGIS with my rails 4 app. My issue is that I would like to continue developing with a 'staging' environment, but can't yet justify paying for two production databases. Staging is obviously just a clone of production, so just pointing both apps to the same DB url (post) would likely cause some major headaches.
Is there any way to partition the database, or another strategy you'd recommend?
Initial answer from heroku support is no, but I'm hoping there's a scrappy workaround.
Thanks!
First off, I would highly suggest just paying the extra $50/mo. For that, you get all kinds of cool stuff like forking and pipelines, as well as the fact that this is kind of hacky. I honestly don't know if this might end up wiping your production data when you clear the staging database. Please make backups before trying this.
I'll view this answer as an answer to a technical challenge rather than a business decision. Without further ado,
Setting up multiple environments on the same database with Heroku Postgres schemas
First, I deleted the existing dev database and added a production database to my production app.
heroku addons:add heroku-postgresql:crane
> Adding heroku-postgresql:crane on test-shared-app... done, v# ($50/mo)
> Attached as HEROKU_POSTGRESQL_RED_URL
This attached a database under the RED color, so replace HEROKU_POSTGRESQL_RED_URL with the appropriate color for your app.
This attaches a database to the production app, but we need to connect to the same app for staging. First, create the staging schema
heroku run "bundle exec rails runner 'ActiveRecord::Base.connection.execute(%q{CREATE SCHEMA staging})'"
Next, create the staging app. See Managing Multiple Environments for an App for more information.
heroku create --remote staging test-shared-app-staging
heroku config:set RACK_ENV=staging RAILS_ENV=staging --remote staging
Then, copy the environment data from your existing app. Add ?schema_search_path=staging to the end of the URL.
heroku config --remote heroku --shell
# make note of your database URLs
heroku config:set --remote staging \
DATABASE_URL=postgres://...?schema_search_path=staging \
HEROKU_POSTGRESQL_RED_URL=postgres://...?schema_search_path=staging
And push to staging
git push staging master
Now, run migrations on staging
heroku run --remote staging bundle exec rake db:migrate
And try it out.
My "app" is running at http://test-shared-app.herokuapp.com/posts and http://test-shared-app-staging.herokuapp.com/posts. You can see the source at https://github.com/benmanns/heroku-shared-app.
If I were you, I would use production DB until the right moment (start making money or getting more users, etc). I would replicate all the tables in production DB and give the new tables new names by prepending something like "stag_{original_table_name}. So, you would have two different sets of the same tables. In your models, make them use the new table on staging environment:
class Foo < ActiveRecord::Base
self.table_name = "staging_#{self.class.name}" if Rails.env.staging?
I am pretty cheap... and this may be an ugly solution in the eyes of the true Rails masters.
Heroku Schemas is another approach to this; it's a Heroku plugin that basically lets you run a single command to apply Benjamin Manns's solution of multiple schemas.

How do I force Capistrano deployed app to use my development database?

I have a app that I'm deploying to a development server using Capistrano. I'd like to force this deployment to use the development database. So far the only way I've managed to do it is to make my production database info in database.yml equal to the development info. But this is a complete hack.
I've tried setting rails_env to development in deploy.rb but that hasn't worked.
Thoughts?
I ended up using the solution over here. Basically a recipe to replace a line in environment.rb after deploy but before restart.
The problems seems to be with DreamHost's Passenger config. It assumes you're running in production mode.
I'd use Capistrano Ext in order to define multiple deployment environments. I have used this in the past to deply staging and production installations of my apps, so I think it'd work well for you.
Jamis Buck has a writeup if you'd like an overview on how to use it.

Resources