Zum Inhalt springen

CodeCharter pro Repository mit config.yml konfigurieren

CodeCharter pro Repository konfigurieren mit .codecharter/config.yml. Profile, Parameter, Severities, Regel-Aktivierung und Pfad-Scopes.

CodeCharter liest eine einzige Konfigurationsdatei, .codecharter/config.yml, aus eurem Repository. Sie steuert, welche Regel-Profile gelten, die Werte einstellbarer Regel-Parameter, die Severity je Regel, welche Findings ein- oder ausgeschaltet sind und welche Pfade analysiert werden. Eine Datei deckt das gesamte Repository ab, und mit Pfad-scopes variiert ihr die Konfiguration für einzelne Ordner.

Ablage und Auffinden

Legt die Datei unter .codecharter/config.yml im Repository ab. Wenn CodeCharter eine Datei analysiert, sucht es .codecharter/config.yml ausgehend vom Verzeichnis der Datei aufwärts bis zur Repository-Wurzel. Eine Konfiguration im Wurzelverzeichnis gilt damit für alles darunter.

config.yml selbst ist eine eingecheckte Datei, keine lokale. Nur zwei Pfade unterhalb von .codecharter/ gehören in die .gitignore:

.codecharter/cache/
.codecharter/config.local.yml

Nehmt nicht den gesamten Ordner .codecharter/ in die .gitignore auf. Ein pauschaler Ausschluss entfernt config.yml still aus der Versionskontrolle, sodass Profile, Overrides und Ausschlüsse nie in einem Commit landen und jedes Teammitglied, ebenso wie die CI, stillschweigend ohne jede Konfiguration analysiert. Nur cache/ (heruntergeladene Regel-Bundles) und config.local.yml (siehe unten) sind maschinenlokal; config.yml ist die geteilte, eingecheckte Quelle der Wahrheit.

Daneben gibt es optional .codecharter/config.local.yml für persönliche, maschinenlokale Überschreibungen. Diese Datei wird nie eingecheckt (sie ist durch den obigen .gitignore-Eintrag abgedeckt) und hat Vorrang vor config.yml. Nutzt sie, um lokal eure Regelversionen mitlaufen zu lassen oder eine Regel auf eurem Rechner leiser zu stellen, ohne die geteilte Konfiguration zu ändern. Die CI, die diese Datei nie sieht, bleibt reproduzierbar.

Ein vollständiges Beispiel

version: 1

# Anzuwendende Regel-Profile, neueste zuerst. Ein blanker Slug oder @latest
# folgt der neuesten veröffentlichten Version, eine exakte Version pinnt sie.
# Plattform-Profile nutzen die Form org/slug.
profiles:
  - dotnet-base@1.4.2
  - security@latest
  - acme/house-style@^2.1.0

# Lokale Regelverzeichnisse, aufgelöst gegen das Repository-Root. Sie laufen
# nach den Profilen; bei doppelter Regel-ID gewinnt die spätere Quelle.
# Erfordert 1.6.4.
rules:
  - .codecharter/rules

# Werte für einstellbare Regel-Parameter, adressiert über rule-slug.paramName.
params:
  cyclomatic-complexity.max: "15"
  method-length.maxLines: "60"

# Severity je Regel. Hier lässt sich ausschließlich die Severity überschreiben.
overrides:
  magic-number:
    severity: warning
  empty-catch-block:
    severity: error

# Findings ausschalten. Optional auf einen Namespace (in:) oder auf Entities
# beschränken, deren gemeldeter Name einem Glob entspricht (match:): bei Typen
# und Members vollqualifiziert, bei Events und Findings auf Vorkommen-Ebene
# einfach.
ignore:
  - rule: namespace-distance
    in: Acme.Generated
  - rule: todo-comment
  - rule: const-naming
    match: "*InstanceMemberBindingFlags"

# Eine Regel wieder einschalten, nachdem sie breiter ignoriert wurde (z. B. in
# einem Scope).
include:
  - rule: todo-comment

# Pfade, die vollständig von der Analyse ausgeschlossen werden (Glob-Muster).
exclude:
  - "**/tests/**"
  - "**/obj/**"
  - "**/Migrations/**"

# Das Test-Coverage-Gate: Schwelle, Größe der Report-Ausschnitte, Parallelität
# der Testläufe, die Dateien, die nicht in die Coverage-Zahl einfließen, und die
# Verzeichnisse, die nie nach Testprojekten durchsucht werden. Gilt
# repositoryweit, nie je Scope.
coverage:
  minimum-percent: 99.5
  snippet-context-lines: 3
  max-parallel-test-projects: 4
  exclude:
    - "**/*.Designer.cs"
  excluded-directories:
    - "vendor/**"

