June 9, 2014

Use Jenkins to Automatically Deploy a Git Repository to Heroku

I spent some of the weekend trying to get my git repository (Gitblit) to work with Jenkins and Heroku on one of my Windows servers. My plan was to set up a job in Jenkins that would poll my git repository every 15 minutes for changes and push any changes out to my Heroku application (Dexstr, for anyone who's interested). I thought the process would be pretty simple, but I ran into a bunch of issues and it ended up taking me more than a few hours to finish.

I'll run through everything I did to set up Heroku and Jenkins. All of these steps should be done on the machine that's running Jenkins and not your dev machine.

1. Set Up Heroku

The first thing you'll want to do is download Heroku Toolbelt; it's going to install a CLI tool for managing your Heroku projects and a git client for you.

Once that's installed, you'll want to log in to Heroku, generate a SSH public key, and upload it to Heroku. It's pretty simple, just run the following command in Command Prompt/PowerShell (or Terminal if you're on OS X):

heroku login

It will ask for your Heroku credentials (email address and password). When generating your public key, if you're on a private computer, feel free to leave the password blank (read more about it on Heroku's support page).

Note: You should also be prompted at some point to add Heroku as a trusted host (if you're on a Windows box). You'll want to do this, it will make the Jenkins side of things a lot easier.

2. Generate a SSH Public Key

If you've already logged into Heroku using Command Prompt and somehow skipped generating a key, you can generate a new one at any time by running ssh-keygen. If you're lucky, you should be able to just run the following in Command Prompt, but if you're like me, you'll need to run the second line instead:

ssh-keygen

"c:\program files (x86)\git\bin\ssh-keygen.exe"

Again, just skip the passphrase in most cases.

3. Upload Your Keys to Heroku

Alright, so now that you've generate your public key, it's time to upload them to Heroku. Using the CLI tool that Heroku provides in the toolbelt that you downloaded earlier, run the following in Command Prompt:

heroku keys:add

This command should grab the keys generate in your user's .ssh folder and upload them to Heroku. If you did this right, you should receive an email from Heroku saying a new key was added.

4. Install the Jenkins Git Plugin

This is another pretty simple step. Download the Git plugin through Jenkins' Plugin Manager.

5. Create a New Jenkins Job

For my particular project, I just created a free-style software project job in Jenkins.

The first thing you'll want to do while creating the job is to add both git repositories (your private git repository and Heroku's repository) to Jenkins. In Heroku's case, you'll want to click on "Advanced" and name the repository something (like "heroku").

For credentials, add the SSH public key by using the third bullet (From the Jenkins master ~/.ssh); the username for the public key can be found in the email that Heroku sent you earlier. Note: Make sure that Jenkins is running as the local user or you might run into trouble. More information here.

In my particular case, I chose to have the job poll my git repository every 15 minutes to look for changes. You can do the same by adding a build trigger by checking "Poll SCM" and enter the following in for the schedule:

H/15 * * * *

The last thing you need to do in Jenkins is to add a post-build action to push changes out to Heroku. The git plugin should give you the option of adding a "Git Publisher" step.

Save the project and you should be good to go.

Looking back on all of this, I'd probably consider moving Gitblit, Jenkins, and Redmine (the software I use to manage my projects) over to a Linux box just because of the little Windows quirks that pop up when working on things like this, but that might just be because I'm using a Windows box and that the idea of a Linux box sounds better after wasting a few hours with permission problems.

Note: If your Heroku repository is empty, you will need to push something out to to it. Use the following commands:

heroku git:remote -a APP_NAME

git push heroku master

Further Reading/Sources

  1. Continuous Deployment to Heroku With Jenkins
  2. Continuous Delivery for Heroku With Jenkins
  3. Running Jenkins in Windows with regular user account to see executables in PATH
  4. Managing Your SSH Keys
  5. Jenkins, GIT plugin and Windows