limkopi ☕️

security | dev | finance | life

github instagram
Jenkins + Windows Slave + MSBuild
Mar 10, 2019
7 minutes read

We have a problem in building, testing and deploying our prototypes. It’s getting more apparent that we need an automated process to make ourselves more efficient and productive.

My interns have been helping us to build this last year. They did a really awesome job. Unfotunately, this has never been taken off well because there is no permanent role that owns and mandates this entire process. So… I decided to take up the DevOps role temporarily. While my workload will increase tremendously, I kind of think that this is a good chance for me to learn more about automated pipelines. Most importantly, we really need a push to make our prototypes even better.

Background

So anyway, we are using Visual C++ and Standard C/C++ for our prototypes. We need an automated pipeline to build our prototypes for different architectures and run tests on different operating systems.

My intern had already explored the possibility of setting up Windows slave with Jenkins to build, run and tests Standard C++ projects. What we are really missing from the pipeline is the ability to automate the process for Visual C++ projects and that’s the major problem that we need to solve immediately.

Jenkins + Blue Ocean

Jenkins is an open-source automation server. It has multiple plugins that can support automated building, testing and deploying of any projects. Blue Ocean is a plugin developed by the Jenkins team to support the creation of continuous delivery (CD) pipelines. We need them to start building our automated process.

As usual, we use Docker.

docker run --name jenkins \
-p 8080:8080 \
-p 50000:50000 \
-v jenkins-data:/var/jenkins_home \
jenkinsci/blueocean

Once you have everything started, you will be greeted with this screen when you navigate to localhost:8080 (or whichever you have chosen to be your web port).

Unlocking Jenkins with password shown on your docker logs

In the next few screens, you will need to install the plugins to support your projects. Minimally, we will need to install Pipeline, Pipeline Stage View, SSH, SSH Slaves, SSH agents and Git to support our purpose.

Some of the plugins that I have installed

Once everything is done, you will be brought to the homepage. Tada! That’s all you need to do for Jenkins!

Setting up a Windows Slave

Before we can start creating our pipeline, we need a Windows slave (duh). I will running Windows 2008 Server x64 using VMWare. The setup process should be same for other Windows versions.

There are three methods that you can communicate to a slave:

1. Java 
2. SSH
3. WMI

My personal preference is SSH so this tutorial will be based on SSH. If you prefer Java or WMI, you will need to Google for the tutorials.

Pre-Requisite

In our Windows slave, we need to install the following software:

  1. OpenSSH for Windows to communicate with Jenkins Master
  2. Tools for Visual Studio 2017 to build Visual C++ projects in Windows slave
  3. .NET Framework 4.6 to build Visual C++ projects in Windows slave
  4. Git for Windows to clone projects in Windows slave
  5. > JDK 8 to run Jenkins jar failes

We will also need our Windows slave can communicate with Jenkins. You can verify by checking if you can access Jenkins using your host machine’s IP address at port 8080 in the Windows slave.

OpenSSH

1. Extract OpenSSH to C:\\Program Files\\OpenSSH
2. Install the service using powershell (powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1)

By default, the service will not start automatically after restart. Go to Start > Services and manually enable the auto-start services for OpenSSH Server and OpenSSH Authentication Agent.

Access your Windows Slave via SSH from Jenkins for the first time to create the known_hosts file. This step is mandatory. On your host machine:

If you have issues accessing via SSH, chances are your firewall is blocking the connection. Add rules to ensure that SSH port is accessible from other machines.

Tools for Visual Studio 2017

Run the installer in your Windows slave and select all the necessary packages for your project. The vs_buildtool installer is also great in creating offline packages. I have to research on this matter because our server is not connected to the Internet.

In case you are in the same situation, you will need to download all the necessary packages using the Internet-connected machine. Then, you need to use the following command to create an offline package in C:\VS_Offline:

vs_BuildTools.exe --layout c:\VS_Offline --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Workload.VCTools --lang en-US

Take the package to the offline machine and manually install every certificate in ./certificates folder. After that you should be able to install all the packages using vs_build.tools.exe provided in the package folder.

Jenkins Configuration

Once you are ready, you can return to Jenkins Homepage to configure your Windows slave. Click Manage Jenkins:

Scroll down the page and click on Manage Nodes

Click on New Node on the sidebar

Then give your slave a name and select “Permanent Agent”. You will be brought to the page to configure the Windows slave. Take time to understand the configuration as they are very crucial to the success of the setup.

Once you are done, you will be brought back to the page to manage the nodes. Click on your newly created nodes and click “Launch agent”.

If you see the following error:

This means that you have not attempted to access your Windows slave from Jenkins. Otherwise, you should be able to see the similar output like this:

Congratulations, you have successfully setup your Windows slave!

Setting up Your First Jenkinsfile

Now, we need to create pipeline to tell Jenkins the actions that we need to take to build, test and deploy our products. I’m going to download and upload the sample VC2017 project created by Microsoft to my private Bitbucket repository for the purpose of this article.

First, create a new Jenkinsfile in the sample project.

Next, add the following content to the file:

pipeline {
agent { node {label 'tests'} }
  stages {
    stage('Build') {
      steps {
        echo 'Building..'
      }
    }
    stage('Test') {
      steps {
        echo 'Testing..'
      }
    }
    stage('Deploy') {
      steps {
        echo 'Deploying....'
      }
    }
  }
}

If you have labeled your Windows slave using a different string, you should change the label accordingly in the Jenkinsfile. In this Jenkinsfile, we told Jenkins that the pipeline will deploy to nodes that are labeled as “tests”. There are three stage (Build, Test, Deploy). In each stage, we will output the respective actions.

Make sure your Jenkinsfile is pushed to the repository. And now you are ready to create the pipeline.

Creating Your First Jenkins Pipeline

Access Blue Ocean via http://localhost:8080/blue. Follow the instruction to create pipeline with your Bitbucket server (or Git server). Once you create the pipeline, Jenkins will automatically run the pipeline for the first time.

It will be colored green if your pipeline has executed successfully. Otherwise it will be appeared in red color.

The stages are exactly the ones that you have defined in the Jenkinsfile in the previous section.o You can always customise to your project requirements. If you return to your Windows slave, you can see the checked out files appearing in the “Remote Directory” that you have configured previously. For my case, I can find them in C:\Jenkins.

Now, let’s try to build our project and run it in our Windows slave.

Modify Jenkinsfile to add the following two new lines:

pipeline {
agent { node {label 'tests'} }
  stages {
    stage('Build') {
      steps {
        echo 'Building..'
        bat "\"C:\\Program files (x86)\\Microsoft visual studio\\2017\\Buildtools\\msbuild\\15.0\\bin\\msbuild.exe\""
      }
    }
    stage('Test') {
      steps {
        echo 'Testing..'
        bat "\"C:\\Jenkins\\workspace\\vcsamples_master\\Outputs\\Win32\\Debug\\ConsoleApplication1.exe\""
      }
    }
    stage('Deploy') {
      steps {
        echo 'Deploying....'
      }
    }
  }
}

We will use MSBuild (provided by Tools for Visual Studio) to build our solution with default configuration during our “Build” stage and run the executable during the “Test” stage. Commit the new file and re-run the pipeline.

You can directly view the build logs when you expand the steps on Jenkins. This is really useful to find out what might have gone wrong is the execution is unsuccessful.

If you click on “Test” stage, you can also view the output of running the application. Unfortunately, this sample project does not print out any output. Hence, it is an empty log.

Conclusion

That’s it!

I am planning to run multiple Windows slaves to cover different operating systems and architectures. Most likely, I will need to label the slaves by their architectures and create some batch files to run the correct executables.


Back to posts