Files
PolyTraderSharp/docs/LEITFADEN-CI.md
T
RichardandClaude Opus 5 5507db3e32 CI fuer Gitea Actions: Build und Tests auf Linux plus Waechter gegen Rueckfaelle
Die Plattformneutralitaet war nach dem WinForms-Ausbau eine Momentaufnahme: eine
einzige net10.0-windows-Zeile oder ein "using System.Drawing" genuegt, und der
Linux-Build ist kaputt, ohne dass es auf einer Windows-Maschine auffaellt - dort
baut es weiter. Genau das faengt die CI ab, und zwar auf Linux.

.gitea/workflows/ci.yml, zwei Jobs auf ubuntu-latest:

- build-test: restore, build, die 476 Tests (brauchen keine DB, laufen gegen
  EF-InMemory), Linux-Publish. Der Publish ist kein Selbstzweck - dort faellt
  auf, wenn ein Paket doch windows-only ist. Anschliessend wird geprueft, dass
  die Executable, appsettings.json, setup.json und libSkiaSharp.so wirklich im
  Ergebnis liegen.
- guard: keine windows-TFMs, kein UseWindowsForms/UseWPF, keine windows-only
  using-Direktiven, keine versionierten Secret-Dateien, keine anfaelligen Pakete.

Alle Waechter sind in beide Richtungen gegengeprueft: sie schlagen bei
simulierten Regressionen an (windows-TFM, UseWindowsForms, using System.Drawing,
getrackte packager.config.json samt dc_sub_-Token, Newtonsoft 11.0.2) und
schweigen beim Ist-Zustand. Die Namespace-Pruefung trifft bewusst nur echte
using-Direktiven: im Bestand steht an vielen Stellen erklaert, WARUM
System.Drawing nicht verwendet wird, und das darf keinen Fehlalarm ausloesen.

Der Schwachstellen-Check ist Punkt 1 der wiederkehrenden Audit-Checkliste aus
dem Sicherheitskonzept - laeuft ab jetzt bei jedem Push statt quartalsweise von
Hand. Er wuerde zum Beispiel anschlagen, wenn der Newtonsoft-Pin im Core faellt.

Bewusst kein -warnaserror: die 15 vorhandenen Warnungen muessten erst weg, sonst
ist die CI ab dem ersten Tag rot und wird ignoriert.

WICHTIG - die CI laeuft noch nicht: auf der Gitea-Instanz ist kein Actions-Runner
registriert (auf Repo-, Benutzer- und Instanzebene geprueft, ueberall 0).
has_actions ist true, es fehlt nur der Runner. Einrichtung Schritt fuer Schritt
in docs/LEITFADEN-CI.md Abschnitt 3.

.gitattributes neu: erzwingt LF fuer .yml/.sh/.service. Entwickelt wird mit
autocrlf=true auf Windows, ausgefuehrt auf Linux - ein Shell-Skript mit CRLF
scheitert dort mit irrefuehrenden Meldungen. Bisher gab es keine .gitattributes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-22 11:25:01 +02:00

6.5 KiB

Leitfaden: Continuous Integration

Stand: 22.08.2026 · Workflow: .gitea/workflows/ci.yml

Status: Der Workflow liegt, der Runner fehlt noch. Gitea 1.26.2 hat Actions aktiviert (has_actions: true), aber auf der Instanz ist kein einziger Runner registriert — geprüft auf Repo-, Benutzer- und Instanzebene. Bis Abschnitt 3 erledigt ist, passiert bei einem Push nichts. Der Workflow ist dann sofort lauffähig, ohne weitere Änderung.


1. Warum überhaupt

PolyTrader soll auf einem Linux-Server laufen. Der plattformneutrale Zustand wurde am 22.08.2026 mit dem WinForms-Ausbau hergestellt — und er driftet ohne Wächter wieder weg. Eine einzige net10.0-windows-Zeile oder ein using System.Drawing genügt, und der Linux-Build ist kaputt, ohne dass es auf einer Windows-Entwicklermaschine auffällt: dort baut es weiter.

Genau deshalb läuft die CI auf Linux. Sie ist kein Selbstzweck, sondern die einzige Instanz, die den mühsam hergestellten Zustand verteidigt.

2. Was geprüft wird

Zwei Jobs, beide auf ubuntu-latest:

build-test — Build & Tests

Schritt Zweck
dotnet restore Der lokale Feed lib/nuget (Deploymentcenter-SDK) ist relativ eingebunden und liegt im Repo — nichts einzurichten
dotnet build -c Release Baut alle 7 Projekte
dotnet test Die 476 Tests. Brauchen keine Datenbank — sie laufen gegen EF-InMemory
dotnet publish -r linux-x64 Kein Selbstzweck: hier fällt auf, wenn ein Paket doch windows-only ist
Publish-Prüfung Erwartet PolyTrader.App.Avalonia, appsettings.json, setup.json und libSkiaSharp.so — ohne die native Skia-Bibliothek wäre Avalonia auf Linux nicht lauffähig

guard — Plattformneutralität & Hygiene

