Using Atlassian Bamboo to build Xamarin apps

I just finished rebuilding/updating my continuous integration environment with the latest version of Atlassian Bamboo, so I thought I'd document the process for other people that may want to do the same as I had to do some research to get everything working.

Setup

Here's a diagram providing a high level overview of how my environment is setup: 

The first machine ("builder") is a Windows 8.1 machine hosting the Atlassian Bamboo web application.   This machine is not used as a build agent.  It's only job is to coordinate the builds and to store the build artifacts.

The second machine ("buildserver01") is a Mac Mini running OS X 10.9 with VMWare Fusion installed on it.  There are two separate OS X 10.9 virtual machines running on it, each with the Bamboo build agent running and a full development stack (Xamarin.iOS, Xamarin.Mac and Xamarin.Android and Xcode).  The virtual machines are used to build all of my Xamarin projects. The reason there are two virtual machines is so that I can either run builds in parallel or do builds against both the Stable and Beta (or Alpha) channel of Xamarin at any time depending on how I change the build agent settings.

The third machine ('buildserver02") is a Windows 8.1 machine with the Bamboo build agent and Visual Studio 2013 installed.  This server is used to build and test TouchDraw related web services which get deployed to a Windows Server 2012 machine.

Additionally, I have an iPad 2 running iOS 7 and a Motorola Xoom connected to one of the virtual machine instances for running automated tests natively on a device.

Bamboo Configuration

Before you can start configuring your build plans, you need define the capabilities that each of the build agents have.  Once your remote agents are up and running (or right away if you're using a local agent), you can define "executables" that are available on that agent:

As shown in the screenshot,  we need to define both the "mdtool" and "xbuild" executables.  The "mdtool" command will be used for building Xamarin.iOS and Xamarin.Mac projects, and the "xbuild" command will be used for building Xamarin.Android projects.

Building an App

In order to build a Xamarin.iOS or a Xamarin.Mac project, you can use the "mdtool" executable that configured earlier.  Essentially, you just need to tell which configuration you want to build (AdHoc|iPhone, AppStore|iPhone, Debug|iPhoneSimulator, etc...) and pass in the path of your solution:

To build a Xamarin.Android project you basically do the same thing, but with the "xbuild" executable: 

Google ChromeScreenSnapz016.png

Unit Testing

Unit Testing a Xamarin.iOS or a Xamarin.Android project is a bit more complicated as you need to do that in the simulator or on a device. This is what took me the longest time to figure out.

The key piece is to use the Touch.Server tool that is mentioned in this blog post.  It will launch unit test project on the target (simulator or real device) and save the test results in a local file.

Once you have that tool installed (I actually store it in the source code repository so it's available to every build agent I configure) you can invoke it like this from a script in your build plan:

mono --debug path/to/Touch.Server.exe \
 --launchsim path/to/project/Debug/TestProject.app \
 -autoexit \
 -logfile=test-reports/TestProject.xml

In the example above it's launching the unit test project on the iPad simulator.  You can use one of the other command line options for Touch.Server.

Bamboo can also parse the results of tests results in the  NUnit 2 XML format to display in the dashboard; however the unit test projects created by the Xamarin tools don't return XML results by default, so you'll need to modify them.

I've added the following to all of the AppDelegates and Activities for my mobile tests:

runner = new TouchRunner (window);
try
{
 runner.Writer = new NUnitOutputTextWriter (runner, new TcpTextWriter("localhost",16384), new NUnitLite.Runner.NUnit2XmlOutputWriter ());
}
catch (Exception)
{
 // Do nothing
}

The snippet above tells the runner to write it's result to a specific TCP port on localhost, and to use the NUnit2 XML format.  By wrapping in a try/catch block, I can run the same unit tests locally on my development machine, since in that case we'd get an exception when it can't connect to Touch.Server.

Lastly, you can't use the version of Touch.Server exactly as it is on GitHub right now.  You'll need to make a small modification to it in order for things to work.  The problem is that the current code adds a header to the results file, which is fine with text based results; however makes XML based tests results un-parseable by Bamboo.  The solution is to comment out lines 87-91 before you build Touch.Server to prevent it from writing a header.

Once you have that configured, you'll be able to see your test results in the Bamboo dashboard after a build:

Google ChromeScreenSnapz018.png



Pirated Apps in the App Store

I don't know if other app developers are running into this problem; however I'm increasingly having to spend time policing the iOS App Store looking for apps that infringe on my app and my intellectual property.

Earlier this year, another developer friend informed me that he noticed there were apps in the App Store using TouchDraw screenshots (or snippets of screenshots combined with screenshots other apps) to try to sell their app.  I've been dealing unsuccessfully to try to get those removed; however as of today it's been taken up another level...

This morning I received an email from what seemed like a customer asking for support for the app "Diagram Touch" that he just purchased.  I informed him that "Diagram Touch" is not an app we sell, and that he should contact the developer of that app for support.  

It's not the first time that a customer has contacted us for support for a competitors app, so I was going to be helpful and provide the link to the developers website.  When I looked up that app in the App Store though, there wasn't a link to their website or a support email address which made me suspicious.

At that point I decided I'd purchase the app (and later request a refund) to figure out why the customer thought this was our app.  What I found absolutely shocked me.  "Diagram Touch" was nothing more than a cracked (two year old) version of TouchDraw that had been repackaged with a different splash screen and different icons.  

All of the sample drawings, libraries and any resources files that referenced TouchDraw had been removed or edited; however as in that version many strings were hard coded there were still references to TouchDraw to be found in the app. 

Additionally, I would think the fact that the App Store screenshots are so different from the submitted app, that this would have triggered a closer look by the reviewer.

 Once I found this, I decided to look in the app store to see if there were any newer apps that looked fishy to me that I hadn't seen before.  I quickly found another app called "Diagram to Go" that also looked fishy because it was blatantly ripping off the icon that I use for the Android version of TouchDraw as well as using screenshots of TouchDraw sample drawings in their screenshots. 

I decided to purchase this app as well to see if it was also just repackaging a cracked older version of TouchDraw.  In this case, I found out it was a cracked and repackaged older version of OmniGraffle that had been modified in the way TouchDraw was in the other case (modified splash screens, icons and resources).  Again, like the other app, the supplied screenshots are so different from the actual app, I don't see how it couldn't have raised flags to an App reviewer.

I have filed complaints with Apple Legal; however as the 4 other apps that I found back in May using TouchDraw screenshots are still for sale in the App Store I don't have much hope for a satisfactory resolution.  

I'll post updates here as this unfolds.

Update:  As of this morning (Wednesday, July 3rd) the first app has been removed from the App Store, and the second app is only for sale in the Egyptian app store.

 

Android Device Testing

Several of my developer friends have contacted me over the past few months to ask me about which devices we test TouchDraw for Android on given that there are lots of little layout differences depending on the device you're on.  Now that it is available for non-Samsung devices (and now available globally via the Google Play store), I thought it's finally time to publicly document which devices we test and develop with.

Early on, we decided that we needed the UI to be adaptive based on the screen size, pixel density and orientation of the device so that we could try to maximize the area dedicated to the drawing canvas and deliver an app that could work well on devices with a 4" screen or bigger.  The unfortunate side effect of that decision was that we kept needing more devices as we created layouts targeting the different configuration.  While we could have used the emulator, we we felt that we couldn't get a feel for the size of the tap targets and the general usability without real physical devices.

Here's a table the outlines the final tally of devices that test, target and develop with:

LDPI MDPI HDPI XHDPI
small
normal Samsung Galaxy S2 Samsung Galaxy S3
Google Nexus 4
large Samsung Galaxy Tab 2 7.0 Google Nexus 7 (TVDPI) Samsung Galaxy Note
Samsung Galaxy Note 2
xlarge Motorola Xoom
Samsung Galaxy Note 2 10.1
Asus Transformer Infinity Google Nexus 10

As you can see, we don't support or target devices with LDPI and/or small screens; however given TouchDraws' target mareket I don't think we're excluding many potential customers. You'll also notice that we consider the Nexus 7 (even though it's an TVDPI device) to be our Large/HDPI test device, since there don't seem to be too many of these devices in the (mainstream) wild.

It may seem a bit excessive to try to target so many combinations individually; however by doing so, we were able to build the app in a way that it is (and can easily be) optimized for the device you're using it on instead of a "one size fit" all compromised UI.

The surprise for most people is that of all of the devices above, the one that we target and test on first is the Galaxy Tab 2 7.0.  We've found that because of it's resolution (1024x600) and low screen density that if we can come up with a UI paradigm that works on it, we can usually scale it up to the other devices.  Also, being the lowest powered device, it's the best way to get immediate feedback on potential performance implications of new drawing features.  With that said, the more we test with the Nexus 7, the more we find that it's the worst performer of all devices and is slowly becoming our device for performance tuning.

In addition the screen issues, I also should mention that at least for us it was important to have actual devices with different hardware accessories as well.  Specifically, we wanted test devices with styluses (which the Galaxy Note devices provide) and hardware keyboards (which the keyboard dock of the Transformer Infinity provides).

Realistically, I don't think we could have developed TouchDraw (at least with the level of polish that it has) without this many device variations to test with. 

As our stable of test devices grows and/or changes ove time I'll try to make an effort to update this for future reference, though once I finally have time to play with the Xamarin Test Cloud, we may not need many more devices.