Maven Native Chronicles, Part 2: Setting Up a Windows Jenkins Node
Jul 26, 2015, 11:16 AM
- Maven Native Chronicles, Part 1: Figuring Out nar-maven-plugin
- Maven Native Chronicles, Part 2: Setting Up a Windows Jenkins Node
- Maven Native Chronicles, Part 3: Improving Native Artifact Handling
- Maven Native Chronicles: Running Automated Notes-based Tests
Before I get to the meat of this post, I want to point out that Ulrich Krause wrote a post on a similar topic today and you should read it.
The build process I've been working with involves a Jenkins server running on OS X (in order to build iOS binaries), and so it will be useful to have a Windows instance set up as well to run native builds and, importantly, tests. Jenkins comes with support for distributed builds and makes it relatively straightforward.
To start with, I installed VirtualBox and went through the usual Windows setup process - it shouldn't matter too much which major version of Windows you use, as long as it's 64-bit, in order to be able to generate and test both types of binaries. Once that was running, I installed the latest 64-bit JDK followed by Visual Studio Community, which is a pretty smooth process (for all their faults, Microsoft knows how to treat developers). To provide access to the VM from the Mac host, I added a second network adapter to the VM and set it to host-only networking:
During this process, I found Jump Desktop to be a very useful tool. Since the Mac host runs SSH, I was able to set up an RDP connection to the Windows VM using an SSH tunnel, which Jump does transparently for you. This made for a much better experiencing than VNCing into the Mac and controlling Windows in the VirtualBox window in there.
Next, I decided that the route I wanted to take to control the Windows slave was SSH, since SSH is the bee's knees. I installed Cygwin, which creates a fairly Unix-like environment on top of Windows, and included OpenSSH in the process. After going through the afore-linked setup process, I had SSH access to the Windows machine (including, thanks to SSH proxying, remote access via the primary build server). On the Jenkins side on the Mac, I installed the "Cygpath plugin" (which is in the built-in plugin manager) to avoid any of the issues mentioned on the wiki page. The configuration in Jenkins is relatively straightforward (I will probably end up changing the base directory to be a clean Jenkins home, since I hadn't initially been sure if I needed Jenkins installed on the slave):
With that, I was able to set the build to run on servers with the "windows" label, kick it off, and start going through its complaints until I had it working.
First off, I had some more Java setup to do, specifically creating a system environment variable named
JAVA_HOME and setting it to the root of the JDK ("C:\Program Files\Java\jdk1.8.0_51" in this case). Then, I set up Maven, which is something of an awkward process on Windows, but not TOO bad. I downloaded the latest binaries, unzipped them to "C:\Program Files\maven", added an environment variable of
M2_HOME to point to that:
I also added
%M2_HOME%\bin;C:\Program Files (x86)\MSBuild\12.0\Bin to the end of the
PATH variable, to cover both the Maven tools and the
msbuild executable for later.
I ran into a bit of weirdness when it came to setting up configuration for SSH and Maven, specifically because it seems that Cygwin has two home folders for the logged-in user: the Unix-style
/home/jesse and the normal Windows
C:\Users\jesse (which is available in Cygwin as
/cygdrive/c/Users/jesse). Since this Jenkins build checks out the code from GitHub via SSH, I needed to copy over the
id_rsa file for the Jenkins user: this went into
/home/jesse/.ssh/id_rsa. In order to configure Maven, though, the settings file went to
Eventually, it slogged its way through the build to completion, including a successful run of the integration tests. I still need to figure out the best way to get the resultant artifacts back out (or maybe it will be best to just deploy from both to the same Artifactory server), but this seems to do the main task for me.