If you are building and deploying code within Visual Studio and find its hard to scale up a team of developers, few things can alleviate your pain better than a Continuous Integration (CI) System.
Never heard of continuous integration or you don’t know if it’s right for you? Take a moment and read from the start of this article. But if you know what CI is and that Jenkins is right for you, click here to jump to the setup steps!
What is CI?
What Are the Benefits of CI?
How Do You Stand Up a CI System?
What makes Jenkins a Good/Bad CI Choice?
For this example, I simply created a project called “JenkinsTestApp” using the default MVC template that came with Visual Studio 2013. I chose to include a UnitTest project by clicking the checkbox when prompted, and I named it “UnitTests”.
If you closely follow these steps and once you have the system installed, you should have a working CI system in less than 30 minutes!
Step 1: Install Jenkins
Download and install Jenkins https://jenkins-ci.org/ on your chosen build server. By default, the URL for Jenkins is http://localhost:8080. If you need to make changes to the port number, edit c:\Program Files (x86)\Jenkins\jenkins.xml and change 8080 to your port number.
Step 2: Install Visual Studio
Install Visual Studio 2013 on your CI System.
Step 3: Setup Jenkins to Build .NET Projects
Go to http://localhost:8080 and you should see this:
Click on Manage Jenkins and you should see this:
Click on Manage Plugins, click the Available tab and search for “msbuild”. Select it to install and click the Download now and install after restart. Jenkins will restart. After 15 – 30 seconds you should be able to return to http://localhost:8080
After you are back in Jenkins, return to the Manage Jenkins screen, and this time click Configure System. On this screen, click the Add MSBuild button. After this section has expanded, you should fill in “MS Build 2013” for the Name value, and “c:\Program files (x86)\MSBuild\12.0\bin\amd64\msbuild.exe” for the Path to MSBuild value. You will get a Jenkins warning, but it’s safe to ignore. Finally, click the Save button at the bottom of the page.
Jenkins is now setup to build .NET projects!
Step 4: Setup Jenkins to work with GIT
Install GIT for Windows on your CI System https://msysgit.github.io/
As shown earlier for the MSBuild plugin, install the GIT Plugin in Jenkins.
To configure the GIT plugin, go into the Configure System screen again, and fill in the GIT section by setting “Default” as the Name value, and “c:\Program files (x86)\Git\cmd\git.exe” as the Path to Git executable value as shown:
Now Jenkins is setup to work with GIT!
Step 5: Create a New Build and Have Source Code Cloned from GIT
Go to the homepage of Jenkins or go to http://localhost:8080 and click New Item type in “Jenkins Test App” for the Item Name, choose “Freestyle project” and click OK.
Next, scroll down to the Source Code Management section, and choose GIT. Set your Repository URL. For my example, I set a path to a local repository, but yours could be a URL to GitHub, Stash, or something else.
For right now, click Save, and go out to the Dashboard of the Jenkins Test App project. Click Build Now. If you are fast enough, you will see that a new build will show up in the Build History, and you can click on the progress bar to show the Console output to see what Jenkins is doing in real time. Otherwise you can always click on a past build, and then click Console to see what tasks Jenkins actually performed.
For this step, all we wanted Jenkins to do was to pull our source code from the Git repository. Next, we’ll have Jenkins do some real work.
Step 6: Modify Jenkins to Build the .NET Project
Go back to the Jenkins Test App Dashboard, click Configure and scroll down to the Build section. Click Add Build Step and choose Build a Visual Studio project or solution using MSBuild. For the MSBuild Build File, choose your solution file, for this example, I’m using “JenkinsTestApp.sln”.
You can always verify the solution name and path by viewing the Workspace of the Jenkins project.
Click Save, then click Build. Open the Console. Notice that after Jenkins has cloned the GIT repository, it has build the .NET solution using msbuild.
Step 7: Modify Jenkins to Run Unit Tests
Go back to the Jenkins Test App Dashboard and click Configure and scroll down to the Build section. Click Add Build Step and choose Execute Windows batch command and enter the following text to run the unit tests. These commands will also clean-up the results from previous unit test runs.
if exist "%WORKSPACE%\TestResults.trx" (
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\mstest.exe" /resultsfile:"%WORKSPACE%\TestResults.trx" /testcontainer:"%WORKSPACE%\UnitTests\bin\Debug\UnitTests.dll" /nologo
Again, if you are confused on the path of your unit test project, check the Project Workspace.
Next, scroll down to the Post-build Actions and click the Add post-build action button and choose Publish MSTest test results report. Enter the file name “TestResults.trx”.
After this, click Save, then click Build. Open the Console. Notice that after Jenkins has cloned the GIT repository and build the .NET solution using msbuild, it will run any unit tests using mstest.exe.
Notice that I have a broken unit test and it will show on the individual build page when a build breaks.
If you click the Latest Test Results, you will see the details of the failure:
Step 8: Add a GIT Trigger to Start a Build on Jenkins Every Time Code is Pushed
While you could keep pushing the Build button every time you commit code, you would have to remember to do that and it’s certainly NOT continuously integrating! Now is time to change this.
You could have Jenkins poll your GIT repository for changes, but it’s much cleaner if you do pushes. To do this, we’ll install a GIT Hook.
Locate the project’s GIT repository hooks folder:
Inside it, create a file called “post-receive”. Inside that file, paste the following code:
# Remember to point this to the correct url and port number!
#watch spaces in Jenkins Project Names, they will need to be url encoded to %20
echo "Triggering Build on Jenkins server $JenkinsUrl"
It should look like this when you are done (Note: I changed my port to 8088 as I have a conflict on port 8080):
To test this, modify one of your code files by adding a space to the end of a line, just to create a change. Then commit this change and push it to your remote repository. If you are using a command line GIT client, you will see the following:
On Jenkins, you’ll also see that the build was started by an anonymous user:
Now, every code change that is committed and pushed is built and tested on Jenkins. The only thing left to do is to deploy our binaries.
Step 9: Modify Jenkins to Build Web Packages and Deploy Them to the IIS Server
Go back to the Jenkins Test App Dashboard and click Configure and scroll down to the Build section. Click Add Build Step and choose Execute Windows batch command and enter the following text to create the web packages:
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe" "JenkinsTestApp\JenkinsTestApp.csproj" /T:Build;Package /p:Configuration=DEBUG /p:OutputPath="obj\DEBUG" /p:DeployIisAppPath="/Default Web Site/JenkinsTestApp" /p:VisualStudioVersion=11.0
Make sure to change the DeployIisAppPath to the actual IIS deploy path for your application.
Do this step one more time, but this time paste the following text to deploy the web packages:
"C:\Program Files (x86)\IIS\Microsoft Web Deploy\msdeploy.exe" -verb:sync -source:package="JenkinsTestApp\obj\Debug\_PublishedWebsites\JenkinsTestApp_Package\JenkinsTestApp.zip" -dest:auto,computerName=localhost -allowUntrusted=true
Make sure to change the above computerName value to the actual IIS computer name that you want your web packages to be deployed to.
Click Save. Now click the Build button. Take a look at the Console, and you will see your application being packaged and then deployed to your local IIS’s Virtual Directory of JenkinsTestApp.
This is what the deployed app looks like:
Congrats! You now have a working CI system that will help you catch bugs early, release features sooner, and enable you get back to coding!