Setting up a build environment in VS Code

in utopian-io •  7 years ago  (edited)

What Will I Learn?

In this tutorial we will look at how to setup a build environment using Visual Studio Code, Subversion, MSBuild, and TeamCity.

Requirements

  • Visual Studio Code
  • TeamCity 
  • Subversion 
  • TortoiseSVN 
  • MSBuild (Comes with Visual Studio)
  • NUnit 
  • MSBuild Community tasks 

Difficulty

Intermediate

Tutorial Contents

  • Creating a Subversion repository
  • Creating our project structure
  • Creating a few simple tests
  • Creating our build file
  • Setting up our TeamCity project
  • The moment you’ve been waiting for
  • Interesting reports and what not in TeamCity

Setting up a build environment in VS Code

In this tutorial we will look at how to setup a build environment using Visual Studio Code, Subversion, MSBuild, and TeamCity. 

When working in teams having a structured approach to integration is essential. Continuous integration (CI) servers offer such integration. Amongst other things CI can help developers, and management track the health of a project by looking at the project statistics often provide with CI software. There are many CI products out there, some are free, and others are not.In this article we will use TeamCity as our CI server. TeamCity is easy to setup and maintain yet it provides a wealth of functionality. It also provides support for pretty much all mainstream source control systems (e.g. Subversion, Team Foundation Server, etc.) and build technologies (MSBuild, ANT, etc.). We will use the following technologies in this article to setup our build server:

  • Visual Studio Code
  • TeamCity 
  • Subversion 
  • TortoiseSVN 
  • MSBuild (Comes with Visual Studio)
  • NUnit 
  • MSBuild Community tasks 

If you don’t have some of the aforementioned products on your machine then please go and install them now. The installation used for each is the default, you need not change anything.

Creating a Subversion repository

This step of the process is pretty straightforward. All we need to do is create a directory on our hard drive that will house our Subversion repository. For this example I have created the Subversion repository at c:\Svn\Tests\MyApp. Creating a Subversion repository requires you to create a new folder, then using TortoiseSVN you can right click on the folder and select the Create repository here item.

Figure 1: Creating the Subversion repository

Now that we have our repository all setup we will perform a checkout. Before we do this though create a folder where you intend to house the Visual Studio project. On my machine I created a folder called MyApp and performed the checkout there.

Figure 2: Performing the checkout

After you have clicked the menu item to perform a checkout you will be asked to specify the location of the MyApp Subversion repository we created earlier. If you created the repository at c:\Svn\Tests\MyApp then simply specify that, otherwise specify the location you chose.

Figure 3: Specifying the location of the repository

After performing the previous step you will be greeted with a confirmation message.

Figure 4: Checkout confirmation message

Creating our project structure

The project we will base this article on is incredibly simple. We will create a solution in the MyApp directory we made a checkout to in the previous step that contains two class library projects:

  • MyApp
  • MyApp.Tests

Figure 5: Our project structure

You should now have a directory MyApp that contains the solution.

Figure 6: Directory structure

Before we check the code in just yet we need to add a few things. First add a folder called ReferenceAssemblies. This folder will hold any assemblies that our project depends on. To that folder copy and paste nunit.framework.dll from the directory you installed NUnit. We will now add a reference to this assembly in our MyApp.Tests project.

Figure 7: Adding a reference to nunit.framework.dll

As well as adding a reference to nunit.framework.dll, go ahead and make a reference to MyApp from MyApp.Tests.The penultimate step for now is to right click on the MyApp folder and select the Add Tortoise SVN menu item.

Figure 8: Adding the items within the MyApp folder to the repository

Now the items are added to the repository we will commit them.

Figure 9: Committing the files to the repository

After committing the files to the repository you will be greeted with a success message as well as a listing of all the files added to the repository.

Figure 10: Confirmation of the commit

Creating a few simple tests

Now we will create a PersonTest class in the MyApps.Tests project, and a Person class in the MyApps project. The PersonTest class will contain two simple tests that verify the first and last name are correct of a Person object. You will probably do this using a test driven approach, but for this simple example we will just add them and make sure they pass.

Listing 1: PersonTest.cs

using NUnit.Framework;  
namespace MyApp.Tests  
{  
    [TestFixture]  
    public class PersonTest  
    {  
        [Test]  
        public void FirstNameTest()  
        {  
            Person actual = new Person("Granville", "Barnett");  
            Assert.AreEqual("Granville", actual.FirstName);  
        }  
        [Test]  
        public void LastNameTest()  
        {  
            Person actual = new Person("Granville", "Barnett");  
            Assert.AreEqual("Barnett", actual.LastName);  
        }  
    }  
}

