This is a very basic but very useful pipeline to have as a template and share with dev Teams.

It mainly includes some of the useful Azure DevOps tasks and functionalities to test a dotnet project, publish test results, build a docker container, scan it for vulnerabilities, authenticate to a container registry, publish the built image, set variables depending on the source branch, triggers on custom branches …

trigger:
  tags:
    include:
    - 'v-*'
  branches:
    include:
    - master
    - develop
    - feature/*

variables:
  - name: microservice
    value: my-microservice
  - name: deployenv
    value: dev
  - name: acr-name
    value: my-container-registry
  - name: acr-connection
    value: cr-connection
  - name: imagetag
    value: latest-$(Build.SourceVersion)
  - ${{ if eq(variables['Build.SourceBranchName'], 'master') }}: 
    - name: imagetag
      value: masterTag
  - ${{ if eq(variables['Build.SourceBranchName'], 'develop') }}:
    - name: imagetag
      value: dev-$(Build.SourceVersion)
  - ${{ if startsWith(variables['Build.SourceBranch'], 'refs/tags/int-') }}:
    - name: imagetag
      value: $(Build.SourceBranchName)
    - name: acr-connection
      value: int-cr-connection
    - name: acr-name
      value: my-int-container-registry
  - ${{ if startsWith(variables['Build.SourceBranch'], 'refs/tags/stg-') }}:
    - name: imagetag
      value: $(Build.SourceBranchName)
    - name: acr-connection
      value: stg-cr-connection
    - name: acr-name
      value: my-stg-container-registry

stages:
- stage: Test
  pool: 
   vmImage: ubuntu-latest
  jobs:
  - job: TestJob
    steps:
    - checkout: self
      submodules: recursive
    - task: NuGetAuthenticate@0
    # Run tests and auto publish test results.
    - task: UseDotNet@2
      displayName: 'Use .NET Core sdk'
      inputs:
        packageType: sdk
        version: 5.0.x
    - task: DotNetCoreCLI@2
      inputs:
        command: 'test'
        #https://github.com/coverlet-coverage/coverlet/issues/984#issuecomment-720478526
        arguments: '--collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura'

    - task: PublishCodeCoverageResults@1
      inputs:
        codeCoverageTool: 'Cobertura'
        summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'
        
- stage: DockerBuild
  condition: not(startsWith(variables['Build.SourceBranch'], 'refs/heads/feature/'))
  jobs:
  - job: BuildJob
    steps:
    - checkout: self
      submodules: recursive
    - task: Docker@2
      displayName: Login to ACR
      inputs:
        command: login
        containerRegistry: $(acr-connection)

    - task: Docker@2
      displayName: Build
      inputs:
        command: build
        repository: $(microservice)
        tags: $(imagetag)

    - task: CmdLine@2
      displayName: Scan Container
      inputs:
        script: |
          docker run --rm \
          -v /var/run/docker.sock:/var/run/docker.sock \
          -v $HOME/Library/Caches:/root/.cache/ \
          -v "$(pwd):/src" \
          aquasec/trivy \
          --exit-code 0 \
          --severity LOW,MEDIUM,HIGH \
          --format template --template "@contrib/junit.tpl" \
          -o src/junit-report-low-med-high.xml \
          --ignore-unfixed \
          '$(acr-name)/$(microservice):$(imagetag)'
            
          docker run --rm \
          -v /var/run/docker.sock:/var/run/docker.sock \
          -v $HOME/Library/Caches:/root/.cache/ \
          -v "$(pwd):/src" \
          aquasec/trivy \
          --exit-code 0 \
          --severity CRITICAL \
          --format template --template "@contrib/junit.tpl" \
          -o src/junit-report-crit.xml \
          --ignore-unfixed \
          '$(acr-name)/$(microservice):$(imagetag)'
    - task: PublishTestResults@2
      displayName: Publish Scan Test Results
      inputs:
        testResultsFormat: "JUnit"
        testResultsFiles: "**/junit-report-*.xml"

    - task: Docker@2
      displayName: Push image
      inputs:
        containerRegistry: $(acr-connection)
        repository: $(microservice)
        command: push
        tags: $(imagetag)