Showing Bicep Linting Issues as Errors and Warnings in Azure DevOps Pipelines

Introduction

Previously Rik Hepworth has posted on ‘Importing bicep lint output as test results in Azure DevOps pipelines’. In his post he showed how you could move from using the ARM-TTK to validate ARM templates to using the built inBicep Linter.

Rik’s solution involved taking the Bicep Lint output and converting it via the .SARIF format to JUnit so that it could be published to an Azure DevOps pipeline run as a set of test results.

Linting as test results

The problem is are linting issues really failed tests?

An Alternative Approach

The Bicep linter, based on its bicepconfig.json defined configuration, will return issues as either an error or a warning when a build is done.

Is it not a better solution to return these as errors and warnings in the pipeline, just as you would for MSbuild?

Returning the linting issues in this manner actually involves less steps than Rik’s solution. Basically we run a Bicep build from within a AzureCLI@2 task and then process the output to return any issues as Azure DevOps errors and warnings. The advantage of using the AzureCLI@2 task is that it is automatically kept up to date to the current Bicep version.

The critical step that is easy to forget is to set the powershellerrorActionPreference: 'continue' so that the script does not fail on the first error

Note: the 2>&1 at the end of the az bicep build command to ensure that the error stream is captured in the $output variable.

steps:
  - task: AzureCLI@2
    displayName: 'Build Bicep files'
    inputs:
      azureSubscription: 'My Azure Subscription'
      scriptType: 'ps'
      scriptLocation: 'inlineScript'
      useGlobalConfig: true
      powershellerrorActionPreference: 'continue' # we handle the errors in the script
      inlineScript: |
        # create folder if it doesn't exist
        if (!(Test-Path -Path $(Build.SourcesDirectory)\Bicep\ARMOutput)) {
          New-Item -ItemType Directory -Path $(Build.SourcesDirectory)\Bicep\ARMOutput
        }
        write-host "Build the Bicep file"
        $output = az bicep build --file $(Build.SourcesDirectory)\Bicep\RootTemplate-Main.bicep --outdir $(Build.SourcesDirectory)\Bicep\ARMOutput 2>&1
        write-host "Process the output"
        $output | foreach-object {
           if ($_ -match 'Error') {
              Write-Host "##vso[task.logissue type=error]$_"
           } 
           if ($_ -match 'Warning') {
               Write-Host "##vso[task.logissue type=warning]$_"
           }
        }        

Conclusion

For many projects this solution will give a more actionable result than Rik’s process.

The time that will not be true is if you wish to import the linting issues into a tool such as SonarQube, where using the .SARIF format will be vital.