{"id":2113,"date":"2016-01-08T10:23:52","date_gmt":"2016-01-08T10:23:51","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=2113"},"modified":"2025-06-13T15:56:24","modified_gmt":"2025-06-13T22:56:24","slug":"continuous-deployment-with-jenkins-and-net","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/","title":{"rendered":"Continuous Deployment with Jenkins &amp; .NET"},"content":{"rendered":"<p>This is the first blog post of two about Jenkins and Couchbase. This first post is a general introduction to Continuous Deployment: <span style=\"font-weight: 400\">you\u2019re going to learn to use<\/span> Jenkins to deploy a .NET application automatically. The second blog post will be focusing more on how to use Jenkins to set-up test data in Couchbase before running your test code.<\/p>\n<p>As a .NET developer you are probably using Visual Studio. Hitting F5 in Visual Studio compiles the source code and starts the debugger. If you are like me you will hit F5 many times during development and bug hunting.<\/p>\n<p>But what happens when the code is ready for prime time? Deployment happens!<\/p>\n<p>When I need to publish an application I often choose the laziest option: manually copying the executable to the destination, manually installing and manually starting the application.<\/p>\n<p>It\u2019s \u201cfun\u201d the first few times, but in the end it gets really difficult; particularly keeping track of changes and manual updates\/deployments. To be honest, this manual approach does not scale very well: it takes unnecessary time and it\u2019s prone to human errors in the deployment process.<\/p>\n<p>A more mature option would be to have an automated infrastructure to handle deployment. Such infrastructure is often referred to as Continuous Integration\/ Continuous Deployment.<\/p>\n<p>Using Continuous Integration\/Continuous Deployment, enables a workflow like this:<\/p>\n<ul>\n<li>Code, build and test locally on your dev. box (as usual)<\/li>\n<li>Check source code into a development branch in your favourite Source Control Management System.<\/li>\n<li>Optional code review by team members.<\/li>\n<li>Merge your changes to the main (release) branch.<\/li>\n<li>The CI Server will detect the changes to the main branch and download, compile and deploy\/install your application on the release server.<\/li>\n<\/ul>\n<p>There are no manual steps: it\u2019s all scripted and automatic.<\/p>\n<h2 id=\"toc_3\">Continuous Deployment<\/h2>\n<p>You can choose from a number of Continuous Integration\/Deployment (CI) tools, each with its own caveats. In my set-up I need a CI Server that understands the components in my application.<\/p>\n<p>So let\u2019s take a closer look at my application architecture and components:<\/p>\n<ul>\n<li><strong>Platform<\/strong>: .NET 4.5.2<\/li>\n<li><strong>IDE<\/strong>: Visual Studio 2015 (MSBuild files)<\/li>\n<li><strong>Application type<\/strong>: Windows Service<\/li>\n<li><strong>NuGet<\/strong>: Package Manager used for all references.<\/li>\n<li><strong>Source Control<\/strong>: Git (github.com)<\/li>\n<\/ul>\n<p>The CI Server should be able to understand all components mentioned above and (as I\u2019m lazy) it should be really easy to maintain and set up.<\/p>\n<p>I did a bit of research and from other people&#8217;s experiences and blog posts I found it best to use Jenkins <span style=\"font-weight: 400\">to deploy a Windows service<\/span>.<\/p>\n<h3 id=\"toc_4\">Jenkins<\/h3>\n<p>Jenkins is a build server with a plugin architecture that allows the community to extend what Jenkins can \u201cunderstand\u201d. This architecture makes it easy to extend Jenkins to support MSBuild files, Git version control etc.<\/p>\n<p><a href=\"https:\/\/wiki.jenkins-ci.org\/display\/JENKINS\/Meet+Jenkins\">Meet Jenkins<\/a><\/p>\n<h3 id=\"toc_5\">Set-up<\/h3>\n<p>Jenkins is installed on a build server. In my set-up the build server is the same as the release server, but this can be configured differently.<\/p>\n<p><em>Download and install<\/em> Jenkins for your platform here: https:\/\/jenkins-ci.org\/<\/p>\n<p>After installation Jenkins is available on its default port: <a href=\"https:\/\/localhost:8080\/\">https:\/\/localhost:8080\/<\/a><\/p>\n<h3 id=\"toc_6\">Configure Jenkins<\/h3>\n<p>Jenkins has plugins for understanding Git repositories, MSBuild files and various other technologies. In the current set-up we only need to extend Jenkins with those two plugins.<\/p>\n<h4 id=\"toc_7\">Install the Git Plugin for Jenkins:<\/h4>\n<ol>\n<li>Open Jenkins, <a href=\"https:\/\/localhost:8080\/\">https:\/\/localhost:8080\/<\/a><\/li>\n<li>Navigate to &#8220;Manage Jenkins&#8221;<\/li>\n<li>Navigate to &#8220;Manage Plugins&#8221;<em>Direct link: <a href=\"https:\/\/localhost:8080\/pluginManager\">https:\/\/localhost:8080\/pluginManager<\/a><\/em><\/li>\n<li>Use the &#8220;filter&#8221; box to search for &#8220;Git plugin&#8221; and install the plugin.<\/li>\n<\/ol>\n<h4 id=\"toc_8\">Install the MSBuild Plugin for Jenkins:<\/h4>\n<ol>\n<li>Open Jenkins, <a href=\"https:\/\/localhost:8080\/\">https:\/\/localhost:8080\/<\/a><\/li>\n<li>Navigate to &#8220;Manage Jenkins&#8221;<\/li>\n<li>Navigate to &#8220;Manage Plugins&#8221;<em>Direct link: <a href=\"https:\/\/localhost:8080\/pluginManager\">https:\/\/localhost:8080\/pluginManager<\/a><\/em><\/li>\n<li>Use the &#8220;filter&#8221; box to search for &#8220;MSBUILD plugin&#8221; and install the plugin.<img decoding=\"async\" src=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-04%20at%2014.34.30.png\" alt=\"plugin screen\" \/>Jenkins now understands MSBuild files and Git source control, but we still need to configure the MSBuild Plugin with a path to the <code>msbuild.exe<\/code> we would like to use.<\/li>\n<\/ol>\n<h4 id=\"toc_9\">MSBuild configuration<\/h4>\n<p>When the MSBuild plugin was installed it added its own configuration options to the Jenkins global configuration page.<\/p>\n<ol>\n<li>Navigate to <a href=\"https:\/\/localhost:8080\/\">https:\/\/localhost:8080\/<\/a><\/li>\n<li>Click &#8220;Manage Jenkins&#8221;<\/li>\n<li>Click &#8220;Configure System&#8221;<\/li>\n<li>Scroll down the list until you find &#8220;MSBuild&#8221;<\/li>\n<li>Click the &#8220;MSBuild installations&#8230;&#8221; button<\/li>\n<li>Click \u201cAdd MSBuild\u201d<\/li>\n<li>Give the new MSBuild configuration a name like &#8220;MSBuild-default&#8221;.<\/li>\n<li>In the path field, insert the fully qualified path to <code>msbuild.exe<\/code>On my server the path is: <code>C:Program Files (x86)MSBuild14.0Binmsbuild.exe<\/code>, but this can be different on your system.Read below for more information about MSBuild and how to install it.<\/li>\n<li>Click save.<\/li>\n<\/ol>\n<p><img decoding=\"async\" src=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-05%20at%2013.49.47.png\" alt=\"plugin screen\" \/><\/p>\n<h4 id=\"toc_10\">MSBuild installation<\/h4>\n<p>MSBuild is installed with Visual Studio, it\u2019s the build system that Visual Studio uses when you select &#8220;build&#8221; or hit &#8220;F5&#8221;.<\/p>\n<p>It\u2019s not always feasible or even possible to install Visual Studio on your build machine. This could be due to license and security issues etc.<\/p>\n<p>To accommodate this Microsoft has released a separate package called: &#8220;Microsoft Build Tools 2015&#8221; that contains all you need for using MSBuild.<\/p>\n<p><em>Direct download: <a href=\"https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=48159\">https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=48159<\/a><\/em><\/p>\n<p>After successful installation you have MSBuild available on the build server and with that you get the path value for step 8, above.<\/p>\n<p>With this step done Jenkins is ready to build and deploy with MSBuild and Git.<\/p>\n<h3 id=\"toc_11\">Create a new Jenkins build project<\/h3>\n<p>It\u2019s now time to point Jenkins to the source code and start building.<\/p>\n<ol>\n<li>Open Jenkins, <a href=\"https:\/\/localhost:8080\/\">https:\/\/localhost:8080\/<\/a><\/li>\n<li>Select &#8220;new&#8221;.Direct link <a href=\"https:\/\/localhost:8080\/view\/All\/newJob\">https:\/\/localhost:8080\/view\/All\/newJob<\/a><\/li>\n<li>Give the project a name &#8220;Windows Service Deployment&#8221; or something you can remember.<\/li>\n<li>Select \u201cFreestyle project\u201d.<\/li>\n<li>Select \u201cOk\u201d.<img decoding=\"async\" src=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-04%20at%2014.41.38.png\" alt=\"plugin screen\" \/><\/li>\n<li>Next, expand the \u201cSource Code Management\u201d region by selecting \u201cGit\u201d.<img decoding=\"async\" src=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-05%20at%2010.43.31.png\" alt=\"plugin screen\" \/><\/li>\n<li>Complete the Git configuration by filling in the blanks with a URL to your repository and optionally credentials (if needed).Jenkins can also work with branches. In this set-up I will leave the branch as the default (Master) but you can select whatever fits your needs.If you don&#8217;t already have a Git repository ready for testing, you can use the pre-cooked repository here:<a href=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\">https:\/\/github.com\/martinesmann\/jenkins-ci-template<\/a>The source code contains a few more files than your average &#8220;Hello Windows Service&#8221; solution. I will explain relevant parts later on as they are used. For now we will just treat this as a &#8220;Hello World&#8221; solution.<\/li>\n<li>If you haven\u2019t done so already, click \u201cSave\u201d to persist your changes and navigate back to the main &#8220;Project&#8221; page.<\/li>\n<\/ol>\n<h4 id=\"toc_12\">Testing the Git configuration<\/h4>\n<p>Now we can test if the Git Source Management tab has been configured correctly and that we can clone the source code.<\/p>\n<p>We are not yet building anything, only cloning the source. Building will come in a moment. First, let&#8217;s make sure Jenkins can clone the source from the repository.<\/p>\n<ol>\n<li>Navigate to the &#8220;Project&#8221; page<\/li>\n<li>Click the \u201cBuild Now\u201d to start a &#8220;Build&#8221;.<img decoding=\"async\" src=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-05%20at%2011.07.33.png\" alt=\"plugin screen\" \/><\/li>\n<li>In the &#8220;Build History&#8221; region you should now see a build in progress with the name &#8220;#1&#8221;.<\/li>\n<li>If every completes as expected \u201cSUCCESS\u201d then the bubble maker stays blue, if not it goes red.<\/li>\n<li>To see the build details, click the build number &#8220;#1&#8221;<\/li>\n<li>Then click &#8220;Console Output&#8221;. You should see something similar to what I have here:\n<pre><code class=\"language-none\">Started by user anonymous\r\nBuilding in workspace C:Program Files (x86)JenkinsjobsWindows Service deploymentworkspace\r\nCloning the remote Git repository\r\nCloning repository https:\/\/github.com\/martinesmann\/jenkins-ci-template\r\n&gt; git.exe init C:Program Files (x86)JenkinsjobsWindows Service deploymentworkspace # timeout=10\r\nFetching upstream changes from https:\/\/github.com\/martinesmann\/jenkins-ci-template\r\n&gt; git.exe --version # timeout=10\r\n&gt; git.exe -c core.askpass=true fetch --tags --progress https:\/\/github.com\/martinesmann\/jenkins-ci-template +refs\/heads\/*:refs\/remotes\/origin\/*\r\n&gt; git.exe config remote.origin.url https:\/\/github.com\/martinesmann\/jenkins-ci-template # timeout=10\r\n&gt; git.exe config --add remote.origin.fetch +refs\/heads\/*:refs\/remotes\/origin\/* # timeout=10\r\n&gt; git.exe config remote.origin.url https:\/\/github.com\/martinesmann\/jenkins-ci-template # timeout=10\r\nFetching upstream changes from https:\/\/github.com\/martinesmann\/jenkins-ci-template\r\n&gt; git.exe -c core.askpass=true fetch --tags --progress https:\/\/github.com\/martinesmann\/jenkins-ci-template +refs\/heads\/*:refs\/remotes\/origin\/*\r\n&gt; git.exe rev-parse \"refs\/remotes\/origin\/master^{commit}\" # timeout=10\r\n&gt; git.exe rev-parse \"refs\/remotes\/origin\/origin\/master^{commit}\" # timeout=10\r\nChecking out Revision db11bee4586694774f21e9f38b57af8535c88e1e (refs\/remotes\/origin\/master)\r\n&gt; git.exe config core.sparsecheckout # timeout=10\r\n&gt; git.exe checkout -f db11bee4586694774f21e9f38b57af8535c88e1e\r\nFirst time build. Skipping changelog.\r\nFinished: SUCCESS<\/code><\/pre>\n<p>*What\u2019s important to note here is the <strong>path<\/strong> to the &#8220;workspace&#8221; as this is where the source code is downloaded to and built from. This knowledge can be very helpful when debugging the CI setup.*<\/li>\n<\/ol>\n<h4 id=\"toc_13\">Building the source<\/h4>\n<p>The next step is to compile and build the source code.<\/p>\n<ol>\n<li>Navigate to the &#8220;project&#8221; page<\/li>\n<li>Select \u201cConfigure\u201d<\/li>\n<li>Find the &#8220;Add build step&#8221;<img decoding=\"async\" src=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-05%20at%2011.18.26.png\" alt=\"image\" \/><\/li>\n<li>Select the &#8220;Build a Visual Studio project or solution using MSBuild&#8221;.We need to configure a few values here:\n<ol>\n<li>First, select the MSBuild version (we configured this in a previous step).<\/li>\n<li>Then give the path to the *.sln or *.proj file for your project.<em>For the pre-cooked repository the path is: <code>srcMyWindowsServiceMyWindowsServiceDeploy-Windows-Service-Via-MSBuild.proj<\/code><\/em><strong>Please note<\/strong>: <em>We are not pointing to the solution file, rather we are pointing to a custom MSBuild file that is in the project. This MSBuild file is handling all steps involved with compiling and deploying the Windows Service.<\/em>If you are using the pre-cooked repository, your setup should look like this:<img decoding=\"async\" src=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-05%20at%2011.50.26.png\" alt=\"image\" \/><\/li>\n<li>Click save<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<h4 id=\"toc_14\">NuGet package restore<\/h4>\n<p>If we were to build the project right now it would fail due to missing NuGet packages. Therefore we need to restore the NuGet packages before attempting to build the source.<\/p>\n<p><code>nuget.exe<\/code> makes this task very easy, we simply need to fire this command on the solution file:<\/p>\n<p><code>nuget restore \"path to *.sln\" file<\/code><\/p>\n<p>No surprise Jenkins can handle multiple build steps, so let&#8217;s add a build step to enable NuGet restore.<\/p>\n<ol>\n<li>Navigate to the &#8220;project&#8221; page.<\/li>\n<li>Select &#8220;Configure&#8221;.<\/li>\n<li>Find the &#8220;Add build step&#8221;.<\/li>\n<li>Click &#8220;Add build step&#8221;.<img decoding=\"async\" src=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-05%20at%2021.42.13.png\" alt=\"image\" \/><\/li>\n<li>Select &#8220;Execute Windows batch command&#8221;.<\/li>\n<li>Re-arrange the build order by dragging the new build step to the top.<img decoding=\"async\" src=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-05%20at%2021.44.36.png\" alt=\"image\" \/><\/li>\n<li>In the Command field insert:<code>nuget restore srcMyWindowsService<\/code><\/li>\n<li>Click &#8220;Save&#8221;.<\/li>\n<\/ol>\n<p>We are now ready to build the project!<\/p>\n<h4 id=\"toc_15\">The final test! Primetime!<\/h4>\n<ol>\n<li>Navigate to the project page<\/li>\n<li>Click the &#8220;Build now&#8221; link<\/li>\n<li>Wait for the build to complete<\/li>\n<li>Open &#8220;Windows Explorer&#8221; and navigate to <code>C:<\/code><\/li>\n<li>Confirm that the file \u201cMyWindowsService.log\u201d exists<img decoding=\"async\" src=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-05%20at%2022.22.09.png\" alt=\"image\" \/><\/li>\n<li>Open the file and read the log content.This file was create by our newly installed Windows Service!<\/li>\n<li>Check that the Service is installed and running:\n<ol>\n<li>On Windows open &#8220;Services&#8221; management window<\/li>\n<li>Scroll down to you find the service &#8220;My Windows Service (&#8230;)&#8221;<img decoding=\"async\" src=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-06%20at%2012.49.51.png\" alt=\"image\" \/><\/li>\n<\/ol>\n<\/li>\n<\/ol>\n<p><em>Congratulations!<\/em> You have now successfully configured Jenkins to download, compile and deploy a .NET Windows Service! Automation ROCKS!<\/p>\n<h3 id=\"toc_16\">The source code:<\/h3>\n<p>So far we have not given much attention to the source code, but let\u2019s take a moment to walk through the repository content and structure.<\/p>\n<p>If you navigate to the repository root at:<\/p>\n<p><a href=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\">https:\/\/github.com\/martinesmann\/jenkins-ci-template<\/a><\/p>\n<p>you will find all the usual files as README etc. but also a file called <code>nuget.exe<\/code>.<\/p>\n<p><code>nuget.exe<\/code> is the executable used to restore the solution&#8217;s NuGet package dependencies. You could argue whether or not it\u2019s good practice to have binary files in your source control, but in this case it\u2019s a required dependency for the build system and therefore I have included it.<\/p>\n<p>I have placed <code>nuget.exe<\/code> in the root, to keep it separated from the actual source code and make it easy to find when setting up the build in Jenkins.<\/p>\n<p>If we navigate deeper into the repository to <a href=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/tree\/master\/src\/MyWindowsService\/MyWindowsService\">src\/MyWindowsService\/MyWindowsService\/<\/a> we find four files that do all the hard lifting of compiling and installing the Windows Service.<\/p>\n<p>The main entry point file is <a href=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/blob\/master\/src\/MyWindowsService\/MyWindowsService\/MyWindowsService.csproj\">Deploy-Windows-Service-Via-MSBuild.proj<\/a> it\u2019s a MSBuild file constructed to, not only, compile the source code; but also: stop, uninstall and start the Windows Service application. This is achieved by calling the three batch files as needed: <a href=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/blob\/master\/src\/MyWindowsService\/MyWindowsService\/safeServiceDelete.bat\">safeServiceDelete.bat<\/a>, <a href=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/blob\/master\/src\/MyWindowsService\/MyWindowsService\/safeServiceStart.bat\">safeServiceStart.bat<\/a> and <a href=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/blob\/master\/src\/MyWindowsService\/MyWindowsService\/safeServiceStop.bat\">safeServiceStop.bat<\/a>.<\/p>\n<p>It\u2019s out of the scope for this blog post to explain in detail what each of the four files do, but if you take a look at the files individually I\u2019m sure you will get a very good understanding of their inner workings and how they collaborate.<\/p>\n<p>The Windows Service source code can be viewed and edited in Visual Studio to fit your specific needs. The sample source given in the repository is very simple and only writes a few entries to a text file (log file) and also &#8220;upserts&#8221; a document to Couchbase Server:<\/p>\n<p><a href=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/blob\/master\/src\/MyWindowsService\/MyWindowsService\/Service1.cs\">Service1.cs<\/a><\/p>\n<pre><code class=\"language-C#\">using System;\r\nusing System.Collections.Generic;\r\nusing System.IO;\r\nusing System.ServiceProcess;\r\nusing Couchbase;\r\nusing Couchbase.Configuration.Client;\r\n\r\nnamespace MyWindowsService\r\n{\r\n    public partial class Service1 : ServiceBase\r\n    {\r\n        bool firstRun;\r\n        public Service1()\r\n        {\r\n            InitializeComponent();\r\n        }\r\n\r\n        protected override void OnStart(string[] args)\r\n        {\r\n            firstRun = true;\r\n\r\n            Log(\r\n                LogToCouchbase(new List { \"OnStart:\", DateTime.Now.ToString() })\r\n            );\r\n        }\r\n\r\n        protected override void OnStop()\r\n        {\r\n            Log(\r\n                 LogToCouchbase(new List { \"OnStop:\", DateTime.Now.ToString() })\r\n             );\r\n        }\r\n\r\n        private List Log(List lines)\r\n        {\r\n            try\r\n            {\r\n                File.AppendAllLines(\"c:\\MyWindowsService.log.txt\", lines);\r\n            }\r\n            catch (Exception ex)\r\n            {\r\n                lines.AddRange(\r\n                    new[] {\r\n                        \"Excpetion:\",\r\n                        ex.Message,\r\n                        ex.StackTrace\r\n                    });\r\n            }\r\n\r\n            return lines;\r\n        }\r\n\r\n        private List LogToCouchbase(List lines)\r\n        {\r\n            try\r\n            {\r\n                if (firstRun)\r\n                {\r\n                    var config = new ClientConfiguration\r\n                    {\r\n                        Servers = new List { new Uri(\"https:\/\/10.0.0.4:8091\") }\r\n                    };\r\n\r\n                    ClusterHelper.Initialize(config);\r\n\r\n                    firstRun = false;\r\n                }\r\n\r\n                \/\/ this will overwrite any old log lines!\r\n                var result =\r\n                    ClusterHelper\r\n                    .GetBucket(\"default\")\r\n                    .Upsert(\r\n                        \"MyWindowsService.log.txt\",\r\n                        new\r\n                        {\r\n                            id = \"MyWindowsService.log.txt\",\r\n                            log = string.Join(\"n\", lines)\r\n                        }\r\n                    );\r\n\r\n                lines.AddRange(\r\n                new[] {\r\n                        \"Couchbase result: \",\r\n                        result.Success.ToString(),\r\n                        \"Document Key: \",\r\n                        \"MyWindowsService.log.txt\"\r\n                });\r\n            }\r\n            catch (Exception ex)\r\n            {\r\n                lines.AddRange(\r\n                new[] {\r\n                        \"Excpetion:\",\r\n                        ex.Message,\r\n                        ex.StackTrace\r\n                });\r\n            }\r\n\r\n            return lines;\r\n        }\r\n    }\r\n}<\/code><\/pre>\n<p>If you are new to Couchbase I would suggest taking a look at our .NET tutorial here:<\/p>\n<p><a href=\"https:\/\/github.com\/couchbaselabs\/try-cb-dotnet\">try-cb-dotnet<\/a>.<\/p>\n<h3 id=\"toc_17\">Create your own<\/h3>\n<p>The easiest way to<span style=\"font-weight: 400\"> use Jenkins and .NET to build and deploy <\/span>your own automated Windows Service would most likely be to clone this repository and change the service code in Visual Studio to suit your needs.<\/p>\n<p>Thanks for reading!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is the first blog post of two about Jenkins and Couchbase. This first post is a general introduction to Continuous Deployment: you\u2019re going to learn to use Jenkins to deploy a .NET application automatically. The second blog post will [&hellip;]<\/p>\n","protected":false},"author":54,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1811,1816],"tags":[1567,1565],"ppma_author":[9027],"class_list":["post-2113","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-couchbase-server","tag-continuous-deployment","tag-jenkins"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.8 (Yoast SEO v25.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Jenkins + .NET: Use MSBuild to Achieve Continuous Deployment<\/title>\n<meta name=\"description\" content=\"This post focuses on how to use Jenkins to set-up test data in Couchbase before running your test code for continuous integration\/continuous deployment.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Continuous Deployment with Jenkins &amp; .NET\" \/>\n<meta property=\"og:description\" content=\"This post focuses on how to use Jenkins to set-up test data in Couchbase before running your test code for continuous integration\/continuous deployment.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2016-01-08T10:23:51+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-13T22:56:24+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-04%20at%2014.34.30.png\" \/>\n<meta name=\"author\" content=\"Martin Esmann, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Martin Esmann, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/\"},\"author\":{\"name\":\"Martin Esmann, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/2795ae2ee44b46479499d6fa514b7ee8\"},\"headline\":\"Continuous Deployment with Jenkins &amp; .NET\",\"datePublished\":\"2016-01-08T10:23:51+00:00\",\"dateModified\":\"2025-06-13T22:56:24+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/\"},\"wordCount\":1917,\"commentCount\":5,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"Continuous Deployment\",\"Jenkins\"],\"articleSection\":[\".NET\",\"Couchbase Server\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/\",\"name\":\"Jenkins + .NET: Use MSBuild to Achieve Continuous Deployment\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2016-01-08T10:23:51+00:00\",\"dateModified\":\"2025-06-13T22:56:24+00:00\",\"description\":\"This post focuses on how to use Jenkins to set-up test data in Couchbase before running your test code for continuous integration\/continuous deployment.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Continuous Deployment with Jenkins &amp; .NET\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/2795ae2ee44b46479499d6fa514b7ee8\",\"name\":\"Martin Esmann, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/af6bbf8de1ed87c78bfbc9ac7454a4fc\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/c8aea3b717146fd35e6b3c299ba8b331987c90cb1996f0141f0c6de29aa04c4b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/c8aea3b717146fd35e6b3c299ba8b331987c90cb1996f0141f0c6de29aa04c4b?s=96&d=mm&r=g\",\"caption\":\"Martin Esmann, Developer Advocate, Couchbase\"},\"description\":\"Martin Esmann is a .Net Developer Advocate at Couchbase. He is a passionate developer with a deep focus on Microsoft Technologies like .NET.\",\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/martin-esmann\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Jenkins + .NET: Use MSBuild to Achieve Continuous Deployment","description":"This post focuses on how to use Jenkins to set-up test data in Couchbase before running your test code for continuous integration\/continuous deployment.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/","og_locale":"en_US","og_type":"article","og_title":"Continuous Deployment with Jenkins &amp; .NET","og_description":"This post focuses on how to use Jenkins to set-up test data in Couchbase before running your test code for continuous integration\/continuous deployment.","og_url":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/","og_site_name":"The Couchbase Blog","article_published_time":"2016-01-08T10:23:51+00:00","article_modified_time":"2025-06-13T22:56:24+00:00","og_image":[{"url":"https:\/\/github.com\/martinesmann\/jenkins-ci-template\/raw\/master\/content\/images\/Screen%20Shot%202016-01-04%20at%2014.34.30.png","type":"","width":"","height":""}],"author":"Martin Esmann, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Martin Esmann, Developer Advocate, Couchbase","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/"},"author":{"name":"Martin Esmann, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/2795ae2ee44b46479499d6fa514b7ee8"},"headline":"Continuous Deployment with Jenkins &amp; .NET","datePublished":"2016-01-08T10:23:51+00:00","dateModified":"2025-06-13T22:56:24+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/"},"wordCount":1917,"commentCount":5,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["Continuous Deployment","Jenkins"],"articleSection":[".NET","Couchbase Server"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/","url":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/","name":"Jenkins + .NET: Use MSBuild to Achieve Continuous Deployment","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2016-01-08T10:23:51+00:00","dateModified":"2025-06-13T22:56:24+00:00","description":"This post focuses on how to use Jenkins to set-up test data in Couchbase before running your test code for continuous integration\/continuous deployment.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/continuous-deployment-with-jenkins-and-net\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Continuous Deployment with Jenkins &amp; .NET"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/2795ae2ee44b46479499d6fa514b7ee8","name":"Martin Esmann, Developer Advocate, Couchbase","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/af6bbf8de1ed87c78bfbc9ac7454a4fc","url":"https:\/\/secure.gravatar.com\/avatar\/c8aea3b717146fd35e6b3c299ba8b331987c90cb1996f0141f0c6de29aa04c4b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c8aea3b717146fd35e6b3c299ba8b331987c90cb1996f0141f0c6de29aa04c4b?s=96&d=mm&r=g","caption":"Martin Esmann, Developer Advocate, Couchbase"},"description":"Martin Esmann is a .Net Developer Advocate at Couchbase. He is a passionate developer with a deep focus on Microsoft Technologies like .NET.","url":"https:\/\/www.couchbase.com\/blog\/author\/martin-esmann\/"}]}},"authors":[{"term_id":9027,"user_id":54,"is_guest":0,"slug":"martin-esmann","display_name":"Martin Esmann, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/c8aea3b717146fd35e6b3c299ba8b331987c90cb1996f0141f0c6de29aa04c4b?s=96&d=mm&r=g","author_category":"","last_name":"Esmann","first_name":"Martin","job_title":"","user_url":"","description":"Martin Esmann is a .Net Developer Advocate at Couchbase. He is a passionate developer with a deep focus on Microsoft Technologies like .NET."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2113","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/54"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=2113"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/2113\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=2113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=2113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=2113"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=2113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}