Deployment
With all those scripts behind us, we should get a signed IPA in our OUTPUTDIR. From here on, we can use this IPA and distribute it to our testers. A few options are to either upload our IPA with curl to a custom FTP Directory or our XCode Server or some other custom routine. For this example we stay “simple” and upload our App to HockeyApp via curl.
HockeyApp
HockeyApp is a similar service to TestFlight which offers many options to distribute and test your apps. They offer their own SDK which enables automatic crash reports, analytics and feedback functions in addition to have different user groups for our beta/production builds.
To use HockeyApp, we have to add HOCKEY_APP_ID and HOCKEY_APP_TOKEN to Travis’s global env variables. You can find Hockey’s App ID on your overview page and you can create your Hockey App Token on your settings page. You should add both variables through the travis gem again, to have those encrypted.
florian$: travis encrypt "HOCKEY_APP_ID=APP_ID"
florian$: travis encrypt "HOCKEY_APP_TOKEN=APP_TOKEN"
Add the encrypted variables to your .travis.yml, we need them in our curl command to upload our IPAs to HockeyApp.
The next step and final step is to add one last bash script ipa-upload.sh. Create a bash script next to your other Travis Scripts with the following content:
# file: $SCRIPT_FOLDER/ipa-upload.sh
#!/bin/sh
if [[ "$TRAVIS_PULL_REQUEST" != "false" ]]; then
echo "This is a pull request. No deployment will be done."
exit 0
fi
if [[ "$TRAVIS_BRANCH" != "master" ]]; then
echo "Testing on a branch other than master. No deployment will be done."
exit 0
fi
OUTPUTDIR="$PWD/build/TravisCI-Release-iphoneos"
RELEASE_DATE=`date '+%Y-%m-%d %H:%M:%S'`
RELEASE_NOTES="Build: $TRAVIS_BUILD_NUMBER Uploaded: $RELEASE_DATE"
if [ ! -z "$HOCKEY_APP_ID" ] && [ ! -z "$HOCKEY_APP_TOKEN" ]; then
if [ "$TRAVIS_TAG" == "" ] && [ "$TRAVIS_BRANCH" == "master" ]; then
echo ""
echo "***************************"
echo "* Uploading to Hockeyapp *"
echo "***************************"
curl https://rink.hockeyapp.net/api/2/apps/$HOCKEY_APP_ID/app_versions \
-F status="2" \
-F notify="0" \
-F notes="$RELEASE_NOTES" \
-F notes_type="0" \
-F tags="beta" \
-F ipa="@$OUTPUTDIR/$APP_NAME.ipa" \
-F dsym="@$OUTPUTDIR/$APP_NAME.app.dSYM.zip" \
-H "X-HockeyAppToken: $HOCKEY_APP_TOKEN"
fi
if [[ "$TRAVIS_TAG" == "production" ]]; then
echo ""
echo "***************************"
echo "* Uploading to Hockeyapp *"
echo "***************************"
curl https://rink.hockeyapp.net/api/2/apps/$HOCKEY_APP_ID/app_versions \
-F status="2" \
-F notify="0" \
-F notes="$RELEASE_NOTES" \
-F notes_type="0" \
-F tags="production" \
-F ipa="@$OUTPUTDIR/$APP_NAME.ipa" \
-F dsym="@$OUTPUTDIR/$APP_NAME.app.dSYM.zip" \
-H "X-HockeyAppToken: $HOCKEY_APP_TOKEN"
fi
fi
Put it in place in the ‘after_success:’ build phase after your ‘ipa-signing.sh’ script.
Be sure to check out the IF conditions within the ipa-signing.sh script. They are currently setup to tag releases in HockeyApp differently according to their git tag. The idea behind this is simply to have two different groups of users in HockeyApp. One group for beta users and one group for production users, just add tags to your users on HockeyApp so they get access to the corresponding releases. ‘Beta’ and ‘Production’ for your super users which should get access to both release types and ‘Production’ only for those who should be able to get the production release. Now all you need to do is to submit your give a specific commit the ‘production’ tag to make it a production release on HockeyApp.
Troubleshooting
At this point of our tutorial it’s quite likely that you ran into at least one problem as you don’t have an interactive shell to test your commands. When writing this tutorial this happened to me quite often so my GIT History ended up being a mess especially as you can’t always use pull requests to test your changes.
A great option to test changes would be a Virtual Machine which holds the same environment as the one Travis CI does, unfortunately that’s not an option as Travis doesn’t provide their configuration in a format such as a Vagrant script. So the only remaining possible option to test your scrips are actually local tests in your local terminal.
If that doesn’t help, it’s always an option to use ‘echo’ and ‘set -x’ to print your variables to your Travis CI build log.
It’s quite unfortunate that there’s no other option, but that’s probably an action from Travis’s side to protect their property. If you ever happen to run into serious problems or something you can’t reproduce, the Travis Support is normally reacting on a pretty fast basis trying to help where they can. They’re also more than happy to provide you with a debug VM on their servers for tough problems if you’re a paying customer.
A step further
With all these options and great tweaks outlined, there’s still plenty of room for other extensions. Travis CI offers a bunch of custom which I encourage you to test them. One of my favorite extensions are actually Travis’s notification options. You can easily integrate your favorite chat clients to announce a new version on channels such as IRC, Campfire or Slack. Or another option to extend your scripts are custom webhooks which are supported by Travis to even go a step further than a simple notification.
In addition to those extensions on Travis’s side, there are similar projects such as coverall.io which measures your test coverage history and statistics through their integration with your CI server. These are all ways that help to manage your code and to give you a better insight.
Summary
Automated building, testing and deployment more popular every day and is a great way for many developers to ensure their software still builds against different systems. Many open source projects started to adopt that years ago and you might already have seen buttons such as the well known build: success button.
Travis CI makes standard setups a lot easier than other products such as Jenkins where the work of maintaining a server is added on top of your configuration. Therefore I encourage you to try Travis CI as it’s free for public repositories without having to maintain your own copy of XCode on your private server.
I have setup a special repository here which holds all the code covered in this tutorial, check the releases tab to find different versions of what we covered here. It’s setup to work with subfolder and both options on where to store your certificates. Just set the bash variables at the begging of the .travis.yml file according to your structure and check filenames to match your certificates and you should be up and running in no time!
Go ahead and start using Continuous Integration! It’s a fun ride and a good workflow to work with.