Deploying multiple environments on Heroku (while still hosting code on Github)
As mentioned in an earlier post, Cashflow App is now hosted on Heroku.
The main repository for my code is still hosted on Github. This is where I manage/version it.
When you create an application on Heroku, it is automatically associated with a git repository hosted on Heroku. Deploying changes to your application is as simple as pushing your code to the associated git repository.
Here is a schema of what I want to achieve :
In this post, I will explain how I use Github to version my code and Heroku to deploy it, with 2 different environments. You may also read this article that explains how to deploy your application on Heroku and this one that also explain how to deal with multiple environments.
Setup different environments on Github
On Github, I want to work with 2 branches : a master branch for production and a staging branch for testing. The master branch is what you get when you first clone your repository :
git clone git@github.com:account_name/repository_name.git cd repository_name [master]$
To create a staging branch, just do :
[master]$ git checkout -b staging Switched to a new branch "staging" [staging]$
Then push your local staging branch to Github :
[staging]$ git push origin staging Total 0 (delta 0), reused 0 (delta 0) To git@github.com:account_name/repository_name.git * [new branch] staging -> staging [staging]$
You should now have 2 branches on Github
Create the Heroku Staging App
Now, I will create a Staging app on Heroku. This will create a git repository. I will only push code to this repository when I want to deploy modifications to the Staging app.
[staging]$ heroku create myapp-staging --remote heroku-staging Created http://myapp-staging.heroku.com/ | git@heroku.com:myapp-staging.git Git remote heroku-staging added [staging]$
You'll notice that I specified a custom remote name : heroku-staging. It will allow you to specifically deploy your code to the Staging app.
Your .git/config file should now look like this :
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true [remote "origin"] url = git@github.com:account_name/repository_name.com.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master [remote "heroku-staging"] url = git@heroku.com:myapp-staging.git fetch = +refs/heads/*:refs/remotes/heroku-staging/*
Create the Heroku Production App
Go back to the master branch :
[staging]$ git checkout master Switched to branch "master" [master]$
Create the heroku prod app :
[master]$ heroku create myapp-prod --remote heroku-prod Created http://myapp-prod.heroku.com/ | git@heroku.com:myapp-prod.git Git remote heroku-prod added [master]$
Your .git/config file should now look like this :
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true [remote "origin"] url = git@github.com:account_name/repository_name.com.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master [remote "heroku-staging"] url = git@heroku.com:myapp-staging.git fetch = +refs/heads/*:refs/remotes/heroku-staging/* [remote "heroku-prod"] url = git@heroku.com:myapp-prod.git fetch = +refs/heads/*:refs/remotes/heroku-prod/*
Deploy the Staging app
The Staging app on Heroku is linked to the heroku-staging remote. You'll want to push the code from your staging branch to the heroku-staging/master branch, as show in the first schema :
[master]$ git push heroku-staging staging:master ... To git@heroku.com:myapp-staging.git * [new branch] staging -> master [master]$
staging:master means that you push your staging local branch to the master remote branch. Here, the remote branch is heroku-staging, which is linked to the staging app.
Migrate the staging db :
[master]$ git checkout staging Switched to branch "staging" [staging]$ heroku rake db:migrate --app myapp-staging
Deploy prod app
[staging]$ git checkout master Switched to branch "master" [master]$ git push heroku-prod master ... To git@heroku.com:myapp-prod.git * [new branch] master -> master [master]$
Migrate the prod db :
[master]$ heroku rake db:migrate --app myapp-prod
Make some changes in staging and deploy them
First, switch to the staging branch, and make your changes.
[master]$ git checkout staging Switched to branch "staging" [staging]$ make your change [staging*]$ git commit -a -m "test staging modification"
Then push your modifications to the staging branch on Github :
[staging]$ git push origin staging
Finaly, deploy your modifications to the heroku staging app
[staging]$ git push heroku-staging staging:master
Make some changes in production and deploy them
Switch to the master branch, and make your changes.
[staging]$ git checkout master Switched to branch "master" [master]$ make your change [master*]$ git commit -a -m "test production modification"
Then push your modifications to the master branch on Github :
[master]$ git push origin master
Finaly, deploy your modifications to the heroku prod app
[master]$ git push heroku-prod master
Feel free to comment this solution and to share your tips here.