Listing 2: Person.cs

namespace MyApp  
{  
    public class Person  
    {  
        public string FirstName { get; private set; }  
        public string LastName { get; private set; }  
        public Person(string firstName, string lastName)  
        {  
            FirstName = firstName;  
            LastName = lastName;  
        }  
    }  
}  

If you build the project and run the tests you will see everything is fine. Your project should now look like that in the following Figure.

Figure 11: Project structure

Please make sure that you add the two new files, and commit them to the source code repository using TortoiseSVN before proceeding.

Creating our build file

Before we actually get our hands dirty and start creating our build file we need to do a few things. First create a new folder called BuildTools, this will sit beside ReferenceAssemblies. Go to the location that you installed the MSBuild community tasks and copy and paste the MSBuild.Community.Tasks.dll, and MSBuild.Community.Tasks.Targets files into the BuildTools folder.

Figure 12: Modified directory structure with BuildTools directory

After you have done the previous step add and commit them to the Subversion repository.

The next step is really one of personal preference. On my machine I have an environmental variable that I reference in the build file, this variable is called NUNIT_2_4_8 and points to the bin folder of the directory where NUnit 2.4.8 was installed on my machine. We will reference this variable to make our build file more concise rather than using full paths. If you don’t want to setup the system variable then simply replace the reference to that variable with the full path of the NUnit bin folder. With that done we are ready to actually define our build file.

First open the C# solution we created earlier. In the solution explorer select the top level solution file and add a new item called Build.proj. This file by default will be put in a folder called Solution Items.

Figure 13: Adding what will be our build file

By default Visual Studio will not provide XML support for a .proj file. To remedy this go to Tools -> Options -> Text Editor and then select the File Extension item. Add the proj extension to the list and select XML Editor with Encoding.

Figure 14: Adding XML support for the .proj file

Now we can start to write our MSBuild file. If it’s not already open, open Build.proj and copy and paste the following listing into the file.

<?xml version="1.0" encoding="utf-8"?>  
<Project ToolsVersion="3.5" DefaultTargets="Test"  
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">  
</Project>

In MSBuild what is known as a Target contains Tasks. A task can be anything from making a directory, running unit tests, to invoking a static analysis tool. Notice that the DefaultTargets attribute of the Project element has a value of Test. This means that the Test target will be invoked first.Initially we will create a Build target. All this Build target will do is point to the MSBuild file for our Visual Studio project – MyApp.sln.

<?xml version="1.0" encoding="utf-8"?>  
<Project ToolsVersion="3.5" DefaultTargets="Test"  
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">  
  <Target Name="Build">  
    <MSBuild Projects="MyApp.sln" Properties="Configuration=Release" />  
  </Target>  
</Project> 

Before we continue, if we change the value of the DefaultTargets attribute to Build and then invoke MSBuild we will see that everything works as expected. We can invoke MSBuild by opening the Visual Studio command prompt and using the command: msbuild my_file_location\Build.proj.

Figure 15: Using Build.proj to build the solution

Now revert the DefaultTargets attribute back to the value of Test. Before we can write the Test target we need to import the targets defined in MSBuild.Community.Tasks.Targets. This simply requires the addition of the Import element with the value of the Project property being the path of BuildTools/ MSBuild.Community.Tasks.Targets.

<?xml version="1.0" encoding="utf-8"?>  
<Project ToolsVersion="3.5" DefaultTargets="Test"  
    xmlns="http://schemas.microsoft.com/developer/msbuild/2003">  
  <Import Project="BuildTools\MSBuild.Community.Tasks.Targets"/>  
  <Target Name="Build">  
    <MSBuild Projects="MyApp.sln" Properties="Configuration=Release" />  
  </Target>  
</Project>  

We have everything in place now to create our Test target. This target will use the NUnit task from the community tasks project.

<?xml version="1.0" encoding="utf-8"?>  
<Project ToolsVersion="3.5" DefaultTargets="Test"  
         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">  
  <Import Project="BuildTools\MSBuild.Community.Tasks.Targets"/>  
  <Target Name="Build">  
    <MSBuild Projects="MyApp.sln" Properties="Configuration=Release" />  
  </Target>  
  <Target Name="Test" DependsOnTargets="Build">  
    <NUnit Assemblies="MyApp.Tests\bin\Release\MyApp.Tests.dll"  
           ToolPath="$(NUNIT_2_4_8)" />  
  </Target>  
