Skip to content

Azure DevOps Pipelines

CodeCharter as a task in an Azure pipeline.

CodeCharter runs in Azure Pipelines as a shell step. Robust and easy to pin; besides the CLI download the agent only needs a .NET SDK, which the snippet below installs via UseDotNet@2.

If your repository is hosted on GitHub and only the build runs in Azure Pipelines, you can additionally publish a branded CodeCharter check run and PR comment from this pipeline — see Publish checks from any CI.

Minimal setup

azure-pipelines.yml:

trigger:
  branches:
    include: [main]

pr:
  branches:
    include: [main]

pool:
  vmImage: ubuntu-latest

variables:
  CODECHARTER_VERSION: '1.0.12'

steps:
  - task: UseDotNet@2
    inputs:
      version: '9.0.x'

  - bash: |
      curl -sSL -H "Authorization: Bearer $CODECHARTER_API_KEY" \
        -o codecharter.tar.gz \
        https://codecharter.tools/api/v1/cli/linux-x64/$(CODECHARTER_VERSION)
      mkdir -p /opt/codecharter && tar -xzf codecharter.tar.gz -C /opt/codecharter
      chmod +x /opt/codecharter/codecharter
      echo "##vso[task.prependpath]/opt/codecharter"
    displayName: 'Install CodeCharter CLI'
    env:
      CODECHARTER_API_KEY: $(CodeCharterApiKey)

  - bash: |
      codecharter analyze MySolution.sln --fail-on error --output sarif --output-file codecharter.sarif
    displayName: 'Run CodeCharter'
    env:
      CODECHARTER_API_KEY: $(CodeCharterApiKey)

  - task: PublishPipelineArtifact@1
    condition: always()
    inputs:
      targetPath: codecharter.sarif
      artifactName: codecharter-sarif

codecharter analyze takes the path to a .sln, .slnx, or .csproj file — replace MySolution.sln with your solution path; a bare directory is not accepted.

Pull request runs

The pr: trigger runs the full analysis on every pull request. To report and gate only on lines changed in the PR, add --git-ref to the analyze call:

codecharter analyze MySolution.sln --fail-on error --git-ref origin/main..HEAD

Both the reported findings and the --fail-on gate then apply only to changed lines. The base branch must be present in the local clone for git diff to work.

Exit codes

Use these for pipeline gating:

Code Meaning
0 No findings (or none at/above --fail-on)
1 Findings at/above --fail-on; without --fail-on, any finding at all
2 Usage error (invalid arguments, no rules found)
3 Analysis failed (solution could not be loaded)
6 License error — check the CODECHARTER_API_KEY mapping

API key in a pipeline secret

  1. Generate a key in the portal under API Keys.
  2. In Azure DevOps: Pipelines → Library → Variable groups → New, create the variable CodeCharterApiKey with its value, and click the lock icon to make it a secret.
  3. Reference the variable in the pipeline YAML as shown above.

Naming convention: CodeCharterApiKey is the Azure DevOps library variable name (Azure-specific, uses Pascal case). The env: block in each step maps it to the environment variable CODECHARTER_API_KEY that the CodeCharter CLI reads. Both the "Install" step and the "Run CodeCharter" step need this mapping: the install step uses the key to authenticate the download, and at run time the CLI uses it to automatically mint a short-lived license from the portal. Without a valid license every command exits with code 6. If your subscription has expired, the portal returns HTTP 402 on the download and license endpoints.

Viewing SARIF results

Azure DevOps has no native SARIF viewer. Two good options:

Option A — SARIF Viewer extension

There is a SARIF SAST Scans Tab marketplace extension. After installation a "Scans" tab appears next to Tests and Code Coverage and renders SARIF artifacts.

Option B — Plain-text report

- bash: |
    codecharter analyze MySolution.sln --no-color --output console --output-file codecharter-report.txt
    echo "##vso[task.uploadsummary]$PWD/codecharter-report.txt"
  displayName: 'Publish CodeCharter summary'

Pass --no-color, otherwise the report file contains ANSI color codes.

uploadsummary appends the text to the build summary. Not a fancy UI, but visible.

Caching

When you use portal profiles via .codecharter/config.yml, CodeCharter downloads rule bundles into the .codecharter/cache directory inside your repository. The location is not configurable. You can cache that directory with Cache@2, keyed on the lockfile:

- task: Cache@2
  inputs:
    key: 'codecharter | "$(Agent.OS)" | .codecharter/codecharter.lock.json'
    path: $(Build.SourcesDirectory)/.codecharter/cache
  displayName: 'Cache CodeCharter rule bundles'

Without portal profiles there is nothing to cache.

Self-hosted agents

Works without any changes. The agent needs network access to codecharter.tools. Mirroring the CLI archive into your own artifact feed covers the download, but at run time the CLI still contacts the portal to mint its short-lived license from CODECHARTER_API_KEY — unless you provision a codecharter.license file on the agent.