Recently, I have written several DevOps related articles. Namely:
- Publishing TFSec Terraform Quality Checks to Azure DevOps Pipelines
- Publishing Checkov Terraform Quality Checks to Azure DevOps Pipelines
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
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…
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.
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…
mkdir super-linter.report 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/super-linter.report $(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.
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.
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.
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!