syncova-backup/scripts/build-release.sh
Jerrit Fritzsche 610719c316
Some checks failed
CI / Backend (Go) (push) Failing after 3m7s
CI / Frontend (React/TypeScript) (push) Successful in 37s
CI / Sicherheitsprüfungen (push) Successful in 44s
Syncova Backups V1
Enterprise-Backup-, Recovery-, Verification-, Security- und
Monitoring-Plattform fuer Proxmox VE, Windows, Linux und Dateisysteme.

Der Leitsatz, der fast jede Entscheidung erklaert: Ein Backup gilt erst als
vertrauenswuerdig, wenn Integritaet geprueft und Wiederherstellbarkeit
nachgewiesen wurde. Deshalb steigt ein Wiederherstellungspunkt erst nach einem
tatsaechlich durchgefuehrten Restore-Test auf "recoverable", und Unbekanntes
geht in keine Bewertung als "gut" ein.

Umfang (Phasen 0-23):

- Repository Engine: inhaltsadressierte Bloecke, atomares Commit-Protokoll,
  Katalogaufbau allein aus den Manifesten — ohne Datenbank
- Backup Engine: inhaltsabhaengiges Chunking, Deduplizierung trotz
  Verschluesselung, zstd, AES-256-GCM, Streaming mit Gegendruck
- Agenten fuer Windows und Linux mit Auftragsabholung (Pull-Modell)
- Proxmox-Provider mit beiden Zugriffswegen auf die Sicherungsarchive
- Scheduler, Recovery Engine mit Pruefpunkt, Verification, Unveraenderlichkeit
- Weboberflaeche, Kennzahlen, Meldungen, Berichte, Security Center,
  Ransomware-Heuristik (meldet, handelt nie)
- Disaster Recovery, Haertung, Leistungsmessung, Chaos Testing
- Eingefrorene Vertraege fuer API, Migrationen, Backup-Format und Repository
- Auslieferungspaket fuer linux/amd64, linux/arm64 und windows/amd64

Nicht enthalten und als solches gekennzeichnet: Kapazitaetsprognose, Backup
Copy, Changed Block Tracking bei Proxmox, erweiterte Attribute und ACLs.

Gebaut, aber nie auf echter Hardware gefahren: der Windows-Dienst, die
systemd-Einheit und der verpflichtende Proxmox-Meilenstein — ob eine
wiederhergestellte VM startet, ist ungeprueft. Einzelheiten in CHANGELOG.md
und docs/release-candidate.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 09:10:54 +02:00

