Part 2: Setting up a Build Pipeline in Azure DevOps

This is Part 2 in a series on Azure DevOps.

In Part 1 I created a simple web app called WidgetApi. I then put it under source control and pushed it up to an Azure DevOps repo. In this part we’re going to set up a build and then change our code to trigger a continuous integration build. Open the browser and go to your Azure DevOps portal. You should see all your pushed commits there from Part 1. Awesome. Now there’s a couple of housekeeping things to do before we set up the build.

Shout out to https://devrant.com/rants/1535091/ci-cd-in-a-nutshell

Service Principal

We need a service principal account that has sufficient rights to our Azure subscription to deploy our releases there. Go into Project settings >  Service connections > New Service connection and add an Azure Resource Manager service connection. Give it a name and leave the Resource Group blank. It should look like this:

Read the fine print. Your service principal will have Contributor rights to the subscription for all resource groups so it will able to make sweeping changes. I’m fine with this in my own builds. But if this troubles you there are options. However, I’m not going to go into them here.

Default to Designer View

If you’re very comfortable with YAML then ignore what I’m about to recommend. Otherwise do this: from your portal click on your account icon in the upper right and choose Preview features. Go all the way down and turn off the YAML creation experience:

Create New Build Pipeline

Now we’re ready to create a new build pipeline. A wizard will walk you through the process. The first step is to select your repo. The tool knows about WidgetApi and presents that project by default. Accept and continue. In the second step you choose a template. Pick Azure Web App for ASP.NET.  All kinds of goodness gets configured for you in the pipeline designer view:

Remove the Azure App Service Deploy task. We’re going to do that later in the release pipeline. Save the build and queue it up. If you go into the build itself you can watch it work:

W00t it’s done! Drill down into the details to inspect the build. It looks like we’ve got two warnings:

Remember back in Part 1 when we implemented the async Get operation without an await operator? The build is helpfully pointing that out to us. Let’s go change our code and then we’ll see how continuous integration will trigger a new build for us. Here’s the new code:

[HttpGet]
public async Task<IActionResult> Get()
{
    await Task.Delay(50);
    var items = new List<Widget>()
    {
        new Widget { ID = 1, Name = "Cog", Shape = "Square" },
        new Widget { ID = 2, Name = "Gear", Shape = "Round" },
        new Widget { ID = 3, Name = "Sprocket", Shape = "Octagonal" },
        new Widget { ID = 4, Name = "Pinion", Shape = "Triangular" }
    };

    return Ok(items);
}

In a future post we’re going to add a database and use EF Core but right now let’s just go with this implementation. Modify your code in Visual Studio and push the commit to your Azure DevOps repo just like you did in Part 1. This will trigger a continuous integration (CI) build.

Side note while we wait for the build… Right click on WidgetController.cs and click View History to see the history of commits. Hold down the Ctrl key and select both commits. Then right-click them and you can compare them side by side in Visual Studio. Pretty cool. And you can begin to see why commit messages are very important for you and others.

Well while we’ve been looking at the Git integration features in Visual Studio a new build ran to success:

Click on the title and you can inspect the build progression again. Notice that I still have my missing test warning. And now I see the associated change that triggered the build:

To handle the warning I either have to add unit tests to my project or remove the task from the build pipeline. Obviously in a real-world app you want to add tests and get that warm fuzzy that comes with repeated automated testing of your CI builds.

This is a good place to leave off for this part. In Part 3 I’m going to go over how to set up a release pipeline to two stages (or environments): Development and Production.