Microservice-dotnet-core-ci-pipeline-azure-devops

Build Microservice .NET Core in a CI Pipeline in Azure DevOps

An important feature of DevOps is to give  developer fast feedback if their code changes work. This can be done by automatically building code and running tests every time changes are checked-in.

In this post  I am going  to create a CI pipeline (continuous integration) for ASP .NET Core, to the our Microservice project.

I have changed the Repository and solution name (ProductMicroservice-DotNET-Core-Master)  and created a xUnit Test project (ProductMicroservicesTest). Source code can be found in my Github.

Creating a .NET Core CI Pipeline in Azure DevOps

In the my last posts, I created one ASP .NET Core microservice (ProductMicroservice). In this post, I am going to create a CI pipeline to build  project and run all unit tests in the repository. Source code can be found in my GitHub.

You need to have DevOps Organization and DevOps project. How to create this you can find from here

In your Azure DevOps project, go to Pipelines and click Create Pipeline, according to the following image:

In the next GUI, select where you have your code stored. I have selected GitHub for this project. On the bottom, you can see “Use the classic editor”. This opens the old task-based editor. We needn’t  use this anymore since the new standard is to use YML pipelines. This enables you to have your pipeline in your source control.

With pressing GitHub, asks from you to select a Repository as following image:

I have selected repository: “mehzan07/ProductMicroservice-DotNET-Core-Master”

Authorize to access GitHub

With first time create CI , in DevOps you should Authorize Azure Pipelines to access to your Repository in GitHub. In case your code is in Azure Repos, you needn’t do this step.

Authorize Azure Pipelines to access GitHub

After authorizing Azure Pipelines for GitHub, all your repositories will be displayed. Search and select for the repository, you want to make the CI pipeline for. In my case, I  have selected the ProductMicroservice-DotNET-Core-Master repository.

In the next GUI, you have to approve to install Azure Pipelines in your GitHub repository. This allows Azure DevOps to access the repository and write the code. This is necessary because the CI pipeline will be added to the source control.

This happens only the first time and if  you have your code in Azure DevOps you needn’t do this.

Approve the access to the GitHub repository

Next you should select a template.

Select a Template

Select a template for your CI pipeline. Azure DevOps have many templates like Docker, Kubernetes, PHP, or Node.js. I have .NET Core microservice I have selected  ASP.NET Core template.

 Select ASP.NET Core template for your CI Pipeline

Now the template created a simple CI pipeline and you can use it to build your .NET Core solution, you can see the YAML file:

The created CI Pipeline  from the template

Analyze the CI Pipeline from the Template

Above the .yml editor, you can see the path to the pipeline yml file in your source control. The pipelines folder is in the root folder of your project. In my case, it is mehzan07/ProductMicroservice-DotNET-Core-Master/pipelines/NetCore-CI-azure-pipeline.yml

It is a good idea to name the file to describe what it do. You can find the finished pipeline on GitHub

I have modified and add more steps to addupt to my project and the file is looking as following:

name : NetCore-ProductMicroservice-CI
trigger:
 branches:
 include:
  - master
paths:
 include:
 - ProductMicroservice-DotNET-Core-Master/*
pool:
 vmImage: 'windows-latest'
variables:
 buildConfiguration: 'Release'
steps:
- task: DotNetCoreCLI@2
 inputs:
command: 'restore'
projects: '**/ProductMicroservice*.csproj'
displayName: 'Restore Nuget Packages'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
projects: '**/ProductMicroservice*.csproj'
arguments: '--no-restore'
displayName: 'Build projects'
- task: DotNetCoreCLI@2
inputs:
command: 'test'
projects: '**/*Test.csproj'
arguments: '--no-restore --no-build'
displayName: 'Run Tests'
- task: DotNetCoreCLI@2
inputs:
command: 'publish'
publishWebProjects: false
projects: '**/ProductMicroservice.csproj'
arguments: '--configuration $(buildConfiguration) --no-restore'
modifyOutputPath: false
displayName: 'Publish ProductMicroservice'

The name section is name for Pipeline Name: NetCore-ProductMicroservice-CI The trigger section defines that the pipeline is automatically triggered when something changes on the master branch inside the ProductMicroservice-DotNET-Core-Master folder. The pool section defines that the pipeline is executed on an Windows agent and the variables section lets you define variables for the pipeline. By default, only the buildConfiguration is set to Release.

In the steps: first and second Tasks Restore and executes a dotnet build in and sets the configuration to Release by using the previously defined buildConfiguration variable.

In the third Task: Runs the tests (Unit tests)  and in the fourth Task Publishes , and display name (ProductMicroservice) is set to identify the step easier in the logs.

Additional  steps for CI Pipeline