# Ordnerspezifische Überschreibungen. Jeder Scope matcht ein oder mehrere
# Pfad-Globs und kann jeden der obigen Abschnitte setzen. Die Einstellungen
# gelten nur für Dateien, die der Scope matcht.
scopes:
  - match:
      - "src/Legacy/**"
    overrides:
      magic-number:
        severity: info
    ignore:
      - rule: cyclomatic-complexity

Abschnitte

version

Pflicht. Die Version des Konfigurationsformats. Verwendet version: 1.

org

Optional. Nennt die Organisation, als die die CLI handelt; nötig nur, wenn eure Lizenz mehr als eine Organisation abdeckt. Im üblichen Fall einer einzigen Organisation lasst ihr den Schlüssel ganz weg: Die CLI löst die handelnde Organisation automatisch auf, und org bringt dann nichts.

org: acme
profiles:
  - dotnet-base@1.4.2

org wird wie jeder andere Schlüssel in dieser Datei hierarchisch aufgelöst: Der Wert, der der analysierten Datei am nächsten liegt, gewinnt. Er hat Vorrang vor der Umgebungsvariable CODECHARTER_ORG. Nennt ihr eine Organisation, die eure Lizenz nicht abdeckt, endet die CLI mit Exit-Code 6; deckt eure Lizenz mehr als eine Organisation ab und weder org noch CODECHARTER_ORG benennt eine, endet die CLI mit Exit-Code 64. Siehe Organisation in der CLI wählen.

profiles

Die anzuwendenden Regel-Profile. Jeder Eintrag ist entweder eine Slug-Referenz oder ein lokaler Bundle-Pfad:

  • dotnet-base@1.4.2, eine exakte veröffentlichte Version.
  • security@latest oder ein blankes security, folgt der neuesten veröffentlichten Version und wird bei codecharter update neu aufgelöst.
  • security@^2.1.0 oder security@2.1.*, ein Versionsbereich.
  • acme/house-style@1.0.0, ein Plattform-Profil in der Form org/slug.
  • { path: ./bundles/rules.cgbundle }, ein lokales .cgbundle. Solche Einträge liest nur das Portal; analyze meldet sie als nicht aufgelöste Quelle. Lokale Regeln deklariert ihr stattdessen unter rules:.

rules

Die lokalen Regelverzeichnisse, die ein Lauf liest, jeweils ein Pfad zu einem Ordner mit .ccr- oder .cgr-Dateien, aufgelöst gegen das Repository-Root (das Verzeichnis, das .codecharter/ enthält). Ein Pfad, der das Repository verlässt, wird abgelehnt. Die Verzeichnisse laufen nach profiles: und in der angegebenen Reihenfolge; definieren zwei Quellen dieselbe Regel-ID, gewinnt die spätere, und der Lauf nennt die überdeckte ID. Einträge aus config.local.yml werden hinter denen aus config.yml angehängt.

rules:
  - .codecharter/rules
  - build/conventions/rules

Ein Verzeichnis wird nur gelesen, wenn es hier steht oder mit --rules übergeben wird. Ein rules-Ordner, der bloß existiert, wird nicht aufgenommen, und der Lauf nennt ihn, damit ihr ihn deklarieren könnt. Erfordert CodeCharter 1.6.4: Ältere Versionen ignorieren den Schlüssel ohne Meldung, deshalb weist codecharter config validate darauf hin.

params

Werte für Parameter, die eine Regel anbietet, adressiert über rule-slug.paramName. Werte werden als Zeichenketten geschrieben; CodeCharter prüft sie gegen den deklarierten Typ und Wertebereich des Parameters. Eine Regel ohne Parameter oder ein nicht existierender Parametername wird von codecharter config validate gemeldet.

overrides

Ändert die Severity einer Regel. Das einzige Feld ist severity, eines von error, warning (oder warn) oder info. Um eine Regel ganz abzuschalten, verwendet ihr ignore statt overrides.

ignore und include

ignore schaltet Findings aus, include schaltet sie wieder ein. Jeder Eintrag adressiert eine Regel per Slug und kann das Ziel eingrenzen:

  • in: Acme.Core, gilt nur für Findings in diesem Namespace oder einem darunterliegenden.
  • match: "*Dto", gilt nur für Entities, deren gemeldeter Name dem Glob entspricht. Bei einem Typ, einer Methode, Property oder einem Field ist dieser Name vollqualifiziert (Namespace plus einfacher Name, z. B. Acme.Core.OrderDto), und ein Muster ohne führendes * muss an der Namespace-Wurzel beginnen; ein bloßer einfacher Name wie match: "OrderDto" trifft daher nichts, außer der Typ ist im globalen Namespace deklariert. Events und Findings auf Vorkommen-Ebene (Parameter, Member-Zugriffe und Ähnliches) werden stattdessen mit ihrem einfachen, unqualifizierten Namen gemeldet, sodass ein bloßer einfacher Name dort direkt trifft.

