iOS Continuous Deployment with TeamCity and HockeyApp

November 7, 2014 Tim Johnson

Goal for this setup:

  • Run unit tests and feature tests for your iOS app whenever a commit gets pushed to master.
  • Enable your devs and PM to deploy the latest passing build to staging whenever they want.

First off, if you are interested in CI just to run your unit tests (or XCTest based feature tests), I recommend checking out XCode CI Server. It is easy to set up, integrates with XCode for build alerts and is generally pretty neat. However XCode CI is not very extensible. As soon as you have to run feature tests using a none XCTest framework, or want to archive your .ipa, you need something else. After having used Jenkins on a number of projects I wanted to see what all the fuss was about over in TeamCity land.

Quick opinion on TeamCity: It is great. If you have even the simplest release pipeline (like the one I will describe in this post) it is a better experience than Jenkins. Also, while it is a paid-for product, most of the time the free license can fit your project.

First Stop: Unit Tests

  1. Create a project in TeamCity
  2. Add a Build Configuration
  3. Configure your source code repository settings
    1. I recommend setting “VCS checkout mode” to “Automatically on Agent” to resolve issues with symlinks as mentioned in this post.
  4. In the build steps section, select “Auto Detect Build Steps”
  5. TeamCity will detect your .xcodeproj
    1. It is okay if you use an .xcworkspace and it doesn’t see it. There is a workaround below
  6. Select “Use This” on the xcodeproj you want to run the tests for
  7. Add a “VCS Trigger” in the trigger section so builds occur automatically

Workaround for those who use an .xcworkspace

  1. Edit the settings on your “Xcode Project” build step
  2. Choose the scheme you want to build
  3. Change the “Path to the project or workspace” to your .xcworkspace
  4. Do not do anything else. If you hit “Check/Reparse Project” it will probably not detect your scheme.
  5. I mean, you should hit save, but nothing else.

At this point you should be able to have nice green builds you can be happy about all day long.

Second Stop: Exporting your .ipa as an Artifact

  1. Add a command line build step to your project
    1. Use the following commands as your “Custom Script”
      xcodebuild -workspace <AppName>/<AppName>.xcworkspace -scheme <PrimarySchemeName> archive -archivePath <AppName>.xcarchive
      xcodebuild -exportArchive -exportFormat ipa -archivePath <AppName>.xcarchive -exportPath <AppName> -exportProvisioningProfile <AcceptanceProvisioningProfileName>
  2. In the "General Settings" of you Build Configuration, add "<AppName>.ipa" to the "Artifact Paths" section. This will save your IPA as a Build Artifact.

Now for every successful build you can retrieve a deployable artifact from TeamCity. I would recommend running those commands manually on the command line and trying to deploy the .ipa before putting it in your TeamCity configuration, as getting your Provisioning Profiles in order can sometimes be painful.

Last Stop: Deploying to HockeyApp

HockeyApp is a great way to manage deployments to different groups of users. A great feature of it is its simple API!

We chose to have the following build be a manual kick off, albeit one we use multiple times a day. With a single setting change you can make it automatic.

  1. Under your "Project Settings" (the level above your "Build Configuration") add a new "Build Configuration".
  2. You should not have a need to add your code repository
  3. Under "Dependencies" select "Add new artifact dependency"
    1. For "Depend on", select the "Build Configuration" we created in the previous steps
    2. For "Get artifacts from", I recommend "Last successful build", but there are many interesting choices here that can fit different scenarios. ("Last pinned build" seems particularly useful for giving power to your PM)
    3. For "Artifact rules" keep it simple for now and choose what we entered in the "Artifact Paths" field of the previous "Build Configuration". For instance: <AppName>.ipa
    4. "Clean destination paths before downloading artifacts" is recommended, because I get scared of somehow uploading old assets if file names change
  4. Add a new "Command Line" build step
  5. Use the following command to push your App to HockeyApp (as taken from their documentation)
    set -x
     -F "status=2"
     -F "notify=0"
     -F "notes=Build %build.counter%"
     -F "notes_type=0"
     -F "ipa=@<AppName>.ipa"
     -H "X-HockeyAppToken: <API_Token_From_HockeyApp>"
  6. Rejoice! You have now uploaded your app!

There are numerous ways to handle all of the steps above, but this seemed to the best way to leverage the power of TeamCity and not create additional dependencies. As you can see this also leaves open many additional abilities. For instance, if your acceptance environment relies on a Fake/Mock API server, you could deploy it by adding an additional step to your HockeyApp build configuration. If you have feature tests to run, you can add them as an additional build step to the first "Build Configuration" we created.

Be sure to radiate your CI's build and deploy status using any number of tools, for instance Project Monitor.

About the Author


How Data Science Delivers Retail E-Commerce Analytics, Comparisons & Decisions
How Data Science Delivers Retail E-Commerce Analytics, Comparisons & Decisions

Data science might become the next “hot item” in the fashion industry, and this post provides a business an...

Next Now Available in the PWS Marketplace Now Available in the PWS Marketplace, a service that allows developers to instantly setup geo-distributed broadcast networks to transmit...


Subscribe to our Newsletter

Thank you!
Error - something went wrong!