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:
- Uses the
mcr.microsoft.com/azure-cliimage (which includes Bicep). - Finds all
.bicepand.bicepparamfiles in the repository. - Runs
az bicep lintwith SARIF output for each file. - Combines the SARIF reports and converts them to Code Climate format via
sarif-codeclimate. - Uploads the result as a
codequalityreport 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:
| Job | Purpose |
|---|---|
bicep-lint | Runs az bicep lint on every .bicep / .bicepparam file and produces a combined SARIF artifact. |
bicep-lint-format | Converts 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:
| Input | Default | Description |
|---|---|---|
stage | test | The GitLab CI stage to run the jobs in. |
image | mcr.microsoft.com/azure-cli:2.85.0 | Docker 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_image | node:25.9.0 | Image used for SARIF → Code Climate conversion. |
convert_to_sast | false | Convert code quality results to SAST findings (GitLab Ultimate — can block MRs via approval rules). |
convert_to_sast_image | python:3.14.3-slim | Image for the SAST conversion job. |
skip_setup | false | Skip the default npm install for sarif-codeclimate (useful with custom images). |
enable_mr_pipelines | true | Whether to use merge request pipelines. |
tags | [] | Runner tags. |
allow_failure | true | Whether 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: