Automated Ad-Hoc Beta iPhone App Publishing

A while back, I came across Jeffrey Sambells post about iOS Wireless App Distribution, thought “that’s cool, I could automate most of that” and then promptly forgot about it. A little after this, Hunter Hillegas introduced iOS Beta Builder which I also thought “cool, I could extend that to do some of the automation I thought about” and then forgot about it again.

Ad Hoc app distribution

BetaBuilder-TDO App showing ABC of the Sea metadata

BetaBuilder-TFO App

I already had a small shell script I run to make my .ipa files which saves me from the tediousness of “Build and Archive” and then saving the archived file – if I have to click something, it loses my attention. I already build iOS projects with an extra build configuration called “Ad Hoc” that signs with the current Ad-Hoc distribution profile. Beta Builder nicely took the [cci].ipa[/cci] (which is really just a zip file), discovered the contents and produced a handful of useful things:

  • The manifest file, that iOS 4.0 and newer can use to find the .ipa file.
  • A zip file containing the .ipa file and a copy of the distribution profile, for users that need to use iTunes to load Ad-Hoc builds.
  • A nice index.html to link to all of the above with brief instructions.

Initially I setup Beta Builder to deliver the files it built to a local directory and simply rsync‘ed the structure to my origin HTTP server. That was nice, but it involved too much clicking for my liking. Hunter had hinted that the source would appear on GitHub sometime… but again, I forgot all about it until he posted version 1.0.1 and I happened to want to distribute another build of ABC of the Sea. I was motivated. What I wanted to achieve was to be able to build an Ad-Hoc target in Xcode and then run one script to publish the package. I love this stuff. To get there, I decided I needed:

BetaBuilder HTML page for ABC of the Sea beta release

BetaBuilder generated HTML

  • My existing script that builds an .ipa from the build directory.
  • A non-interactive version of Beta Builder, driven from the command line.
  • For Beta Builder to read more keys from the projects Info.plist file, in particular, to differentiate between the application version and build number.
  • To link to the README.txt file on the HTML page that Beta Builder generates.
  • To have a more useful name for the legacy zip file it generates.
  • And then rsync the resulting files to my origin server.

I made a copy of Beta Builders source tree in a local SVN repository and hacked away (sometime I’ll create a branch and commit it back to GitHub). I won’t belabor over what I changed (diffs and such are attached) but it suffices to say that I can publish my beta releases with one command, sweet.

The scripts

Aside from my hacked version of Beta Builder, there are three shell scripts that run together.

  • /Scripts/ which knows the project and target names to use for a given project.
  • $HOME/bin/package-app that does most of the grunt work.
  • $HOME/bin/sync-iosbeta that copies my local iosbeta directory tree to the origin HTTP server.

The first of these is very simple. Its responsibility is to validate the only parameter it receives (the target configuration name, Debug, Release, Ad Hoc), ensure the build is uptodate (call xcodebuild) and then package it all up.

The real work is done in package-app. The primary function is to build a ZIP file crafted in the correct manner. This is simply a copy of the targets build directory but prefixed with Payload/ in the path. The resulting file is often suffixed with .ipa, but .zip works just as well with all the tools I have tried it with. I since tweaked the script to call my modified Beta Builder and distribute the results, and my tweaks to Beta Builder include steps to name the package as a .ipa, just in case.

This is not the cleanest of shell scripts, but it is functional:

BetaBuilder TFO

My hack to add command-line driven options to BetaBuilder simply uses getopt(3) on the argc/argv parameters in main() and if we recognize any parameters then it never calls UIApplication to fire-up the GUI. For example, output from -h:

However, running the binary directly like this doesn’t give the app access to its bundle, and that’s where the template index.html lives. That is why package-app uses open to run the program (however, this causes NSLog() output to all go to the system logs, not stderr).

Running it

And, for kicks, here’s a snippet of sample output:


All I need do now is email the mailing-list I have of beta testers to let them know build 12 is up and where to find it – and I’ll probably automate that, too!

One thought on “Automated Ad-Hoc Beta iPhone App Publishing

Comments are closed.