Tips For Uploading Apps to Organizations in HockeyApp

Like many others right now, we're in the process of migrating our testing infrastructure from TestFlight to HockeyApp before the TestFlight shutdown next week. As we did in the past with Xamarin and HipChat, we also open sourced the FAKE helper we made for uploading builds to HockeyApp.

For example, to upload a build to HockeyApp and then send a notification to a room in HipChat you can do:

HockeyApp (fun p ->  
  {p with 
    ApiToken = Environment.GetEnvironmentVariable("HockeyAppApiToken")
    File = ipaOrApkPath
  })
|> fun response ->
    HipChatNotification(fun p ->
      {p with 
          AuthToken = Environment.GetEnvironmentVariable("HipChatAuthToken")
          RoomId = Environment.GetEnvironmentVariable("HipChatNotificationRoom")
          Message = ("Successfully deployed to HockeyApp: " + response.ConfigUrl)
          Color = "green"
      }) |> ignore

As part of the transition, we created an organization for the company, and a couple teams within that organization. We then proceeded to run into a few stumbling blocks in getting things working properly, which I wanted to share to hopefully help others avoid the aggravation we went through. It's also entirely possible that we were just doing something wrong or missing something entirely - if that's the case, please do let me know!

API Tokens and Ownership

All of our uploads happen through automated CI builds, so the next thing we did was go to create an API token to use. I was a little disappointed to see that API tokens are managed at the user level, rather than the organization. It's not the end of the world, but it would be nicer if that lived under the organization so that multiple people can manage the same tokens.

The main problem we hit as a result of this is that builds uploaded using this API token would be tied to the user that created the key and not the organization. This makes sense based on the fact that the token is tied to a user and not the organization, but the documentation for uploading a build makes no mention of a way to set the owner for an app. It's possible to transfer the app to the organization on the website through a series of somewhat clunky steps, but this really wouldn't scale well for the volume of apps we process in our system.

Thankfully when I raised the question on Twitter earlier today, HockeyApp was nice enough to respond very quickly with a way to achieve what we needed. The solution is to pass in an owner_id parameter with the upload payload, which can be used to set the owner for the app using its ID. You can get the ID out of the URL when viewing the organization on the site. Here's what that looks like in cURL syntax:

-F "owner_id=3141592" \

Hopefully they add this to their documentation soon. We'll also be publishing an update to the FAKE helper soon that will include the ability to set this ID from your build scripts.

Visibility to Users

Once we got the organization ownership working the next thing we realized was that despite our assumptions, the builds weren't visible to anyone else on my team, despite the fact that I'd added them to the Owners team. There are a couple ways you can go here. First, HockeyApp does have an endpoint at /api/2/apps/APP_ID/app_teams/ID that you can use to assign a team to an app programmatically. This is fine, but what we really wanted was for people in the owners group to automatically get access to everything.

After some digging we came across this checkbox when you're adding/editing an owner for an organization:

User settings

Somehow we'd overlooked that option when initially setting things up. Personally I think this should be the default behavior, since to me an "owner" should be someone with full admin rights across the organization.

Overall things seem to work pretty well in HockeyApp but the user experience definitely leaves quite a bit to be desired, especially given that it's a paid product. Hopefully we'll see some nice updates coming to HockeyApp in the coming months now that they're part of Microsoft.

comments powered by Disqus
Navigation