ignore und include teilen sich ein Aktivierungssignal, das der Reihe nach ausgewertet wird: zuerst die Basis-Ebene, dann jeder passende Scope von oben nach unten. Der letzte passende Eintrag gewinnt. So könnt ihr eine Regel breit ignorieren und für einen engeren Pfad oder Namespace wieder einschalten.

exclude

Glob-Muster für Pfade, die vor jeder Regelauswertung aus der Analyse fallen. exclude ist additiv: die Basis-Muster und die Muster jedes passenden Scopes gelten zusammen.

coverage

Einstellungen für das Test-Coverage-Gate, das codecharter coverage ausführt:

  • minimum-percent: die geforderte Line-Coverage, 0 bis 100. Standard: 100.
  • snippet-context-lines: wie viele Kontextzeilen der Report um jede ungedeckte Region ausgibt.
  • max-parallel-test-projects: wie viele Testprojekte nach dem gemeinsamen Build gleichzeitig laufen, 1 oder mehr. Standard: die Prozessoranzahl, gedeckelt bei 4.
  • exclude: Globs für Quelldateien, die nicht in die Coverage-Zahl einfließen.
  • excluded-directories: Globs für Verzeichnisbäume, die bei der Suche nach Testprojekten komplett übersprungen werden.

Die beiden letzten werden leicht verwechselt. exclude wirkt bei der Messung: Die Tests laufen weiter, die passenden Dateien zählen nur nicht mehr mit. excluded-directories wirkt bei der Suche: Der Baum wird gar nicht betreten, ein Testprojekt darin also nie gefunden und nie ausgeführt. Das erste greift ihr, wenn generierter Code die Zahl drückt, das zweite, wenn ein mitgelieferter Fremdbaum Tests mitbringt, die euch nicht gehören.

Dieser Abschnitt gilt repositoryweit und lässt sich nicht in einem scope setzen. Sein exclude ist unabhängig vom übergeordneten exclude weiter oben: Ein Ordner, den ihr aus der Regelanalyse nehmt, zählt weiterhin zur Coverage, solange ihr ihn nicht auch hier ausschließt.

Ein coverage-Schlüssel in der config.local.yml ersetzt den eingecheckten Wert, statt sich mit ihm zu vermischen. Für beide Glob-Listen heißt das: die lokale Liste ersetzt die eingecheckte Liste vollständig. --min-coverage und --max-parallel auf der Kommandozeile schlagen beide Ebenen.

scopes

Ordnerspezifische Konfiguration. Jeder Scope hat eine match-Liste aus Pfad-Globs und kann jeden der Abschnitte params, overrides, ignore, include und exclude enthalten. Die Einstellungen eines Scopes gelten nur für Dateien, die er matcht. Die Auflösung erfolgt nach dem Prinzip letzter Treffer gewinnt für params, overrides und die Regel-Aktivierung, verankert an der Quelldatei der ausgewerteten Entität; exclude ist additiv über alle passenden Scopes.

Konfiguration prüfen und inspizieren

Drei Befehle helfen euch beim Arbeiten mit der Datei:

  • codecharter config explain <pfad> zeigt die effektive Konfiguration für eine bestimmte Quelldatei, einschließlich der Ebene (Basis oder welcher Scope), aus der jeder Wert stammt. Mit --json erhaltet ihr maschinenlesbare Ausgabe.
  • codecharter config validate prüft die Datei auf strukturelle Fehler, unbekannte Regel-Ids, ungültige Parameterwerte und Einträge, die nie greifen.
  • codecharter config schema gibt ein JSON-Schema für .codecharter/config.yml aus, das Editoren für Vervollständigung und Validierung nutzen können. Mit --out <datei> schreibt ihr es auf die Festplatte.

Um die Datei über die Kommandozeile zu bearbeiten statt von Hand (Parameter und Severities setzen, Profile und Ausschlüsse verwalten, die Datei anlegen und das lokale Overlay synchronisieren), nutzt ihr die config-Schreibbefehle. Jede Bearbeitung erhält eure Kommentare und Formatierung und wird vor dem Schreiben geprüft. Siehe codecharter config.

Verhältnis zu Suppressions

ignore und exclude wirken auf Repository- oder Ordner-Ebene. Um ein einzelnes Finding genau an der Stelle im Code zu unterdrücken, an der es auftritt, verwendet ihr stattdessen einen Inline-Suppression-Kommentar, siehe Suppressions.