feat(devops): configure desktop packaging and introduce semantic versioning
- Added `nativeDistributions` for Linux (.deb), Windows (.msi), and macOS (.dmg) in `build.gradle.kts` with platform-specific settings, embedded JRE, and JVM-args. - Implemented centralized semantic versioning via `version.properties` as the single source of truth, applying it across all builds. - Introduced CI/CD release workflow (`.gitea/workflows/release.yml`) for auto-tagging, artifact builds, and release summaries. - Created `CHANGELOG.md` following Keep-a-Changelog format for tracking changes. - Documented icon requirements and packaging steps in `ICONS_PLACEHOLDER.md`. - Updated DevOps roadmap to reflect completed Sprint C-1 and C-2 tasks. Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
parent
c696b8c50e
commit
7ff48ed3d7
183
.gitea/workflows/release.yml
Normal file
183
.gitea/workflows/release.yml
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
name: Release — Semantic Versioning & Desktop Packaging
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# Trigger: Manuell ODER automatisch wenn version.properties
|
||||
# auf main/master geändert wird.
|
||||
# ---------------------------------------------------------------
|
||||
on:
|
||||
push:
|
||||
branches: [ main, master ]
|
||||
paths:
|
||||
- 'version.properties'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: 'Dry-Run (kein Tag, kein Upload)'
|
||||
required: false
|
||||
default: 'false'
|
||||
|
||||
jobs:
|
||||
# =============================================================
|
||||
# JOB 1: Version lesen & Git-Tag setzen
|
||||
# =============================================================
|
||||
tag-release:
|
||||
name: 🏷️ Git-Tag setzen
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.read-version.outputs.version }}
|
||||
tag: ${{ steps.read-version.outputs.tag }}
|
||||
already_tagged: ${{ steps.check-tag.outputs.already_tagged }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Version aus version.properties lesen
|
||||
id: read-version
|
||||
run: |
|
||||
source <(grep -v '^#' version.properties | grep -v '^$' | sed 's/^/export /')
|
||||
QUALIFIER="${VERSION_QUALIFIER:-}"
|
||||
if [ -z "$QUALIFIER" ]; then
|
||||
VERSION="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}"
|
||||
else
|
||||
VERSION="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${QUALIFIER}"
|
||||
fi
|
||||
TAG="v${VERSION}"
|
||||
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
||||
echo "📦 Version: ${VERSION} | Tag: ${TAG}"
|
||||
|
||||
- name: Prüfen ob Tag bereits existiert
|
||||
id: check-tag
|
||||
run: |
|
||||
TAG="${{ steps.read-version.outputs.tag }}"
|
||||
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
||||
echo "already_tagged=true" >> $GITHUB_OUTPUT
|
||||
echo "⚠️ Tag $TAG existiert bereits — überspringe Tagging"
|
||||
else
|
||||
echo "already_tagged=false" >> $GITHUB_OUTPUT
|
||||
echo "✅ Tag $TAG ist neu"
|
||||
fi
|
||||
|
||||
- name: Git-Tag erstellen & pushen
|
||||
if: steps.check-tag.outputs.already_tagged == 'false' && github.event.inputs.dry_run != 'true'
|
||||
run: |
|
||||
TAG="${{ steps.read-version.outputs.tag }}"
|
||||
VERSION="${{ steps.read-version.outputs.version }}"
|
||||
git config user.name "Gitea CI"
|
||||
git config user.email "ci@mo-code.at"
|
||||
git tag -a "$TAG" -m "Release $VERSION"
|
||||
git push origin "$TAG"
|
||||
echo "🚀 Tag $TAG gepusht"
|
||||
|
||||
# =============================================================
|
||||
# JOB 2: Desktop-Packaging (.deb — Linux)
|
||||
# =============================================================
|
||||
package-linux:
|
||||
name: 📦 Linux .deb Packaging
|
||||
runs-on: ubuntu-latest
|
||||
needs: tag-release
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup JDK 21 (Temurin)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
|
||||
- name: Gradle cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
.gradle
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
|
||||
- name: Make gradlew executable
|
||||
run: chmod +x ./gradlew
|
||||
|
||||
- name: Linux .deb bauen
|
||||
env:
|
||||
_JAVA_OPTIONS: -Djava.awt.headless=true
|
||||
run: |
|
||||
./gradlew :frontend:shells:meldestelle-desktop:packageDeb \
|
||||
--stacktrace --no-daemon
|
||||
|
||||
- name: .deb Artefakt hochladen
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: meldestelle-${{ needs.tag-release.outputs.version }}-linux-deb
|
||||
path: frontend/shells/meldestelle-desktop/build/compose/binaries/main/deb/*.deb
|
||||
if-no-files-found: warn
|
||||
|
||||
# =============================================================
|
||||
# JOB 3: Desktop-Packaging (.msi — Windows)
|
||||
# =============================================================
|
||||
package-windows:
|
||||
name: 📦 Windows .msi Packaging
|
||||
runs-on: windows-latest
|
||||
needs: tag-release
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup JDK 21 (Temurin)
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '21'
|
||||
|
||||
- name: Gradle cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
.gradle
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
|
||||
- name: Windows .msi bauen
|
||||
env:
|
||||
_JAVA_OPTIONS: -Djava.awt.headless=true
|
||||
run: |
|
||||
./gradlew :frontend:shells:meldestelle-desktop:packageMsi `
|
||||
--stacktrace --no-daemon
|
||||
|
||||
- name: .msi Artefakt hochladen
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: meldestelle-${{ needs.tag-release.outputs.version }}-windows-msi
|
||||
path: frontend/shells/meldestelle-desktop/build/compose/binaries/main/msi/*.msi
|
||||
if-no-files-found: warn
|
||||
|
||||
# =============================================================
|
||||
# JOB 4: Release-Summary
|
||||
# =============================================================
|
||||
release-summary:
|
||||
name: 📋 Release-Summary
|
||||
runs-on: ubuntu-latest
|
||||
needs: [ tag-release, package-linux, package-windows ]
|
||||
if: always()
|
||||
|
||||
steps:
|
||||
- name: Summary ausgeben
|
||||
run: |
|
||||
echo "## 🚀 Release ${{ needs.tag-release.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Artefakt | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|----------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Linux .deb | ${{ needs.package-linux.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Windows .msi | ${{ needs.package-windows.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Git-Tag:** \`${{ needs.tag-release.outputs.tag }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
52
CHANGELOG.md
Normal file
52
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Changelog — Meldestelle
|
||||
|
||||
Alle wesentlichen Änderungen an diesem Projekt werden in dieser Datei dokumentiert.
|
||||
|
||||
Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.1.0/).
|
||||
Versionierung folgt [Semantic Versioning](https://semver.org/lang/de/).
|
||||
|
||||
> **Versionsschema:** `MAJOR.MINOR.PATCH[-QUALIFIER]`
|
||||
> - `MAJOR` — Breaking Changes / inkompatible API-Änderungen
|
||||
> - `MINOR` — Neue Features (abwärtskompatibel)
|
||||
> - `PATCH` — Bugfixes (abwärtskompatibel)
|
||||
> - `QUALIFIER` — `SNAPSHOT` (Entwicklung), `beta.N` (Vorversion), leer = Release
|
||||
|
||||
---
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Hinzugefügt
|
||||
|
||||
- Desktop-Packaging konfiguriert: `.deb` (Linux), `.msi` (Windows), `.dmg` (macOS)
|
||||
- Zentrale Versionsdatei `version.properties` (Single Source of Truth für SemVer)
|
||||
- Automatisches Git-Tagging via CI/CD (`release.yml` Gitea Actions Workflow)
|
||||
- `CHANGELOG.md` eingeführt (dieses Dokument)
|
||||
|
||||
---
|
||||
|
||||
## [1.0.0-SNAPSHOT] — 2026-04-03
|
||||
|
||||
### Hinzugefügt
|
||||
|
||||
- **Sprint A:** Docker-Compose-Setup, Healthchecks für alle Services
|
||||
- **Sprint B:** CI/CD Pipeline für Compose Desktop Tests (headless, Xvfb)
|
||||
- **Sprint B:** Gradle-Build-Optimierungen (Cache, Parallel, Wrapper 9.4.0)
|
||||
- **Sprint B:** Onboarding-Wizard (Veranstalter, Verein, Turnier, Bewerb, Abteilung)
|
||||
- **Sprint B:** `BewerbRepository`, `AbteilungRepository`, `DefaultTurnierRepository`
|
||||
- **Sprint B:** `ReiterProfilEditDialog`, `PferdProfilEditDialog` mit `MsValidationWrapper`
|
||||
- **Sprint B:** ÖTO-Regelwerk als Regulation-as-Data (Lizenz-/Altersmatrix, V008/V009 Migrations)
|
||||
- **Sprint B:** Tenant-Isolation Grundstruktur (Multi-Tenant Postgres-Schemas)
|
||||
- **Sprint B:** Architektur-Tests (`:platform:architecture-tests`)
|
||||
|
||||
### Geändert
|
||||
|
||||
- Gradle Wrapper auf `9.3.1` aktualisiert
|
||||
- JVM-Toolchain auf Java 25 angehoben
|
||||
|
||||
---
|
||||
|
||||
<!-- Versions-Links (anpassen sobald Gitea-URL bekannt) -->
|
||||
|
||||
[Unreleased]: https://gitea.mo-code.at/meldestelle/Meldestelle-Biest/compare/v1.0.0-SNAPSHOT...HEAD
|
||||
|
||||
[1.0.0-SNAPSHOT]: https://gitea.mo-code.at/meldestelle/Meldestelle-Biest/releases/tag/v1.0.0-SNAPSHOT
|
||||
|
|
@ -38,9 +38,22 @@ plugins {
|
|||
// ### ALLPROJECTS CONFIGURATION ###
|
||||
// ##################################################################
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Zentrale Versionierung — liest version.properties (SemVer)
|
||||
// ---------------------------------------------------------------
|
||||
val versionProps =
|
||||
java.util.Properties().also { props ->
|
||||
rootProject.file("version.properties").inputStream().use { props.load(it) }
|
||||
}
|
||||
val vMajor = versionProps.getProperty("VERSION_MAJOR", "1")
|
||||
val vMinor = versionProps.getProperty("VERSION_MINOR", "0")
|
||||
val vPatch = versionProps.getProperty("VERSION_PATCH", "0")
|
||||
val vQualifier = versionProps.getProperty("VERSION_QUALIFIER", "").trim()
|
||||
val semVer = if (vQualifier.isBlank()) "$vMajor.$vMinor.$vPatch" else "$vMajor.$vMinor.$vPatch-$vQualifier"
|
||||
|
||||
allprojects {
|
||||
group = "at.mocode"
|
||||
version = "1.0.0-SNAPSHOT"
|
||||
version = semVer
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
|
|
|||
|
|
@ -28,24 +28,37 @@
|
|||
- [x] Headless-Flag: `-Djava.awt.headless=true`
|
||||
- [x] Gradle Wrapper auf `9.4.0` aktualisiert
|
||||
|
||||
### Sprint C — Abgeschlossen
|
||||
|
||||
- [x] **C-1** | Desktop-App Packaging konfiguriert
|
||||
- [x] `compose.desktop.nativeDistributions` vollständig in `build.gradle.kts` konfiguriert
|
||||
- [x] Linux: `.deb`-Paket — `packageDeb` Task, Icon PNG 512×512, `debMaintainer`, `menuGroup`
|
||||
- [x] Windows: `.msi`-Installer — `packageMsi` Task, Icon ICO, `upgradeUuid`, `menuGroup`, `shortcut`
|
||||
- [x] macOS: `.dmg`-Image — `packageDmg` Task, Icon ICNS, `bundleID`, `appCategory`
|
||||
- [x] App-Metadaten: `packageName`, `description`, `vendor`, `copyright`, `licenseFile`
|
||||
- [x] Eingebettetes JRE: `modules(...)` mit minimalem JRE-Footprint konfiguriert
|
||||
- [x] JVM-Args für gepackte App: `-Xms128m`, `-Xmx512m`, `-Dfile.encoding=UTF-8`
|
||||
- [x] Icon-Ressourcen-Verzeichnis angelegt + `ICONS_PLACEHOLDER.md` mit Anforderungen
|
||||
- [ ] ⚠️ **Offen:** Echte Icon-Dateien (`icon.png`, `icon.ico`, `icon.icns`) erstellen/einfügen
|
||||
- [ ] ⚠️ **Offen:** Testinstallation auf Ziel-Betriebssystem durchführen (nach Icon-Erstellung)
|
||||
|
||||
- [x] **C-2** | Semantic Versioning eingeführt
|
||||
- [x] Versionierungsschema definiert: `MAJOR.MINOR.PATCH[-QUALIFIER]`
|
||||
- [x] Zentrale Versionsquelle: `version.properties` im Root-Projekt (Single Source of Truth)
|
||||
- [x] Root `build.gradle.kts`: Version wird aus `version.properties` gelesen (kein Hardcode mehr)
|
||||
- [x] Desktop `build.gradle.kts`: `packageVersion` aus `version.properties` (reines `MAJOR.MINOR.PATCH`)
|
||||
- [x] Git-Tagging-Strategie definiert: `vMAJOR.MINOR.PATCH` (z. B. `v1.0.0`)
|
||||
- [x] Release-Workflow angelegt: `.gitea/workflows/release.yml`
|
||||
- Trigger: Änderung an `version.properties` auf `main`/`master` + manuell (Dry-Run-Option)
|
||||
- Job 1: Version lesen, Tag-Duplikat-Check, Git-Tag erstellen & pushen
|
||||
- Job 2: Linux `.deb` bauen & als Artefakt hochladen
|
||||
- Job 3: Windows `.msi` bauen & als Artefakt hochladen
|
||||
- Job 4: Release-Summary (Markdown-Report)
|
||||
- [x] `CHANGELOG.md` angelegt (Keep-a-Changelog-Format, SemVer)
|
||||
|
||||
---
|
||||
|
||||
## 🔴 Sprint C — Priorität 1 (diese Woche)
|
||||
|
||||
- [ ] **C-1** | Desktop-App Packaging konfigurieren
|
||||
- [ ] `compose.desktop.nativeDistributions` in `build.gradle.kts` konfigurieren
|
||||
- [ ] Windows: `.msi`-Installer bauen
|
||||
- [ ] Linux: `.deb`-Paket bauen
|
||||
- [ ] macOS: `.dmg`-Image bauen (falls erforderlich)
|
||||
- [ ] App-Icon und Metadaten (Name, Version, Publisher) eintragen
|
||||
- [ ] Testinstallation auf Ziel-Betriebssystem durchführen
|
||||
|
||||
- [ ] **C-2** | Semantic Versioning einführen
|
||||
- [ ] Versionierungsschema definieren: `MAJOR.MINOR.PATCH`
|
||||
- [ ] Gemeinsame Versions-Quelle für Frontend und Backend festlegen
|
||||
- [ ] Git-Tagging-Strategie definieren (`v1.0.0`, `v1.0.0-backend`, etc.)
|
||||
- [ ] Release-Tagging in CI/CD-Pipeline integrieren
|
||||
- [ ] `CHANGELOG.md`-Vorlage anlegen
|
||||
## 🔴 Sprint C — Restpunkte
|
||||
|
||||
- [ ] **C-3** | Produktions-Deployment vorbereiten
|
||||
- [ ] Reverse-Proxy-Konfiguration (Nginx / Traefik) für Backend prüfen
|
||||
|
|
@ -72,16 +85,33 @@
|
|||
## 📌 Abhängigkeiten
|
||||
|
||||
| Warte auf | Von wem | Betrifft |
|
||||
|----------------------------|-------------------|---------------------|
|
||||
|-----------------------------|-------------------|---------------------|
|
||||
| ADR-0022 LAN-Sync | 🏗️ Architect B-1 | D-2 mDNS-Infra |
|
||||
| QA: Test-Integration in CI | 🧐 QA C-4 | C-1 Packaging-Tests |
|
||||
| Icon-Dateien (PNG/ICO/ICNS) | 🖌️ UI/UX | C-1 Release-Build |
|
||||
|
||||
---
|
||||
|
||||
## 💡 Empfehlungen (nach Priorität)
|
||||
|
||||
1. **C-1 Desktop-Packaging** — Für erste echte Auslieferung an Endnutzer zwingend notwendig; `.msi`/`.deb` sollten vor
|
||||
dem ersten Beta-Test bereitstehen.
|
||||
2. **C-2 Semantic Versioning** — Ohne klare Versionierung ist kein koordiniertes Release möglich; einfach zu
|
||||
implementieren, hoher Nutzen.
|
||||
3. **D-1 Tenant-Backup** — Wenn eine Veranstaltung = eine Datenbank, muss jeder Tenant einzeln gesichert werden können.
|
||||
1. **Icons erstellen** — Vor dem ersten echten Release-Build müssen `icon.png`, `icon.ico` und
|
||||
`icon.icns` in `frontend/shells/meldestelle-desktop/src/jvmMain/resources/` abgelegt werden.
|
||||
Siehe `ICONS_PLACEHOLDER.md` für Anforderungen und ImageMagick-Schnell-Befehle.
|
||||
2. **Testinstallation** — Nach Icon-Erstellung: `.deb` auf Ubuntu/Debian, `.msi` auf Windows 10/11
|
||||
installieren und Startmenü-Eintrag / Desktop-Verknüpfung prüfen.
|
||||
3. **C-3 Produktions-Deployment** — Reverse-Proxy + HTTPS vor erstem Beta-Test konfigurieren.
|
||||
4. **D-1 Tenant-Backup** — Wenn eine Veranstaltung = eine Datenbank, muss jeder Tenant einzeln
|
||||
gesichert werden können.
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Geänderte Dateien (diese Session)
|
||||
|
||||
| Datei | Änderung |
|
||||
|----------------------------------------------------------------------------------|------------------------------------------------------------------------|
|
||||
| `version.properties` | **NEU** — Zentrale SemVer-Quelle (`1.0.0-SNAPSHOT`) |
|
||||
| `build.gradle.kts` (root) | Version aus `version.properties` statt hardcoded |
|
||||
| `frontend/shells/meldestelle-desktop/build.gradle.kts` | Vollständige `nativeDistributions`-Konfiguration (Linux/Windows/macOS) |
|
||||
| `frontend/shells/meldestelle-desktop/src/jvmMain/resources/ICONS_PLACEHOLDER.md` | **NEU** — Icon-Anforderungen dokumentiert |
|
||||
| `.gitea/workflows/release.yml` | **NEU** — Release-Workflow (Tag + Packaging) |
|
||||
| `CHANGELOG.md` | **NEU** — Keep-a-Changelog-Format |
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
| 👷 Backend | ⚠️ A-1/A-3 offen | 🔴 B-1 teilweise | ⬜ Nicht gestartet | A-1 Rollout + Reiter/Pferde-APIs |
|
||||
| 🎨 Frontend | ✅ Abgeschlossen | 🟡 B-2 teilweise/B-3 teilweise/B-4 offen | ⬜ Nicht gestartet | B-2 StoreV2-Ablösung + B-3 Bewerb-Kontext-Validierung |
|
||||
| 📜 Rulebook | ✅ Abgeschlossen | 🔴 B-2 offen | ⬜ Nicht gestartet | B-2 Spec an Backend übergeben |
|
||||
| 🐧 DevOps | ✅ Abgeschlossen | ✅ Abgeschlossen | 🔴 C-1 offen | C-1 Desktop-Packaging (.msi/.deb) |
|
||||
| 🐧 DevOps | ✅ Abgeschlossen | ✅ Abgeschlossen | ✅ C-1/C-2 fertig | C-3 Produktions-Deployment |
|
||||
| 🧐 QA | ✅ Abgeschlossen | 🔴 B-1..B-4 offen | ⬜ Nicht gestartet | B-2 Onboarding-Tests + B-3 Abteilungs-Tests |
|
||||
| 🖌️ UI/UX | ✅ Abgeschlossen | 🔴 B-1/B-4 offen | ⬜ Nicht gestartet | B-1 Finale Entscheidung Editier-Formulare |
|
||||
| 🧹 Curator | ✅ Abgeschlossen | 🔴 B-1..B-3 offen | ⬜ Nicht gestartet | B-1 Roadmaps pflegen ← *diese Session* |
|
||||
|
|
@ -63,8 +63,14 @@ Diese Aufgaben blockieren andere Agenten und müssen zuerst erledigt werden:
|
|||
|
||||
### 🐧 DevOps Engineer
|
||||
|
||||
1. **C-1** Desktop-Packaging (`.msi` / `.deb`) konfigurieren
|
||||
2. **C-2** Semantic Versioning + Git-Tagging einführen
|
||||
1. ✅ **C-1** Desktop-Packaging (`.msi` / `.deb` / `.dmg`) konfiguriert
|
||||
- `nativeDistributions` vollständig (Linux/Windows/macOS), JRE-Module, JVM-Args
|
||||
- ⚠️ Icons (`icon.png`/`icon.ico`/`icon.icns`) noch ausstehend → 🖌️ UI/UX
|
||||
2. ✅ **C-2** Semantic Versioning + Git-Tagging eingeführt
|
||||
- `version.properties` als Single Source of Truth
|
||||
- `.gitea/workflows/release.yml`: Auto-Tag + `.deb`/`.msi` Packaging
|
||||
- `CHANGELOG.md` angelegt
|
||||
3. 🔴 **C-3** Produktions-Deployment vorbereiten (nächste Session)
|
||||
|
||||
### 🧐 QA Specialist
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,144 @@
|
|||
# 🐧 DevOps — Sprint C: Desktop-Packaging & Semantic Versioning
|
||||
|
||||
> **Datum:** 3. April 2026
|
||||
> **Agent:** 🐧 DevOps Engineer
|
||||
> **Sprint:** C — Aufgaben C-1 und C-2
|
||||
> **Status:** ✅ Implementiert (Icons ausstehend)
|
||||
|
||||
---
|
||||
|
||||
## 📋 Zusammenfassung
|
||||
|
||||
Diese Session implementiert die Desktop-Packaging-Konfiguration (C-1) und führt Semantic
|
||||
Versioning mit Git-Tagging ein (C-2). Beide Aufgaben sind vollständig konfiguriert; der einzige
|
||||
verbleibende manuelle Schritt ist die Erstellung der App-Icons durch 🖌️ UI/UX.
|
||||
|
||||
---
|
||||
|
||||
## ✅ C-1 — Desktop-Packaging konfiguriert
|
||||
|
||||
### Was wurde gemacht
|
||||
|
||||
**`frontend/shells/meldestelle-desktop/build.gradle.kts`** vollständig überarbeitet:
|
||||
|
||||
- `nativeDistributions` für alle drei Plattformen konfiguriert:
|
||||
- **Linux `.deb`**: `packageDeb` Task, PNG-Icon, `debMaintainer`, `menuGroup`, `shortcut`
|
||||
- **Windows `.msi`**: `packageMsi` Task, ICO-Icon, `upgradeUuid` (unveränderliche GUID!), `shortcut`, `dirChooser`
|
||||
- **macOS `.dmg`**: `packageDmg` Task, ICNS-Icon, `bundleID`, `appCategory`
|
||||
- Gemeinsame Metadaten: `packageName`, `description`, `vendor`, `copyright`, `licenseFile`
|
||||
- Eingebettetes JRE mit minimalem Footprint (`modules(...)`)
|
||||
- JVM-Args für gepackte App: `-Xms128m -Xmx512m -Dfile.encoding=UTF-8`
|
||||
- Version wird automatisch aus `version.properties` gelesen (kein Hardcode)
|
||||
|
||||
**`frontend/shells/meldestelle-desktop/src/jvmMain/resources/ICONS_PLACEHOLDER.md`** angelegt:
|
||||
|
||||
- Dokumentiert Icon-Anforderungen (PNG 512×512, ICO Multi-Size, ICNS 1024×1024)
|
||||
- ImageMagick-Schnell-Befehle für Konvertierung
|
||||
|
||||
### Gradle-Befehle
|
||||
|
||||
```bash
|
||||
# Linux .deb bauen
|
||||
./gradlew :frontend:shells:meldestelle-desktop:packageDeb
|
||||
|
||||
# Windows .msi bauen (auf Windows-Runner)
|
||||
./gradlew :frontend:shells:meldestelle-desktop:packageMsi
|
||||
|
||||
# macOS .dmg bauen (auf macOS-Runner)
|
||||
./gradlew :frontend:shells:meldestelle-desktop:packageDmg
|
||||
|
||||
# Alle Plattformen (auf jeweiligem OS)
|
||||
./gradlew :frontend:shells:meldestelle-desktop:packageReleaseDistributables
|
||||
```
|
||||
|
||||
### Offene Punkte
|
||||
|
||||
| # | Aufgabe | Zuständig |
|
||||
|---|-------------------------------------------|-----------|
|
||||
| 1 | `icon.png` (512×512 PNG) erstellen | 🖌️ UI/UX |
|
||||
| 2 | `icon.ico` (Multi-Size ICO) erstellen | 🖌️ UI/UX |
|
||||
| 3 | `icon.icns` (1024×1024 ICNS) erstellen | 🖌️ UI/UX |
|
||||
| 4 | Testinstallation `.deb` auf Ubuntu/Debian | 🐧 DevOps |
|
||||
| 5 | Testinstallation `.msi` auf Windows 10/11 | 🐧 DevOps |
|
||||
|
||||
---
|
||||
|
||||
## ✅ C-2 — Semantic Versioning eingeführt
|
||||
|
||||
### Was wurde gemacht
|
||||
|
||||
**`version.properties`** (neu, Root-Projekt):
|
||||
|
||||
- Single Source of Truth für alle Versionen
|
||||
- Format: `VERSION_MAJOR`, `VERSION_MINOR`, `VERSION_PATCH`, `VERSION_QUALIFIER`
|
||||
- Aktuell: `1.0.0-SNAPSHOT`
|
||||
|
||||
**`build.gradle.kts`** (Root):
|
||||
|
||||
- Version wird aus `version.properties` gelesen statt hardcoded `"1.0.0-SNAPSHOT"`
|
||||
- Alle Subprojekte erben die Version automatisch via `allprojects { version = semVer }`
|
||||
|
||||
**`.gitea/workflows/release.yml`** (neu):
|
||||
|
||||
```
|
||||
Trigger: version.properties geändert auf main/master ODER manuell (Dry-Run-Option)
|
||||
│
|
||||
├── Job 1: tag-release
|
||||
│ ├── Version aus version.properties lesen
|
||||
│ ├── Prüfen ob Tag bereits existiert (Idempotenz)
|
||||
│ └── Git-Tag "vMAJOR.MINOR.PATCH" erstellen & pushen
|
||||
│
|
||||
├── Job 2: package-linux (ubuntu-latest)
|
||||
│ └── packageDeb → Artefakt hochladen
|
||||
│
|
||||
├── Job 3: package-windows (windows-latest)
|
||||
│ └── packageMsi → Artefakt hochladen
|
||||
│
|
||||
└── Job 4: release-summary
|
||||
└── Markdown-Report mit Status aller Jobs
|
||||
```
|
||||
|
||||
**`CHANGELOG.md`** (neu):
|
||||
|
||||
- Keep-a-Changelog-Format
|
||||
- SemVer-Erklärung im Header
|
||||
- `[Unreleased]` Sektion für laufende Änderungen
|
||||
- `[1.0.0-SNAPSHOT]` mit Sprint A+B Zusammenfassung
|
||||
|
||||
### Release-Workflow (manuell)
|
||||
|
||||
```bash
|
||||
# 1. Version erhöhen
|
||||
vim version.properties # z. B. VERSION_MINOR=1, VERSION_QUALIFIER=
|
||||
|
||||
# 2. CHANGELOG aktualisieren
|
||||
vim CHANGELOG.md # [Unreleased] → [1.1.0] mit Datum
|
||||
|
||||
# 3. Commit & Push → CI erstellt automatisch Tag v1.1.0
|
||||
git add version.properties CHANGELOG.md
|
||||
git commit -m "chore: release v1.1.0"
|
||||
git push origin main
|
||||
# → CI: Tag v1.1.0 wird gesetzt, .deb und .msi werden gebaut
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Geänderte Dateien
|
||||
|
||||
| Datei | Art | Beschreibung |
|
||||
|----------------------------------------------------------------------------------|----------|--------------------------------------|
|
||||
| `version.properties` | NEU | Zentrale SemVer-Quelle |
|
||||
| `build.gradle.kts` | GEÄNDERT | Version aus `version.properties` |
|
||||
| `frontend/shells/meldestelle-desktop/build.gradle.kts` | GEÄNDERT | Vollständige Packaging-Konfiguration |
|
||||
| `frontend/shells/meldestelle-desktop/src/jvmMain/resources/ICONS_PLACEHOLDER.md` | NEU | Icon-Anforderungen |
|
||||
| `.gitea/workflows/release.yml` | NEU | Release-Workflow |
|
||||
| `CHANGELOG.md` | NEU | Keep-a-Changelog |
|
||||
| `docs/04_Agents/Roadmaps/DevOps_Roadmap.md` | GEÄNDERT | C-1/C-2 als erledigt markiert |
|
||||
|
||||
---
|
||||
|
||||
## 🔗 Nächste Schritte
|
||||
|
||||
1. **🖌️ UI/UX** → Icons erstellen und in `src/jvmMain/resources/` ablegen
|
||||
2. **🐧 DevOps** → Testinstallation nach Icon-Erstellung
|
||||
3. **🐧 DevOps** → C-3 Produktions-Deployment (nächste Session)
|
||||
|
|
@ -1,9 +1,20 @@
|
|||
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Shell-Modul: Meldestelle Desktop App
|
||||
* Reines JVM/Compose-Desktop-Modul – Desktop-First gemäß MASTER_ROADMAP.
|
||||
* Setzt alle Core- und Feature-Module zu einer lauffähigen Desktop-Anwendung zusammen.
|
||||
*
|
||||
* Packaging:
|
||||
* ./gradlew :frontend:shells:meldestelle-desktop:packageDeb → Linux .deb
|
||||
* ./gradlew :frontend:shells:meldestelle-desktop:packageMsi → Windows .msi
|
||||
* ./gradlew :frontend:shells:meldestelle-desktop:packageDmg → macOS .dmg
|
||||
* ./gradlew :frontend:shells:meldestelle-desktop:packageReleaseDistributables → alle Plattformen
|
||||
*
|
||||
* Version: wird automatisch aus version.properties im Root-Projekt gelesen (SemVer).
|
||||
* Icons: src/jvmMain/resources/icon.png / icon.ico / icon.icns
|
||||
* → siehe ICONS_PLACEHOLDER.md für Anforderungen
|
||||
*/
|
||||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
|
|
@ -13,6 +24,18 @@ plugins {
|
|||
id("org.jetbrains.compose.hot-reload")
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Version aus root version.properties lesen (SemVer)
|
||||
// ---------------------------------------------------------------
|
||||
val versionProps = Properties().also { props ->
|
||||
rootProject.file("version.properties").inputStream().use { props.load(it) }
|
||||
}
|
||||
val vMajor = versionProps.getProperty("VERSION_MAJOR", "1")
|
||||
val vMinor = versionProps.getProperty("VERSION_MINOR", "0")
|
||||
val vPatch = versionProps.getProperty("VERSION_PATCH", "0")
|
||||
// nativeDistributions erwartet reines "MAJOR.MINOR.PATCH" (kein Qualifier)
|
||||
val packageVer = "$vMajor.$vMinor.$vPatch"
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
|
||||
|
|
@ -69,23 +92,88 @@ kotlin {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
compose.desktop {
|
||||
application {
|
||||
mainClass = "at.mocode.desktop.MainKt"
|
||||
|
||||
nativeDistributions {
|
||||
// Ziel-Formate: Linux .deb, Windows .msi, macOS .dmg
|
||||
targetFormats(TargetFormat.Deb, TargetFormat.Msi, TargetFormat.Dmg)
|
||||
packageName = "Meldestelle"
|
||||
packageVersion = "1.0.0"
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Gemeinsame App-Metadaten
|
||||
// -------------------------------------------------------
|
||||
packageName = "meldestelle"
|
||||
packageVersion = packageVer
|
||||
description = "ÖTO-konforme Turnier-Meldestelle – Desktop App"
|
||||
vendor = "mo-code.at"
|
||||
copyright = "© 2024–2026 mo-code.at. Alle Rechte vorbehalten."
|
||||
licenseFile.set(rootProject.file("LICENSE"))
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Linux (.deb)
|
||||
// -------------------------------------------------------
|
||||
linux {
|
||||
// PNG 512×512 px — siehe src/jvmMain/resources/ICONS_PLACEHOLDER.md
|
||||
iconFile.set(project.file("src/jvmMain/resources/icon.png"))
|
||||
}
|
||||
windows {
|
||||
packageName = "meldestelle"
|
||||
// Debian-Kategorie
|
||||
appCategory = "misc"
|
||||
// Menü-Eintrag
|
||||
menuGroup = "Meldestelle"
|
||||
shortcut = true
|
||||
debMaintainer = "support@mo-code.at"
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Windows (.msi)
|
||||
// -------------------------------------------------------
|
||||
windows {
|
||||
// ICO Multi-Size — siehe src/jvmMain/resources/ICONS_PLACEHOLDER.md
|
||||
iconFile.set(project.file("src/jvmMain/resources/icon.ico"))
|
||||
// Eindeutige GUID für Windows Installer Upgrade-Erkennung
|
||||
// WICHTIG: Diese UUID darf sich NIE ändern!
|
||||
upgradeUuid = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
||||
}
|
||||
}
|
||||
menuGroup = "Meldestelle"
|
||||
// Startmenü-Verknüpfung
|
||||
shortcut = true
|
||||
// Desktop-Verknüpfung
|
||||
dirChooser = true
|
||||
perUserInstall = false
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// macOS (.dmg)
|
||||
// -------------------------------------------------------
|
||||
macOS {
|
||||
// ICNS 1024×1024 px — siehe src/jvmMain/resources/ICONS_PLACEHOLDER.md
|
||||
iconFile.set(project.file("src/jvmMain/resources/icon.icns"))
|
||||
bundleID = "at.mocode.meldestelle"
|
||||
appCategory = "public.app-category.productivity"
|
||||
// Für notarisierten Release: signing-Konfiguration hier ergänzen
|
||||
// signing { sign.set(true); identity.set("Developer ID Application: ...") }
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// JVM-Laufzeit-Konfiguration (eingebettetes JRE)
|
||||
// -------------------------------------------------------
|
||||
modules(
|
||||
"java.base",
|
||||
"java.desktop",
|
||||
"java.logging",
|
||||
"java.naming",
|
||||
"java.net.http",
|
||||
"java.sql",
|
||||
"jdk.crypto.ec",
|
||||
"jdk.unsupported",
|
||||
)
|
||||
}
|
||||
|
||||
// JVM-Argumente für die gepackte Anwendung
|
||||
jvmArgs(
|
||||
"-Xms128m",
|
||||
"-Xmx512m",
|
||||
"-Dfile.encoding=UTF-8",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
# App-Icons — Platzhalter
|
||||
|
||||
Folgende Icon-Dateien müssen hier abgelegt werden, bevor ein Release-Build erstellt wird:
|
||||
|
||||
| Datei | Format | Größe | Plattform |
|
||||
|-------------|--------|--------------|----------------|
|
||||
| `icon.png` | PNG | 512×512 px | Linux (.deb) |
|
||||
| `icon.ico` | ICO | 256×256 px | Windows (.msi) |
|
||||
| `icon.icns` | ICNS | 1024×1024 px | macOS (.dmg) |
|
||||
|
||||
## Hinweise
|
||||
|
||||
- PNG: RGBA, transparenter Hintergrund empfohlen
|
||||
- ICO: Multi-Size (16, 32, 48, 64, 128, 256 px) in einer Datei
|
||||
- ICNS: Mit `iconutil` (macOS) oder `png2icns` (Linux) aus PNG erzeugen
|
||||
|
||||
## Schnell-Erzeugung (Linux, ImageMagick)
|
||||
|
||||
```bash
|
||||
# PNG → ICO (Windows)
|
||||
convert icon.png -define icon:auto-resize=256,128,64,48,32,16 icon.ico
|
||||
|
||||
# PNG → ICNS (macOS, benötigt libicns)
|
||||
png2icns icon.icns icon.png
|
||||
```
|
||||
22
version.properties
Normal file
22
version.properties
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# ============================================================
|
||||
# Meldestelle — Zentrale Versionsdatei (Semantic Versioning)
|
||||
# ============================================================
|
||||
# Format: MAJOR.MINOR.PATCH
|
||||
# MAJOR — Breaking Changes / Inkompatible API-Änderungen
|
||||
# MINOR — Neue Features (abwärtskompatibel)
|
||||
# PATCH — Bugfixes (abwärtskompatibel)
|
||||
#
|
||||
# Diese Datei ist die Single Source of Truth für alle Versionen.
|
||||
# Gradle liest sie beim Build; CI/CD setzt Git-Tags basierend darauf.
|
||||
#
|
||||
# Workflow:
|
||||
# 1. Version hier erhöhen (z. B. 1.0.0 → 1.1.0)
|
||||
# 2. Commit + Push
|
||||
# 3. CI erstellt automatisch Git-Tag "v1.1.0"
|
||||
# 4. Release-Artefakte (.msi / .deb / .dmg) werden gebaut und hochgeladen
|
||||
# ============================================================
|
||||
VERSION_MAJOR=1
|
||||
VERSION_MINOR=0
|
||||
VERSION_PATCH=0
|
||||
# Qualifier: leer = Release, "SNAPSHOT" = Entwicklungsstand, "beta.1" = Vorversion
|
||||
VERSION_QUALIFIER=SNAPSHOT
|
||||
Loading…
Reference in New Issue
Block a user