Skip to content

GitLab CI

CodeCharter im GitLab-Pipeline integrieren, als Job mit SARIF-Upload.

GitLab hat keine offizielle CodeCharter-Integration als Component, aber mit ein paar Zeilen YAML läuft die CLI sauber im Pipeline.

Liegt Ihr Repository auf GitHub und läuft nur der Build auf GitLab, können Sie aus dieser Pipeline zusätzlich einen gebrandeten CodeCharter-Check-Run und PR-Kommentar veröffentlichen, siehe Checks aus beliebigem CI veröffentlichen.

Minimal-Setup

.gitlab-ci.yml:

codecharter:
  image: mcr.microsoft.com/dotnet/sdk:9.0
  stage: test
  before_script:
    - curl -sSL -H "Authorization: Bearer $CODECHARTER_API_KEY" -o codecharter.tar.gz https://codecharter.tools/api/v1/cli/linux-x64/latest
    - mkdir -p /opt/codecharter && tar -xzf codecharter.tar.gz -C /opt/codecharter
    - chmod +x /opt/codecharter/codecharter
    - export PATH="/opt/codecharter:$PATH"
  script:
    - codecharter analyze MySolution.sln --fail-on error --output sarif --output-file codecharter.sarif
  artifacts:
    when: always
    paths:
      - codecharter.sarif

Ersetzen Sie MySolution.sln durch den Pfad zu Ihrer Solution- oder Projektdatei. analyze erwartet eine .sln-, .slnx- oder .csproj-Datei, kein Verzeichnis.

API-Key beschaffen

  1. Im Portal unter API Keys einen Key erzeugen.
  2. In GitLab unter Settings → CI/CD → Variables als CODECHARTER_API_KEY hinterlegen, "Protected" und "Masked" anhaken.

Die Variable erfüllt zwei Aufgaben: before_script lädt damit die CLI herunter, und der analyze-Schritt erzeugt damit automatisch eine kurzlebige Lizenz, wenn keine im Cache liegt. Sie muss deshalb dem gesamten Job zur Verfügung stehen, was bei einer GitLab-CI/CD-Variable standardmäßig der Fall ist.

SARIF und GitLab SAST

GitLabs artifacts.reports.sast verarbeitet kein SARIF, sondern erwartet GitLabs eigenes Security-Report-JSON-Schema, das CodeCharter nicht erzeugt. Würde reports.sast auf die SARIF-Datei zeigen, erschiene in der GitLab-Oberfläche nichts.

Die SARIF-Datei (SARIF 2.1.0) ist trotzdem als normales Artifact nützlich: aus dem Pipeline herunterladen, in SARIF-fähige Tools einspeisen oder für Audits archivieren. Um Findings auf Merge Requests sichtbar zu machen, nutzen Sie den Code-Quality-Konverter unter Merge-Request-Reports.

Caching

CodeCharter hat keinen Cache für Analyseergebnisse, durch Caching von Analyse-Output lässt sich also nichts beschleunigen. Cachen lohnt sich nur für den Rule-Bundle-Cache: Wenn Ihr Projekt Portal-Regelprofile nutzt (eine .codecharter/codecharter.lock.json im Verzeichnis .codecharter/), legt die CLI heruntergeladene Bundles in .codecharter/cache ab. Dieses Verzeichnis zu persistieren spart bei warmen Runs den erneuten Bundle-Download:

codecharter:
  # ... wie oben ...
  cache:
    key: codecharter-$CI_COMMIT_REF_SLUG
    paths:
      - .codecharter/cache/

Liegt Ihre Solution-Datei nicht im Repo-Root, passen Sie den Pfad entsprechend an. Ohne Portal-Profile gibt es nichts zu cachen und Sie können diesen Abschnitt überspringen.

Versions-Pinning

Statt /latest/ eine konkrete CLI-Version pullen:

- curl -sSL -H "Authorization: Bearer $CODECHARTER_API_KEY"
    -o codecharter.tar.gz
    https://codecharter.tools/api/v1/cli/linux-x64/1.0.12

Empfehlung: für CI immer pinnen, siehe Versionierung.

