This is a simple plugin for Hudson CI that wraps and provides limited functionality for agvtool and xcodebuild to version and build XCode-based iOS projects. The plugin is mature enough to support building, versioning, IPA packaging and basic testing view OCUnit.
This builder can invoke agvtoool to dynamically update the CFBundleVersion with the current build number prefixed with the current marketing version (as defined by CFBundleShortVersionString) to produce a version number of the form CFBundleShortVersionString.BUILD_NUMBER (e.g. 1.0.456)
The target (optional), configuration (e.g. Debug, Release) and SDK (optional) can be specified in the per-project config along with whether to perform a clean before the build phase.
The builder can be used to package the .app into a .ipa. Since a .app is actually a directory, it can be awkward to work with and, especially, distribute. We can simplify this by packaging the .app into a single .ipa file, which is just a zip file with a well-known internal structure
This plugin will listen to the xcodebuild output when running OCUnit tests and write out JUnit-format test reports that Hudson can understand. Hudson will then use these to publish test failure reports and graphs.
Gotchas & Limitations
- Obviously, the build machine has to be an OSX machine with XCode developer tools installed
- Certificates, Identities and Provisions must be installed on the build machine separately
- When code-signing, a prompt may appear on the build machine asking whether to allow keychain access. This will block the build until it is dismissed. Just select ‘Always Allow’ the first time and it shouldn’t need to ask again.
- If you connect via ssh to the OSX slave, you will need to execute ‘security unlock-keychain’ once you connect to allow the build tools access to the keychain. The alternative is to use the JNLP slave agent
- Make sure you define the CFBundleShortVersionString in your Info.plist. This will be used as the marketing version and will be prepended to the build number when using agvtool
- Derek Stutsman reports that “If your project has the base SDK set to iPhone simulator, the build will crash with a nullreference exception”
This is a maven project that uses the hudson maven plugin. You will first need to add the following to your ~/.m2/settings.xml:
1 2 3 4 5
To clone the repository and build the .hpi, follow these steps:
1 2 3 4 5 6 7 8
The xcode.hpi will be in the target/ directory.
I am awaiting commit access to the hudson repository on java.net so that I can use the official hudson to build the plugin as well as hosting the plugin in the official repository. Until then, you will have to install it by manually uploading the xcode.hpi to hudson. Simply go to ‘Manage Hudson’ > ‘Manage Plugins’ > ‘Advanced’ > ‘Upload Plugin’ and select the xcode.hpi that you either built or downloaded and then select ‘Upload’.
Setting up a build step
Add the XCode build step to a free-style project and set the target (e.g. MyApp), configuration (e.g. Release) and check the build IPA and update version number options. This will give you a single, versioned .ipa file. You can also select to clean the project before a build; while this will make sure that the project is starting from a clean state, it will make large projects take a lot longer.
Setting up a unit test step
Add the XCode build step and this time specify your unit test target (e.g. MyAppTests), configuration (e.g. Debug) and the SDK (e.g. Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.1.sdk/). Leave all the checkboxes unselected. The SDK needs to be supplied here as the unit tests will only be run when building under the simulator’s SDK.
Check the “Publish JUnit test result report” option in the project config and set the value “/test-reports/.xml” under “Test report XMLs”. This will tell Hudson to pick up the JUnit-format test reports.
The source code is hosted on GitHub and made available under the GPLv2 license.
You can download the latest issue tracker.
The xcodebuild/OCUnit output parsing was inspired and based upon Christian Hedin’s ocunit2junit.rb script.