</Project> 

A few things to note, the first is that the target Test depends on Build. This means that the Build target is invoked before the Test target. Second we use the custom NUnit task and point it at the MyApp.Tests.dll and use the environmental variable NUNIT_2_4_8 as the value for the ToolPath attribute. If you run MSBuild again pointing it at Build.proj you will see output that displays the number of tests ran and its associated data.

Figure 16: Build.proj now runs the tests defined in our test project

We have completed our simple MSBuild file. Before we continue lets add and commit Build.proj to our source code repository as we will need it later in TeamCity.

Setting up our TeamCity project

At this moment in time it is worth pointing out that all the heavy lifting has been done, we need only be guided by a wizard now before we have completed what we set out to do.Point your browser at the URL you set TeamCity up to use, and then login. Click on the Administration button in the top right hand corner of the screen and you will be presented with a page with a Create build configuration link.

Figure 17: Creating a new build configuration

After you have clicked on the aforementioned link you enter a series of wizard steps. The first asks you for the name of your project amongst other things. For now we need only be concerned with providing a name for the project. For the name enter MyApp.

Figure 18: Specifying the name for our project

After you have done that go to the next step by clicking on VCS Settings. On this page click the Create and attach new VCS root link. We are taken to a page where we specify a name for our VCS root as well as the type of VCS. For the root name enter MyApp, for the type select Subversion. Upon selecting Subversion a hoard of new options appears. In these new options enter the URL of the Subversion repository; if you have followed my steps then this will be file:/// C:\Svn\Tesst\MyApp. Once you have entered that information click the Test connection button at the bottom of the screen to verify all is well.

Figure 19: Setting up the source control

Figure 20: All is well

Once you have verified everything is ticking over click on the Save button. We are taken back to the Version Control Settings screen, the only difference being that the VCS root has been created. We don’t need to touch anything else on this page so click on the Choose Build Runner button.

Figure 21: Source control settings all setup

On the Build Runner page select MSBuild as the build runner. Upon selecting MSBuild we are now asked to provide the path of our build file, here we simply enter Build.proj. Make sure also to select the .NET 3.5 version of MSBuild. Now click the Save button.

Figure 22: Setting up the build runner

For the last step we need only define what triggers a new build. To do this click on the Build triggering link. On the Build triggering page check the Enable triggering when files are checked into VCS. This will kick off a new build every time someone checks into the source repository. Now click the Save button.

Figure 23: Specifying when a new build is triggered

The moment you’ve been waiting for

If like me you are a little impatient and don’t want to submit something to Subversion to kick a build off simply click on the Run button in the top right hand corner.

Figure 24: Igniting the engine for the first time

Once you’ve hit the magic Run button head over to the projects page by clicking the Projects tab. On the Projects page you will either see the build as running, or if you have a super fast computer then you will see the result of the build.

Figure 25: The result of our efforts

Go get a drink, then we will look at a few interesting things that TeamCity offers.

Interesting reports and what not in TeamCity

If you click on the MyApp link from the Projects tab you will see the build history of the project. Furthermore we can take a look at the change log, the success rate of our builds, the time our builds have spent in the queue etc.

Figure 26: Build history, yes I made a typo when specifying the build file first time around

If you click on the actual build number you can see a little information about that build. Because we have very few things of interest going on in our build click on the Tests tab. On the Tests page we can see all the tests that ran during the build.

Figure 27: They all passed! Someone ring my mum and tell her the great news

Obviously this isn’t a definitive traversal of all the features TeamCity offers but hopefully you are getting a sense that it offers some interesting features to complement your build experience.

Summary

In this tutorial we did a fair amount, we set up a Subversion source control repository, then we created our own MSBuild file that used custom tasks, and finally we brought it all together in the form of a continuous integration product. Hopefully I have given you enough to go and explore MSBuild a little further as this is a pretty core technology in the Microsoft stack these days. You may have also seen some possible value that a continuous integration setup can add to your team. I strongly suggest you research what CI can bring to your team. 



Posted on Utopian.io - Rewarding Open Source Contributors

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Your contribution cannot be approved because it does not follow the Utopian Rules.

  • Tutorials must be technical instructions that teach non-trivial aspects of an Open Source project.

You can contact us on Discord.
[utopian-moderator]