Skip to content

GitHub Actions

CodeCharter in your GitHub workflow using the official bochmann-software/codeguard action.

The official action bochmann-software/codeguard@v1 is the fastest way to integrate CodeCharter into a GitHub workflow. It handles the CLI download, caching, and publishing findings as PR annotations.

Recommended: also install the CodeCharter GitHub App. The action then publishes a branded CodeCharter check run and PR comment through the app — no pull-requests: write permission and no GitHub token on the runner. Without the app the action still works and falls back to a workflow-token comment.

Minimal setup

.github/workflows/codecharter.yml:

name: CodeCharter

on:
  pull_request:
  push:
    branches: [main]

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '9.0.x'
      - uses: bochmann-software/codeguard@v1
        with:
          solution: Acme.Web.sln
          api-key: ${{ secrets.CODECHARTER_API_KEY }}

Done. Findings automatically appear as inline annotations on the PR.

Getting an API key

  1. Generate a key in the portal under API Keys.
  2. Store it as CODECHARTER_API_KEY in the GitHub repo under Settings → Secrets → Actions.

The action reads the key, authenticates against the portal, and pulls the CLI version selected by the version input (default latest).

Execution model

The action runs the CLI natively on the runner — it does not use Docker and does not pull a container image. On each run it:

  1. downloads the self-contained CLI archive matching the runner's platform (win-x64, linux-x64, osx-x64, osx-arm64) from the portal, authenticated with the API key,
  2. verifies the archive against the SHA-256 checksum the portal advertises,
  3. runs the CLI directly against your checked-out solution.

The downloaded binary is cached between runs (see Caching). Because no container is involved, Linux x64, Windows x64, and macOS (x64 and arm64) runners all work — GitHub-hosted and self-hosted alike. Other platforms (for example Linux arm64) fail with an explicit error.

Inputs

Input Default Description
api-key Required. API key from the portal.
solution first .sln / .slnx Which solution to analyze. When omitted, the action picks the first .sln/.slnx it finds (sorted alphabetically). It fails with an error when none is found and warns when multiple exist.
fail-on error Threshold for build failures (info, warn, error, never). warning is also accepted as a synonym for warn.
severity-threshold info Minimum severity to report and annotate (info, warn, error).
rules (empty) Path to a rules directory in your repository (e.g. .codecharter/rules). Leave empty to use the built-in default rules.
diff false On pull requests, scope both the reported findings and the fail-on gate to the lines changed by the PR. The PR base commit must be reachable on the runner; use actions/checkout with fetch-depth: 0. Has no effect on non-pull_request events.
version latest Which CLI version to download. Recommendation: pin it. Accepts latest, v1, v1.4, or an exact pin like v1.4.2.
sarif-output If set, SARIF is additionally written to this file.
cache true Cache the downloaded CLI binary between workflow runs.
portal-base-url Override the portal endpoint, e.g. for a self-hosted or staging portal. Defaults to the public portal.
require-rules false Fail instead of silently using bundled sample rules when no rules directory exists.
baseline Path to a baseline file; only findings not present in it fail the build. Generate a baseline via the CLI's --write-baseline flag.
telemetry false Opt-in usage event. It contains aggregated finding counts per rule (rule ID, severity, count) plus your account and installation identifiers. No source code, file paths, or finding locations are sent.
comment true Post or update a sticky PR summary comment. Requires permissions: pull-requests: write when not using the CodeCharter app.
comment-key Discriminator string so multiple CodeCharter steps in one workflow keep separate sticky comments.
github-token ${{ github.token }} Token used to post the PR comment.

Outputs

Output Description
findings-total Total number of findings
findings-error Number of error findings
findings-warn Number of warn findings
findings-info Number of info findings
sarif-path Path to the SARIF file, if generated

Full setup: SARIF + Code Scanning

If you want to see findings in the Security tab of your GitHub repo:

- uses: bochmann-software/codeguard@v1
  id: codecharter
  with:
    solution: Acme.Web.sln
    api-key: ${{ secrets.CODECHARTER_API_KEY }}
    sarif-output: codecharter.sarif

- name: Upload SARIF
  if: always()
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: codecharter.sarif

if: always() ensures the upload step runs even when a previous step failed (for example, if CodeCharter exits with a non-zero code because findings exceeded the fail-on threshold). Without it, GitHub Actions would skip the upload whenever an earlier step did not succeed.

Matrix builds

If your solution builds on multiple OSes but CodeCharter is deterministic, the analysis only needs to run once:

jobs:
  build:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - run: dotnet build

  codecharter:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - uses: actions/checkout@v4
      - uses: bochmann-software/codeguard@v1
        with:
          api-key: ${{ secrets.CODECHARTER_API_KEY }}

Self-hosted runners

Works without any changes as long as the runner meets these prerequisites:

  • Network access to codecharter.tools. The action always downloads the CLI from the portal; there is no mode that uses a pre-installed binary. The CLI also mints its short-lived license from the API key against the portal on each run.
  • A .NET SDK that can build your solution. The action logs a warning when no dotnet is detected on the runner.
  • zstd or gzip on the PATH if you want the CLI binary cached between runs. Without either of them the action skips the cache with a warning and downloads the CLI fresh on every run; set cache: 'false' to silence the warning.

On runners without portal access the action cannot be used. Install the CLI binary on the runner manually, place a full codecharter.license there, and call codecharter directly in a run: step instead — see Offline or long-lived runners.

Version pinning

Recommendation: pin the action to a specific minor version and upgrade infrequently.

- uses: bochmann-software/codeguard@v1   # Major pinning, gets v1.x.y updates
- uses: bochmann-software/[email protected] # Minor pinning, static
- uses: bochmann-software/codeguard@<sha> # SHA pinning, most conservative

We follow SemVer (see Versioning) and do not break contracts within a major version.

Caching

The action automatically caches the downloaded CLI binary between workflow runs, keyed by runner platform and CLI version. Exact pins (e.g. v1.4.2) are cached indefinitely; moving selectors (latest, v1, v1.4) are re-resolved daily so a cache hit never serves a stale build for long. The analysis itself runs in full on every invocation; analysis results are not cached between runs.

On a medium-sized solution a warm run typically completes in 5–15 seconds.

Disable manually when debugging unexplained cache effects:

- uses: bochmann-software/codeguard@v1
  with:
    cache: 'false'
    api-key: ${{ secrets.CODECHARTER_API_KEY }}

If PR annotations don't appear

GitHub shows inline annotations in the Files changed view only for pull requests. On direct push runs the annotations still appear on the workflow run summary, just not inline in the code. If you expect inline PR annotations, make sure the workflow triggers on pull_request.

When results are published through the CodeCharter app, the check run shows at most 50 inline annotations per run; with more findings, only the first 50 appear as annotations.

Permissions

With the CodeCharter GitHub App installed, the action posts results through the app and the workflow only needs contents: read.

Without the app the action falls back to posting a comment via the workflow token, which additionally requires pull-requests: write:

permissions:
  contents: read
  pull-requests: write   # only needed without the CodeCharter app

If you also upload SARIF to GitHub Code Scanning, add security-events: write:

permissions:
  contents: read
  security-events: write
  pull-requests: write   # only needed without the CodeCharter app