Jede Download-Antwort enthält einen X-CodeCharter-Sha256-Header. Vergleichen Sie ihn mit der Prüfsumme des heruntergeladenen Archivs, wenn Sie die Integrität des Downloads im Job verifizieren wollen.

Self-Hosted GitLab Runner

Ein Self-Hosted Runner braucht bei jedem Pipeline-Run Zugriff auf codecharter.tools, denn das before_script oben lädt die CLI jedes Mal herunter. Weitere Anpassungen sind nicht nötig: das Minimal-Setup nutzt mcr.microsoft.com/dotnet/sdk aus Microsofts öffentlichem Registry. Spiegelt Ihre Organisation Docker-Images intern, beziehen Sie das .NET-SDK-Image stattdessen aus Ihrem eigenen Mirror.

In abgeschotteten Netzen: das CLI-Binary auf den Runner spiegeln und mit lokalem Pfad statt Curl-Download arbeiten.

Merge-Request-Reports

GitLabs "Code Quality"-Sektion auf MRs erwartet eine JSON-Datei im GitLab-Code-Quality-Schema (nicht SARIF). CodeCharter erzeugt dieses Format nicht von Haus aus, den Konverter müssen Sie selbst schreiben.

Eine minimale jq-Abbildung von CodeCharter-JSON-Output auf das GitLab-Schema sieht so aus:

codecharter analyze MySolution.sln --fail-on error --output json --output-file codecharter.json
jq '[.violations[] | {
  description: .message,
  check_name:  .ruleId,
  severity:    (if .severity == "error" then "major" elif .severity == "warning" then "minor" else "info" end),
  fingerprint: .fingerprint,
  location: { path: .filePath, lines: { begin: .lineNumber } }
}]' codecharter.json > codequality.json

Danach das Ergebnis als GitLab-Artifact verdrahten:

artifacts:
  reports:
    codequality: codequality.json

Der JSON-Output enthält bereits einen stabilen fingerprint pro Violation, der nicht von Zeilennummern abhängt. GitLab zeigt deshalb keine doppelten Annotations, wenn sich unbeteiligte Zeilen verschieben.

Merge-Request-Pipelines: nur geänderte Zeilen

In MR-Pipelines können Sie mit --git-ref sowohl die gemeldeten Findings als auch das --fail-on-Gate auf die im MR geänderten Zeilen beschränken:

codecharter-mr:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  variables:
    GIT_DEPTH: 0
  script:
    - codecharter analyze MySolution.sln --fail-on error --git-ref $CI_MERGE_REQUEST_DIFF_BASE_SHA..HEAD

--git-ref führt intern git diff <range> --unified=0 aus, der Basis-Commit muss also im Clone vorhanden sein (daher GIT_DEPTH: 0).

Für Legacy-Codebasen gibt es außerdem Baseline-Unterstützung: --write-baseline hält die aktuellen Findings einmalig fest, --baseline lässt Output und --fail-on danach nur noch auf neue Findings wirken.

Exit-Codes

Für das Pipeline-Debugging nutzt codecharter analyze diese Exit-Codes:

Code Bedeutung
0 Keine gate-relevanten Findings
1 Findings auf oder über dem --fail-on-Level; ohne --fail-on jedes Finding
2 Bedienfehler (ungültige Optionen, defekte Baseline, ...)
3 Solution oder Projekt konnte nicht geladen werden
6 Lizenzfehler

Schlägt der Job plötzlich beim Download oder beim Analyze-Schritt mit HTTP 402 fehl, ist die Subscription abgelaufen. Sowohl der CLI-Download als auch das Erzeugen der Lizenz liefern in diesem Fall 402.

Pipeline-Variablen

Praktische Variablen, die im Job zur Verfügung stehen:

Variable Verwendung
$CI_PROJECT_DIR Repo-Root
$CI_COMMIT_REF_SLUG Branch-Name für Caching
$CI_MERGE_REQUEST_IID MR-Nummer wenn vorhanden
$CI_MERGE_REQUEST_DIFF_BASE_SHA MR-Basis-Commit für --git-ref
$CODECHARTER_API_KEY Ihr Secret