Deployment-Gesamtkonzept¶
Status: Aktuell — Stand 01.06.2026 Gilt für: Core-Repo (
easySale) und alle Client-Repos (easysale-client-*)
Inhaltsverzeichnis¶
- Architektur in einem Satz
- Grundprinzipien
- Repos und Verantwortlichkeiten
- Branch- und Release-Strategie
- Firebase-Projekt-Strategie
- Release-Flow Schritt für Schritt
- Hotfix-Flow
- Rollback
- Backward-Compatibility-Regeln
- iOS-Besonderheit
- Commands Übersicht
- Workflows Übersicht
- 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) Pflichtrelease/*(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:
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:
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:
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:
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¶
- Release-Commands im Detail: .github/copilot-instructions.md
- Workflow-Übersicht: .github/workflows/README.md
- Backup & Restore: AGENTS.md → Abschnitt „BACKUP & RESTORE COMMAND SYSTEM"
- Killswitch (Emergency): AGENTS.md → Abschnitt „KILLSWITCH COMMAND SYSTEM"