How to setup CI and CD in Azure Devops, completely free

by admin
Azure DevOps pipelines

As you probably already know, hosting your code in Azure Devops is completely free (with certain limits that is). You might not know know, however, that Azure Devops also has free build minutes.

If you don’t know DevOps yet, check it out here: https://azure.microsoft.com/services/devops/.

What does that even mean? Well, that means that you won’t have to manually build and publish your project to your server(s) anymore. You can pretty much fully automate that.

I have posted a few of our frequently used Azure DevOps Build Pipeline configurations at the bottom. We have a configuration for the following situations:

This article shows how to set it all up with a new .net core web application, I am using a freshly generated ASP.NET Core web application (Model-View-Controller) template.

Create a new Visual Studio Project

Create a new pipeline

Navigate to your DevOps environment, open the project you want to create a pipeline for and click on Pipelines in the left menu.

Create a new Azure Devops pipeline

Step 1 – Click on the ‘Create Pipeline’ button and then select ‘Azure Repos Git’.

Add an Azure Repos Git to your pipeline

Step 2 – Select the repository you are working in
I created a project called “Sample” which defaults with a “Sample” repository, so I select that one!

Step 3 – Select the pipeline configuration
Since we are using .NET Core, we will be selecting the appropiate template, press the ‘show more’ button and scroll down until you see ASP.NET Core and select it.

Step 4 – The actual pipeline configuration
Now, Azure devops shows us the default content, which is not much..

Default build pipeline configuration

I replaced it with the following content:

# ASP.NET Core
# Build and test ASP.NET Core projects targeting .NET Core.
# Add steps that run tests, create a NuGet package, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core

trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

variables:
  buildConfiguration: 'Release'


steps:
- script: dotnet build Sample/Sample/Sample.csproj --configuration $(buildConfiguration)
  displayName: 'dotnet build Sample/Sample/Sample.csproj $(buildConfiguration)'

- task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    publishWebProjects: false
    projects: '**/Sample.csproj '
    arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory) /p:EnvironmentName=Production'

- task: PublishBuildArtifacts@1
  inputs:
      targetPath: '$(Build.ArtifactStagingDirectory)'

The following modifications were made:
dotnet build – I added the path to the csproj file, this is especially useful if you have multiple projects in your solution and only want to build one. The build pipeline builds everything by default, which adds a lot of unnecessarily minutes to your build time.
dotnet publish – This generates the files ready for publishing, the path to the csproj is also added here. As well as a /p: EnvironmentName variable. This variable corresponds to your appsettings.{environment}.json file and makes it easy to publish your files with the right configuration.
Publish build artifacts – you need this step for the release pipeline, this is the artifact that you will publish to your destination server.

That’s pretty much it for this step, please do note however that this project is fairly simple. No NPM/Yarn or bundling. I will post a few different frequently used build pipeline configurations at the bottom of this article.

Create a release pipeline

Click on the Releases button in the left side menu to open the Releases pipelines section. Click the New pipeline button.

We will be publishing to IIS in this example. Search for IIS website deployment in the template selector that pops up. Select it and press apply.

Release configuration
Azure DevOps new release pipeline

Step 1 – Click on the add an artifact text and select the settings as provided below (if you have a different repository name, you will see a different source project name).

Artifact selection


Step 2 – Configure your Continious Deployment triggers

Release configuration

Press the lightning icon, and configure the settings as follows:

CD configuration

This triggers the release pipeline each time the build pipeline is built. So, whenever you commit or submit a PR to the master branch it will be built and then deployed through this release pipeline. If you do not want that, just don’t enable these triggers and manually create a release whenever you want to run this pipeline.

Step 3 – Configure the IIS deployment

Now that we selected our artifact from the build pipeline, it’s time to configure the ‘release stage’. Click on the ‘Tasks’ section at the top to configure ‘Stage 1’.

We have to configure the various IIS steps by clicking on each row and configuring whatever is inside. Click on ‘IIS deployment’ to start.

Azure Pipelines Release steps configuration

Click on the gear wheel icon right next to the ‘Deployment group’ to configure a group, then follow the steps on the page, the instructions are quite clear! The deployment group holds your machine(s) that you want to deploy your application to. Make sure to enable the ‘Use a personal access token in the script for authentication’ so that you don’t have to generate one manually when installing the worker on your server.

Azure DevOps Pipelines deployment group

After executing this Powershell script, select the deployment group in your deployment group selector.

Now, right click on the ‘IIS Web app manage’ row and click ‘duplicate’. Rename the ‘IIS web app manage’ and the ‘IIS Web app deploy’ tasks as follows:

IIS web app manage

I always use this setup when deploying with IIS. The first step shuts down the website, the second step publishes the content, finally, the third step starts the IIS site again. This is done because .NET Core keeps some DLL files locked when your application is in use, resulting in a failed release sometimes.

Configure everything as follows:

Azure Devops Pipelines configuration

Website name = the IIS website name on your server

