Very lately I have worked on setting up some continuous integration (CI) using MSbuild for my C# project. In this blog series I will explain to you how to set up continuous integration.
First of all we will start with creating a MSBuild script which will compile our code. We will also create a small batch file for easy executing the MSbuild script.
When that is in place, we will add several targets to the build script to run for example unit tests, integration tests, code coverage, packaging etc.
So we will take the agile approach and improve our build process based on validated learning.
First of all we need some basic knowledge about MSbuild. I think there are enough pages around on the web which will give you a basic introduction. A good starting point would be the MSDN documentation for MSBuild.
Let’s consider we have the following project structure within our Git repository / local file system.
- src (contains our source code)
- lib (contains build output, and third party libs not available on nuget)
- reports (contains code coverage reports, test scenarios and test results)
- ci.msbuild (your msbuildfile)
- ci.msbuild.cmd (your batch file to execute the build on your local machine)
ci.msbuild
In this first version of our build file we only have one target (Compile). This target will build our projects. We do not use the solution file because someone can disable items from the build in the solution configuration. By using the projects explicitly we are sure all necessary projects will be build. We also have a PropertyGroup to define some variables.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="Compile">
<PropertyGroup>
<Configuration>Debug</Configuration>
<Platform>AnyCPU</Platform>
<DefineSolutionProperties>false</DefineSolutionProperties>
<RootPath>$(MSBuildProjectDirectory)</RootPath>
<SrcPath>$(RootPath)\src</SrcPath>
<ReportsPath>$(RootPath)\reports</ReportsPath>
<ToolsPath>$(RootPath)\tools</ToolsPath>
<Packages>$(SrcPath)\packages</Packages>
</PropertyGroup>
<Target Name="Compile">
<Message Importance="high" Text="Compiling projects"/>
<MSBuild Projects="$(SrcPath)\MyProject.Core\MyProject.Core.csproj"
Properties="Configuration=$(Configuration);Platform=$(Platform)" />
<MSBuild Projects="$(SrcPath)\MyProject.Web\MyProject.Web.csproj;$(SrcPath)\MyProject.Win\MyProject.Win.csproj"
Properties="Configuration=$(Configuration);Platform=$(Platform)"
BuildInParallel="true" />
</Target>
</Project>
</noscript>
ci.msbuild.cmd
Using following batch file we can easy execute the build script and providing a Configuration for the build.
@echo off
setlocal
set msbuild="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe"
set /p configChoice=Choose your build configuration (Debug = d, Release = r? (d, r)
if /i "%configChoice:~,1%" EQU "D" set config=Debug
if /i "%configChoice:~,1%" EQU "R" set config=Release
%msbuild% _ci.msbuild /nologo /m /v:m /t:Compile /p:Configuration=%config%
pause
endlocal
As you can see we use msbuild.exe and passing our ci.msbuild file as an argument. The /nologo parameter removes some msbuild header texts from the console output. The /m parameter enables parallel build based on the processors available in your machine. The /v:m parameter sets the verbosity to minimal so not everything gets outputted to the console. The /t:Compile parameter tells msbuild.exe to execute the Compile target from our build file and the /p:Configuration=%config% parameter injects our build configuration (Debug/Release) into the build.
When we would skip the /p parameter the default Configuration will be Debug as defined in the PropertyGroup of our build script. When we skip the /t parameter the default target Compile will be executed as defined in our msbuild file.
So for now you are able to build your projects using a simple batch file. In the next part of this blog I will describe adding a LoadNuGetPackages target which will download all the Nuget packages based on your package configs. At least most of us are using Nuget today. We will also be adding a Clean target which will clean our directories before we will compile again, so we won’t get stuck with possible old assemblies from earlier compiles. Please share this article with your friends and please be curious for the next part of this series .
The post CI with Jenkins, MSBuild, Nuget and Git part 1 appeared first on Marco Franssen.