From cf7371fb4096f0d448b1048c43a9cf7223e06174 Mon Sep 17 00:00:00 2001 From: fds2610-bot Date: Thu, 23 Jul 2026 15:17:48 +0200 Subject: [PATCH 1/2] =?UTF-8?q?Deploy-Skript=20update.sh=20mit=20DB-Migrat?= =?UTF-8?q?ionssystem=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kopiert den git-Stand nach /var/www/html (config.php bleibt unangetastet), prüft PHP-Syntax vorab und wendet ausstehende Migrationen aus migrations/ über eine schema_migrations-Tracking-Tabelle an. Tests werden ausgeführt, sobald welche existieren. Co-Authored-By: Claude Sonnet 5 --- .gitignore | 1 + migrations/README.md | 31 +++++++++++++++ migrations/run_migrations.php | 63 ++++++++++++++++++++++++++++++ update.sh | 72 +++++++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 migrations/README.md create mode 100644 migrations/run_migrations.php create mode 100755 update.sh diff --git a/.gitignore b/.gitignore index e56bd73..b13a64d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ html/config.php info.php config.php *.old +html/.Trash-1000 diff --git a/migrations/README.md b/migrations/README.md new file mode 100644 index 0000000..6d74471 --- /dev/null +++ b/migrations/README.md @@ -0,0 +1,31 @@ +# Datenbank-Migrationen + +Migrationen liegen hier als `.sql`-Dateien, benannt nach dem Schema: + +``` +0001_kurze_beschreibung.sql +0002_naechste_aenderung.sql +``` + +`update.sh` ruft `migrations/run_migrations.php ` auf. Das Skript: + +- legt bei Bedarf die Tabelle `schema_migrations` an (Spalte `filename` als Primary Key), die protokolliert, welche Dateinamen bereits angewendet wurden +- führt alle noch nicht angewendeten `.sql`-Dateien in Dateinamen-Reihenfolge aus +- bricht beim ersten Fehler sofort ab (die fehlgeschlagene Datei wird NICHT als angewendet markiert, alle vorherigen bleiben es) + +## Regeln für neue Migrationen + +- Immer die nächste freie, vierstellige Nummer verwenden (`0003_...`). Eine bereits vergebene Nummer nie wiederverwenden, eine bereits angewendete Datei nachträglich nicht mehr ändern (neue Migration statt Änderung der alten). +- So schreiben, dass sie **keine Breaking Changes** verursachen, z. B.: + - `CREATE TABLE IF NOT EXISTS ...` statt `CREATE TABLE ...` + - Neue Spalten nullable oder mit `DEFAULT` anlegen, statt bestehende `NOT NULL`-Constraints nachträglich zu erzwingen + - Kein `DROP TABLE` / `DROP COLUMN` ohne vorherige Rücksprache +- Migrationen möglichst idempotent halten (`IF NOT EXISTS`), damit ein erneuter Lauf nach einem Teilfehler nicht sofort wieder bricht. + +## Historie + +`init.sql` (Ausgangsschema für Neuinstallationen) und `update.sql` (bereits manuell eingespieltes Aktien-Modul) liegen bewusst außerhalb dieses Verzeichnisses, da beide bereits auf allen bekannten Servern produktiv sind. Ab jetzt werden neue Schema-Änderungen ausschließlich als nummerierte Migration hier abgelegt. + +## Hinweis + +`run_migrations.php` bindet die produktive `config.php` per `require` ein, um die bestehende `$pdo`-Verbindung wiederzuverwenden. Da `config.php` `session_start()` aufruft, legt der CLI-Lauf dabei eine kurzlebige, ungenutzte Session-Datei an — das ist unschädlich, aber erwähnenswert. diff --git a/migrations/run_migrations.php b/migrations/run_migrations.php new file mode 100644 index 0000000..79cd1c5 --- /dev/null +++ b/migrations/run_migrations.php @@ -0,0 +1,63 @@ +exec( + "CREATE TABLE IF NOT EXISTS schema_migrations ( + filename VARCHAR(255) NOT NULL PRIMARY KEY, + applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP + )" +); + +$applied = $pdo->query("SELECT filename FROM schema_migrations")->fetchAll(PDO::FETCH_COLUMN); + +$files = glob($migrationsDir . '/*.sql') ?: []; +sort($files, SORT_STRING); + +$pending = array_values(array_filter( + $files, + fn(string $f): bool => !in_array(basename($f), $applied, true) +)); + +if (empty($pending)) { + echo "Keine neuen Migrationen.\n"; + exit(0); +} + +foreach ($pending as $file) { + $name = basename($file); + echo "-> Migration $name ... "; + + $sql = file_get_contents($file); + if ($sql === false || trim($sql) === '') { + fwrite(STDERR, "\nMigration $name ist leer oder konnte nicht gelesen werden.\n"); + exit(1); + } + + try { + $pdo->exec($sql); + $stmt = $pdo->prepare("INSERT INTO schema_migrations (filename) VALUES (?)"); + $stmt->execute([$name]); + echo "OK\n"; + } catch (Throwable $e) { + fwrite(STDERR, "\nFEHLER bei $name: " . $e->getMessage() . "\n"); + fwrite(STDERR, "Abbruch. Bereits erfolgreich angewendete Migrationen bleiben markiert, $name muss manuell geprueft werden.\n"); + exit(1); + } +} + +echo "Alle Migrationen angewendet.\n"; diff --git a/update.sh b/update.sh new file mode 100755 index 0000000..591b420 --- /dev/null +++ b/update.sh @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# +# Deployt den aktuellen git-Stand dieses Projektverzeichnisses in den Webroot +# und wendet danach ausstehende Datenbank-Migrationen an. +# +# Aufruf (im Projektverzeichnis): +# ./update.sh +# +# Optional per Umgebungsvariable überschreibbar: +# WEBROOT=/anderer/pfad ./update.sh +# CONFIG_FILE=/anderer/pfad/config.php ./update.sh + +set -euo pipefail + +PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WEBROOT="${WEBROOT:-/var/www/html}" +CONFIG_FILE="${CONFIG_FILE:-$WEBROOT/config.php}" + +log() { echo "==> $*"; } +fail() { echo "FEHLER: $*" >&2; exit 1; } + +cd "$PROJECT_DIR" + +command -v php >/dev/null 2>&1 || fail "php ist nicht installiert bzw. nicht im PATH." +[ -d "$WEBROOT" ] || fail "Webroot $WEBROOT existiert nicht." +[ -w "$WEBROOT" ] || fail "Keine Schreibrechte auf $WEBROOT." + +# --- 1. Sicherstellen, dass das Projektverzeichnis sauber ist --- +if ! git diff --quiet || ! git diff --cached --quiet; then + fail "Lokale Änderungen im Projektverzeichnis vorhanden - bitte erst committen oder stashen." +fi + +# --- 2. Neuesten Stand holen --- +log "git pull..." +git pull --ff-only + +# --- 3. PHP-Syntaxcheck als Sicherheitsnetz vor dem Kopieren --- +log "Prüfe PHP-Syntax..." +while IFS= read -r -d '' file; do + php -l "$file" >/dev/null || fail "Syntaxfehler in $file - es wird nichts kopiert." +done < <(find html -name '*.php' -print0) + +# --- 4. Dateien kopieren, config.php bleibt unangetastet --- +log "Kopiere Dateien nach $WEBROOT..." +config_backup="" +if [ -f "$CONFIG_FILE" ]; then + config_backup="$(mktemp)" + cp "$CONFIG_FILE" "$config_backup" +fi + +cp -r html/. "$WEBROOT/" + +if [ -n "$config_backup" ]; then + cp "$config_backup" "$CONFIG_FILE" + rm -f "$config_backup" +fi + +# --- 5. Datenbank-Migrationen --- +if [ -d migrations ] && [ -f migrations/run_migrations.php ]; then + log "Wende Datenbank-Migrationen an..." + php migrations/run_migrations.php "$CONFIG_FILE" +fi + +# --- 6. Tests --- +if [ -f tests/run.sh ]; then + log "Führe Tests aus..." + bash tests/run.sh +else + log "Noch keine Tests vorhanden - werden später ergänzt." +fi + +log "Update abgeschlossen." From 97c7fd73e0f40946f71eaad1dd93434e47345b38 Mon Sep 17 00:00:00 2001 From: fds2610-bot Date: Thu, 23 Jul 2026 15:22:16 +0200 Subject: [PATCH 2/2] README auf V.2.1 versioniert, Deploy-Skript und Migrationssystem dokumentiert Co-Authored-By: Claude Sonnet 5 --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 7cf589a..d37cf13 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,12 @@ Dokumentiere Ausgaben on-the-go als Webapp - [ ] Zusammenfassen von mehreren Einträgen zu einer Aktie - [ ] Prüfen ob APIKEYS leer sind und ggfs die Aktualisierung ausblenden +## V.2.1 + +- [X] `update.sh` zum Deployen auf einen Zielserver: prüft PHP-Syntax, kopiert den aktuellen git-Stand ins Webroot (ohne die produktive `config.php` zu überschreiben) und wendet danach ausstehende Datenbank-Migrationen an. +- [X] neues Verzeichnis `migrations/` mit versioniertem Migrationssystem: nummerierte `.sql`-Dateien werden über eine `schema_migrations`-Tabelle nachverfolgt und jeweils nur einmal angewendet (siehe `migrations/README.md` für die Konvention). +- [X] Platzhalter in `update.sh` für einen automatischen Testlauf, sobald Tests existieren. + ## V.2.0 - [X] neue Haupt-Funktion: Aktien zeigt eine Liste mit gespeicherten, zu beobachtenden Aktien