Files
qt-migration-copilot-demo/docs/developer-push-policy.md
T

7.1 KiB

Entwicklerhinweise: Anforderungen bei Push und Pull Request

Dieses Repository verwendet Jenkins-basierte PR- und Branch-Policies.
Ziel ist, dass Code bereits vor dem Merge bestimmte Qualitätsanforderungen erfüllt.

Diese Datei beschreibt, was bei einem Push erwartet wird, was in Jenkins geprüft wird und wie du Fehler lokal vermeiden kannst.


Überblick

Bei Pushes und Pull Requests werden automatisierte Policies ausgeführt.

Je nach Build-Typ gelten leicht unterschiedliche Vergleichsregeln:

  • bei Pull Requests wird gegen den Zielbranch verglichen, z. B. origin/main
  • bei normalen Branch-Builds wird auf eine lokale Vergleichsbasis zurückgefallen, z. B. HEAD~1, falls kein Zielbranch-Ref verfügbar ist

Die eigentlichen Qualitätsanforderungen bleiben gleich.


Was beim Push / PR geprüft wird

1. .clang-format muss vorhanden sein

Im Repository-Root muss eine Datei .clang-format liegen.

Ohne diese Datei schlägt der Policy-Check fehl.


2. Geänderte C/C++-Dateien müssen korrekt formatiert sein

Für geänderte C/C++-Dateien wird clang-format geprüft.

Betroffen sind insbesondere Dateien mit diesen Endungen:

  • .c
  • .cc
  • .cpp
  • .cxx
  • .h
  • .hh
  • .hpp
  • .hxx

Wenn eine Datei nicht korrekt formatiert ist, schlägt der Build fehl.

Lokal prüfen

clang-format --dry-run --Werror <datei>

Lokal automatisch formatieren

clang-format -i <datei>

Beispiel:

clang-format -i main.cpp tests/test_main.cpp

3. Zu geänderten C/C++-Dateien muss ein passender Test existieren

Wenn du eine C/C++-Datei änderst, muss ein passender Test vorhanden sein.

Es wird nach Tests in diesen Verzeichnissen gesucht:

  • tests/
  • test/
  • qt6-after/qt6-migrated-benchmark/tests/

Unterstützte typische Testnamen sind zum Beispiel:

  • test_<name>.cpp
  • <name>_test.cpp
  • <name>test.cpp
  • <name>gtest.cpp

Zusätzlich erkennt die Policy auch ähnliche Dateinamen heuristisch, solange test oder gtest im Dateinamen vorkommt.

Beispiel

Wenn du main.cpp änderst, ist z. B. passend:

tests/test_main.cpp

Wenn kein passender Test gefunden wird, schlägt der Build fehl.


4. Nur gültig SSH-signierte Commits sind erlaubt

Neue Commits im geprüften Bereich müssen gültig mit SSH signiert sein.

Die Jenkins-Policy prüft Commit-Signaturen gegen eine erlaubte Signiererdatei:

ci/allowed_signers

Wenn ein Commit:

  • nicht signiert ist
  • nicht per SSH signiert ist
  • mit einem nicht erlaubten SSH-Schlüssel signiert ist

dann schlägt der Build fehl.


SSH-signierte Commits einrichten

1. SSH-Signing-Key erzeugen

Falls du noch keinen dedizierten Signing-Key hast:

ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_signing -C "dein.name@example.com"

2. Git für SSH-Signing konfigurieren

git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519_signing.pub
git config --global commit.gpgsign true

Damit werden neue Commits automatisch mit deinem SSH-Key signiert.


3. Öffentlichen Schlüssel zur Allowlist hinzufügen

Dein öffentlicher Schlüssel muss in ci/allowed_signers eingetragen sein.

Format:

<principal> <public-key>

Beispiel:

max.mustermann@example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...

Ohne Eintrag in ci/allowed_signers wird dein signierter Commit in Jenkins trotzdem abgelehnt.


4. Optional: lokale Verifikation aktivieren

Wenn du lokal dieselbe Vertrauenskette wie Jenkins verwenden willst:

