ab75911b72
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
140 lines
12 KiB
Markdown
140 lines
12 KiB
Markdown
---
|
|
phase: 18-desktop-client-fertigstellen
|
|
plan: 02
|
|
subsystem: infra
|
|
tags: [gitea-actions, ci-cd, tauri, actions-cache, release-assets]
|
|
|
|
# Dependency graph
|
|
requires:
|
|
- phase: 18-desktop-client-fertigstellen (Plan 01)
|
|
provides: .gitea/scripts/desktop-collect.sh, .gitea/scripts/desktop-version.sh, desktop-dist/manifest.json-Form
|
|
provides:
|
|
- "Job desktop in .gitea/workflows/ci.yml (Linux-AppImage mit Tag-Version, Cargo-Zwischenspeicher, actions/cache-Uebergabe)"
|
|
- "publish haengt an desktop (needs: desktop), holt Pakete per actions/cache/restore mit fail-on-cache-miss: true, prueft das Manifest hart"
|
|
- "publish-images.sh bricht im echten Baupfad ohne desktop-dist/manifest.json ab"
|
|
- "publish-release.sh: upload_asset() laedt jede Manifest-Datei idempotent als Release-Anhang hoch (GET -> DELETE vorhandener -> POST multipart)"
|
|
affects: [18-05-windows-cross-bau-pipeline-beweis, 18-06-freigabe-release-anhang]
|
|
|
|
actuals:
|
|
tokens: 2586
|
|
tasks: 2
|
|
commits: 2
|
|
plan_head_before: cd62de1
|
|
|
|
tech-stack:
|
|
added: []
|
|
patterns:
|
|
- "Cross-Job-Uebergabe per actions/cache/save + actions/cache/restore (Schluessel exakt am Commit-SHA, kein restore-keys-Fallback fuer die Uebergabe selbst) statt der auf dieser Gitea-Instanz unzuverlaessigen upload-/download-artifact-Actions"
|
|
- "Zweite Header-Datei ohne Content-Type: application/json fuer multipart-Uploads (curl -F) neben der bestehenden JSON-Header-Datei — gleiche umask 077/mktemp/trap-Mechanik, Token nie als Argument"
|
|
- "Idempotenter Datei-Upload nach dem bereits etablierten GET-dann-PATCH/POST-Muster von publish-release.sh: GET .../assets, vorhandene Datei gleichen Namens per DELETE entfernen, dann frisch per POST hochladen"
|
|
|
|
key-files:
|
|
created: []
|
|
modified:
|
|
- .gitea/workflows/ci.yml
|
|
- .gitea/scripts/publish-images.sh
|
|
- .gitea/scripts/publish-release.sh
|
|
|
|
key-decisions:
|
|
- "Kopfkommentar-Verweis auf 'desktop-version.sh' im neuen CI-Job-Schritt entfernt (nur als run-Zeile belassen), weil sonst grep -c 'desktop-version.sh' in der Datei auf 2 statt der geforderten 1 Fundstelle gestiegen waere — reine Kommentarformulierung, keine Verhaltensaenderung."
|
|
- "In der 404-Verzweigung von publish-release.sh wird ID jetzt explizit als Variable gesetzt (vorher nur inline in der Echo-Zeile berechnet), damit sie fuer die nachfolgende Upload-Schleife in beiden Zweigen (200 und 404) verfuegbar ist."
|
|
- "Upload-Schleife ueber die Manifest-Dateinamen laeuft als `for FNAME in $(jq -r ...)` statt `jq ... | while read`, damit ein `exit 1` innerhalb von upload_asset() unter dash/sh tatsaechlich das ganze Skript beendet und nicht nur eine Pipe-Subshell (POSIX-sh-Pipelines laufen in eigenen Subshells)."
|
|
|
|
patterns-established: []
|
|
|
|
requirements-completed: [DESK-01, DESK-04]
|
|
|
|
coverage:
|
|
- id: D1
|
|
description: "Job desktop laeuft nach test auf main und bei Tags v*, baut das Linux-AppImage mit der Tag-Version (System-Abhaengigkeiten, Rust-Toolchain per rustup, Cargo-Zwischenspeicher, cargo check/clippy, alte Bundles entfernen, Bau, desktop-collect.sh --require linux) und uebergibt desktop-dist/ per actions/cache an publish"
|
|
requirement: "DESK-01"
|
|
verification:
|
|
- kind: other
|
|
ref: "grep-Batterie aus dem Plan (CI-OK: Job-Schluessel, needs, Cache-Schluessel x2, fail-on-cache-miss, kein upload-artifact, System-Abhaengigkeiten, Skript-Aufrufe) + node-Struktur-Check der Job-Reihenfolge quality/test/desktop/publish"
|
|
status: pass
|
|
human_judgment: true
|
|
rationale: "Der eigentliche Pipeline-Lauf (Rust-Bau, apt-Installation, Cargo-Cache-Verhalten auf dem echten act_runner) kann von diesem Executor nicht ausgefuehrt werden — nur die YAML-Struktur und die POSIX-sh-Skripte sind lokal pruefbar. Der echte gruene Lauf wird laut Plan/Objective erst in 18-05 bewiesen (gemeinsam mit dem Windows-Cross-Bau)."
|
|
- id: D2
|
|
description: "publish bricht hart ab, wenn das Manifest aus dem Zwischenspeicher fehlt (fail-on-cache-miss im Workflow + expliziter test -f/jq-Schritt + zweites Netz in publish-images.sh vor der Docker-Bau-Schleife)"
|
|
requirement: "DESK-01"
|
|
verification:
|
|
- kind: other
|
|
ref: "sh -n .gitea/scripts/publish-images.sh + GITHUB_REF=refs/tags/v1.1.0 sh .gitea/scripts/publish-images.sh --print-plan (liefert weiterhin 4 push-Zeilen, da der Probelauf vor der neuen Pruefung endet) + Code-Inspektion der neuen if [ ! -f desktop-dist/manifest.json ]-Pruefung vor der Bau-Schleife"
|
|
status: pass
|
|
human_judgment: false
|
|
- id: D3
|
|
description: "publish-release.sh haengt bei Tags jede Datei aus dem Manifest idempotent als Release-Datei an den Gitea-Release (GET assets -> vorhandene Datei gleichen Namens per DELETE entfernen -> POST multipart); das Token verlaesst nie die Header-Datei"
|
|
requirement: "DESK-04"
|
|
verification:
|
|
- kind: other
|
|
ref: "sh -n .gitea/scripts/publish-release.sh + sh .gitea/scripts/publish-release.sh --dry-run --tag v1.1.0 (nennt POST .../assets?name=Tessera-1.1.0.AppImage aus dem echten Manifest von 18-01, kein Netzaufruf, kein Token) + grep-Batterie (HDR_AUTH x4, genau ein upload_asset(), files[].name, kein curl mit GITEA_TOKEN als Argument)"
|
|
status: pass
|
|
human_judgment: true
|
|
rationale: "Der idempotente GET/DELETE/POST-Roundtrip gegen die echte Gitea-API (inkl. multipart-Upload einer ~107-MB-Datei) ist nur im echten CI-Lauf pruefbar; der Probelauf beweist ausschliesslich die Skript-Logik und den erwarteten Zielpfad. Der echte Beweis folgt beim naechsten Freigabe-Tag (18-06, human-check laut Plan-Verifikation Punkt 4)."
|
|
|
|
duration: 8min
|
|
completed: 2026-09-16
|
|
status: complete
|
|
---
|
|
|
|
# Phase 18 Plan 02: CI-Pipeline fuer den Desktop-Client — Job `desktop`, Cache-Uebergabe, Release-Anhaenge Summary
|
|
|
|
**Neuer CI-Job `desktop` baut das Linux-AppImage mit Tag-Version und uebergibt es per `actions/cache` an `publish`, das ohne Manifest hart abbricht; `publish-release.sh` haengt jede Datei aus `manifest.json` idempotent (GET/DELETE/POST) als Release-Anhang an — der echte Pipeline-Lauf folgt in 18-05.**
|
|
|
|
## Performance
|
|
|
|
- **Duration:** 8 min
|
|
- **Started:** 2026-09-16T14:13:35Z (Aktenstand-Zeitstempel nach 18-01)
|
|
- **Completed:** 2026-09-16T14:21:32Z
|
|
- **Tasks:** 2
|
|
- **Files modified:** 3
|
|
|
|
## Accomplishments
|
|
- `.gitea/workflows/ci.yml`: neuer Job `desktop` zwischen `test` und `publish` — Systemabhaengigkeiten (vollstaendige apt-Liste fuer den bloßen `ubuntu-latest`-Runner, Pitfall 5), Rust-Toolchain per `rustup` (kein Rust im Runner-Abbild), Cargo-Zwischenspeicher (`actions/cache@v4`, Schluessel ueber `Cargo.lock`-Hash), Version aus dem Freigabe-Tag (`desktop-version.sh`), `cargo check`/`cargo clippy` (D-16), alte Bundle-Reste entfernen, Linux-AppImage bauen, `desktop-collect.sh --require linux`, Uebergabe per `actions/cache/save` mit Schluessel `desktop-dist-${{ gitea.sha }}`.
|
|
- `publish` haengt jetzt an `desktop` (`needs: desktop`) statt an `test`, holt die Pakete per `actions/cache/restore` mit `fail-on-cache-miss: true` und prueft das Manifest zusaetzlich explizit (`test -f` + `jq .`) — Job bricht sichtbar ab statt ein Abbild ohne Desktop-Pakete zu bauen.
|
|
- `publish-images.sh`: zweites Netz gegen einen Cache-Fehlschlag — im echten Baupfad (nicht im `--print-plan`-Probelauf) bricht das Skript ohne `desktop-dist/manifest.json` mit Exit 1 ab, bevor irgendein `docker build` laeuft.
|
|
- `publish-release.sh`: neue Funktion `upload_asset()` nach dem bereits etablierten GET-dann-PATCH/POST-Idempotenzmuster der Datei — pro Manifest-Datei erst pruefen, ob ein Anhang gleichen Namens existiert (`GET .../assets`), diesen ggf. entfernen (`DELETE`), dann frisch hochladen (`POST multipart`, Feld `attachment`). Neue Header-Datei `$HDR_AUTH` (nur `Authorization`, kein JSON-Content-Type) fuer den multipart-Upload — gleiche `umask 077`/`mktemp`/`trap`-Mechanik wie die bestehende `$HDR`-Datei, Token verlaesst nie eine `curl`-Kommandozeile. `--dry-run` listet zusaetzlich die geplanten Uploads aus dem vorhandenen Manifest.
|
|
|
|
## Task Commits
|
|
|
|
Each task was committed atomically:
|
|
|
|
1. **Task 1: Job desktop (Linux-AppImage) und Uebergabe an publish per actions/cache** - `a6ffe05` (feat)
|
|
2. **Task 2: Release-Dateien idempotent an den Gitea-Release haengen** - `75a8e40` (feat)
|
|
|
|
**Plan metadata:** commit pending (this SUMMARY + STATE.md/ROADMAP.md/REQUIREMENTS.md)
|
|
|
|
## Files Created/Modified
|
|
- `.gitea/workflows/ci.yml` - Job `desktop` (Linux-AppImage, Cargo-Cache, actions/cache-Uebergabe), `publish` haengt an `desktop`, holt Pakete per Cache-Restore mit hartem Abbruch
|
|
- `.gitea/scripts/publish-images.sh` - Harte Manifest-Pruefung vor der Docker-Bau-Schleife im echten Baupfad
|
|
- `.gitea/scripts/publish-release.sh` - `HDR_AUTH`, `upload_asset()`, `DESKTOP_DIST`/`MANIFEST`-Variablen, Upload-Schleife nach Release-Anlage/-Aktualisierung, erweiterter `--dry-run`
|
|
|
|
## Decisions Made
|
|
- Kopfkommentar-Referenz auf `desktop-version.sh` im neuen CI-Schritt-Kommentar weggelassen (nur als tatsaechliche `run:`-Zeile vorhanden), damit die Zaehl-basierte Abnahmekriterien-Pruefung (`grep -c 'desktop-version.sh'` == 1) exakt erfuellt wird — keine funktionale Aenderung.
|
|
- `ID` in der 404-Verzweigung von `publish-release.sh` (neuer Release) jetzt als Variable gesetzt statt nur inline in der Log-Zeile berechnet, damit dieselbe Variable in beiden Case-Zweigen (bestehender und neuer Release) fuer die nachfolgende Upload-Schleife zur Verfuegung steht.
|
|
- Die Upload-Schleife ueber Manifest-Dateinamen nutzt `for FNAME in $(jq -r '.files[].name' "$MANIFEST")` statt einer `jq | while read`-Pipe, weil ein `exit 1` innerhalb der aufgerufenen `upload_asset()`-Funktion in einer POSIX-sh-Pipe-Subshell nur die Subshell beendet hatte, nicht das gesamte Skript — mit `for ... in $(...)` bleibt der Fehlerpfad im Hauptprozess und `set -eu` wirkt wie erwartet.
|
|
|
|
## Deviations from Plan
|
|
|
|
None - plan executed exactly as written.
|
|
|
|
## Issues Encountered
|
|
- Die im Plan/`<verify>` verwendeten `grep`-Muster mit `${{ ... }}` (z. B. `desktop-dist-${{ gitea.sha }}`) liefern in dieser Ausfuehrungsumgebung ueber die interaktive `grep`-Shell-Funktion (ugrep-basierter Shim von Claude Code) faelschlich 0 Treffer, obwohl die Zeile exakt vorhanden ist — bestaetigt durch direkten Vergleich mit `command grep`/`/usr/bin/grep` (GNU grep 3.11), die beide korrekt 2 Treffer liefern. Alle `<verify>`- und `<acceptance_criteria>`-Pruefungen wurden deshalb zusaetzlich mit `command grep` wiederholt und sind gruen; die Datei selbst ist unveraendert von diesem Werkzeug-Artefakt betroffen. Kein Code-Problem, reine Umgebungs-Eigenheit dieser Sitzung.
|
|
|
|
## User Setup Required
|
|
|
|
None - no external service configuration required.
|
|
|
|
## Next Phase Readiness
|
|
- Der Job `desktop` und die Cache-Uebergabe an `publish` stehen; `publish` kann kein Abbild mehr ohne Desktop-Pakete bauen; `publish-release.sh` laedt Manifest-Dateien idempotent hoch — 18-05 kann direkt den Windows-Cross-Bau (cargo-xwin, NSIS) in denselben `desktop`-Job erweitern und den echten Pipeline-Lauf mit beiden Dateien beweisen.
|
|
- Kein Blocker. Der reale CI-Lauf (act_runner, echter Cache-Server, echter Gitea-Upload) ist laut Plan-Objective bewusst nicht Teil dieses Plans — er wird in 18-05 (Pipeline-Beweis) und beim naechsten Freigabe-Tag (18-06, Release-Anhang) gefuehrt.
|
|
- `REGISTRY_TOKEN` (Precondition Task 2) bleibt unveraendert im Einsatz; keine neue Secret-Konfiguration noetig.
|
|
|
|
---
|
|
*Phase: 18-desktop-client-fertigstellen*
|
|
*Completed: 2026-09-16*
|
|
|
|
## Self-Check: PASSED
|
|
|
|
All modified files verified on disk (`.gitea/workflows/ci.yml`, `.gitea/scripts/publish-images.sh`, `.gitea/scripts/publish-release.sh`). Both task commits found in `git log` (`a6ffe05`, `75a8e40`). All plan-level `<verification>` items re-run and passing: `CI-OK` (Job-Struktur, Cache-Schluessel x2, `fail-on-cache-miss`, kein `upload-artifact`, Skript-Aufrufe), `IMAGES-OK` (`sh -n`, vier `push`-Zeilen im Probelauf, Manifest-Pruefung vorhanden), `RELEASE-OK` (`sh -n`, Probelauf nennt `assets?name=Tessera-1.1.0.AppImage`, `HDR_AUTH` x4, genau ein `upload_asset()`, `files[].name`, kein Token in einer `curl`-Zeile) — alle Pruefungen zusaetzlich mit `command grep`/GNU grep gegengeprueft (siehe "Issues Encountered" zum `ugrep`-Shim-Artefakt dieser Sitzung).
|