How to use Bicep Lint in GitLab CI?

If you manage Azure infrastructure with Bicep, you probably already know about its built-in linter that checks your templates for syntax errors and best practice violations. But are you running it in your CI pipeline? In this article I’ll show how to integrate Bicep linting into GitLab CI using the codequality-os-scanners-integration component — a GitLab-maintained collection of open-source code quality scanners that plug straight into GitLab’s Code Quality widget.

Disclosure: I’m the author of the merge request that added bicep-lint support to this component.

Why lint Bicep in CI? #

Running az bicep lint locally is useful, but it doesn’t scale across a team. Integrating it into CI gives you:

  • Consistent enforcement — every merge request gets the same checks regardless of who authored it.
  • Visibility — findings show up directly in the GitLab merge request Code Quality widget, so reviewers don’t need to run anything locally.
  • Shift-left feedback — authors see issues before code is merged.

The codequality-os-scanners-integration component #

The codequality-os-scanners-integration is a GitLab CI/CD Catalog component that wraps many popular open-source linters (PMD, ESLint, TFLint, Hadolint, etc.) and converts their output to the Code Climate format that GitLab understands. One of the scanners it ships is bicep-lint.

Under the hood the component:

  1. Uses the mcr.microsoft.com/azure-cli image (which includes Bicep).
  2. Finds all .bicep and .bicepparam files in the repository.
  3. Runs az bicep lint with SARIF output for each file.
  4. Combines the SARIF reports and converts them to Code Climate format via sarif-codeclimate.
  5. Uploads the result as a codequality report artifact — GitLab picks it up automatically.

Basic usage #

Add the following to your .gitlab-ci.yml:

1include:
2  - component: $CI_SERVER_FQDN/components/code-quality-oss/codequality-os-scanners-integration/bicep-lint@1.3.2

That’s it. With this single include your pipeline gets two jobs:

JobPurpose
bicep-lintRuns az bicep lint on every .bicep / .bicepparam file and produces a combined SARIF artifact.
bicep-lint-formatConverts the SARIF output to Code Climate JSON so GitLab can display findings in the MR widget.

Both jobs run in the test stage by default and are set to allow_failure: true.

Available inputs #

The component accepts the following inputs you can override:

InputDefaultDescription
stagetestThe GitLab CI stage to run the jobs in.
imagemcr.microsoft.com/azure-cli:2.85.0Docker image used to execute the Bicep linter (must include az CLI with Bicep).
bicep_lint_args'**/*.bicep **/*.bicepparam'File glob passed to the linter.
sarif_codeclimate_converter_imagenode:25.9.0Image used for SARIF → Code Climate conversion.
convert_to_sastfalseConvert code quality results to SAST findings (GitLab Ultimate — can block MRs via approval rules).
convert_to_sast_imagepython:3.14.3-slimImage for the SAST conversion job.
skip_setupfalseSkip the default npm install for sarif-codeclimate (useful with custom images).
enable_mr_pipelinestrueWhether to use merge request pipelines.
tags[]Runner tags.
allow_failuretrueWhether the job is allowed to fail.

Customizing the stage #

If your pipeline already defines stages, you may want to run the linter in a different one:

1include:
2  - component: $CI_SERVER_FQDN/components/code-quality-oss/codequality-os-scanners-integration/bicep-lint@1.3.2
3    inputs:
4      stage: verify

Customizing linter rules with bicepconfig.json #

The Bicep linter reads configuration from a bicepconfig.json file at the root of your repository (or next to the template). You can enable, disable or change the severity of individual linter rules. For example:

 1{
 2  "analyzers": {
 3    "core": {
 4      "rules": {
 5        "no-unused-params": {
 6          "level": "error"
 7        },
 8        "no-unused-vars": {
 9          "level": "warning"
10        },
11        "prefer-interpolation": {
12          "level": "warning"
13        }
14      }
15    }
16  }
17}

Commit this file and the CI job will pick it up automatically — no extra pipeline configuration needed.

Combining with other scanners #

Because the component is part of a larger collection, you can add more linters in the same pipeline. For instance, if your repo also contains Terraform and Dockerfiles:

1include:
2  - component: $CI_SERVER_FQDN/components/code-quality-oss/codequality-os-scanners-integration/bicep-lint@1.3.2
3  - component: $CI_SERVER_FQDN/components/code-quality-oss/codequality-os-scanners-integration/tflint@1.3.2
4  - component: $CI_SERVER_FQDN/components/code-quality-oss/codequality-os-scanners-integration/hadolint@1.3.2

Alternatively, use the all-in-one wrapper that auto-detects scanners based on file types:

1include:
2  - component: $CI_SERVER_FQDN/components/code-quality-oss/codequality-os-scanners-integration/codequality-oss@1.3.2

Blocking merge requests with SAST (GitLab Ultimate) #

On GitLab Ultimate you can convert Code Quality findings into SAST vulnerabilities and use Merge Request Approval Rules to block merges:

1include:
2  - component: $CI_SERVER_FQDN/components/code-quality-oss/codequality-os-scanners-integration/bicep-lint@1.3.2
3    inputs:
4      convert_to_sast: true

Self-managed GitLab instances #

If you are running a self-managed GitLab, you can mirror the component repository to your instance. Make sure the mirrored project is set as a CI/CD Catalog project and has a project description so that new versions get released to your catalog automatically.

Wrapping up #

Adding Bicep linting to your GitLab CI pipeline is a one-liner thanks to the codequality-os-scanners-integration component. It gives your team immediate, visible feedback on Bicep best-practice violations right in the merge request — no extra tooling required.

Resources:

comments powered by Disqus