Using Azure DevOps to automagically release .NET Core apps

“Rub a little devops on it” – Donovan Brown

No idea if Donovan coined this phrase, but he says it in a lot of his videos. I also originally misquoted this–apologies! So, Azure DevOps and all its components are pretty badass. From File-new-project to deployed to Azure with continuous integration in minutes. No joke. I started screwing around with it this evening, and it’s probably going to take longer to write this blog post.

So, what will I assume you have?

  • An Azure subscription
    • If not, go sign up. Nothing we’re doing costs money and you’ll get a $200 credit to explore
  • .NET Core (2.1 or higher) installed and working on the command line
    • e.g. the ability to run: dotnet –version
  • Visual Studio Code
  • Basic understanding of git commands

And what will you learn?

How to go from zero to full continuous integration for a .NET Core app. So, anytime you git push, Azure DevOps will trigger a build, test the build, archive it, then a Pipeline will take the build artifact, and deploy it to Azure App Service.

Let’s get on with it

Browse over to to get started–there could be some redirects. I’m honestly not sure if I’ve been using the latest interfaces, etc. I think DevOps/Pipelines/etc is still evolving.

Create a project. Name it something cool. Give it a description if you want. Leave the defaults the way they are: git for source control, Agile for methodology. You should be sitting at a page that looks something like this if you named your project: blog-project.

New project dashboard

You can generate git credentials or simply clone the empty repo in VS Code. I chose the latter. Tell VS Code where to save your repo and Bob’s your uncle. Remember when I said you needed .NET Core all setup? Well, it’s go time. After you open the repo in VS Code, open its Terminal and try out that dotnet –version command just to make sure things are in order.

If that command shows a version 2.1 or greater, keep going. Let’s whip together a new .NET Core MVC app:

dotnet new mvc

This will template out a really basic MVC web app, restore packages, setup build files, etc. Go ahead and slam that F5 key, tell VS Code this is a .NET Core app, install any extensions it wants, and voila–web app! Add a .gitignore file (the Visual Studio one should work fine for our application) and push your code.

Assuming nothing went wrong yet, you should be able to see the code in DevOps:

DevOps interface showing source code

The Build

Continuous integration starts with automagically triggered builds i.e. push code, trigger a build, pray you didn’t break it. The default MVC template doesn’t have a test project, so we will see minor warnings in the DevOps interface when we look at the logs. But it is supported (and recommended) to automate your unit/integration testing as well.

Click on Pipelines in the blue menu bar. You should be staring at an appropriately empty screen with a button to create a new pipeline. This is the overarching theme of what we’re doing. We can have build pipelines, release pipelines, etc. Create a new pipeline, the defaults should be in place: where your repo lives (Azure, in our case,) the project, and relevant branch to build from.

The next step tells DevOps what kind of project this is. In our case, it’s a .NET Core app, so apply that, and a build pipeline will be templated according to what ordinarily happens when you run dotnet build. Moving along…

Don’t let the next screen intimidate you. It’s powerful, but we’re just focusing on a couple parts right now. Flip over to the Triggers tab, check the box to Enable continuous integration, and click Save & Queue. “Save & Queue” means DevOps will queue up a build with the code in the repo you specified. We’ll need this in a minute.

The Release/Deployment

Next up, we need to get DevOps to deploy our app once a build is done. This is where I assume you have the following setup in Azure:

  • A web app
  • A service plan–the free F1 service plan is fine

In the blue menu bar again, hover over Pipelines, and click Releases. There’s another button to create a new pipeline, so go ahead and slap that bad boy. So, what are we looking at? An empty release pipeline:

Basically, we’re going to add an artifact from the build, then tell it to deploy (stage) it to our Azure web app. Click Add an artifact, and try to make your screen look like this:

You’re simply identifying the project and build from which to grab the artifact–it’s just a zip file. Go ahead and add that artifact.

Next, click Add a stage. This is where we tell it where to deploy the build. Fortunately, there’s a template for what we need: Azure App Service deployment. Apply that, then click the text in the stage that should say “1 job, 1 task”

Specify the Azure subscription and App Service name where the project will live. To do this, you’ll need to authorize with your Azure account.

Once you’ve specified the subscription and app service so the release stage knows where to put the deployment, you need to click the “Deploy Azure App Service” step and tell it where specifically get the build artifact. Click the meatballs menu, and browse all the way down to the .zip file. The location might look something like:

_blog-project-ASP.NET Core-CI/drop/

The last step in DevOps is to tell this release pipeline to trigger when there is a build artifact available. Click back on the stage (in the screenshot above, it’s on the left and it says “Stage 1”) Then, click the lightning bolt icon and enable the release pipeline to create a new release whenever the artifact is available. Be sure to save the release pipeline.

At this point, we’re all set. So, how do we see it in action? You can monitor individual steps/tasks in the build as well as the release. Back up to the blue menu bar, hover over Pipelines, and select either Builds or Releases. Within each of these pages, as builds and releases are triggered, you can actually click the name, and see individual task logs that even update in realtime if you want to watch them! Below is a screenshot of the build, and releases have similar logging.

The final step is to push a new change to your app, wait a couple minutes, and surf over to your public app service URL. Just sprinkle a little DevOps on it!

Leave a Reply