diff --git a/README.md b/README.md index 964cbe4..a11d63c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,231 @@ # sandbox -jenkins testing repobranch protection test +Test- und Beispiel-Repository für einen lokalen Dev-Platform-Stack mit: +- **Gitea 1.22.x** +- **Jenkins Multibranch Pipeline** +- **Webhook-Trigger von Gitea nach Jenkins** +- **C++/CMake/Ninja Build** +- **PR Policy Checks** +- **Docker-basiertem CI-Agent** -branch main protection test +--- + +## Aktueller Funktionsumfang + +Dieses Repository und das zugehörige Jenkins/Gitea-Setup können aktuell: + +### SCM / Repository +- Repository in **Gitea** hosten +- Änderungen per **Git Push** empfangen +- **Pull Requests** in Gitea verwalten +- Webhooks von Gitea an Jenkins senden + +### Jenkins / CI +- Jenkins als **Multibranch Pipeline** verwenden +- Branches und Pull Requests automatisch erkennen +- Builds durch **Push Events** automatisch starten +- Build-Status an Gitea zurückmelden + +### Build-Umgebung +- Pipeline-Schritte in einem **Docker-Container** ausführen +- dafür ein vorbereitetes CI-Image verwenden +- folgende Tools im CI bereitstellen: + - `python3` + - `clang-format` + - `cmake` + - `ninja` + - `git` + - `g++` + - `make` + +### C++ Projektbasis +- minimales Beispielprogramm über `main.cpp` +- Build mit **CMake** +- Testausführung über **CTest** +- Testdateien unter `tests/` + +--- + +## Repository-Struktur + +```text +. +├── .clang-format +├── CMakeLists.txt +├── Dockerfile.ci +├── Jenkinsfile +├── README.md +├── ci/ +│ └── check_pr_policies.py +├── main.cpp +└── tests/ + └── test_main.cpp +``` + +--- + +## CI / Jenkins Pipeline + +Die Jenkins-Pipeline umfasst aktuell diese Schritte: + +1. **Checkout** + - Repository aus Gitea auschecken + - zusätzliche Fetch-/Submodule-Schritte ausführen + +2. **Policy Checks** + - `ci/check_pr_policies.py` ausführen + - Formatierung und Testbezug prüfen + +3. **Configure** + - CMake-Buildverzeichnis erzeugen + +4. **Build** + - Projekt mit CMake/Ninja bauen + +5. **Test** + - Tests über `ctest` ausführen + +6. **Cleanup** + - Workspace am Ende bereinigen + +--- + +## PR Policy Checks + +Für geänderte C/C++-Dateien werden in der CI folgende Regeln geprüft: + +- `.clang-format` muss im Repository vorhanden sein +- geänderte C/C++-Dateien müssen mit `clang-format` konform sein +- zu geänderten C/C++-Dateien muss ein passender Test unter `tests/` oder `test/` vorhanden sein + +### Vergleichsbasis der Policy + +Die Policy unterscheidet zwischen Pull-Request-Builds und normalen Branch-Builds: + +- **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 + +Damit funktioniert die Policy sowohl in PR-Builds als auch bei regulären Branch-Indexing- oder Branch-Build-Läufen. + +--- + +## Docker-basierter CI-Agent + +Die Pipeline verwendet ein vorbereitetes Docker-Image statt bei jedem Lauf ein neues Build-Image zu erzeugen. + +### Beispiel +Das Image wird lokal oder auf dem Build-Host gebaut: + +```bash +docker build -t lifemaps/ci-cpp:latest -f Dockerfile.ci . +``` + +Danach nutzt Jenkins dieses Image als Build-Agent. + +### Vorteile +- schnellere PR-Builds +- reproduzierbare Toolchain +- keine langen `apt install`-Phasen pro Build +- saubere Trennung zwischen Jenkins-Controller und Build-Umgebung + +--- + +## Branch- und PR-Workflow + +Der aktuelle Workflow unterstützt: + +- Arbeiten auf Feature-Branches +- Öffnen von Pull Requests gegen `main` +- automatisches Bauen von PRs +- Rückmeldung des Build-Status an Gitea + +Empfohlen ist: + +- keine direkten Änderungen auf `main` +- Änderungen über Feature-Branch + Pull Request +- Merge erst nach erfolgreichem CI-Lauf + +--- + +## Lokales Arbeiten + +### Formatierung prüfen +```bash +clang-format --dry-run --Werror main.cpp tests/test_main.cpp +``` + +### Formatierung anwenden +```bash +clang-format -i main.cpp tests/test_main.cpp +``` + +### CI-Policy lokal testen +```bash +python3 ci/check_pr_policies.py +``` + +### Build lokal ausführen +```bash +cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug +cmake --build build --parallel +ctest --test-dir build --output-on-failure +``` + +--- + +## Voraussetzungen auf Jenkins-Seite + +Für das Setup werden u. a. folgende Jenkins-Plugins benötigt: + +- `docker-workflow` +- `pipeline-model-definition` +- `workflow-scm-step` +- `workflow-cps` +- `ws-cleanup` +- `gitea` +- `git` +- `git-client` +- `scm-api` +- `workflow-multibranch` + +Zusätzlich muss der Jenkins-Container Zugriff auf Docker haben, z. B. über: + +- Docker CLI im Jenkins-Container +- Mount von `/var/run/docker.sock` + +--- + +## Webhook / Automatischer Trigger + +Gitea ist so konfiguriert, dass **Push Events** an Jenkins gemeldet werden. + +Beispiel-Endpunkt: + +```text +https://jenkins.life-maps.com/gitea-webhook/post +``` + +Damit können automatisch Jenkins-Builds für Branches und Pull Requests ausgelöst werden. + +--- + +## Beispielziel des Repositories + +Dieses Repository dient aktuell als: + +- Referenz für Jenkins/Gitea-Integration +- Testumgebung für PR-Policies +- Minimalbeispiel für C++/CMake-basierte CI +- Grundlage für weitere CI- und Policy-Erweiterungen + +--- + +## Status + +Aktuell ist das Setup geeignet für: + +- Jenkins/Gitea-Webhook-Integration +- Pull-Request-basierte CI +- C++/CMake/Ninja Beispielprojekte +- Policy-basierte Qualitätsprüfungen im PR-Prozess \ No newline at end of file diff --git a/ci/check_pr_policies.py b/ci/check_pr_policies.py index fd87dcc..0e20a65 100644 --- a/ci/check_pr_policies.py +++ b/ci/check_pr_policies.py @@ -34,7 +34,10 @@ def git_ref_exists(ref: str) -> bool: except subprocess.CalledProcessError: return False -def resolve_target_ref() -> str: +def is_pull_request_build() -> bool: + return bool(os.environ.get("CHANGE_ID")) + +def resolve_target_ref() -> str | None: raw = os.environ.get("CHANGE_TARGET", "").strip() candidates = [] @@ -52,13 +55,27 @@ def resolve_target_ref() -> str: if git_ref_exists(ref): return ref - print("ERROR: Kein gültiger Ziel-Branch-Ref gefunden. Geprüft:", ", ".join(candidates)) - sys.exit(1) + return None def changed_files(): target = resolve_target_ref() - print(f"Vergleiche gegen Ziel-Ref: {target}") - out = run(f"git diff --name-only {target}...HEAD") + + if target: + print(f"Vergleiche gegen Ziel-Ref: {target}") + out = run(f"git diff --name-only {target}...HEAD") + return [line.strip() for line in out.splitlines() if line.strip()] + + if is_pull_request_build(): + print("ERROR: Kein gültiger Ziel-Branch-Ref für PR-Build gefunden.") + sys.exit(1) + + if git_ref_exists("HEAD~1"): + print("Kein Ziel-Branch-Ref gefunden, verwende HEAD~1 für Branch-Build.") + out = run("git diff --name-only HEAD~1..HEAD") + return [line.strip() for line in out.splitlines() if line.strip()] + + print("Keine Vergleichsbasis gefunden, behandle alle versionierten Dateien als geändert.") + out = run("git ls-files") return [line.strip() for line in out.splitlines() if line.strip()] def is_cpp_file(path: Path) -> bool: diff --git a/hook-test.txt b/hook-test.txt deleted file mode 100644 index 044762d..0000000 --- a/hook-test.txt +++ /dev/null @@ -1 +0,0 @@ -hook test Di 4. Aug 00:08:29 CEST 2026 diff --git a/protected-main-test.txt b/protected-main-test.txt deleted file mode 100644 index 1157fae..0000000 --- a/protected-main-test.txt +++ /dev/null @@ -1 +0,0 @@ -should fail diff --git a/push-hook-test.txt b/push-hook-test.txt deleted file mode 100644 index f2d2344..0000000 --- a/push-hook-test.txt +++ /dev/null @@ -1 +0,0 @@ -push-hook-test Di 4. Aug 00:11:58 CEST 2026