Continuous Deployment to Heroku With Jenkins

Heroku is an easy way to host your apps. It is simple and runs in the cloud - so you avoid the need for servers and a lot of infrastructure automation scripting. Unfortunately, there aren’t many good Continuous Integration or Continuous Delivery options that can run on Heroku1, so if you’re a firm believer in CI/CD you will still need some servers outside of Heroku.

So, how do you add Heroku deployments into you pipeline if you are running a CI server outside heroku? This Jenkins setup is working for me:

Heroku Setup

If you don’t already have multiple environments in Heroku, you’ll need to set that up. Check out the Heroku guide on Managing Multiple Environments for an App.

tl;dr: Heroku environments are really distinct apps. They each have their own set of plugins and collaborators, so make two apps with the same plugins. I wouldn’t share the collaborators - the team can push to CI, but only CI should push to production.

Here’s an sample of a two-environment setup:

Heroku setup
1
2
heroku create --stack cedar --addons scheduler your-app
heroku create --stack cedar --addons scheduler --remote production your-app-prod

Jenkins Setup

Here’s what you need to do on the Jenkins side:

Plugins

Install Jenkins GIT plugin

Create the Post Deploy Job

Create a new job named your-app-postdeploy. It should run whatever is necessary to complete a deployment after a git push to Heroku. Probably something along the lines of:

Jenkins Execute shell Setting
1
heroku rake db:migrate db:seed --app your-app-prod

Setup both Git repos as SCMs

Git Repositories Repository URL git@heroku.com:your-app.git Repository URL git@heroku.com:your-app-prod.git Name production Branches to build Branch Specifier (blank for default):

Setup the build

Setup whatever your CI would normally do if you weren’t using Heroku environments. If your CI tests include an integration phase that hits http://your-app.heroku.com then you should probably include the same steps as your post-deploy job (with –app your-app).

Setup the merge and push

Git Publisher Push Only If Build Succeeds true Merge Results true Branches Branch to push master Target remote name production

Setup the post-deploy trigger

Build other projects Projects to build your-app-postdeploy Trigger only if build succeeds

Summary

This should get you Continuous Deployment from Jenkins to Heroku. There are a couple caveats:

  • You may get a merge conflict if someone manually pushes changes to production that were not pushed through your-app/master. You shouldn’t do that anyways.
  • This is Continuous Deployment, not Continuous Delivery. You would need to make some changes to support a manual gate before production. The only opportunity this provides for a manual gate (between deployment and post-deployment) is not a viable option.
  • Your application may be broken between the deploy and post-deploy. This is usually just a few seconds. You could briefly enable Heroku maintenance mode if the user experience is an issue.

  1. Travis-CI is one. It only seems to support public GitHub repos and is still in alpha. Tddium is another. It is a paid service and Heroku does not currently recommend allowing it to push to production.

Comments