Azure Devops Pipelines configuration
Configuration of ‘Stop website’ task
Azure Devops Pipelines configuration
Configuration of ‘publish content’ task
Azure Devops Pipelines configuration
Configuration of ‘Start website’ task

That’s it! The application will now automatically release a new version on your machine whenever your build pipeline successfully completes.

Various quick-start Azure build Pipeline YAML configurations

Below a few of our most used build pipeline configurations! For each configuration, replace the {projectname} with your own project name. Also replace the trigger at the top with the branch name you want to run the pipeline for.

.NET Core 3.1 MVC with NPM and Gulp

# ASP.NET Core
# Build and test ASP.NET Core projects targeting .NET Core.
# Add steps that run tests, create a NuGet package, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

variables:
  solution: '**/{projectname}.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '10.x'
  displayName: 'Install Node.js'

- task: NuGetToolInstaller@1

- task: NuGetCommand@2
  inputs:
    restoreSolution: '$(solution)'

- task: Npm@1
  displayName: 'npm install'
  inputs:
    workingDir: 'src/{projectname}.Mvc'
    verbose: true

- task: gulp@0
  displayName: 'gulp build'
  inputs:
    gulpFile: src/{projectname}.Mvc/gulpfile.js
    targets: build

- task: DotNetCoreCLI@2
  displayName: 'Publish'
  inputs:
    command: 'publish'
    publishWebProjects: false
    projects: '**/{projectname}.Mvc.csproj'
    arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory) /p:EnvironmentName=Production'
    zipAfterPublish: true

- task: PublishBuildArtifacts@1
  inputs:
      targetPath: '$(Build.ArtifactStagingDirectory)'

.NET Framework MVC with NPM and Gulp

# ASP.NET Core (.NET Framework)
# Build and test ASP.NET Core projects targeting the full .NET Framework.
# Add steps that publish symbols, save build artifacts, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core

trigger:
- development

pool:
  vmImage: 'windows-latest'

variables:
  solution: '**/{projectname}.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'
  DOTNET_HOST_PATH: 'dotnet'

steps:
- task: NuGetToolInstaller@1

- task: NuGetCommand@2
  inputs:
    restoreSolution: '$(solution)'

- task: Npm@1
  displayName: 'npm install'
  inputs:
    verbose: true
    workingDir: 'src/{projectname}.Mvc'

- task: Npm@1
  displayName: 'npm run copy-node-modules'
  inputs:
    verbose: true
    command: 'custom'
    customCommand: 'run copy-node-modules'
    workingDir: 'src/{projectname}.Mvc'

- task: Npm@1
  displayName: 'npm run create-bundles'
  inputs:
    verbose: true
    command: 'custom'
    customCommand: 'run create-bundles'
    workingDir: 'src/{projectname}.Mvc'

- task: VSBuild@1
  inputs:
    solution: '**/{projectname}.Mvc.csproj'
    msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(build.artifactStagingDirectory)\WebApp.zip" /p:DeployIisAppPath="Default Web Site" /p:EnvironmentName=Staging'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'
    msbuildArchitecture: x64

- task: PublishBuildArtifacts@1

.NET Core 3.1 API/Console/Class library project

# ASP.NET Core
# Build and test ASP.NET Core projects targeting .NET Core.
# Add steps that run tests, create a NuGet package, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core

trigger:
- development

pool:
  vmImage: 'ubuntu-latest'

variables:
  buildConfiguration: 'Release'

steps:
- task: NuGetCommand@2
  displayName: 'Restore nuget packages'
  inputs:
    command: 'restore'
    restoreSolution: '**/*.sln'
    feedsToUse: 'select'
    vstsFeed: '22b7b215-fc48-4aa0-9ea1-ef6364aa988a'

- task: DotNetCoreCLI@2
  displayName: 'Build'
  inputs:
    command: 'build'
    projects: '**/{projectname}.csproj'
    arguments: '--configuration $(buildConfiguration)'
    feedsToUse: 'select'
    vstsFeed: '22b7b215-fc48-4aa0-9ea1-ef6364aa988a'

- task: DotNetCoreCLI@2
  displayName: 'Publish'
  inputs:
    command: 'publish'
    publishWebProjects: false
    projects: '**/{projectname}.csproj'
    arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory) /p:EnvironmentName=Staging'

- task: PublishBuildArtifacts@1
  inputs:
      targetPath: '$(Build.ArtifactStagingDirectory)'

Angular 9/10

# Node.js with Angular
# Build a Node.js project that uses Angular.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript

trigger:
- development

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '10.x'
  displayName: 'Install Node.js'

- script: |
    npm install -g @angular/cli
    npm install
    ng build --prod
  displayName: 'npm install and build'

- task: ArchiveFiles@2
  inputs:
    rootFolderOrFile: 'dist'
    includeRootFolder: false
    archiveType: 'zip'
    archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
    replaceExistingArchive: true    

- task: PublishBuildArtifacts@1
  inputs:
      PathtoPublish: '$(Build.ArtifactStagingDirectory)'
      ArtifactName: 'drop'
      publishLocation: 'Container'

Related Posts

Leave a Comment