170 lines
6.4 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Baut das Auslieferungspaket der Version V1 (Phase 23).
#
# Das Paket enthält alles, was §25 des Umsetzungsplans verlangt: Server,
# Oberfläche, beide Agenten, Repository-Werkzeuge, Migrationen und die
# Dokumentation. Es ist bewusst **ein** Verzeichnisbaum je Zielplattform und
# kein Installationsprogramm: Ein Betreiber soll sehen können, was er auspackt.
#
# Aufruf: make release (oder scripts/build-release.sh)
set -euo pipefail
# releaseVersion ist die Version des Pakets.
#
# Ohne Git-Tag der Kurz-Hash — nie eine erfundene Nummer: Ein Paket, dessen
# Version man nicht auf einen Stand zurückführen kann, ist bei einer
# Fehlersuche wertlos.
releaseVersion="${BUILD_VERSION:-$(git describe --tags --always --dirty 2>/dev/null || echo "0.1.0-dev")}"
# distributionRoot ist das Ausgabeverzeichnis.
distributionRoot="dist"
# targetPlatforms sind die ausgelieferten Zielplattformen.
#
# Das Format ist "betriebssystem/architektur/dateiendung". macOS ist bewusst
# nicht dabei: Dort wurde entwickelt, aber der Plan nennt es nicht als Ziel, und
# eine Plattform auszuliefern, für die es kein Betriebskonzept gibt, weckt
# Erwartungen, die niemand einlöst.
targetPlatforms=(
"linux/amd64/"
"linux/arm64/"
"windows/amd64/.exe"
)
# serverCommands sind die Programme der Control Plane.
serverCommands=(
"syncova-api:apps/api/cmd/syncova-api"
"syncova-migrate:apps/api/cmd/syncova-migrate"
"syncova-admin:apps/api/cmd/syncova-admin"
"syncova-repo:apps/api/cmd/syncova-repo"
"syncova-dr:apps/api/cmd/syncova-dr"
"syncova-proxmox:apps/api/cmd/syncova-proxmox"
"syncova-bench:apps/api/cmd/syncova-bench"
)
# agentCommand ist das Programm des Agenten.
agentCommand="syncova-agent:apps/agent/cmd/syncova-agent"
# windowsServerCommands sind die Programme, die es auch für Windows gibt.
#
# Der vollständige Server läuft unter Linux; für Windows wird der Agent
# ausgeliefert und dazu die Werkzeuge, die ein Betreiber dort tatsächlich
# braucht. Alles andere zu übersetzen, nur weil es übersetzt, ergäbe Programme
# ohne Betriebskonzept.
windowsServerCommands=(
"syncova-repo:apps/api/cmd/syncova-repo"
)
echo "Syncova V1 — Auslieferungspaket ${releaseVersion}"
echo
rm -rf "${distributionRoot}"
mkdir -p "${distributionRoot}"
# ---------------------------------------------------------------------------
# 1. Oberfläche
# ---------------------------------------------------------------------------
#
# Zuerst, weil sie am längsten braucht und weil ein Fehler hier den ganzen Lauf
# ungültig macht: Ein Paket ohne Oberfläche ist kein vollständiges Paket.
echo "==> Weboberfläche"
if [[ ! -d apps/web/node_modules ]]; then
echo " Abhängigkeiten fehlen — 'make web-install' zuerst ausführen." >&2
exit 1
fi
(cd apps/web && npm run build >/dev/null)
if [[ ! -f apps/web/dist/index.html ]]; then
echo " Der Bau der Oberfläche hat kein index.html erzeugt." >&2
exit 1
fi
# ---------------------------------------------------------------------------
# 2. Programme je Zielplattform
# ---------------------------------------------------------------------------
for platformEntry in "${targetPlatforms[@]}"; do
IFS='/' read -r targetOS targetArch binaryExtension <<< "${platformEntry}"
packageName="syncova-${releaseVersion}-${targetOS}-${targetArch}"
packageRoot="${distributionRoot}/${packageName}"
echo "==> ${targetOS}/${targetArch}"
mkdir -p "${packageRoot}/bin" "${packageRoot}/migrations" "${packageRoot}/docs" \
"${packageRoot}/deployment"
# Welche Programme in dieses Paket gehören.
commandList=("${agentCommand}")
if [[ "${targetOS}" == "windows" ]]; then
commandList+=("${windowsServerCommands[@]}")
else
commandList+=("${serverCommands[@]}")
fi
for commandEntry in "${commandList[@]}"; do
commandName="${commandEntry%%:*}"
commandPath="${commandEntry#*:}"
# CGO aus: Ein statisch gebundenes Programm läuft auf jeder
# Distribution, unabhängig von deren libc-Version. Ohne diesen Schalter
# scheitert der Start auf einem älteren System mit einer Meldung über
# GLIBC, die niemand einem Backupprogramm zuordnet.
CGO_ENABLED=0 GOOS="${targetOS}" GOARCH="${targetArch}" \
go build -trimpath -ldflags "-s -w -X main.buildVersion=${releaseVersion}" \
-o "${packageRoot}/bin/${commandName}${binaryExtension}" "./${commandPath}"
echo " ${commandName}${binaryExtension}"
done
# Die Oberfläche gehört nur zum Serverpaket.
if [[ "${targetOS}" != "windows" ]]; then
mkdir -p "${packageRoot}/web"
cp -R apps/web/dist/. "${packageRoot}/web/"
fi
# Migrationen als Dateien **zusätzlich** zur Einbettung: Sie stecken bereits
# im Binary, aber ein Betreiber, der eine Abfrage nachvollziehen will, soll
# sie lesen können, ohne den Quellbestand zu holen.
cp migrations/*.sql "${packageRoot}/migrations/"
cp migrations/checksums.txt "${packageRoot}/migrations/"
cp -R docs/. "${packageRoot}/docs/"
cp README.md CHANGELOG.md "${packageRoot}/"
cp deployment/docker-compose.yml "${packageRoot}/deployment/" 2>/dev/null || true
cp deployment/syncova-agent.service "${packageRoot}/deployment/" 2>/dev/null || true
# Prüfsummen je Paket. Sie liegen **im** Paket, damit sich der Inhalt auch
# dann prüfen lässt, wenn nur er übertragen wurde.
(cd "${packageRoot}" && find . -type f ! -name SHA256SUMS -exec shasum -a 256 {} \; \
| sed 's|\./||' | sort -k2 > SHA256SUMS)
# Archiv: tar für Unix, zip für Windows — das jeweils übliche Format. Ein
# tar.gz auf einem Windows-Server auszupacken verlangt Zusatzwerkzeug.
if [[ "${targetOS}" == "windows" ]]; then
(cd "${distributionRoot}" && zip -qr "${packageName}.zip" "${packageName}")
else
(cd "${distributionRoot}" && tar -czf "${packageName}.tar.gz" "${packageName}")
fi
done
# ---------------------------------------------------------------------------
# 3. Prüfsummen über die Archive
# ---------------------------------------------------------------------------
(cd "${distributionRoot}" && shasum -a 256 ./*.tar.gz ./*.zip 2>/dev/null \
| sed 's|\./||' | sort -k2 > SHA256SUMS)
echo
echo "Auslieferungspakete:"
(cd "${distributionRoot}" && ls -lh ./*.tar.gz ./*.zip 2>/dev/null \
| awk '{printf " %-52s %s\n", $9, $5}')
echo
echo "Prüfsummen: ${distributionRoot}/SHA256SUMS"