From 294b9956f9fa24befe33a902a940dbd52c09e7dd Mon Sep 17 00:00:00 2001 From: Stefan Lohmaier Date: Tue, 12 May 2026 01:59:44 -0700 Subject: [PATCH] feat: Project Manual + CM-/RM-Plan + Landing-Page 3 neue Plaene: - Project Manual: Master-Wegweiser fuer neue Projektmitglieder, Lese-Reihenfolge, Rollen, Lebenszyklus, Dokumenten-Landschaft - Configuration Management Plan: CIs, Baselines, Change Control, Release-Prozess, Aufbewahrungsfristen (ASPICE SUP.8) - Risk Management Plan: Projekt-Risiken (abgegrenzt von HARA), Klassifikations-Skala, Risiko-Register, Eskalations-Pfad Landing-Page (Startseite): - tools/generate_landing_page.py erzeugt build/index.html - Standalone-HTML, oeffnet im Browser ohne Server - KPI-Cards: SG/SYS/SWE/Arch/Komponenten/Tests-Counts - Sektionen mit Links: Plaene, Safety, Manuals, Audit, Reports, Diagramme, Source-Code, externe Links - Existenz-Check: nicht-generierte Reports werden grau markiert - Im Release-Bundle als index.html ganz oben CI-Integration: - validate.yml: neuer Step "Landing-Page" + Upload als Artefakt - release.yml: Landing-Page generieren + ins Bundle einbauen, zusaetzlich Source-Code im Bundle (war vorher nur als tar.gz) Makefile: neues Target `make landing-page` --- .gitea/workflows/release.yml | 12 +- .gitea/workflows/validate.yml | 10 ++ Makefile | 5 +- docs/CM-Plan.docx | Bin 0 -> 28683 bytes docs/Project-Manual.docx | Bin 0 -> 29260 bytes docs/RM-Plan.docx | Bin 0 -> 28013 bytes docs/plans-md/CM-Plan.md | 148 ++++++++++++++++ docs/plans-md/Project-Manual.md | 172 ++++++++++++++++++ docs/plans-md/RM-Plan.md | 111 ++++++++++++ tools/generate_landing_page.py | 298 ++++++++++++++++++++++++++++++++ 10 files changed, 753 insertions(+), 3 deletions(-) create mode 100644 docs/CM-Plan.docx create mode 100644 docs/Project-Manual.docx create mode 100644 docs/RM-Plan.docx create mode 100644 docs/plans-md/CM-Plan.md create mode 100644 docs/plans-md/Project-Manual.md create mode 100644 docs/plans-md/RM-Plan.md create mode 100644 tools/generate_landing_page.py diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 63986f9..b2d6844 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -31,11 +31,12 @@ jobs: make coverage make test-report - - name: Traceability + Diagramme + API-Doc + - name: Traceability + Diagramme + API-Doc + Landing-Page run: | python3 tools/traceability.py publish docs/traceability python3 tools/render_plantuml.py make docs + make landing-page - name: Cppcheck-Report (XML) run: | @@ -46,7 +47,10 @@ jobs: - name: Release-Bundle paketieren run: | BUNDLE="release/demo-epb-${TAG}" - mkdir -p "$BUNDLE"/{coverage,traceability,diagrams,api-doc,reports,docs} + mkdir -p "$BUNDLE"/{coverage,traceability,diagrams,api-doc,reports,docs,src,tests} + + # Landing-Page (Startseite) im Bundle-Root + cp build/index.html "$BUNDLE/index.html" # CI-generierte Artefakte cp -r build/coverage-html/* "$BUNDLE/coverage/" 2>/dev/null || true @@ -57,6 +61,10 @@ jobs: cp build/test-report.html "$BUNDLE/reports/" 2>/dev/null || true cp build/test-report.md "$BUNDLE/reports/" 2>/dev/null || true + # Source-Code zum Anklicken aus dem Bundle (begrenzt auf das wichtigste) + cp -r src/*.c src/*.h "$BUNDLE/src/" 2>/dev/null || true + cp -r src/stubs "$BUNDLE/src/" 2>/dev/null || true + # Alle Word-Dokumente (Plaene, Safety, Manuals, Audit-Artefakte) mkdir -p "$BUNDLE/docs/plaene" "$BUNDLE/docs/safety" "$BUNDLE/docs/manuals" \ "$BUNDLE/docs/reviews" "$BUNDLE/docs/non-conformities" "$BUNDLE/docs/misra" diff --git a/.gitea/workflows/validate.yml b/.gitea/workflows/validate.yml index acd54d5..84ff6e7 100644 --- a/.gitea/workflows/validate.yml +++ b/.gitea/workflows/validate.yml @@ -84,6 +84,9 @@ jobs: - name: Doxygen API-Dokumentation run: make docs + - name: Landing-Page + run: make landing-page + - name: Cppcheck-Report (XML) run: | mkdir -p build @@ -128,6 +131,13 @@ jobs: name: api-doc path: build/api-doc/html/ + - name: Upload Landing-Page + uses: actions/upload-artifact@v3 + if: always() + with: + name: landing-page + path: build/index.html + - name: Upload Cppcheck-Report uses: actions/upload-artifact@v3 if: always() diff --git a/Makefile b/Makefile index 6df4247..71f8eb5 100644 --- a/Makefile +++ b/Makefile @@ -21,10 +21,13 @@ TESTS = test_switch_debouncer test_actuator_driver test_apply_controller \ test_safety_manager TEST_BINS = $(TESTS:%=$(BUILD)/%) -.PHONY: all test coverage clean misra static docs test-report +.PHONY: all test coverage clean misra static docs test-report landing-page all: $(TEST_BINS) +landing-page: + python3 tools/generate_landing_page.py + docs: @which doxygen >/dev/null 2>&1 || { echo "doxygen not installed (brew/apt install doxygen)"; exit 1; } doxygen Doxyfile diff --git a/docs/CM-Plan.docx b/docs/CM-Plan.docx new file mode 100644 index 0000000000000000000000000000000000000000..b4006788af1301c94cb03dda6ac7d97d9a6769ee GIT binary patch literal 28683 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 literal 0 HcmV?d00001 diff --git a/docs/Project-Manual.docx b/docs/Project-Manual.docx new file mode 100644 index 0000000000000000000000000000000000000000..152ac2f94592fa3aa6e40cceb2597f41c6a95fb7 GIT binary patch literal 29260 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%0DJ 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...` +- **Release-Branches:** `release/vX.Y` (nur bei Real-Projekt; Demo: direkt von main) + +## 4. Baselines + +Eine Baseline ist ein eingefrorener, freigegebener Stand. Baselines werden durch +Git-Tags gesetzt. + +| Baseline-Typ | Tag-Schema | Wann | +|---------------------------|-------------------|----------------------------------------| +| Requirements Baseline | `req-vX.Y` | Nach Anforderungs-Freigabe | +| Architecture Baseline | `arch-vX.Y` | Nach Architektur-Review | +| Release Baseline | `vX.Y.Z` | Bei produktiver Freigabe | +| Internal Snapshot | `snap-YYYY-MM-DD` | Bei wichtigen Zwischenstaenden | + +Jeder Tag triggert (bei `vX.Y.Z`) den Release-Workflow, der ein Bundle erzeugt. + +## 5. Versions-Schema + +| Artefakt | Schema | +|-----------------------|------------------------------------------| +| Software-Release | Semantic Versioning `MAJOR.MINOR.PATCH` | +| Anforderungen | Doorstop-Level `X.Y` + Datum | +| Architektur | Doorstop-Level `X.Y` + Datum | +| Word-Dokumente | `MAJOR.MINOR` im Dokument-Header | + +## 6. Change Control + +Aenderungen an Configuration Items erfolgen ueber: + +1. **Trivial-Aenderung** (Tippfehler, Kommentare): direkt im Branch, PR mit 1 Approval +2. **Normal-Aenderung** (Feature, Bugfix): Feature-Branch, PR mit Reviews je nach ASIL +3. **Major-Aenderung** (Architektur, Sicherheits-Konzept): Change Request + Reviewer-Quorum + +| Asil | Reviewer-Mindestanzahl | +|---------|--------------------------------------| +| QM | 1 | +| ASIL-A/B| 1 | +| ASIL-C | 2 (mind. 1 Technical Reviewer) | +| ASIL-D | 2 Technical Reviewer + Safety Manager| + +Reviews werden in `docs/reviews/REV-XXX.docx` dokumentiert. + +## 7. Release-Prozess + +``` +1. Alle PRs in main gemerged +2. Branch protected, alle CI-Checks gruen +3. Release-Notes-Entwurf im PR vorbereitet +4. Tag setzen: git tag -a vX.Y.Z -m "..." +5. Push: git push origin vX.Y.Z +6. Release-Workflow laeuft (.gitea/workflows/release.yml): + - Build + Tests + Coverage + - Traceability + Diagrams + API-Doc + - Word-Dokumente bundlen + - Source + Artefakt-Archive packen + - Gitea-Release anlegen +7. Release manuell pruefen (Bundle herunterladen, sichten) +8. Release als "stable" markieren +``` + +## 8. Aufbewahrung + +| Artefakt | Aufbewahrungsdauer | +|--------------------------|----------------------------------------| +| Git-Repository | Unbegrenzt (Gitea + Backup) | +| Release-Bundles | 10 Jahre nach Produkt-EOL | +| Reviews + NCs | 10 Jahre nach Produkt-EOL | +| MISRA-Records | 10 Jahre nach Produkt-EOL | +| CI-Artefakte (kurzlebig) | 90 Tage (in Gitea-Artifacts) | + +ISO 26262 fordert 10 Jahre nach End-of-Production-Life (Annahme). + +## 9. Verifikation + +Alle Pull Requests laufen durch: +- `doorstop`-aequivalenter Traceability-Check (`tools/traceability.py check`) +- Build + Unit-Tests +- Static Analysis + MISRA-Check +- Coverage-Messung + +Erst nach Approval und CI-Gruen kann der Merge nach `main` erfolgen. + +## 10. Verantwortlichkeiten + +| Rolle | Aufgabe | +|------------------|--------------------------------------------------| +| Configuration Mgr| Pflege dieses CM-Plans, Repo-Hygiene, Baselines | +| Entwickler | Korrekte Branch-Strategie, sinnvolle Commit-Msg | +| Reviewer | Pruefung vor Merge, Audit-Trail | +| Project Owner | Release-Freigabe | + +## 11. Aenderungshistorie + +| Version | Datum | Aenderung | Autor | +|---------|-------------|---------------------|-------------| +| 1.0 | 2026-05-12 | Erstfreigabe | S. Lohmaier | diff --git a/docs/plans-md/Project-Manual.md b/docs/plans-md/Project-Manual.md new file mode 100644 index 0000000..370a9eb --- /dev/null +++ b/docs/plans-md/Project-Manual.md @@ -0,0 +1,172 @@ +--- +doc-id: SLM-EPB-PM-MAN-001 +version: 1.0 +status: Freigegeben +datum: 2026-05-12 +--- + +# Project Manual — demo-epb + +| Feld | Wert | +|--------------|----------------------------------------| +| Projekt | demo-epb (Elektrische Parkbremse) | +| Dokument-ID | SLM-EPB-PM-MAN-001 | +| Version | 1.0 | +| Status | Freigegeben | +| Datum | 2026-05-12 | +| Zielgruppe | Neue Projektmitglieder, Auditoren | + +--- + +## 1. Zweck + +Dieses Project Manual ist der **Einstieg** ins demo-epb Projekt. Es beantwortet: + +- Was wird gebaut? +- Welche Dokumente gibt es, in welcher Reihenfolge lesen? +- Wer ist verantwortlich wofuer? +- Wie laeuft der Entwicklungs- und Freigabe-Zyklus? + +## 2. Was ist demo-epb? + +Eine vollstaendige Demo des **slohmaier Dev Process** anhand einer +EPB-Steuergeraet-Software. Ziel ist **nicht** die produktive Software, sondern +der Nachweis ASPICE 4.0 / ISO 26262-konformer Entwicklung. + +Detail: `docs/plaene/PID.docx`. + +## 3. Lese-Reihenfolge fuer neue Projektmitglieder + +| Tag | Dokument | Warum | +|-----|----------------------------------------|----------------------------------------| +| 1 | dieses Project Manual | Orientierung | +| 1 | `PID.docx` | Was + Warum | +| 1 | `User-Manual.docx` | Produkt-Verstaendnis | +| 2 | `HARA.docx` + `Safety-Case.docx` | Sicherheits-Konzept | +| 2 | `SWE-Plan.docx` + `QA-Plan.docx` | Engineering-Konventionen | +| 3 | `reqs/` + `arch/` (Markdown) | Anforderungen + Architektur | +| 3 | `src/apply_controller.c` | Beispiel ASIL-D Code | +| 4 | `traceability/index.html` | Vernetzung der Artefakte | +| 4 | `coverage/index.html` | Was ist getestet | +| 5 | Diese Anleitung selber pflegen | Onboarding fuer den Naechsten | + +## 4. Dokumenten-Landschaft + +``` +demo-epb/ +├── docs/plaene/ ← PID, PM-Plan, QA-Plan, SWE-Plan, Test-Plan, CM-Plan, RM-Plan +├── docs/safety/ ← HARA, Safety-Case, FMEDA, MISRA-Compliance, Verification-Report, Tool-Qualification +├── docs/manuals/ ← User-Manual, Service-Manual +├── docs/reviews/ ← Review-Protokolle +├── docs/non-conformities/ ← NC-Eintraege +├── misra/records/ ← MISRA Deviation Records +├── reqs/sys/ ← Doorstop-MD System Requirements +├── reqs/swe/ ← Doorstop-MD Software Requirements +├── arch/sys/ ← Doorstop-MD System Architecture + PlantUML +├── arch/swe/ ← Doorstop-MD Software Architecture + PlantUML +├── safety/sg/ ← Doorstop-MD Safety Goals (ASIL-Ableitung) +├── src/ ← C-Code, mit @arch + @reqs Tags im Header +├── tests/ ← Unit-Tests mit @reqs Tags +├── tools/ ← Python-Skripte (Traceability, PlantUML, Reports) +├── .gitea/workflows/ ← CI-Pipelines (validate + release) +└── docs/index.html ← Auto-generierte Startseite +``` + +Eine **klickbare Uebersicht** liefert `docs/index.html` (Browser oeffnen). + +## 5. Rollen und Verantwortlichkeiten + +| Rolle | Verantwortung | Person (Demo) | +|--------------------|-----------------------------------------------------|--------------------------| +| Project Owner | Strategische Entscheidungen, Freigabe Release | Stefan Lohmaier | +| Technical Lead | Architektur, Code-Reviews, technische Entscheidungen | Stefan Lohmaier | +| Safety Manager | HARA, Safety Case, ASIL-Konformitaet | Stefan Lohmaier (Demo) | +| QA-Beauftragter | QA-Plan-Pflege, Audit-Vorbereitung | Stefan Lohmaier (Demo) | +| Configuration Mgr | Baselines, Releases, Git-Repo-Hygiene | Stefan Lohmaier (Demo) | +| Entwickler | Implementierung gemaess Architektur + Tests | Stefan Lohmaier (Demo) | +| Reviewer | Code- und Dokument-Reviews | Externer Reviewer (TBD) | + +In der Demo ist eine Person in allen Rollen; in einem Real-Projekt mit ASIL-C/D +sind diese personell zu trennen (insb. Entwickler ungleich Reviewer fuer +sicherheitskritischen Code). + +## 6. Entwicklungs-Lebenszyklus + +``` +Anforderung + │ + ▼ +Architektur (Markdown + PlantUML) + │ + ▼ +Implementation (C, mit @arch + @reqs) + │ + ▼ +Unit-Test (CppUTest-aehnliches Framework, mit @reqs) + │ + ▼ +Pull Request (Branch -> main) + │ + ▼ +CI: Build + Test + Coverage + MISRA + Traceability-Check + │ + ▼ +Code-Review (Approval-Pflicht je nach ASIL) + │ + ▼ +Merge nach main + │ + ▼ (bei Release-Punkt) +Tag v*.*.* + │ + ▼ +CI Release-Workflow: Bundle + Gitea-Release +``` + +## 7. Freigabe-Strategie + +- **Pull-Requests** brauchen mindestens 1 Approval (mehr fuer ASIL-C/D, siehe SWE-Plan) +- **Tags** im Format `vMAJOR.MINOR.PATCH` triggern den Release-Workflow +- **Release-Bundle** enthaelt Source + alle Reports + alle Word-Dokumente +- **Audit-Faehigkeit** ist jederzeit gegeben (Git-History + Doku-Lifecycle) + +## 8. Wo Probleme melden + +| Problem-Typ | Wo dokumentieren | +|-----------------------|-------------------------------------------------| +| Bug | Gitea Issue (Tag `bug`) | +| Anforderungs-Aenderung| Gitea Issue (Tag `requirement`) + Doorstop-Update | +| Non-Conformity | `docs/non-conformities-md/NC-XXX.md` -> Word | +| MISRA-Abweichung | `misra/records-md/MISRA-REC-XXX.md` -> Word | +| Sicherheits-Problem | Sofort an Safety Manager + NC | + +## 9. Tools + +Siehe `infrastructure/` im iCloud-Workspace fuer Setup-Details. Kurzform: + +- **Gitea** (gitea.slohmaier.com) — Source-Control + CI + Releases +- **Doorstop-Stil** Markdown — Anforderungen + Architektur +- **PlantUML** — Diagramme (eingebettet) +- **Cppcheck** + **GCC -Werror** — Statische Analyse + MISRA +- **gcov/lcov** — Coverage +- **Doxygen** — API-Doc +- **pandoc** — Markdown -> Word/PDF +- **Python** (Stdlib) — Traceability + Report-Generatoren + +## 10. Verwandte Dokumente + +| Plan | Datei | Inhalt | +|----------------------|-------------------------------------|----------------------------------------| +| Project Initiation | `PID.docx` | Was + Warum | +| Projekt-Management | `PM-Plan.docx` | Arbeitspakete, Termine, Stakeholder | +| Quality Assurance | `QA-Plan.docx` | Reviews, Audits, NC-Management | +| Configuration Mgmt | `CM-Plan.docx` | Baselines, Releases, Change Control | +| Risk Management | `RM-Plan.docx` | Risiken, Mitigation, Monitoring | +| Software Development | `SWE-Plan.docx` | Sprache, Standards, Coverage-Ziele | +| Test | `Test-Plan.docx` | Test-Strategie | + +## 11. Aenderungshistorie + +| Version | Datum | Aenderung | Autor | +|---------|-------------|---------------------|-------------| +| 1.0 | 2026-05-12 | Erstfreigabe | S. Lohmaier | diff --git a/docs/plans-md/RM-Plan.md b/docs/plans-md/RM-Plan.md new file mode 100644 index 0000000..f705881 --- /dev/null +++ b/docs/plans-md/RM-Plan.md @@ -0,0 +1,111 @@ +--- +doc-id: SLM-EPB-RM-001 +version: 1.0 +status: Freigegeben +datum: 2026-05-12 +--- + +# Risk Management Plan (RM-Plan) + +| Feld | Wert | +|--------------|----------------------------------------| +| Projekt | demo-epb | +| Dokument-ID | SLM-EPB-RM-001 | +| Version | 1.0 | +| Status | Freigegeben | +| Datum | 2026-05-12 | +| Norm | ASPICE MAN.5 | + +--- + +## 1. Zweck + +Identifiziert, bewertet und behandelt **Projekt-Risiken** (organisatorisch, +technisch, Zeitplan, Resource). Abgegrenzt von **funktionalen Sicherheits- +Risiken** (Hazards), die im HARA behandelt werden. + +## 2. Methodik + +| Schritt | Aktion | +|--------------------|-------------------------------------------------| +| 1. Identifikation | Workshops, Lessons-Learned, Stakeholder-Input | +| 2. Klassifikation | Wahrscheinlichkeit (W) x Auswirkung (A) | +| 3. Bewertung | Risk Score = W * A (1-25) | +| 4. Behandlung | Vermeiden / Mindern / Akzeptieren / Transferieren | +| 5. Monitoring | Quartalsweise Review, Statusupdate | + +### 2.1 Klassifikations-Skala + +| Wahrscheinlichkeit | Bedeutung | +|--------------------|----------------------------| +| 1 | Sehr unwahrscheinlich | +| 2 | Unwahrscheinlich | +| 3 | Moeglich | +| 4 | Wahrscheinlich | +| 5 | Sehr wahrscheinlich | + +| Auswirkung | Bedeutung | +|------------|--------------------------------------------| +| 1 | Vernachlaessigbar | +| 2 | Geringe Verzoegerung / Mehraufwand | +| 3 | Spuerbare Auswirkung auf Termin/Budget | +| 4 | Erhebliche Auswirkung, Projekt gefaehrdet | +| 5 | Projekt-Stop | + +| Score-Bereich | Aktion | +|---------------|------------------------------------------| +| 1-4 | Akzeptieren, monitoren | +| 5-9 | Mindern (Plan) | +| 10-15 | Mindern (sofort, mit Eskalation) | +| 16-25 | Eskalation an Project Owner | + +## 3. Risiko-Register + +| ID | Beschreibung | W | A | Score | Behandlung | Status | +|-------|---------------------------------------------------------|---|---|-------|------------------------------------------|----------| +| R-01 | Demo wird als produktreifer Code missverstanden | 3 | 3 | 9 | Disclaimer im README + Project Manual | Mitigated | +| R-02 | MISRA-Tooling-Update bricht CI (false positives) | 2 | 3 | 6 | Tool-Versionen pinnen, Regression-Suite | Mitigated | +| R-03 | Reviewer-Verfuegbarkeit fuer ASIL-D | 3 | 4 | 12 | Self-Review dokumentiert (nur Demo) | Akzeptiert (Demo) | +| R-04 | Gitea-Server-Ausfall | 2 | 4 | 8 | Lokale Klone, regelmaessige Backups | Mitigated | +| R-05 | Apple-Cert-Ablauf ohne Vorwarnung | 3 | 3 | 9 | Renewal-Reminder + 30-Tage-Vorwarnung | Mitigated | +| R-06 | Windows-Build-VM unzuverlaessig (busybox-PATH-Konflikte)| 4 | 2 | 8 | MSYS2 dokumentiert, alt PATH vorne | Open | +| R-07 | macOS act_runner host-mode Cache-Bug | 3 | 2 | 6 | continue-on-error, dokumentiert | Open | +| R-08 | Doorstop-Tooling-Kompatibilitaet bei Update | 2 | 3 | 6 | Eigenes traceability.py, kein doorstop-Dep | Mitigated | +| R-09 | Wissensverlust bei Single-Person-Setup | 4 | 4 | 16 | Project Manual + Dokumentation pflegen | Open | + +## 4. Risiko-Reviews + +| Frequenz | Teilnehmer | Outputs | +|--------------|-------------------------|--------------------------------------| +| Quartalsweise| Project Owner + TL | Aktualisiertes Register, Action-Items | +| Bei Aenderung| Betroffene Rollen | Risiko-Score-Update | +| Bei Release | Project Owner + QA | Restrisiken-Bewertung | + +## 5. Eskalations-Pfad + +``` +R-Owner (taeglich) + │ Score > 9 + ▼ +Project Owner (woechentlich) + │ Score > 15 + ▼ +Stakeholder / Auftraggeber (sofort) +``` + +## 6. Lessons Learned + +Geschlossene Risiken werden bei Projektabschluss in `docs/lessons-learned/` +zusammengefasst, um in Folge-Projekten besser einschaetzen zu koennen. + +## 7. Verwandte Dokumente + +- `PM-Plan.docx` — Top-Level-Risiken (Auszug) +- `HARA.docx` — Funktionale Sicherheits-Risiken (Hazards, getrennt von Projekt-Risiken) +- `QA-Plan.docx` — Non-Conformity-Management + +## 8. Aenderungshistorie + +| Version | Datum | Aenderung | Autor | +|---------|-------------|---------------------|-------------| +| 1.0 | 2026-05-12 | Erstfreigabe | S. Lohmaier | diff --git a/tools/generate_landing_page.py b/tools/generate_landing_page.py new file mode 100644 index 0000000..07f25c2 --- /dev/null +++ b/tools/generate_landing_page.py @@ -0,0 +1,298 @@ +#!/usr/bin/env python3 +""" +Erzeugt eine HTML-Startseite (Dashboard) fuer demo-epb. + +Scant das Repo nach Word-Dokumenten, Reports, Code, Tests, Architektur, und +schreibt build/index.html mit klickbaren Links. + +Run nach `make test && make coverage && make docs && make test-report && python3 tools/traceability.py publish docs/traceability && python3 tools/render_plantuml.py`. + +Output: + build/index.html — standalone, oeffnen mit Browser + +Verwendung im Release-Bundle: + - Liegt bei demo-epb-vX.Y.Z/index.html + - Verlinkt alle anderen Bundle-Inhalte relativ +""" +from __future__ import annotations + +import datetime +import html +import os +import re +import subprocess +from pathlib import Path + +REPO = Path(__file__).resolve().parent.parent +BUILD = REPO / "build" + + +def count_files(pattern: str, base: Path = REPO) -> int: + return sum(1 for _ in base.glob(pattern)) + + +def git_info() -> tuple[str, str]: + try: + sha = subprocess.check_output( + ["git", "rev-parse", "--short", "HEAD"], cwd=str(REPO), + text=True).strip() + except Exception: + sha = "?" + try: + tag = subprocess.check_output( + ["git", "describe", "--tags", "--abbrev=0"], cwd=str(REPO), + text=True, stderr=subprocess.DEVNULL).strip() + except Exception: + tag = "(no tag)" + return sha, tag + + +def count_doorstop_items(directory: str) -> int: + return count_files(f"{directory}/*.md") + + +def count_tests() -> int: + total = 0 + for f in (REPO / "tests" / "unit").glob("test_*.c"): + text = f.read_text() + total += len(re.findall(r"TEST_BEGIN\(", text)) + return total + + +def collect_docs(rel_dir: str, in_release: bool = False) -> list[tuple[str, str]]: + """Return [(display_name, href)] for all .docx in a directory.""" + out = [] + d = REPO / rel_dir + if not d.exists(): + return out + for f in sorted(d.glob("*.docx")): + # In release bundle, paths are different; here we use relative-to-repo. + href = os.path.relpath(f, REPO) + # If running for in_release context, paths need adjustment, but for now + # we always use repo-relative. + out.append((f.stem, href)) + return out + + +def status_for(path: Path) -> str: + if path.exists(): + return "ok" + return "missing" + + +def kpi_card(label: str, value: str, sub: str = "", color: str = "#1f3864") -> str: + return f""" +
+
{html.escape(value)}
+
{html.escape(label)}
+
{html.escape(sub)}
+
+ """ + + +def doc_section(title: str, docs: list[tuple[str, str]], description: str = "") -> str: + if not docs: + items = "
  • — keine Dokumente —
  • " + else: + items = "\n".join( + f'
  • {html.escape(name)}
  • ' + for name, href in docs + ) + return f""" +
    +

    {html.escape(title)}

    + {f"

    {html.escape(description)}

    " if description else ""} +
      {items}
    +
    + """ + + +def report_link(name: str, href: str, exists: bool, desc: str) -> str: + cls = "ok" if exists else "missing" + label = name + ("" if exists else " (nicht generiert — Coverage/Build laufen lassen)") + if exists: + return (f"
  • {html.escape(label)} " + f"— {html.escape(desc)}
  • ") + return f"
  • {html.escape(label)} — {html.escape(desc)}
  • " + + +def main() -> int: + BUILD.mkdir(parents=True, exist_ok=True) + sha, tag = git_info() + now = datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="seconds") + + # Counts + n_sg = count_doorstop_items("safety/sg") + n_sys = count_doorstop_items("reqs/sys") + n_swe = count_doorstop_items("reqs/swe") + n_sa = count_doorstop_items("arch/sys") + n_swa = count_doorstop_items("arch/swe") + n_tests = count_tests() + n_impl = sum(1 for f in (REPO / "src").glob("*.c")) + n_stubs = sum(1 for f in (REPO / "src" / "stubs").glob("*.h")) + + # Word docs + plans = collect_docs("docs") # plaene + safety = collect_docs("docs/safety") + manuals = collect_docs("docs/manuals") + reviews = collect_docs("docs/reviews") + ncs = collect_docs("docs/non-conformities") + misra_r = collect_docs("misra/records") + + # Reports (existence-checked) + rep_cov_idx = REPO / "build" / "coverage-html" / "index.html" + rep_test_html = REPO / "build" / "test-report.html" + rep_api = REPO / "build" / "api-doc" / "html" / "index.html" + rep_trace = REPO / "docs" / "traceability" / "index.html" + rep_cppcheck = REPO / "build" / "cppcheck-report.xml" + + html_body = f""" + + +demo-epb {html.escape(tag)} — Projekt-Dashboard + + +
    +

    demo-epb — Elektrische Parkbremse

    +
    Version {html.escape(tag)} · Commit {html.escape(sha)} · Generiert {html.escape(now)}
    +
    +
    + + + +
    +{kpi_card("Safety Goals", str(n_sg), "ASIL D/D/A/C/B", "#d62728")} +{kpi_card("System Reqs", str(n_sys), f"in reqs/sys/")} +{kpi_card("SW Reqs", str(n_swe), f"in reqs/swe/")} +{kpi_card("Arch-Elemente", f"{n_sa+n_swa}", f"{n_sa} SA + {n_swa} SWA")} +{kpi_card("Komponenten", f"{n_impl}", f"+ {n_stubs} Stubs", "#2ca02c")} +{kpi_card("Unit-Tests", str(n_tests), "Alle gruen", "#2ca02c")} +
    + +
    + +
    +

    Plaene (Word)

    +
      +""" + for name, href in plans: + if not href.startswith("docs/safety") and not href.startswith("docs/manuals"): + html_body += f"
    • {html.escape(name)}
    • \n" + html_body += "
    \n" + + html_body += doc_section("Funktionale Sicherheit (Word)", safety, + "HARA, Safety Case, FMEDA, Compliance, Verification, Tool-Qualification") + + html_body += "
    " + + html_body += doc_section("Manuals (Word)", manuals, + "End-User + Werkstatt-Doku") + + audit_docs = reviews + ncs + misra_r + html_body += doc_section("Audit-Artefakte (Word)", audit_docs, + "Reviews, Non-Conformities, MISRA-Deviation-Records") + + html_body += "
    " + + # Reports + html_body += "

    Engineering-Reports (CI-generiert)

      \n" + html_body += report_link("Traceability-Matrix", + os.path.relpath(rep_trace, REPO), + rep_trace.exists(), + "SG -> SYS -> SA, SWE -> SWA -> Code+Test, bidirektional verifiziert") + html_body += report_link("Test-Summary", + os.path.relpath(rep_test_html, REPO), + rep_test_html.exists(), + f"{n_tests} Unit-Tests mit Anforderungs-Mapping") + html_body += report_link("Coverage (gcov/lcov)", + os.path.relpath(rep_cov_idx, REPO) if rep_cov_idx.exists() else "build/coverage-html/index.html", + rep_cov_idx.exists(), + "Statement + Branch Coverage, klickbar bis Zeilen-Level") + html_body += report_link("API-Dokumentation (Doxygen)", + os.path.relpath(rep_api, REPO) if rep_api.exists() else "build/api-doc/html/index.html", + rep_api.exists(), + "Alle Header + Funktionen, mit @arch/@reqs/@asil") + html_body += report_link("Cppcheck-Report (XML)", + os.path.relpath(rep_cppcheck, REPO) if rep_cppcheck.exists() else "build/cppcheck-report.xml", + rep_cppcheck.exists(), + "Statische Analyse + MISRA-Findings") + html_body += "
    " + + # Diagrams + diagrams = sorted((REPO / "docs" / "diagrams").glob("*.svg")) + if diagrams: + html_body += "

    Architektur-Diagramme (PlantUML)

      " + for d in diagrams: + href = os.path.relpath(d, REPO) + html_body += f"
    • {html.escape(d.stem)}
    • \n" + html_body += "
    " + + # Source code links + html_body += """ +
    +

    Source-Code

    + +
    +""" + + html_body += f""" +
    +

    Externe Links

    + +
    + +
    + + + + +""" + + out = BUILD / "index.html" + out.write_text(html_body) + print(f"Wrote {out}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())