From 6b83af7d733005b1d3628f57d5f596e92357a154 Mon Sep 17 00:00:00 2001 From: mhoennig Date: Wed, 22 Jul 2026 07:05:40 +0200 Subject: [PATCH] scripts/deploy-prod: Ziel aus git-ignorierter scripts/deploy.env (Fallback) Ohne Ziel-Argument liest das Skript DEPLOY_TARGET aus scripts/deploy.env (git-ignoriert; Vorlage scripts/deploy.env.example ist eingecheckt). Argument hat weiterhin Vorrang. Der Wert wird bewusst NICHT via `source` gelesen, weil bash bei `host:~/pfad` die Tilde nach dem ':' lokal expandieren wuerde; stattdessen roh ausgelesen, Whitespace/CR + umgebende Quotes gestrippt, das ~ bleibt fuer die Remote-Seite erhalten. Lokal verifiziert: Fallback greift, ~ bleibt in unquoted/single-/ double-quoted erhalten (kein lokales $HOME), Quotes entfernt. .gitignore: scripts/deploy.env ergaenzt (die vorhandene .env-Regel greift wegen des abweichenden Dateinamens nicht). README (de/en) aktualisiert; Beispielpfad auf die htdocs-ssl-Direktaufschaltung umgestellt. Co-Authored-By: Claude Opus 4.8 --- .gitignore | 2 ++ README.de.md | 18 +++++++++++------ README.md | 18 +++++++++++------ scripts/deploy-prod.sh | 41 ++++++++++++++++++++++++++++---------- scripts/deploy.env.example | 11 ++++++++++ 5 files changed, 67 insertions(+), 23 deletions(-) create mode 100644 scripts/deploy.env.example diff --git a/.gitignore b/.gitignore index 9044acb..42afcc7 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,8 @@ frontend/dist/ .env .env.local *.local +# Deploy-Ziel (scripts/deploy-prod.sh) — lokal halten; Vorlage .example bleibt drin +scripts/deploy.env # === Temporäres === tmp/ diff --git a/README.de.md b/README.de.md index c7120b6..99e5ba7 100644 --- a/README.de.md +++ b/README.de.md @@ -89,18 +89,24 @@ Workflow ersetzt ihn sonst aus `VERSION` + Commit-Zahl). **Bequemer: `scripts/deploy-prod.sh`.** Das Skript macht genau den obigen Prod-Build **und** die beiden Nacharbeiten (LICENSE danebenlegen + Link geradeziehen, Footer-Version + Commit-Link wie beim Pages-Workflow) und spiegelt -das Ergebnis per rsync/SSH auf einen Server. Zielpfad als einziges Pflichtargument: +das Ergebnis per rsync/SSH auf einen Server: ```bash -scripts/deploy-prod.sh mih00@mih00.hostsharing.net:~/doms/javagil.de/subs-ssl/werkbaum/ +scripts/deploy-prod.sh mih00@mih00.hostsharing.net:~/doms/werkbaum.javagil.de/htdocs-ssl ``` +Das Ziel ist entweder dieses Argument oder — ohne Argument — die Variable +`DEPLOY_TARGET` aus der **git-ignorierten** Datei `scripts/deploy.env` (Vorlage: +`scripts/deploy.env.example`, einmal kopieren und den Pfad eintragen). Ein +Argument hat Vorrang. + Ohne `-y` zeigt es zuerst eine `--dry-run`-Vorschau und fragt nach. `rsync --delete` sorgt dafür, dass am Ziel **nichts Altes** stehen bleibt — das -Zielverzeichnis gilt also als exklusiv für Werkbaum. (Hostsharing: für eine -**Subdomain** wie `werkbank.javagil.de` unter der aufgeschalteten Domain -`javagil.de` ist das Web-Verzeichnis `…/subs-ssl//`; eine direkt -aufgeschaltete Domain läge unter `…/htdocs-ssl/`.) +Zielverzeichnis gilt also als exklusiv für Werkbaum (eine laufende Let's-Encrypt- +Challenge unter `.well-known/` wird per `--filter=protect` ausgenommen, web- +taugliche Rechte 755/644 werden erzwungen). (Hostsharing: eine **direkt +aufgeschaltete** Domain liefert aus `…/htdocs-ssl/`; als **Subdomain** unter einer +anderen Domain läge das Web-Verzeichnis in `…/subs-ssl//`.) ## Projektdokumente diff --git a/README.md b/README.md index fb18cf4..a4df241 100644 --- a/README.md +++ b/README.md @@ -87,18 +87,24 @@ from `VERSION` + commit count). **Easier: `scripts/deploy-prod.sh`.** The script runs exactly that prod build **and** both fix-ups (drop `LICENSE` alongside + straighten the link, footer version + commit link just like the Pages workflow) and mirrors the result to a -server via rsync/SSH. The target path is the only required argument: +server via rsync/SSH: ```bash -scripts/deploy-prod.sh mih00@mih00.hostsharing.net:~/doms/javagil.de/subs-ssl/werkbaum/ +scripts/deploy-prod.sh mih00@mih00.hostsharing.net:~/doms/werkbaum.javagil.de/htdocs-ssl ``` +The target is either this argument or — with no argument — the `DEPLOY_TARGET` +variable from the **git-ignored** file `scripts/deploy.env` (template: +`scripts/deploy.env.example`, copy it once and fill in the path). An argument +takes precedence. + Without `-y` it first shows a `--dry-run` preview and asks for confirmation. `rsync --delete` ensures **nothing old** is left at the target — so the target -directory is treated as exclusive to Werkbaum. (Hostsharing: for a **subdomain** -like `werkbank.javagil.de` under the parent domain `javagil.de` the web directory -is `…/subs-ssl//`; a directly-served domain would live under -`…/htdocs-ssl/`.) +directory is treated as exclusive to Werkbaum (an in-flight Let's Encrypt +challenge under `.well-known/` is spared via `--filter=protect`, and web-friendly +755/644 permissions are enforced). (Hostsharing: a **directly-served** domain is +served from `…/htdocs-ssl/`; as a **subdomain** under another domain the web +directory would be `…/subs-ssl//`.) ## Project documents diff --git a/scripts/deploy-prod.sh b/scripts/deploy-prod.sh index b8bacc5..854f6e3 100755 --- a/scripts/deploy-prod.sh +++ b/scripts/deploy-prod.sh @@ -9,15 +9,19 @@ # nichts Altes stehen. # # Verwendung: -# scripts/deploy-prod.sh [-y] +# scripts/deploy-prod.sh [-y] [rsync-ziel] # # -y ohne Rückfrage spiegeln (sonst erst Vorschau via --dry-run + Nachfrage) # -# Beispiel (Hostsharing, Subdomain werkbank.javagil.de unter der Domain -# javagil.de — deshalb `subs-ssl/`; wäre die Domain direkt aufgeschaltet, läge -# das Web-Verzeichnis in `htdocs-ssl/`): +# Das Ziel ist entweder das Argument ODER — wenn keins angegeben ist — die +# Variable DEPLOY_TARGET aus der git-ignorierten Datei scripts/deploy.env +# (Vorlage: scripts/deploy.env.example). Ein Argument hat Vorrang. # -# scripts/deploy-prod.sh mih00@mih00.hostsharing.net:~/doms/javagil.de/subs-ssl/werkbaum/ +# Beispiel (Hostsharing, direkt aufgeschaltete Domain werkbaum.javagil.de — +# Web-Verzeichnis in `htdocs-ssl/`; als Subdomain unter einer anderen Domain +# läge es stattdessen in `subs-ssl//`): +# +# scripts/deploy-prod.sh mih00@mih00.hostsharing.net:~/doms/werkbaum.javagil.de/htdocs-ssl # # ACHTUNG: Das Zielverzeichnis wird als exklusiv für Werkbaum angenommen — # `--delete` entfernt dort ALLES, was nicht zum Bundle gehört. @@ -43,16 +47,31 @@ for arg in "$@"; do esac done -if [ -z "$TARGET" ]; then - echo "Usage: $0 [-y] " >&2 - echo " z.B. $0 mih00@mih00.hostsharing.net:~/doms/javagil.de/subs-ssl/werkbaum/" >&2 - exit 2 -fi - # ---- Repo-Wurzel (Skript ist unter scripts/) ---- ROOT="$(cd "$(dirname "$0")/.." && pwd)" cd "$ROOT" +# ---- Ziel: Argument hat Vorrang, sonst scripts/deploy.env (git-ignoriert) ---- +ENV_FILE="$ROOT/scripts/deploy.env" +if [ -z "$TARGET" ] && [ -f "$ENV_FILE" ]; then + # Bewusst NICHT via `source` lesen: bash würde bei `host:~/pfad` das ~ nach dem + # ':' LOKAL expandieren. Stattdessen roh auslesen (letzte Definition gewinnt), + # trailing Whitespace/CR und umgebende Quotes strippen — das ~ bleibt so für + # die Remote-Seite erhalten. + TARGET="$(sed -n -E 's/^[[:space:]]*DEPLOY_TARGET[[:space:]]*=[[:space:]]*//p' "$ENV_FILE" \ + | tail -1 | sed -E 's/[[:space:]]+$//')" + TARGET="${TARGET#\"}"; TARGET="${TARGET%\"}" + TARGET="${TARGET#\'}"; TARGET="${TARGET%\'}" + [ -n "$TARGET" ] && echo "==> Ziel aus scripts/deploy.env: ${TARGET}" +fi + +if [ -z "$TARGET" ]; then + echo "Usage: $0 [-y] " >&2 + echo " oder DEPLOY_TARGET in scripts/deploy.env setzen (Vorlage: scripts/deploy.env.example)" >&2 + echo " z.B. $0 mih00@mih00.hostsharing.net:~/doms/werkbaum.javagil.de/htdocs-ssl" >&2 + exit 2 +fi + # ---- 1) Prod-Build (ohne Build-Hinweis) ---- if [ ! -d frontend/node_modules ]; then echo "==> node_modules fehlt — npm ci" diff --git a/scripts/deploy.env.example b/scripts/deploy.env.example new file mode 100644 index 0000000..1a0a35d --- /dev/null +++ b/scripts/deploy.env.example @@ -0,0 +1,11 @@ +# Vorlage für scripts/deploy.env — kopieren und anpassen: +# cp scripts/deploy.env.example scripts/deploy.env +# +# scripts/deploy.env ist git-ignoriert (enthält deinen Server/Pfad) und wird von +# scripts/deploy-prod.sh benutzt, wenn KEIN Ziel als Argument übergeben wird. +# Ein Argument hat immer Vorrang. +# +# Wert = rsync-Ziel (user@host:pfad). Das `~` wird auf der Remote-Seite +# aufgelöst; Anführungszeichen sind optional. Keine Kommentare hinter dem Wert. + +DEPLOY_TARGET=mih00@mih00.hostsharing.net:~/doms/werkbaum.javagil.de/htdocs-ssl