I have added new steps to restore NuGet packages, build the solution, run tests, and publish the solution. The publish step should only be run when the pipeline was triggered by the master branch.

The build script has been removed and select the .NET Core task on the right side, and  select restore as command and **/ProductMicroservice*.csproj as the path to the projects to restore each project starting with ProductMicroservice.

Now  time is run pipeline by pressing to  Save and Run theen pipeline will be added to your source control and then executed.

It takes a little time and  then shows the result, first for Summary and then you can click to the Tests to see how the tests has been run. 

Pipeline is executed and sucess.

Now press to the Tests and see result: 

Result of tests (all tests are succeed).

how to start an existence  yml file for ci-pipeline from Github repository

You can do as before (choose a new pipline) give the repository from GitHub and in the end  finde existence pipline press to it and in the upper right find the pipline (example: Pipelines/azure-pipelines.yml ) and save it then you have an existence pipeline yml file:

Run Tasks only when the Master Branch triggered the build and succeeded

As we created we modified the YAML file the  publish task runs always, even if we don’t want to create a release.

I want  the pipeline to be more efficient to run this task only when the build was triggered by the master branch. To do that, we should add a custom condition to the publish task. I want to run the publis h only when the previous steps succeeded and when the build was not triggered by a pull request. we do this with the following code:

task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    publishWebProjects: false
    projects: '**/ProductMicroservice.csproj'
    arguments: '--configuration $(buildConfiguration) --no-restore'     modifyOutputPath: false
  displayName: 'Publish ProductMicroservice`
  condition: and(succeeded(), ne(variables['Build.Reason'],'PullRequest'))

and the final YAML file is as following:

name : NetCore-ProductMicroservice-CI
trigger:
  branches:
    include:
      - master
  paths:
    include:
      - ProductMicroservice-DotNET-Core-Master/*
pool:
  vmImage: 'windows-latest'
variables:
  buildConfiguration: 'Release'
steps:
- task: DotNetCoreCLI@2
  inputs:
    command: 'restore'
    projects: '**/ProductMicroservice*.csproj'
  displayName: 'Restore Nuget Packages'
- task: DotNetCoreCLI@2
  inputs:
    command: 'build'
    projects: '**/ProductMicroservice*.csproj'
    arguments: '--no-restore'
  displayName: 'Build projects'
- task: DotNetCoreCLI@2
  inputs:
    command: 'test'
    projects: '**/*Test.csproj'
    arguments: '--no-restore --no-build'
  displayName: 'Run Tests'
- task: DotNetCoreCLI@2
  inputs:
    command: 'publish'
    publishWebProjects: false
    projects: '**/ProductMicroservice.csproj'
    arguments: '--configuration $(buildConfiguration) --no-restore'
    modifyOutputPath: false
  displayName: 'Publish ProductMicroservice'
  condition: and(succeeded(), ne(variables['Build.Reason'],'PullRequest'))

The final YAML file

How to get the published file from the Azure devops pipeline?

you have to add the following in the end of yml file:

Copy and publish binaries:

- powershell: gci env:* | sort-object name | Format-Table -AutoSize | Out-File $env:BUILD_ARTIFACTSTAGINGDIRECTORY/environment-variables.txt
- task: Files@2
 inputs:
 sourceFolder: '$(Build.SourcesDirectory)'
 contents: '**/$(BuildConfiguration)/**/?(*.exe|*.dll|*.pdb)'  targetFolder: '$(Build.ArtifactStagingDirectory)'
 - task: PublishBuildArtifacts@1
  inputs:  pathToPublish: '$(Build.ArtifactStagingDirectory)'  artifactName: drop

Download artifacts:

- powershell: gci env:* | sort-object name | Format-Table -AutoSize | Out-File $env:BUILD_ARTIFACTSTAGINGDIRECTORY/environment-variables.txt

- task: DownloadBuildArtifacts@0
  inputs:
 buildType: 'current'
 downloadType: 'single'
 artifactName: 'drop' 
downloadPath: '$(System.ArtifactsDirectory)'

After running of pipeline we see “1 publis”, press to this you can find a file with name: environment-variables.text which contains all environment definitions but there is no binary code to download and run it.

The new pipeline yml file is: azure-pipelines.yml in the ProductMicroservice-DotNET-Core-Master/Pipelines/ in the Github.

Source code can be found on  my GitHub.

Conclusion

CI pipelines help developers to get fast feedback to the code changes. These pipelines can build code and run tests every time something changed.

In my next post, I will explain,  Run CI Pipeline with pull request   how to add code coverage to the results to get  more information about the code changes, and then I will show how to run your code with every pull request.

This post is part of Azure DevOps step by step.

Back to home page

Leave a Reply

Your email address will not be published. Required fields are marked *