364 lines
16 KiB
Makefile
364 lines
16 KiB
Makefile
# ==============================================================
|
|
# BAN YARO — Makefile
|
|
# Deploy-Strategie: rsync vom Mac zur DS (kein git auf DS nötig)
|
|
# Git wird nur lokal auf dem Mac und für Forgejo-Backup genutzt.
|
|
# ==============================================================
|
|
|
|
DS_HOST := ds
|
|
DS_IP := 10.47.11.10
|
|
# Hinweis: NPM braucht 10.47.11.99 als Forward-IP (Macvlan-Shim), nicht .10
|
|
DS_SSH_PORT := 4711
|
|
DS_PATH := /volume1/docker/banyaro
|
|
DS_PATH_STAGING := /volume1/docker/banyaro-staging
|
|
CONTAINER := banyaro
|
|
CONTAINER_STAGING:= banyaro-staging
|
|
SERVICE := banyaro
|
|
GIT_REMOTE := origin
|
|
DOCKER := sudo /usr/local/bin/docker
|
|
VERSION ?= $(shell grep '"version"' backend/static/manifest.json | grep -o '[0-9]*\.[0-9]*\.[0-9]*' | head -1)
|
|
|
|
# tar: was NICHT auf die DS übertragen wird
|
|
TAR_EXCLUDE := --exclude='.git' \
|
|
--exclude='./data' \
|
|
--exclude='./backend/venv' \
|
|
--exclude='./backend/__pycache__' \
|
|
--exclude='./.env' \
|
|
--exclude='./*.db' \
|
|
--exclude='./tiles' \
|
|
--exclude='./.DS_Store'
|
|
|
|
.PHONY: help deploy deploy-clean staging release sync push restart build stop status \
|
|
logs logs-f shell db dev clean-cache check-ssh reports bump test tiles tiles-deploy
|
|
|
|
# ----------------------------------------------------------
|
|
# SSH-Prüfung — Abhängigkeit aller DS-Befehle
|
|
# ----------------------------------------------------------
|
|
check-ssh:
|
|
@if ! nc -z -w3 $(DS_IP) $(DS_SSH_PORT) 2>/dev/null; then \
|
|
echo ""; \
|
|
echo " ✗ DS nicht erreichbar ($(DS_IP):$(DS_SSH_PORT))"; \
|
|
echo ""; \
|
|
echo " SSH-Port $(DS_SSH_PORT) ist geschlossen oder DS offline."; \
|
|
echo " → Port in Fritz!Box / DS-Firewall öffnen, dann erneut versuchen."; \
|
|
echo ""; \
|
|
exit 1; \
|
|
fi
|
|
|
|
# ----------------------------------------------------------
|
|
# Hilfe
|
|
# ----------------------------------------------------------
|
|
help:
|
|
@echo ""
|
|
@echo " Ban Yaro — verfügbare Befehle:"
|
|
@echo ""
|
|
@echo " make deploy Sync + Rebuild + Neustart (mit Layer-Cache, häufigster Befehl)"
|
|
@echo " make deploy-clean Wie deploy, aber --no-cache (bei requirements-Änderungen)"
|
|
@echo " make sync Nur Dateien zur DS übertragen (ohne Rebuild)"
|
|
@echo " make push Nur Git push zu Forgejo (Backup/Versionierung)"
|
|
@echo " make restart Container neustarten (kein Rebuild)"
|
|
@echo " make build Docker neu bauen (ohne Neustart)"
|
|
@echo " make stop Container stoppen"
|
|
@echo " make status Container-Status anzeigen"
|
|
@echo ""
|
|
@echo " make logs Letzte 100 Zeilen"
|
|
@echo " make logs-f Live-Log-Stream"
|
|
@echo " make shell Bash im Container"
|
|
@echo " make db SQLite-Shell"
|
|
@echo ""
|
|
@echo " make dev Lokaler Dev-Server auf Mac (Port 8001)"
|
|
@echo " make clean-cache SW-Cache-Version erhöhen + restart"
|
|
@echo " make reports Quartalsberichte generieren + committen"
|
|
@echo ""
|
|
|
|
# ----------------------------------------------------------
|
|
# DEPLOY — der Haupt-Befehl
|
|
# 1. Git push (Backup)
|
|
# 2. rsync zum DS
|
|
# 3. Docker rebuild + restart
|
|
# ----------------------------------------------------------
|
|
deploy: check-ssh
|
|
@echo "→ Git push (Backup)..."
|
|
@git push $(GIT_REMOTE) main
|
|
@echo "→ Sync zu DS..."
|
|
@COPYFILE_DISABLE=1 tar czf - $(TAR_EXCLUDE) . | ssh $(DS_HOST) "tar xzf - -C $(DS_PATH)/"
|
|
@echo "→ Docker rebuild + restart (mit Layer-Cache)..."
|
|
@ssh $(DS_HOST) " \
|
|
cd $(DS_PATH) && \
|
|
$(DOCKER) compose down && \
|
|
$(DOCKER) compose build && \
|
|
$(DOCKER) compose up -d"
|
|
@echo ""
|
|
@echo " ✓ Deploy fertig. Letzte Logs:"
|
|
@ssh $(DS_HOST) "$(DOCKER) logs $(CONTAINER) --tail=15"
|
|
|
|
# ----------------------------------------------------------
|
|
# DEPLOY-CLEAN — erzwingt Neuaufbau ohne Layer-Cache
|
|
# Nötig wenn: requirements.txt geändert, System-Pakete aktualisiert,
|
|
# oder nach einem kaputten Image-State
|
|
# ----------------------------------------------------------
|
|
deploy-clean: check-ssh
|
|
@echo "→ Git push (Backup)..."
|
|
@git push $(GIT_REMOTE) main
|
|
@echo "→ Sync zu DS..."
|
|
@COPYFILE_DISABLE=1 tar czf - $(TAR_EXCLUDE) . | ssh $(DS_HOST) "tar xzf - -C $(DS_PATH)/"
|
|
@echo "→ Docker rebuild (--no-cache) + restart..."
|
|
@ssh $(DS_HOST) " \
|
|
cd $(DS_PATH) && \
|
|
$(DOCKER) compose down && \
|
|
$(DOCKER) compose build --no-cache && \
|
|
$(DOCKER) compose up -d"
|
|
@echo ""
|
|
@echo " ✓ Deploy fertig. Letzte Logs:"
|
|
@ssh $(DS_HOST) "$(DOCKER) logs $(CONTAINER) --tail=15"
|
|
|
|
# ----------------------------------------------------------
|
|
# STAGING — develop-Branch auf Staging deployen (Port 3012)
|
|
# ----------------------------------------------------------
|
|
staging: check-ssh
|
|
@echo "→ Git push develop..."
|
|
@git push $(GIT_REMOTE) develop
|
|
@echo "→ Sync zu DS (Staging)..."
|
|
@COPYFILE_DISABLE=1 tar czf - $(TAR_EXCLUDE) . | ssh $(DS_HOST) "tar xzf - -C $(DS_PATH_STAGING)/"
|
|
@echo "→ Staging rebuild + restart..."
|
|
@ssh $(DS_HOST) " \
|
|
cd $(DS_PATH_STAGING) && \
|
|
$(DOCKER) compose -f docker-compose.staging.yml down && \
|
|
$(DOCKER) compose -f docker-compose.staging.yml build && \
|
|
$(DOCKER) compose -f docker-compose.staging.yml up -d"
|
|
@echo ""
|
|
@echo " ✓ Staging fertig — https://staging.banyaro.app"
|
|
@ssh $(DS_HOST) "$(DOCKER) logs $(CONTAINER_STAGING) --tail=10"
|
|
|
|
# ----------------------------------------------------------
|
|
# STAGING-DB — Produktions-DB in Staging kopieren (interaktiv, braucht sudo)
|
|
# Aufruf: make staging-db
|
|
# ----------------------------------------------------------
|
|
staging-db: check-ssh
|
|
@echo "→ Produktions-DB nach Staging kopieren..."
|
|
@ssh -t $(DS_HOST) " \
|
|
sudo cp $(DS_PATH)/data/banyaro.db $(DS_PATH_STAGING)/data/banyaro.db && \
|
|
sudo chmod 666 $(DS_PATH_STAGING)/data/banyaro.db && \
|
|
echo '✓ DB kopiert'"
|
|
|
|
# ----------------------------------------------------------
|
|
# TILES — DACH-Vektortiles (planetiler → PMTiles), lokal bauen + ausliefern
|
|
# Voraussetzung: Docker Desktop läuft, osmium installiert (brew install osmium-tool).
|
|
# make tiles DACH neu generieren (download → merge → planetiler)
|
|
# make tiles-deploy dach.pmtiles auf Staging ausliefern (atomar)
|
|
# make tiles-deploy ENV=prod dach.pmtiles auf Produktion ausliefern (atomar)
|
|
# Monatlich neu generieren hält die Karte aktuell. Datei liegt im data-Volume,
|
|
# NICHT im Image — wird per Range-Route (/tiles) ausgeliefert.
|
|
# ----------------------------------------------------------
|
|
TILES_DIR := tiles/build
|
|
# DACH + alle angrenzenden Länder (15). Reihenfolge egal — osmium merge -H + time-filter
|
|
# dedupliziert Grenz-Nodes. Output bleibt dach.pmtiles (Frontend referenziert den Namen).
|
|
TILES_REGIONS := germany austria switzerland france italy czech-republic poland \
|
|
slovakia hungary slovenia netherlands belgium luxembourg denmark liechtenstein
|
|
PLANETILER_IMAGE := ghcr.io/onthegomap/planetiler:latest
|
|
TILES_TARGET := $(if $(filter prod,$(ENV)),$(DS_PATH),$(DS_PATH_STAGING))
|
|
|
|
tiles:
|
|
@mkdir -p $(TILES_DIR)
|
|
@echo "→ Geofabrik-Extrakte laden ($(TILES_REGIONS))..."
|
|
@for r in $(TILES_REGIONS); do \
|
|
echo " $$r"; \
|
|
curl -fsSL -o $(TILES_DIR)/$$r.osm.pbf https://download.geofabrik.de/europe/$$r-latest.osm.pbf; done
|
|
@echo "→ merge (History) + time-filter dedup → dach.osm.pbf..."
|
|
@# Geofabrik-Extrakte können versetzte Stände haben (z.B. germany älter als at/ch) →
|
|
@# Grenz-Nodes mit abweichender Version. Als History mergen + auf 'jetzt' snapshotten
|
|
@# liefert genau eine Version pro ID (planetiler braucht eindeutige, sortierte IDs).
|
|
@osmium merge -H $(foreach r,$(TILES_REGIONS),$(TILES_DIR)/$(r).osm.pbf) -o $(TILES_DIR)/dach-hist.osm.pbf --overwrite
|
|
@osmium time-filter $(TILES_DIR)/dach-hist.osm.pbf -o $(TILES_DIR)/dach.osm.pbf --overwrite
|
|
@# History + Einzel-PBFs jetzt freigeben (spart ~Quellsumme an Spitzen-Plattenplatz vor planetiler).
|
|
@rm -f $(TILES_DIR)/dach-hist.osm.pbf $(foreach r,$(TILES_REGIONS),$(TILES_DIR)/$(r).osm.pbf)
|
|
@echo "→ planetiler → dach.pmtiles (disk-backed mmap)..."
|
|
@docker run --rm -v "$(CURDIR)/$(TILES_DIR):/data" $(PLANETILER_IMAGE) \
|
|
--osm-path=/data/dach.osm.pbf --download --output=/data/dach.pmtiles --force \
|
|
--storage=mmap --nodemap-storage=mmap
|
|
@echo ""
|
|
@echo " ✓ Tiles gebaut:"; ls -lh $(TILES_DIR)/dach.pmtiles
|
|
|
|
tiles-deploy: check-ssh
|
|
@if [ ! -f $(TILES_DIR)/dach.pmtiles ]; then echo "❌ $(TILES_DIR)/dach.pmtiles fehlt — erst 'make tiles'"; exit 1; fi
|
|
@echo "→ Ausliefern nach $(TILES_TARGET)/data/tiles/ (atomarer Swap)..."
|
|
@ssh $(DS_HOST) "mkdir -p $(TILES_TARGET)/data/tiles"
|
|
@scp -O $(TILES_DIR)/dach.pmtiles $(DS_HOST):$(TILES_TARGET)/data/tiles/dach.pmtiles.tmp
|
|
@ssh $(DS_HOST) "mv -f $(TILES_TARGET)/data/tiles/dach.pmtiles.tmp $(TILES_TARGET)/data/tiles/dach.pmtiles"
|
|
@echo " ✓ dach.pmtiles ausgeliefert ($(if $(filter prod,$(ENV)),PRODUKTION,Staging))"
|
|
@# Cache-Bust: TILES_VER in map-gl-style.js hochzählen (sonst liefert der Browser bis 24h alte Tiles).
|
|
@NEWVER=$$(date +%Y%m%d%H%M); \
|
|
sed -i '' "s/var TILES_VER = '[0-9]*';/var TILES_VER = '$$NEWVER';/" backend/static/js/map-gl-style.js; \
|
|
echo " ↻ TILES_VER → $$NEWVER — JETZT Frontend ausliefern: make bump && make $(if $(filter prod,$(ENV)),deploy,staging)"
|
|
|
|
# ----------------------------------------------------------
|
|
# RELEASE — develop → main → Production (VERSION= pflichtangabe)
|
|
# Beispiel: make release VERSION=1.1.0
|
|
# ----------------------------------------------------------
|
|
release: check-ssh
|
|
@if [ -z "$(VERSION)" ]; then \
|
|
echo "❌ Bitte VERSION setzen: make release VERSION=1.1.0"; exit 1; fi
|
|
@echo "→ Merge develop → main (v$(VERSION))..."
|
|
@git checkout main
|
|
@git merge develop --no-ff -m "Release v$(VERSION)"
|
|
@sed -i '' 's/"version": "[^"]*"/"version": "$(VERSION)"/' backend/static/manifest.json
|
|
@sed -i '' "s/const APP_VERSION = '[^']*'/const APP_VERSION = '$(VERSION)'/" backend/static/js/app.js
|
|
@git add backend/static/manifest.json backend/static/js/app.js
|
|
@git commit --amend --no-edit
|
|
@git tag "v$(VERSION)"
|
|
@git push $(GIT_REMOTE) main --tags
|
|
@echo "→ Production deployen..."
|
|
@$(MAKE) deploy
|
|
@git checkout develop
|
|
@git merge main
|
|
@git push $(GIT_REMOTE) develop
|
|
@echo ""
|
|
@echo " ✓ Release v$(VERSION) veröffentlicht 🚀"
|
|
|
|
# ----------------------------------------------------------
|
|
# SYNC — nur Dateien zur DS übertragen, kein Docker-Rebuild
|
|
# ACHTUNG: ALLE Dateien (CSS/JS/HTML/Python) sind ins Image gebacken!
|
|
# sync+restart reicht für NICHTS — immer: make deploy
|
|
# ----------------------------------------------------------
|
|
sync: check-ssh
|
|
@echo "→ Sync zu DS..."
|
|
@COPYFILE_DISABLE=1 tar czf - $(TAR_EXCLUDE) . | ssh $(DS_HOST) "tar xzf - -C $(DS_PATH)/"
|
|
@echo " ✓ Sync fertig."
|
|
|
|
# ----------------------------------------------------------
|
|
# PUSH — nur Git, ohne DS-Deploy
|
|
# ----------------------------------------------------------
|
|
push:
|
|
git push $(GIT_REMOTE) main
|
|
|
|
# ----------------------------------------------------------
|
|
# RESTART — kein Rebuild, nur Container neu starten
|
|
# Reicht nur für Umgebungsvariablen-Änderungen (.env)
|
|
# ----------------------------------------------------------
|
|
restart: check-ssh
|
|
@ssh $(DS_HOST) " \
|
|
cd $(DS_PATH) && \
|
|
$(DOCKER) compose restart $(SERVICE)"
|
|
@echo " ✓ Neugestartet."
|
|
|
|
# ----------------------------------------------------------
|
|
# BUILD — nur Docker-Image neu bauen (mit Layer-Cache)
|
|
# ----------------------------------------------------------
|
|
build: check-ssh
|
|
@ssh $(DS_HOST) " \
|
|
cd $(DS_PATH) && \
|
|
$(DOCKER) compose build"
|
|
|
|
# ----------------------------------------------------------
|
|
# STOP
|
|
# ----------------------------------------------------------
|
|
stop: check-ssh
|
|
@ssh $(DS_HOST) "cd $(DS_PATH) && $(DOCKER) compose down"
|
|
@echo " ✓ Gestoppt."
|
|
|
|
# ----------------------------------------------------------
|
|
# STATUS
|
|
# ----------------------------------------------------------
|
|
status: check-ssh
|
|
@ssh $(DS_HOST) "$(DOCKER) ps \
|
|
--filter name=$(CONTAINER) \
|
|
--format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'"
|
|
|
|
# ----------------------------------------------------------
|
|
# LOGS
|
|
# ----------------------------------------------------------
|
|
logs: check-ssh
|
|
@ssh $(DS_HOST) "$(DOCKER) logs $(CONTAINER) --tail=100"
|
|
|
|
logs-f: check-ssh
|
|
@ssh $(DS_HOST) "$(DOCKER) logs $(CONTAINER) -f"
|
|
|
|
# ----------------------------------------------------------
|
|
# SHELL im Container
|
|
# ----------------------------------------------------------
|
|
shell: check-ssh
|
|
@ssh -t $(DS_HOST) "$(DOCKER) exec -it $(CONTAINER) bash"
|
|
|
|
# ----------------------------------------------------------
|
|
# SQLite
|
|
# ----------------------------------------------------------
|
|
db: check-ssh
|
|
@ssh -t $(DS_HOST) "$(DOCKER) exec -it $(CONTAINER) \
|
|
sqlite3 /data/banyaro.db"
|
|
|
|
# ----------------------------------------------------------
|
|
# DEV — lokaler Server auf Mac (kein Docker, kein DS)
|
|
# ----------------------------------------------------------
|
|
dev:
|
|
@cd backend && \
|
|
test -d venv || python3 -m venv venv && \
|
|
. venv/bin/activate && \
|
|
pip install -q -r requirements.txt && \
|
|
KI_MODE=off ENV=development \
|
|
JWT_SECRET=dev-secret \
|
|
DB_PATH=./dev.db \
|
|
MEDIA_DIR=$${MEDIA_DIR:-/tmp/banyaro-media} \
|
|
BREEDER_DOCS_DIR=$${BREEDER_DOCS_DIR:-/tmp/banyaro-breeder} \
|
|
uvicorn main:app --reload --port 8001
|
|
|
|
# ----------------------------------------------------------
|
|
# REPORTS — Quartalsberichte generieren und committen
|
|
# Berichte laufen im Container (DB-Zugriff), werden lokal gespeichert
|
|
# ----------------------------------------------------------
|
|
REPORT_DATE := $(shell date +%Y-%m-%d)
|
|
REPORT_SECTIONS := sicherheit funktionsumfang dateien nutzer partner server
|
|
|
|
reports: check-ssh
|
|
@mkdir -p reports
|
|
@echo "→ Berichte generieren ($(REPORT_DATE))..."
|
|
@for section in $(REPORT_SECTIONS); do \
|
|
echo " → $$section..."; \
|
|
ssh $(DS_HOST) "$(DOCKER) exec $(CONTAINER) python3 scripts/generate_reports.py $$section" \
|
|
> reports/$(REPORT_DATE)-$$section.md; \
|
|
done
|
|
@echo "→ Berichte committen..."
|
|
@git add reports/
|
|
@git diff --cached --quiet || git commit -m "Reports $(REPORT_DATE) — Quartalsbericht"
|
|
@echo ""
|
|
@echo " ✓ Alle Berichte erstellt und committed:"
|
|
@for section in $(REPORT_SECTIONS); do \
|
|
echo " reports/$(REPORT_DATE)-$$section.md"; \
|
|
done
|
|
|
|
|
|
# ----------------------------------------------------------
|
|
# BUMP — zentrale Versions-Erhöhung (VERSION-Datei + sw.js + app.js + index.html)
|
|
# Aufruf:
|
|
# make bump → liest aus VERSION, erhöht +1, schreibt zurück, propagiert in alle Frontend-Stellen
|
|
# make bump APP_VER=2000 → setzt VERSION explizit auf 2000
|
|
# Backend liest APP_VER beim Startup aus VERSION (siehe main.py:_read_app_ver()).
|
|
# ----------------------------------------------------------
|
|
bump:
|
|
@if [ ! -f VERSION ]; then echo "0" > VERSION; fi
|
|
@CUR=$$(cat VERSION | tr -d '[:space:]'); \
|
|
if [ -n "$(APP_VER)" ]; then NEW="$(APP_VER)"; else NEW=$$(($$CUR + 1)); fi; \
|
|
printf "%s" "$$NEW" > VERSION; \
|
|
sed -i.bak -E "s/const VER[[:space:]]*=[[:space:]]*'[0-9]+'/const VER = '$$NEW'/" backend/static/sw.js && rm -f backend/static/sw.js.bak; \
|
|
sed -i.bak -E "s/const APP_VER[[:space:]]*=[[:space:]]*'[0-9]+'/const APP_VER = '$$NEW'/" backend/static/js/app.js && rm -f backend/static/js/app.js.bak; \
|
|
sed -i.bak -E "s/\?v=[0-9]+/?v=$$NEW/g" backend/static/index.html && rm -f backend/static/index.html.bak; \
|
|
sed -i.bak -E "s/\?v=[0-9]+/?v=$$NEW/g" backend/static/landing.html && rm -f backend/static/landing.html.bak; \
|
|
echo " ✓ APP_VER $$CUR → $$NEW (VERSION, sw.js, app.js, index.html, landing.html aktualisiert)"
|
|
|
|
# ----------------------------------------------------------
|
|
# TEST — Smoke-Tests gegen isolierte Test-DB (kein Docker, kein DS)
|
|
# ----------------------------------------------------------
|
|
test:
|
|
@cd backend && test -d venv || python3 -m venv venv
|
|
@backend/venv/bin/pip install -q -r backend/requirements.txt pytest pytest-asyncio
|
|
@backend/venv/bin/python -m pytest -q
|
|
|
|
# ----------------------------------------------------------
|
|
# CACHE leeren — SW-Version erhöhen, dann restart
|
|
# Nach größeren CSS/JS-Änderungen wenn SW gecacht hat
|
|
# ----------------------------------------------------------
|
|
clean-cache: check-ssh
|
|
@NEW_VER="by-v$$(date +%s)"; \
|
|
ssh $(DS_HOST) " \
|
|
sed -i \"s/by-v[0-9]*/$$NEW_VER/g\" \
|
|
$(DS_PATH)/backend/static/sw.js"
|
|
@$(MAKE) restart
|
|
@echo " ✓ Cache-Version erhöht."
|