Recently, I have written several DevOps related articles. Namely:

This article is the 3rd one on a similar topic, but specifically focuses on the GitHub Super-Linter.

The GitHub Super-Linter is a simple combination of various linters (41 at the time of this writing), written in bash, to help validate your source code.

Quality Checks for Terraform

The GitHub Super-Linter is actually unique, in that, it covers quite a lot of languages.

At the time of this writing, it has coverage for (to name a few):

  • Azure Resource Manager (ARM) templates
  • AWS CloudFormation templates
  • Docker
  • JSON
  • Markdown
  • PowerShell
  • Terraform
  • YAML

When you look at the documentation for the Super-Linter, you will see that we can run the linter locally through a Docker container. Here is the command you can use to do so:

docker run -e RUN_LOCAL=true -v /path/to/local/codebase:/tmp/lint github/super-linter

So, to use this in our Azure DevOps pipeline, we can simply do this…

Azure Pipeline code running GitHub Super-Linter Docker container
Azure Pipeline code running GitHub Super-Linter Docker container

When you run this in the Azure pipeline, this is the type of output you would see. Notice that the execution exits with a non-zero exit code if a potential problem is detected. This enables us to be able to use it in a CI/CD pipeline and exit/error-out, as we would expect to.

Azure Pipeline displaying GitHub Super-Linter Exit Code
Azure Pipeline displaying GitHub Super-Linter Exit Code

If you’ve read the other 2 articles I wrote, you know that we’re trying to extract this output and publish it as test results in the pipeline, so let’s do that.

Publish the Results

In Azure Pipelines, the Publish Test Results task is used to publish test results. But how do we get the results out of the container, and into one of the supported results formats?

Here’s what worked for me…

docker pull github/super-linter:latest

docker run -e RUN_LOCAL=true -e OUTPUT_DETAILS=detailed -e OUTPUT_FORMAT=tap -v $(System.DefaultWorkingDirectory):/tmp/lint --name outputDir github/super-linter:latest
docker cp outputDir:/tmp/lint/ $(System.DefaultWorkingDirectory)/GHLinterReport

Here, we are telling the GitHub Super-Linter Docker container, that we want detailed output, and the output format to be TAP (which is the only supported format). We are also copying the report from the Docker container (the docker cp command), into a directory that the pipeline has access to.

In case you have not had the opportunity to read the other DevOps articles I’ve shared recently, we are using the Azure DevOps Publish Test Results task. This task supports specific formats (namely CLI, JSON, JUnit XML). So, it does not support the TAP format. This means we need to do a little more work first.

Time to convert

In order to publish and visualize the test results, we need to take the resulting TAP file(s), and convert them to a usable format.

Knowing that the Publish Test Results task supports the JUnit format, I Googled “convert tap to junit” and came across the NPM Tap-JUnit formatter. I also came across R2Devops’s Super_Linter example of converting the GitHub Super-Linter report to publish in Azure Pipelines.

Using these as reference examples, this is the script task that worked for me. The primary lines are the following:

tap-junit --pretty --suite TFLint --input super-linter-TERRAFORM.tap --output $(System.DefaultWorkingDirectory)/Converted --name TFLint-Report.xml

tap-junit --pretty --suite TerraScan --input super-linter-TERRAFORM_TERRASCAN.tap --output $(System.DefaultWorkingDirectory)/Converted --name TerraScan-Report.xml

Now in my case, I knew that I was targeting Terraform for the test results. The TAP report that is produced is labelled “super-linter-TERRAFORM.tap” and “super-linter-TERRAFORM_TERRASCAN.tap” respectively. If you’re curious how to identify that, you can use the PublishBuildArtifacts task to capture the raw file output as a pipeline artifact. Alternatively, you could make the TAP-JUNIT call into a loop, and more dynamic if needed.

Note: The SED commands were taken from the R2DevOps example.

Azure Pipeline - GitHub Super-Linter - Convert TAP Script
Azure Pipeline – GitHub Super-Linter – Convert TAP Script

Publishing the results

Now that we have the report(s) converted to JUnit format, we can use the Publish Test Results task and see the results. Because the GitHub Super-Linter has multiple linters that it executes, there are multiple reports available, and subsequently that you need to convert.

In my case, I created two explicit Publish Test Results tasks. You may wonder why. First, so that I could point to each specific converted XML file. But also, notice how I have included the ‘testRunTitle‘ field in the task.

Azure Pipeline - GitHub Super-Linter - Publish Test Results
Azure Pipeline – GitHub Super-Linter – Publish Test Results

When we look at the Test Results in the pipeline, notice how each test result is grouped by the Title. This way, I can easily see what tests passed/failed for TFLint, and TerraScan respectively; versus seeing one giant mixed list.

Azure Pipeline - GitHub Super-Linter - Test Results
Azure Pipeline – GitHub Super-Linter – Test Results


In this example, we were able to use the GitHub Super-Linter, and take the resulting TAP report, convert it to JUnit XML, and publish that as Test Results to the Azure pipeline! There was a few extra steps needed, but this allows us to have a clear and clean Test Report.

If you have any other ideas or suggestions for similar articles around DevOps, Infrastructure-as-Code (IaC), Terraform, etc. let me know!