mkdir -p ~/.config/git
cp ci/allowed_signers ~/.config/git/allowed_signers
git config --global gpg.ssh.allowedSignersFile ~/.config/git/allowed_signers

5. Signierten Commit erstellen

git add .
git commit -S -m "Meine Änderung"
git push

Wenn commit.gpgsign=true gesetzt ist, signiert Git Commits in der Regel automatisch.


6. Signatur lokal prüfen

git log --show-signature -1
git verify-commit HEAD

Lokaler Minimal-Check vor dem Push

Vor dem Push solltest du mindestens diese Schritte ausführen:

Format anwenden

clang-format -i main.cpp tests/test_main.cpp

Policy lokal ausführen

python3 ci/check_pr_policies.py

Projekt lokal im CI-Container bauen

Zuerst das lokale CI-Image bauen:

docker build -t lifemaps/ci-cpp:latest -f Dockerfile.ci .

Danach das Projekt im Container bauen und testen:

docker run --rm -it \
  -v "$PWD:/workspace" \
  -w /workspace \
  lifemaps/ci-cpp:latest \
  bash -lc '
    cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug &&
    cmake --build build --parallel &&
    ctest --test-dir build --output-on-failure
  '

Damit wird dieselbe Toolchain verwendet wie in der Jenkins-CI.

Policy-Check lokal im CI-Container ausführen

docker run --rm -it \
  -v "$PWD:/workspace" \
  -w /workspace \
  lifemaps/ci-cpp:latest \
  bash -lc 'python3 ci/check_pr_policies.py'

Verhalten in Jenkins

Die Jenkins-Pipeline umfasst typischerweise diese Stages:

  1. Checkout
  2. Policy Checks
  3. Configure
  4. Build
  5. Test
  6. Cleanup

Wenn die Policy-Checks fehlschlagen, werden die späteren Build- und Test-Stages nicht mehr ausgeführt.


Typische Fehlerursachen

Formatfehler

Beispiel:

ERROR: Formatfehler in tests/test_main.cpp

Lösung

clang-format -i tests/test_main.cpp

Kein passender Test gefunden

Beispiel:

ERROR: Kein passender Test unter tests/, test/ oder qt6-after/qt6-migrated-benchmark/tests für main.cpp gefunden.

Lösung

  • passenden Test anlegen
  • Testdatei passend benennen
  • Test in einem der erlaubten Testverzeichnisse ablegen

Commit nicht gültig SSH-signiert

Beispiel:

ERROR: Commit ist nicht gültig mit erlaubtem SSH-Signierer signiert: <sha>

Lösung

  • SSH-Signing lokal korrekt konfigurieren
  • prüfen, ob der richtige Schlüssel verwendet wird
  • prüfen, ob der öffentliche Schlüssel in ci/allowed_signers eingetragen ist
  • Commit neu erstellen oder neu signieren

.clang-format fehlt

Beispiel:

ERROR: .clang-format fehlt im Repository-Root.

Lösung

  • .clang-format im Repository-Root anlegen oder wiederherstellen

Empfohlener Workflow

  1. Feature-Branch erstellen
  2. Änderungen implementieren
  3. Test ergänzen oder anpassen
  4. Code formatieren
  5. Commit SSH-signiert erstellen
  6. lokal Policy, Build und Tests ausführen
  7. pushen
  8. Pull Request öffnen
  9. Jenkins-Ergebnis prüfen
  10. erst bei grünem Status mergen

Kurz-Checkliste vor jedem Push

  • C/C++-Dateien sind formatiert
  • passender Test existiert
  • Commit ist SSH-signiert
  • öffentlicher Schlüssel steht in ci/allowed_signers
  • python3 ci/check_pr_policies.py läuft erfolgreich
  • Build und Tests laufen lokal

Ziel der Regeln

Die Policies sollen sicherstellen, dass:

  • Code konsistent formatiert ist
  • Änderungen nachvollziehbar getestet sind
  • nur autorisierte Signierer Commits einbringen
  • PRs frühzeitig automatisiert validiert werden