# ===================================================================== # Fortlaufende Prüfung (CI) – VORBEREITET, läuft derzeit nirgends. # # Dieses Projekt hat noch kein Fernarchiv. Diese Datei behauptet also # nicht, es gebe CI – sie liegt bereit, damit nach dem ersten `git push` # in ein GitHub-Repository die Prüfung ohne weiteren Handgriff # anspringt. Einrichtung und Begründung: docs/fernarchiv.md. # # Die CI erfindet kein zweites Regelwerk: Der Job „gate“ ruft exakt # `npm run gate` auf – dieselbe Vollstufe wie am Arbeitsplatz (Typen, # Linter, Vitest, Bau, Playwright-E2E samt axe je Ansicht). Ändert sich # das Gate in app/package.json, folgt die CI automatisch; ein zweiter, # hier abgeschriebener Befehlssatz würde genau dann auseinanderlaufen, # wenn es darauf ankommt. # # windows-latest, weil die Anwendung für Windows gebaut und ausgeliefert # wird: Die E2E-Läufe messen Kontrast und Zielgrößen im echten # Electron-Fenster, und nur der Windows-Lauf prüft die Plattform, die # tatsächlich bei Anwendern steht. (Unter Linux käme zusätzlich die # Frage nach einer Bildschirmumgebung für Electron dazu – hier nicht.) # ===================================================================== name: Gate on: push: pull_request: branches: [main] workflow_dispatch: # Der Lauf liest nur den Quellstand. Kein Schreibrecht, weil die CI hier # nichts veröffentlicht – gebaut und ausgeliefert wird am Arbeitsplatz # (docs/veroeffentlichen.md). permissions: contents: read # Wer zweimal kurz hintereinander schiebt, braucht den ersten Lauf nicht # mehr. Windows-Läufer zählen auf das Freikontingent doppelt. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: gate: name: Gate (Vollstufe) runs-on: windows-latest timeout-minutes: 40 defaults: run: working-directory: app steps: - name: Quellstand holen uses: actions/checkout@v4 # `engines` in app/package.json verlangt Node >= 22.12.0. Bewusst die # 22er-Linie fest verdrahtet statt `node-version-file`: ein „>=“-Bereich # würde dort stillschweigend auf die jeweils neueste Hauptversion # springen, und die CI soll dieselbe Linie prüfen wie der Arbeitsplatz. - name: Node einrichten uses: actions/setup-node@v4 with: node-version: 22 cache: npm cache-dependency-path: app/package-lock.json # `npm ci` genügt: `better-sqlite3` liefert N-API-Prebuilds, die unter # Node wie unter Electron ohne Neubau laufen (deshalb steht in # electron-builder.yml `npmRebuild: false`; Näheres in app/README.md, # Abschnitt „Native Module“). `npm run rebuild` gehört hier also nicht # hin. Über `prepare` läuft auch hooks:einrichten – im Runner # wirkungslos, aber harmlos: hier committet niemand. - name: Abhängigkeiten installieren run: npm ci # Nachgesehen: Keine Suite unter e2e/ startet einen Browser. Alle laufen # über `_electron` gegen das Electron aus node_modules, und axe-core wird # als Quelltext in die Seite injiziert (e2e/axe-hilfe.ts) – gerade weil # `@axe-core/playwright` in Electron scheitert. Dieser Schritt lädt also # einen Chromium herunter, den heute kein Test benutzt. Er bleibt # trotzdem stehen: Er ist der versionierte Befehl aus package.json, und # ein künftiger browserbasierter Test soll an seiner Sache scheitern, # nicht an einer fehlenden Installation. Wer Minuten sparen will, # streicht ihn. - name: Playwright-Browser installieren run: npm run test:e2e:install # CI=true (von GitHub gesetzt) schaltet in playwright.config.ts # forbidOnly, einen Wiederholungsversuch und den HTML-Bericht ein. # `gepackt.spec.ts` übergeht sich hier mit Grund – die CI baut kein # Installationspaket, und der Stempelbericht am Ende sagt das # ausdrücklich, statt grün zu melden, was nicht geprüft wurde. - name: Vollstufe des Gates run: npm run gate # Anlage 4 des Prüfplans (docs/barrierefreiheit-pruefplan.md) verlangt # die axe-Ausgaben der CI-Läufe „mit Datum und Commit-Kennung“ – als # Anlage, nicht als Ergebnis. Der Artefaktname trägt die Commit-Kennung, # Datum und Auslöser stehen am Lauf. # # Was der Bericht NICHT hergibt: dieselbe Anlage verlangt die Ausgaben # auch „je Farbschema“, und die E2E-Suiten prüfen axe bisher nur im # voreingestellten Schema. Der Upload erledigt diesen Punkt also nicht, # er belegt nur den geprüften Teil. # # `if: always()`, weil gerade der rote Lauf den Bericht braucht: Die # axe-Befunde stehen im Fehlertext der jeweiligen Prüfung. - name: Playwright-Bericht als Anlage sichern if: always() uses: actions/upload-artifact@v4 with: name: playwright-bericht-${{ github.sha }} path: app/playwright-report/ if-no-files-found: warn # Spuren (Traces) entstehen nur bei Fehlschlägen (retain-on-failure) – # deshalb `ignore` statt `warn`: Ein grüner Lauf ohne Spuren ist der # Normalfall und keine Meldung wert. - name: Fehlspuren sichern if: always() uses: actions/upload-artifact@v4 with: name: testspuren-${{ github.sha }} path: app/test-results/ if-no-files-found: ignore # Eigener Job, weil die Inhaltsprüfung nichts mit dem App-Gate teilt: # reine Python-Standardbibliothek, kein npm, kein Fenster. Ubuntu, weil # die Skripte plattformunabhängig lesen (Ein- und Ausgabe ausdrücklich # UTF-8) und der Runner schneller startet als Windows. # # Nachgesehen für alle drei Skripte: importiert werden nur io, json, re, # sys, collections, dataclasses und pathlib – pruefe_glossar.py zusätzlich # pruefe_erklaerungen.py, dessen Fundstellenprüfung es erbt. Kein pip-Schritt # nötig. `diagnose_kreuze.py` gehört deshalb ausdrücklich NICHT hierher: Es # braucht PyMuPDF und das nicht versionierte Katalog-PDF. # # Die Skripte lösen ihre Pfade über __file__ auf und brauchen deshalb kein # bestimmtes Arbeitsverzeichnis. Sie lesen nur Eingechecktes: # content/katalog/katalog.json, content/erklaerungen.json, # content/glossar.json und den Gesetzesindex content/gesetze/index.json – # die rohen Gesetzes-XML sind nicht versioniert und werden hier auch nicht # gebraucht. inhalte: name: Inhalte prüfen (Katalog, Erklärungen, Glossar) runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Quellstand holen uses: actions/checkout@v4 - name: Python einrichten uses: actions/setup-python@v5 with: python-version: "3.12" - name: Katalog gegen Sollwerte prüfen run: python data-pipeline/validate_catalog.py - name: Erklärungen gegen Katalog und Gesetzesindex prüfen run: python data-pipeline/pruefe_erklaerungen.py # Aus demselben Grund wie unten beim Glossar: Der Prüfer erzeugt jede # seiner 23 Fehlerarten einmal absichtlich und fällt durch, sobald eine # davon unbemerkt bliebe. - name: Erklärungsprüfung selbst prüfen run: python data-pipeline/pruefe_erklaerungen.py --selbsttest - name: Glossar gegen Katalog und Gesetzesindex prüfen run: python data-pipeline/pruefe_glossar.py # Die Prüfung der Prüfung: Sie verletzt jede Glossarregel einmal # absichtlich und fällt durch, sobald eine Verletzung unbemerkt bliebe. # Ohne diesen Schritt wäre der vorige nicht mehr wert als seine # Rückgabe – eine Regel, die stumm nichts mehr prüft, meldet dort # weiterhin grün. - name: Glossarprüfung selbst prüfen run: python data-pipeline/pruefe_glossar.py --selbsttest