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
- Generate a key in the portal under API Keys.
- In Azure DevOps:
Pipelines → Library → Variable groups → New, create the variableCodeCharterApiKeywith its value, and click the lock icon to make it a secret. - 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.