Skip to content

Contributing

tom-schorn edited this page Sep 26, 2026 · 2 revisions

Mitmachen

Duofy steht unter der AGPL-3.0. Du darfst es nutzen, betreiben, ändern und weitergeben. Wer eine geänderte Fassung als Netzdienst anbietet, muss seinen Quellcode ebenfalls offenlegen — das ist die einzige Bedingung, die über „nimm es" hinausgeht.


Was gebraucht wird

Nicht nur Code. In dieser Reihenfolge nützlich:

Echte Grenzfälle. Duofy ist aus einem Haushalt entstanden und trägt dessen Blickwinkel. Wenn bei dir etwas nicht aufgeht — eine Zahlungsform, die nicht passt, eine Einnahme, die in kein Feld will, eine Aufteilung, die Duofy nicht kennt — dann ist das die wertvollste Rückmeldung überhaupt. Aufschreiben, Issue aufmachen.

Fehler. Was hast du getan, was hast du erwartet, was passierte. Wenn du kannst: Browser und ob es reproduzierbar ist.

Formulierungen. Beschriftungen, Fehlermeldungen, Wiki-Seiten. Wer zum ersten Mal draufschaut, sieht Unklarheiten, die man selbst nicht mehr sieht.

Übersetzungen. Die Oberfläche gibt es vorerst nur auf Deutsch, sie ist aber für weitere Sprachen gebaut — wie das geht, steht auf der Seite Neue Sprache beitragen. Das Wiki, das README, Issues und diese Seite bleiben deutsch.

Code. Siehe unten.


Bevor du anfängst

Zu jeder Arbeit gehört ein Issue. Nicht als Bürokratie, sondern damit nicht zwei Leute dasselbe bauen und einer die Arbeit wegwirft.

  1. Schau in die offenen Issues, ob es schon eins gibt
  2. Wenn nicht, mach eins auf und beschreibe, was du vorhast
  3. Schreib einen Kommentar, dass du es übernimmst — dann wird es dir zugewiesen

Wer zugewiesen ist, hat den Part. Ohne Zuweisung weiß niemand, dass daran gearbeitet wird. Wenn du nicht weiterkommst oder die Lust verlierst, schreib es ins Issue und gib es zurück. Das ist völlig in Ordnung und besser, als es still liegen zu lassen.

Bei größeren Sachen: erst reden, dann bauen. Ein Issue mit „so würde ich es machen" kostet zehn Minuten. Ein fertiger Pull Request, der in die falsche Richtung geht, kostet einen Abend.


Der Weg

Fork  →  feat/9-kurzbeschreibung  →  Pull Request gegen main

Es gibt nur einen Hauptzweig, main (Trunk), und keine langen Zweige daneben. Ein Branch ist höchstens ein Stück lang und wird immer von main abgezweigt.

Branch-Muster: typ/issue-nummer-kurzbeschreibung. Typen: feat, fix, docs, refactor, test, chore.

feat/9-income-commitment-type
fix/12-category-labels
docs/7-installation-page

Sprache: Code, Kommentare, Commit- und PR-Titel sind englisch. Issues, Wiki und README sind deutsch.

Jeder Commit folgt den Conventional Commits und macht genau eine Sache. Ein Pull Request wird per Rebase-Merge übernommen, nicht per Squash: die Einzelcommits bleiben erhalten, und aus ihnen entstehen Version und Changelog. Deshalb prüft die Pipeline jeden Betreff und den Titel des Pull Requests:

Betreff Nächste Version
fix: correct the category label Patch
feat: add income as its own type Minor
feat!: remove plan states Major
docs: · test: · refactor: · chore: keine

GitHubs „Revert“-Betreffe und fixup!-Commits müssen vor dem Merge umformuliert werden, sonst fallen sie durch die Prüfung.

Commits signieren: git commit -s. Das setzt eine Signed-off-by-Zeile und ist die Zusicherung, dass du das Recht hast, den Beitrag beizusteuern — das Developer Certificate of Origin. Ein Workflow prüft es; ohne Signatur bleibt der Pull Request rot.

Nachträglich setzen geht:

git rebase --signoff main

Größe. Richtwert: unter 300 geänderte Zeilen, Tests und Migrationen nicht mitgezählt. Ab etwa 1000 wird vorher geteilt.

Migrationen gibt der Maintainer frei, bevor sie gemerged werden.


Was ein Pull Request erfüllen muss

Vier Prüfungen laufen automatisch:

Prüfung Was sie will
titel Titel und jeder Commit-Betreff nach dem Muster oben
dco jeder Commit signiert
backend ruff check und pytest
frontend Typen, Lint, Tests, Build

Lass sie vorher lokal laufen, dann wartest du nicht:

cd backend && uv run ruff check app/ tests/ && uv run pytest -q
cd frontend && npx tsc --noEmit -p tsconfig.app.json && npx tsc --noEmit -p tsconfig.test.json && npm run lint && npm run build

Dazu zwei Dinge, die kein Automat prüfen kann:

Neue Logik bringt einen Test mit. Was eine Regel rechnet, wird geprüft. Die Backend-Tests brauchen ein echtes Postgres (POSTGRES_DB muss „test“ enthalten, die Tests löschen alle Tabellen) — Näheres in den Programmierrichtlinien.

Ändert sich ein Feature, ziehst du das Wiki nach. Und wer an der Oberfläche arbeitet, hält sich an den UI-Leitfaden im Repository (docs/ui/README.md).

Keine echten Daten im Diff. Keine Namen, Beträge, Kontonummern, Zugangsdaten, keine Screenshots mit echten Zahlen. Das ist eine Finanz-App; was einmal in der Historie steht, steht dort für immer.

Wie der Code aussehen soll, steht in den Programmierrichtlinien. Die sind keine Geschmacksfragen, sondern die Summe von Fehlern, die schon Zeit gekostet haben.


Was danach passiert

Jedes Stück wird unabhängig geprüft, bevor es gemerged wird: erst gegen die Abnahmekriterien des Issues, dann auf Qualität und Sicherheit. Ich schaue drauf und schreibe, was mir auffällt. Rechne mit Rückfragen — meistens nach dem Warum, seltener nach dem Wie.

Es kann sein, dass ich einen Beitrag nicht übernehme. Nicht weil er schlecht ist, sondern weil er in eine Richtung geht, die ich für Duofy nicht will. Das sage ich dann mit Begründung und nicht mit Schweigen. Deshalb der Rat weiter oben: bei größeren Sachen vorher reden.

Wenn du eine Richtung willst, die ich nicht will, ist ein Fork keine Niederlage, sondern der Sinn der Lizenz. Sie ist genau dafür gemacht.


Umgangsform

Es gibt keinen langen Verhaltenskodex, dafür einen Satz: rede mit Leuten so, wie du am Küchentisch mit ihnen reden würdest.

Duofy handelt von Geld, und Geld ist bei vielen ein wunder Punkt. Wer hier von Schulden, Rückständen oder knappen Monaten erzählt, um einen Fehler zu erklären, tut etwas Unangenehmes — und hilft dabei. Entsprechend antworten.

Wer das nicht kann, ist hier nicht dabei.


Und wenn du nur eine Frage hast

Mach ein Issue auf. Auch für Fragen. Es gibt keine Mailingliste, keinen Chat und kein Forum — und solange das Projekt so klein ist, wäre alles davon ein leerer Raum.

Clone this wiki locally