The easy way to push packages into HockeyApp from CI

As I mentioned in my last post, we use HockeyApp to distribute one of our internal mobile applications. As a platform, it provides many wonderful features including distribution, crash reports, feedback forms, analytics and team management. It’s also been acquired by Microsoft recently, which I’m sure will mean a lot of interesting things coming in the Windows 10 timeframe…

Our build and release pipeline is completely automated – just like they all should be! We have a very simple branching strategy (as we only ever have a couple of people working on it). We use pull requests to manage feature branches and anything that hits the master branch goes live. HockeyApp has a REST API that allows you to upload new versions quite easily.

We went through a couple of iterations before this process became easy though. At first we tried pushing packages using PowerShell. This didn’t work too well… unfortunately the API uses multiple form fields to accept the parameters and PowerShell’s built-in web commands aren’t the easiest to accomplish this with. So we wrote a C# console app to do it. This worked, but was a little nasty because we actually needed to compile and include it as an artefact for a later build to use.

We revisited this later and thought that if we are going to push all the packages into artefacts then we could just use curl from a Mac (or Linux) build agent. This made it really easy! We could now use three simple shell commands to push the packages to hockey app –

1. iOS

curl \

-F "status=2" \

-F "notify=1" \

-F "ipa=@dist/MyApp-%CiBuildNumber%.ipa" \

-H "X-HockeyAppToken: %HockeyAppToken%" \

2. Android

curl \

-F "status=2" \

-F "notify=1" \

-F "ipa=@dist/com.mycompany.myapp-signed.apk" \

-H "X-HockeyAppToken: %HockeyAppToken%" \

3. Windows Phone

curl \

-F "status=2" \

-F "notify=1" \

-F "ipa=@dist/MyApp.WP_Release_ARM.xap" \

-H "X-HockeyAppToken: %HockeyAppToken%" \

They’re all the same right…? Yep – that’s the point. The only thing you need to remember is that the application IDs need to be the right one for your platform and you need to ensure you have the right package names.

The commands above have been parameterised so that you can store the application IDs and HockeyApp token as TeamCity parameters. This would be really handy if you wanted to say have multiple release channels (alpha/beta/RTW) by using a build template and setting the parameters on each configuration.

You may also notice the CiBuildNumber parameter in the iOS command. As this is a chained build we can pick up the Continuous Integration build’s number (which we’ve set up to be a version number – e.g. and add it as a configuration parameter so that we can easily reference it in scripts.

And that’s it!


Posted on 30 January, 2015, in Dev Stuff, Xamarin and tagged , , . Bookmark the permalink. 2 Comments.

  1. Hi,
    I tried to use the command for Windows and get this error :

    [ Invoke-WebRequest : Cannot bind parameter ‘Headers’. Cannot convert the “X-HockeyAppToken:” value of type “System.String” to type “System.Collections.IDictionary”.]

    Do you have an idea of how can I fix it?

    Thank you.

    • Hi,

      In case you haven’t got it already, you need to pass a dictionary to Invoke-webRequest, so it will look like -headers @{ ‘X-HockeyAppToken’ = ‘mytoken’ }

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: