Zum Inhalt

Deployment-Gesamtkonzept

Status: Aktuell — Stand 01.06.2026 Gilt für: Core-Repo (easySale) und alle Client-Repos (easysale-client-*)


Inhaltsverzeichnis

  1. Architektur in einem Satz
  2. Grundprinzipien
  3. Repos und Verantwortlichkeiten
  4. Branch- und Release-Strategie
  5. Firebase-Projekt-Strategie
  6. Release-Flow Schritt für Schritt
  7. Hotfix-Flow
  8. Rollback
  9. Backward-Compatibility-Regeln
  10. iOS-Besonderheit
  11. Commands Übersicht
  12. Workflows Übersicht
  13. Support-Fenster und Backports

1. Architektur in einem Satz

Pull-Modell mit Branches-only: Core veröffentlicht Releases als permanente release/x.y.z-Branches (Branch Protection Pflicht, keine Git-Tags). Client-Repos entscheiden selbst, wann sie eine neue Core-Version übernehmen — per core:upgrade-Command. Anschließend deployt der Client per release:client-Command in sein eigenes Firebase-Projekt.

Kein Push aus dem Core in Client-Repos, keine zentrale Inventur, keine clients.json.


2. Grundprinzipien

2.1 Pull statt Push

Das Core-Repo informiert keinen Client aktiv über neue Releases. Jeder Client entscheidet selbst, wann er upgraded. Vorteile: - Kunden können bei Bedarf bewusst auf einer älteren Version bleiben (z.B. wegen laufender Schulung). - Kein zentrales Registry der Clients nötig. - Keine ausgehende Authentifizierung Core → Client.

2.2 Branches als Releases (keine Tags)

Jede veröffentlichte Version lebt als permanenter Branch release/x.y.z. Vorteile gegenüber Tags: - Hotfixes direkt commitbar (Branch ist nicht frozen). - Branch Protection verhindert versehentliches force-push oder delete. - Übersicht in der GitHub UI ohne extra Tag-View.

2.3 Backward-kompatibles Schema (Expand/Contract)

Niemals Breaking Changes am Firestore-Schema in einem Patch oder Minor. Neue Felder optional, alte Felder erst nach Migrationsfenster löschen. Details in Abschnitt 9.

2.4 Build once, deploy once

Build-Artefakte werden im Client-Build-Workflow erzeugt und genau einmal deployed (kein Rebuild beim Deploy). Garantiert dass produktiv geht, was getestet wurde.

2.5 Per-Customer-Customizing nur im Client-Repo

Kundenspezifische Anpassungen liegen ausschließlich im Client-Repo unter lib/<customer>_custom/. Core bleibt für alle Kunden identisch.


3. Repos und Verantwortlichkeiten

Core-Repo: Tech-Schuppen/easySale

Inhalt: - Shared Library (core/shared/) - ERP- und Shop-App (core/apps/) - Cloud Functions (core/functions/) - Firestore Rules, Indexes, Storage Rules - Reusable Workflows (.github/workflows/client-*.yml) - Handbuch (handbook/) - Onboarding-Templates für neue Clients (onboarding/templates/)

Aufgaben: - Feature-Entwicklung - Bugfixes - Release-Branches erstellen via release:ship - Hotfixes via release:hotfix

Was Core NICHT macht: - Kein Deploy in Kunden-Firebase-Projekte - Keine Benachrichtigung an Client-Repos (Pull-Modell)

Client-Repos: Tech-Schuppen/easysale-client-<kunde>

Naming-Convention: Strikt easysale-client-<kunde>. Damit ist Auto-Discovery via GitHub API möglich (kein clients.json nötig).

Inhalt: - pubspec mit easysale_core-Pin (x.y.z oder Branch release/x.y.z) - Kunden-Customizing unter lib/<kunde>_custom/ - Kunden-spezifische Branding-Assets - Firebase-Config (google-services.json, GoogleService-Info.plist) - firebase/.firebaserc mit Kunden-Projekt-ID - Workflows die die Reusable-Workflows aus Core aufrufen

Aufgaben: - Core-Version aktuell halten via core:upgrade - Eigene Releases deployen via release:client[:web|:ios|:firebase]

Ein Firebase-Projekt pro Kunde

Kunde Firebase-Projekt Web-URL
Mustermann GmbH easysale-mustermann https://mustermann.web.app
Beispiel AG easysale-beispiel https://beispiel.web.app

Region: europe-west3 (Frankfurt) — Pflicht, keine Ausnahmen.


4. Branch- und Release-Strategie

Core-Repo Branches

Branch Zweck Schutz
main Aktive Entwicklung Protected (PR + Reviews)
release/x.y.z Permanenter Release-Branch Protected (kein force-push, kein delete, PR + 1 Reviewer)
hotfix/x.y.z-<kurz> Temporärer Branch für Hotfix-PR Nur kurzfristig

Versionierung (SemVer)

Berechnet automatisch aus Conventional Commits beim release:ship:

Commit-Präfix Bump
feat!: oder BREAKING CHANGE: Major (2.3.5 → 3.0.0)
feat: Minor (2.3.5 → 2.4.0)
fix: / chore: / refactor: / perf: / docs: Patch (2.3.5 → 2.3.6)

Client-Repo Branches

Branch Zweck
main Aktueller Stand des Clients (welche Core-Version + Customizing)
chore/core-upgrade-x.y.z PR-Branch für Core-Upgrade

Client-Repos haben keine Release-Branches — jeder Deploy aus main ist der aktuelle Stand.

Branch Protection Setup (Pflicht)

In GitHub Settings für easySale:

  • main: PR required, 1 Reviewer, Status checks (ci-test-core, ci-audit-firestore-rules) Pflicht
  • release/* (Pattern): kein force-push, kein delete, PR required, 1 Reviewer

5. Firebase-Projekt-Strategie

Kein Dev, kein Staging

Wir haben kein separates Dev- oder Staging-Projekt. Begründung: - Schema ist backward-kompatibel → Tests in Prod ohne Datenkorruption möglich. - Tenant-Isolation via dediziertem Test-User (test@<kunde>.local). - Test-User-Daten werden vom DSGVO-Cleanup-Job nicht gelöscht (eigene Markierung).

Testing in Produktion (kontrolliert)

Test-Art Wie
Functions-Tests Firebase Emulator (FIRESTORE_EMULATOR_HOST=...)
Flutter Widget/BLoC-Tests flutter test lokal + CI
Integration in Prod Test-User in dediziertem Tenant, isoliert
Smoke-Test nach Deploy Manuell via Test-User-Login

Region

Alle GCP-Ressourcen (Firestore, Functions, Storage, Scheduler, Pub/Sub) in europe-west3 (Frankfurt). Abweichung = sofort als Finding melden.


6. Release-Flow Schritt für Schritt

6.1 Core-Release erstellen

Im Core-Repo:

release:ship

KI führt aus: 1. Working Tree prüfen, auf main wechseln, git pull --ff-only. 2. Tests grün? (flutter analyze, npm test). 3. Nächste Version aus Conventional Commits berechnen, Vorschlag + Bestätigung. 4. pubspec.yaml + CHANGELOG.md bumpen, commiten als chore(release): bump to x.y.z. 5. Branch release/x.y.z erstellen, push. 6. CI abwarten (ci-test-core muss grün sein). 7. Erfolgsmeldung.

6.2 Client auf neue Version upgraden

Im Client-Repo:

core:upgrade 2.4.0       # explizit
core:upgrade --latest    # höchste verfügbare Version

KI führt aus: 1. Verify release/2.4.0 existiert im Core-Repo (via gh api). 2. easysale_core: 2.4.0 in pubspec(s) setzen. 3. flutter pub get, flutter analyze. 4. Branch chore/core-upgrade-2.4.0 + PR auf main.

Entwickler reviewt und merged den PR.

6.3 Client deployen

Im Client-Repo nach gemergtem Upgrade-PR:

release:client                              # Web + Android + Firebase (Standard)
release:client --platforms=ios              # nur iOS (Self-Hosted Mac-Runner)
release:client --platforms=web,firebase     # Web + Rules nachschieben (Hotfix)
release:client --platforms=firebase         # nur Rules + Functions (Backend-only)
release:client --platforms=all              # alles inkl. iOS + Handbook

KI führt aus: 1. Vorprüfung (clean, auf main, Core-Version verifiziert). 2. Client-Patch-Version bumpen, CHANGELOG-Eintrag. 3. Build-Workflows triggern via gh workflow run. 4. Build abwarten, dann Deploy-Workflows mit Artifact-Run-ID triggern. 5. Output mit URLs + Track-Status.


7. Hotfix-Flow

Bug in release/2.3.0 der nicht in neueren Releases existiert (oder dort schon gefixt wurde).

Im Core-Repo:

release:hotfix 2.3.0 auth-loop

KI führt aus: 1. Verify release/2.3.0 existiert. 2. Branch checkouten, hotfix/2.3.0-auth-loop erstellen. 3. Fix anwenden (durch Entwickler oder KI, ein einziger fix:-Commit). 4. Patch-Version bumpen (2.3.0 → 2.3.1), CHANGELOG-Eintrag. 5. Push + PR auf release/2.3.0 via gh pr create.

Reviewer merged via GitHub-UI (Branch Protection verhindert direkten Push).

Anschließend pro betroffenem Client:

core:upgrade 2.3.1
release:client

Harte Regeln: - Nur fix:-Commits — wenn ein feat:-Commit reinrutscht: Abbruch. - Kein automatischer Backport auf andere Release-Branches. Wenn der Bug in release/2.3.0 UND release/2.4.0 ist → release:hotfix zweimal aufrufen.


8. Rollback

Web (sofort, < 2 min)

Firebase Console → Hosting → frühere Version → „Rollback".

Android

Google Play Console → frühere Version aus Internal Track wieder zur Production-Promotion einreichen.

iOS

App Store Connect → frühere TestFlight-Build wieder zur Review einreichen (langsamer wegen Apple Review).

Backend (Rules / Functions)

git checkout release/x.y.(z-1) -- core/firestore.rules core/functions
firebase deploy --only firestore:rules,functions --project <kunde>

Daten-Rollback

Siehe Backup & Restore — Firestore Point-in-Time-Recovery oder Backup-Restore.


9. Backward-Compatibility-Regeln

Schema-Änderungen MÜSSEN dem Expand/Contract-Muster folgen:

Erlaubt jederzeit (Expand)

  • Neue Felder hinzufügen → optional, mit Default
  • Neue Collections hinzufügen
  • Neue Cloud Functions hinzufügen
  • Bestehende Functions erweitern (neue Parameter optional)

Verboten in Patch und Minor

  • Felder löschen oder umbenennen
  • Required-Status auf bestehende Felder setzen
  • Function-Signaturen brechen
  • Firestore-Indexes löschen während ältere Clients sie noch nutzen

Erlaubt nur in Major (Contract)

  • Felder löschen — nach Migrationsfenster (mind. 1 Major-Version Karenz)
  • Breaking-Änderungen an Function-Signaturen
  • Required-Felder neu setzen

Migrations-Pflicht bei Major

  • Migration-Skript in core/functions/scripts/migrate_<thema>_vX.js
  • Migration läuft als Cloud Function (one-shot) oder Job
  • CHANGELOG dokumentiert Migration explizit als BREAKING CHANGE

10. iOS-Besonderheit

iOS ist teurer und langsamer als Web/Android. Deshalb getrennter Befehl.

Aspekt Web/Android iOS
Build-Runner GitHub-hosted Self-hosted mac-mini-stefan
Build-Dauer ~5–10 min ~15–25 min
Distribution Firebase Hosting / Play Internal TestFlight
Promotion sofort live (Web) / Play UI (Android) Apple Review (Tage)

Empfehlung: - release:client bei jedem Core-Upgrade. - release:client --platforms=ios bewusst, gebündelt mit anderen Mobile-Features, nicht bei jedem Patch.


11. Commands Übersicht

Core-Repo (in easySale)

Command Zweck
release:ship [x.y.z] Release-Branch erstellen, Version automatisch aus Commits
release:hotfix <x.y.z> <kurz> Patch-Bump auf bestehendem Release-Branch via PR

Client-Repo (in easysale-client-*)

Command Zweck
core:upgrade [x.y.z\|--latest] Core-Version im pubspec aktualisieren, PR
release:client Deploy 1–n Plattformen (default: web,android,firebase)
release:client --platforms=ios Nur iOS → TestFlight (Self-Hosted Mac-Runner)
release:client --platforms=firebase Nur Rules + Functions, kein App-Build
release:client --platforms=handbook Nur Client-Handbuch nach Cloudflare Pages
release:client --platforms=all Alle 5 Plattformen inkl. iOS + Handbook

Vollständige Spezifikation: .github/copilot-instructions.md → Abschnitt „RELEASE COMMAND SYSTEM".


12. Workflows Übersicht

Naming-Konvention: <kategorie>-<zweck>.yml. Details in .github/workflows/README.md.

Im Core-Repo

Workflow Trigger Zweck
ci-test-core.yml PR / Push Core-Tests
ci-test-flutter.reusable.yml workflow_call Reusable: Flutter-Tests im Client
ci-audit-firestore-rules.yml PR mit Rule-Änderungen Schatten-Collection-Check
client-build-{web,android,ios}.yml workflow_call Vom Client aufgerufen, baut Artifact
client-deploy-{web,android,ios}.yml workflow_call Vom Client aufgerufen, deployed Artifact
security-scan-{flutter,functions}.yml Cron pub outdated / npm audit
security-pin-expiry.yml Cron Zertifikats-Pin-Warnung 90 Tage
ops-system-checks.yml Cron Schreibt Health-Ergebnisse nach Firestore
handbook-publish.yml Push auf main mit Doc-Änderung Deployt MkDocs

Im Client-Repo (Onboarding-Templates)

Workflow Zweck
client-auto-build.yml (Template) Triggert Core-Build-Workflows beim Client-Push
client-manual-deploy.yml (Template) Manuelles Deploy via UI
client-ci.yml (Template) Ruft Core ci-test-flutter.reusable.yml mit Client-App-Pfad auf

13. Support-Fenster und Backports

Support-Policy

  • Aktuelle Major-Version + eine vorherige Major-Version werden gewartet.
  • Beispiel bei Major 3.x aktuell: 3.x und 2.x bekommen Security/Critical Hotfixes.
  • Ältere Versionen: Upgrade verpflichtend ODER bezahlter Backport laut Wartungsvertrag.

Was passiert wann

Szenario Reaktion
Bug in aktueller Major (3.x) release:hotfix 3.x.y
Bug in vorheriger Major (2.x), Kunde betroffen release:hotfix 2.x.y
Bug in ganz alter Version (1.x) Kunde wird zum Upgrade gedrängt, kostet sonst extra
Security-Critical in jeder Version Hotfix für alle, Kunden müssen core:upgrade machen

Kommunikation

  • Hotfix-PR mergt → Entwickler informiert betroffene Kunden per E-Mail.
  • Kein automatisches Push / Notify aus Core (Pull-Modell).

Verwandte Dokumente