Deploying to Heroku from TeamCity

Previously I discussed our TeamCity configuration using RVM and mentioned that we often use git to deploy projects. Today I’ll share an example of how a TeamCity build agent can trigger deployments of a application hosted on Heroku and some of the challenges I found.

Add an ssh config entry for the project’s access to Heroku

Much like shared github access I need to be able to specify which ssh key a particular project’s connections to heroku should use. Since I want to use client side checkouts I can’t specify a private key within TeamCity but I do know that all my compatible build agents are local so I can add a new entry to `~/.ssh/config` and define a host which will allow me to connect to Heroku with a particular key.

# Heroku for #{new_project}
Host heroku-#{new_project}
HostName heroku.com
User git
ForwardAgent yes
IdentityFile /home/teamcity/.ssh/teamcity_#{new_project}_rsa

Add a ssh key to the Heroku account
Now I need to add this new key to the Heroku account for this project by installing the heroku gem in my project’s gemset and using the `heroku` command line to add the key. Heroku stores the account credentials used in `~/.heroku` and the user account running my build agents might need to connect to many different heroku accounts. I could switch my heroku credentials, upload a key, and have different projects deploy using different accounts. However since I find it useful to be able to run the heroku command line (see below) I found it preferable to have a single `teamcity` heroku account added to every project as a collaborator.
If you find it necessary to switch between Heroku accounts frequently this tool from Aeonscope might be useful: managing multiple heroku accounts

Now I can add a key to the current project’s Heroku account.
heroku keys:add ~/.ssh/teamcity_#{new_project}_rsa

Deploying to Heroku
Now I can add a simple TeamCity build configuration which pushes code to Heroku once a particular revision passes the tests.

Command executable git
Command parameters push git@heroku-#{new_project}:#{new heroku project’s name}.git master

A project's deployment build configuration


Deploying and running database migrations
I don’t want my app trying to respond to requests while waiting for a database migration to finish so now it becomes necessary to put the app in maintenance mode before deploying and migrating.

Command executable sh
Command parameters -c heroku maintenance:on –app #{new_project} && sleep 60 && git push git@heroku.com:#{new_project}.git master && heroku rake db:migrate –app #{new_project} && heroku maintenance:off –app #{new_project}

I found that I need to add a delay between turning on maintenance mode for the app and pushing to heroku. Attempting to push immediately fails with the error `Heroku push rejected, your slug is currently being compiled. Please try again later.` Even with a significant delay I still see this error occasionally and have to rerun the deploy build but at this point I don’t know of a way to make sure heroku can handle a new revision before attempting to push changes.

Now I can use TeamCity to automatically deploy changes to Heroku as soon as my project’s tests pass.

This entry was posted in Web and tagged , , , , , . Bookmark the permalink.

4 Responses to Deploying to Heroku from TeamCity

  1. Ross Hale says:

    Hi guys, I spent about half of yesterday trying to figure out the ‘Heroku push rejected, your slug is currently being compiled. Please try again later.’ problem. And today I figured it out!

    Currently there is no API for checking to see if your slug is being recompiled. So, simply do a get request on your app and check for a response code of 422. When you get the 422, your app is in maintenance mode and the slug has successfully been recompiled.

    I baked this into my heroku_deploy script here: http://github.com/rosshale/heroku_deploy

    The code snippet looks something like this:

    response_code = 200
    while (response_code != 422)
    response_code = HTTParty.get(“http://your_application.heroku.com”).code
    end

    Hopefully that helps someone out there!

  2. Sahir Memon says:

    Hey guys, I got a question. How do you specifiy where the project git file is when you’re doing this? I am asking because my build log reports this:

    [21:22:30]: Step 2/2: Deploy to Heroku (Command Line)
    [21:22:30]: [Step 2/2] Starting: git push git@heroku-project:project.git master
    [21:22:30]: [Step 2/2] in directory: /home/teamcity/TeamCity/buildAgent/work/c463bb084d1493f0
    [21:22:30]: [Step 2/2] fatal: Not a git repository (or any of the parent directories): .git
    [21:22:30]: [Step 2/2] Process exited with code 128
    [21:22:30]: [Step 2/2] Step Deploy to Heroku (Command Line) failed

    any ideas?

    Thanks

    • Alon Salant says:

      This is probably too late to be useful to Sahir but is worth posting for someone else…

      You need to change your VCS Settings at

      Configuration Steps: 2 Version Control Settings: Checkout Settings

      Set ‘VCS Checkout Mode’ to ‘Automatically on agent’ to have the git repo cloned instead of exported into the agent work directory.

  3. Alon Salant says:

    Jonah, I totally used this today! Thanks for writing it up!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>