86

I'd like to be able to push code to dev.myapp.com for testing and then to www.myapp.com for production use. Is this possible with Heroku?

August Lilleaas
  • 54,010
  • 13
  • 102
  • 111
Tom Lehman
  • 85,973
  • 71
  • 200
  • 272

5 Answers5

142

Your interface to Heroku is essentially a Git branch. The Heroku gem does some work through their API, but within your Git repository, it's just a new remote branch.

heroku create yourapp # production
git br -D heroku # delete the default branch

heroku create staging-yourapp # staging
git br -D heroku # delete the default branch

Once you set up multiple applications on Heroku, you should be able to configure your Git repository like this:

git remote add staging git@heroku.com:staging-yourapp.git
git push origin staging

git remote add production git@heroku.com:yourapp.git
git push origin production

I usually work in a 'working' branch, and use Github for my master.

Assuming that's the case for you, your deploy workflow would probably look something like:

git co -b working
# do some work

# push to github:
git co master
git merge working
git push

# push to staging:
git co staging
git merge master
git push origin staging

# push to production
git co production
git merge master
git push origin production
Luke Bayes
  • 3,234
  • 2
  • 25
  • 20
  • Thanks -- this makes some sense (I suck at git). Question: Suppose I'm working on some cutting-edge changes on branch "edge". How can I push that branch to staging-myapp without affecting myapp (which currently is running on the master branch)? Does `git push staging edge work`? – Tom Lehman Aug 24 '09 at 05:21
  • In the interest of getting you going, you would just merge edge to your staging branch and push it. Your production branch is separate and clean. You can always branch it and make changes that only merge back there. – Luke Bayes Aug 27 '09 at 19:08
  • 5
    Instead of creating apps with the default 'heroku' remote branch and after deleting it, you can use a much nicer solution like: `heroku create yourapp --remote your-remote` – dombesz Mar 21 '11 at 12:05
  • That sounds great to me, I don't have time to confirm right now. If you can edit the answer to reflect this information, please do! – Luke Bayes Apr 21 '11 at 05:31
  • 2
    Once you set this up, all your `heroku` commands need to include `--app staging` or `--app production`. Is there any way to set a default? (Asking as a comment b/c this seems too targeted to be a full-fledged SO question.) – Paul A Jungwirth Jul 22 '11 at 22:50
  • 3
    @PaulAJungwirth To set a default Heroku app, use something like "git config heroku.remote staging". More in the Heroku docs at https://devcenter.heroku.com/articles/multiple-environments. – grifaton Sep 03 '12 at 19:10
  • @HoraceLoeb- Answer to your original comment: `git push staging edge:master` – Yarin Oct 01 '13 at 12:39
  • Since Heroku is pulling from `staging` and `production`, what purpose does the `master` branch serve? Couldn't you simplify and make `master` the home for the production code? – Jeff Oct 05 '13 at 16:12
  • The sample workflow seems misleading – AFAICT you're not pushing to GitHub, the staging server, and the production server; you're pushing to the `master` branch on GitHub, the `staging` branch on GitHub, and the `production` branch on GitHub. – Zach Apr 28 '14 at 21:25
  • Hey @Zach - The lines above where you see, "git remote add" actually update the .git/config file and create a connection between those local branches and the non-Github remote targets. – Luke Bayes Jul 06 '14 at 19:51
  • It was so easy. Thank you – HarshMarshmallow May 07 '15 at 22:30
19

This explains everything you need to know if your a newbie like me: http://devcenter.heroku.com/articles/multiple-environments

Tom Lehman
  • 85,973
  • 71
  • 200
  • 272
LearningRoR
  • 26,582
  • 22
  • 85
  • 150
10

A key part of the original question is about linking up the staging app to a subdomain (dev.myapp.com) of the main app (www.myapp.com). This hasn't been addressed in any of the answers.

Step 1: Configure both production ('myapp') and staging ('staging-myapp') versions of your app as is indicated in the answer by Luke Bayes

Step 2: In your domain management system (e.g. GoDaddy):

Create a CNAME record:  dev.myapp.com 
that points to:   proxy.heroku.com

Step 3: Configure Heroku to route dev.myapp.com to staging-myapp:

heroku domains:add dev.myapp.com --app staging-myapp

After the CNAME record has had time to propagate, you will be able to run your staging app at dev.myapp.com.

Don Leatham
  • 2,694
  • 4
  • 29
  • 41
  • 1
    how about access control so it doesn't show up in google etc. and people don't stumble upon it and think its the real thing? any nice solutions? – brittohalloran Jun 14 '12 at 16:07
  • Yes, the easiest way is to skip the GoDaddy step and access the "dev" version of your app directly off the Heroku domain using the Heroku URL. (e.g. http://stormy-lake-5483.heroku.com.) However, if you want to have 'dev' off your domain as described here, you can always install a robots.txt file to tell google, bing, et. al. to not index your dev site. That will help keep it out of the search engines. – Don Leatham Jun 16 '12 at 03:05
  • I ended up adding a `before_filter` hook to my `application_controller` to catch EVERYTHING in staging and force the user to login as an admin, then set an admin cookie so I can still see the app from the point of view of a 'non-admin'. Working pretty good for me. – brittohalloran Jun 16 '12 at 03:28
8

You should check the heroku_san

It does a pretty good job juggling with environments on heroku.

jlfenaux
  • 3,263
  • 1
  • 26
  • 33
7

Things are easier now. Here's how you do it...

Create an app for each environment

$ heroku create myapp --remote production
$ heroku create myapp-staging --remote staging

This will create named remote repos for each app, which you can see in .git/config.

You can now use either the --app or --remote switches to target a particular app:

$ heroku info --app myapp-staging
$ heroku info --remote staging

Set Rails environments

For Rails apps, Heroku defaults to the "production" environment. If you want your staging app to run in a staging environment, create the environment in your project and set the corresponding RAILS_ENV and RAKE_ENV environment variables on the app:

$ heroku config:set RACK_ENV=staging RAILS_ENV=staging --remote staging

Configure environments

If you have other configuration variables you'll need to pass them in for each environment as well.

$ heroku config:set AWS_KEY=abc --remote staging
$ heroku config:set AWD_SECRET=123 --remote staging
...etc

That's a huge pain though so I just use my snappconfig gem and run

$ rake heroku:config:load[myapp-staging]

to load my project's YAML config files into Heroku.

Deploy

Now you just push to Heroku like this:

$ git push staging master
$ git push production master

and migrate like this:

$ heroku run rake db:migrate --remote staging
$ heroku run rake db:migrate --remote production

(See Managing Multiple Environments for an App | Heroku Dev Center for more info and shortcuts.)

Yarin
  • 173,523
  • 149
  • 402
  • 512
  • Setting `RAILS_ENV` and `RACK_ENV` to `staging` is discouraged by Heroku: "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." More on this here: https://devcenter.heroku.com/articles/deploying-to-a-custom-rails-environment – Koen. May 12 '14 at 15:34
  • @Koen- Trying to manage complex Rails configurations without the context of environments is totally impractical in my experience, whether on Heroku or otherwise. If you have a whole set of connection strings, API keys, etc for your staging app and another for your production app, are you really gonna set those config vars individually for each? That's just asking for trouble- Heroku is giving bad advice here. – Yarin May 13 '14 at 16:24
  • Thanks. I am looking for staging that really get a real URL, probably with commithash. I think this is something that Zeit Now or Netlify made it easy. – Polv Feb 07 '20 at 01:32