Prüfung Schlägt fehl bei
Zielframeworks irgendeinem <TargetFramework>…-windows in einer .csproj
WinForms/WPF <UseWindowsForms>true oder <UseWPF>true
Namespaces echten using System.Windows.Forms; / using System.Drawing;-Direktiven in src/ oder tests/
Secret-Dateien deploy/packager.config.json, appsettings.Local.json, master.key, openrouter.key, .gitea-token oder server_settings.xml versioniert; oder einem Deploymentcenter-Token im Klartext
Schwachstellen dotnet list package --vulnerable --include-transitive findet etwas

Zur Namespace-Prüfung: Sie trifft bewusst nur echte using-Direktiven, keine Kommentare. Im Bestand steht an vielen Stellen erklärt, warum System.Drawing nicht verwendet wird — das darf keinen Fehlalarm auslösen. Beide Richtungen sind gegengeprüft.

Zum Schwachstellen-Check: Das ist Punkt 1 der wiederkehrenden Audit-Checkliste aus sicherheit/SICHERHEITSKONZEPT.md — läuft ab jetzt bei jedem Push statt quartalsweise von Hand. Er würde zum Beispiel anschlagen, wenn der Newtonsoft.Json-Pin im Core entfernt wird: Nethereum 6.1.0 löst dann transitiv auf 11.0.2 auf (GHSA-5crp-9r3c-p9vr, Schweregrad hoch).

Die Warnungen des Builds (aktuell 15) lassen die CI nicht fehlschlagen. -warnaserror wäre hier verfrüht: die vorhandenen Warnungen müssten erst abgearbeitet werden, sonst ist die CI ab dem ersten Tag rot und wird ignoriert.

3. Runner einrichten (einmalig)

Ohne Runner führt Gitea den Workflow nicht aus. Der Runner ist ein eigenes Programm (act_runner), das sich beim Gitea-Server meldet und Jobs abholt. Er läuft sinnvollerweise auf dem Gitea-Host (192.168.178.10) oder jeder anderen Maschine im selben Netz, die Docker hat.

3.1 Registrierungstoken holen

In der Weboberfläche: Repo → Einstellungen → Actions → Runner → „Runner erstellen". Dort steht ein Token der Form . Alternativ instanzweit unter Website-Verwaltung → Actions → Runner, wenn der Runner mehreren Repos dienen soll — für den Anfang genügt der Repo-Runner.

3.2 Runner per Docker starten

docker run -d --restart always \
  --name gitea-runner \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /opt/gitea-runner:/data \
  -e GITEA_INSTANCE_URL=http://192.168.178.10:8418 \
  -e GITEA_RUNNER_REGISTRATION_TOKEN=<TOKEN_AUS_3.1> \
  -e GITEA_RUNNER_NAME=polytrader-runner \
  -e GITEA_RUNNER_LABELS=ubuntu-latest:docker://catthehacker/ubuntu:act-latest \
  gitea/act_runner:latest

Das GITEA_RUNNER_LABELS-Feld ist der kritische Teil. Es bildet runs-on: ubuntu-latest aus dem Workflow auf ein Container-Image ab. Fehlt das Label, bleibt der Job auf „warten auf Runner" stehen, ohne Fehlermeldung. Das Image catthehacker/ubuntu:act-latest bringt Node mit, das actions/checkout und actions/setup-dotnet benötigen.

Der Mount von docker.sock ist nötig, weil der Runner die Job-Container selbst startet.

3.3 Prüfen

curl -s -H "Authorization: token $(cat ~/.gitea-token)" http://192.168.178.10:8418/api/v1/repos/Richard/PolyTraderSharp/actions/runners

Steht dort "total_count": 0, hat sich der Runner nicht registriert — dann in die Logs sehen: docker logs gitea-runner.

Danach den Workflow von Hand anstoßen: Repo → Actions → CI → „Run workflow" (workflow_dispatch ist im Workflow vorgesehen). Der erste Lauf dauert länger, weil das .NET-SDK heruntergeladen wird.

4. Wenn kein Internetzugang besteht

actions/setup-dotnet lädt das SDK von Microsoft. Ist der Runner offline, gibt es zwei Wege:

  1. Container-Image mit SDK statt setup-dotnet — im Workflow je Job ergänzen:
    container:
      image: mcr.microsoft.com/dotnet/sdk:10.0
    
    Dann muss das setup-dotnet-Steps-Paar entfallen. Achtung: Dieses Image bringt kein Node mit; actions/checkout braucht es. Entweder ein eigenes Image bauen (dotnet/sdk:10.0 + nodejs) oder auschecken per git clone statt per Action.
  2. SDK im Runner-Image vorinstallieren und setup-dotnet weglassen.

Weg 1 mit eigenem Image ist der sauberere, sobald das Netz wirklich zu ist.

5. Was die CI (noch) nicht tut

  • Kein Deployment. Die Auslieferung läuft über den Deploymentcenter-Packager (deploy/packager.config.json, siehe Schnitt D-4). Das bewusst nicht automatisiert, solange die Live-Abnahme aussteht.
  • Keine Integrationstests gegen eine echte MySQL. Die Testsuite läuft gegen EF-InMemory. Ein MySQL-Service-Container wäre der nächste sinnvolle Ausbauschritt, wenn die Repository-Schicht einmal gegen echtes SQL geprüft werden soll.
  • Kein -warnaserror. Siehe Kasten in Abschnitt 2.