# Makefile für die Entwicklung an Syncova. # # Überblick über alle Ziele: make help SHELL := /bin/bash # Verzeichnis für gebaute Binaries. BIN_DIR := bin # Compose-Datei der lokalen Entwicklungsumgebung. COMPOSE_FILE := deployment/docker-compose.yml # Datei mit der lokalen Konfiguration. Sie wird von "make dev-env" erzeugt. ENV_FILE := .env # Version, die in die Binaries eingebrannt wird. # Ohne Git-Tag wird der Kurz-Hash des Commits verwendet. BUILD_VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "0.1.0-dev") # Linker-Flags setzen die Version zur Bauzeit. GO_LDFLAGS := -X main.buildVersion=$(BUILD_VERSION) # Zu prüfende Go-Pakete. # # node_modules wird ausgeschlossen: einzelne NPM-Pakete bringen eigenen Go-Code # mit, der sonst in Tests, Lint und Schwachstellenprüfung auftauchen würde. GO_PACKAGES := $(shell go list ./... 2>/dev/null | grep -v '/node_modules/') # Verzeichnisse mit eigenem Go-Quelltext (für gofmt, das keine Paketpfade kennt). GO_SOURCE_DIRS := apps/api apps/agent packages migrations # Alle Rezepte laufen mit den Variablen aus der .env, sofern vorhanden. ifneq (,$(wildcard $(ENV_FILE))) include $(ENV_FILE) export endif .DEFAULT_GOAL := help .PHONY: help help: ## Zeigt diese Übersicht @echo "Syncova – verfügbare Ziele:" @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-18s\033[0m %s\n", $$1, $$2}' # --------------------------------------------------------------------------- # Entwicklungsumgebung # --------------------------------------------------------------------------- .PHONY: dev-env dev-env: ## Erzeugt .env mit einem zufälligen Datenbankpasswort @if [ -f $(ENV_FILE) ]; then \ echo "$(ENV_FILE) existiert bereits – es wird nicht überschrieben."; \ exit 0; \ fi @cp .env.example $(ENV_FILE) @# Das Passwort wird lokal zufällig erzeugt, damit es nirgends eingecheckt ist. @GENERATED_PASSWORD="$$(openssl rand -base64 24 | tr -d '/+=' | head -c 32)"; \ # secretscan:erlaubt: erfundener Testwert sed -i.bak "s|^SYNCOVA_DB_PASSWORD=.*|SYNCOVA_DB_PASSWORD=$$GENERATED_PASSWORD|" $(ENV_FILE); \ rm -f $(ENV_FILE).bak @# Ohne Verschlüsselungsschlüssel startet kein Dienst; er wird deshalb @# gleich miterzeugt. openssl liefert genau die geforderten 32 Byte. @GENERATED_KEY="$$(openssl rand -base64 32)"; \ sed -i.bak "s|^SYNCOVA_ENCRYPTION_KEYS=.*|SYNCOVA_ENCRYPTION_KEYS=v1:$$GENERATED_KEY|" $(ENV_FILE); \ rm -f $(ENV_FILE).bak @chmod 600 $(ENV_FILE) @echo "$(ENV_FILE) wurde mit zufälligem Datenbankpasswort und Verschlüsselungsschlüssel erzeugt." .PHONY: dev-up dev-up: require-env ## Startet PostgreSQL und wartet auf Betriebsbereitschaft @docker compose --env-file $(ENV_FILE) -f $(COMPOSE_FILE) up -d --wait @echo "PostgreSQL ist bereit." .PHONY: dev-down dev-down: ## Stoppt die lokale Umgebung (Daten bleiben erhalten) @docker compose -f $(COMPOSE_FILE) down .PHONY: dev-reset dev-reset: ## Stoppt die Umgebung und LÖSCHT alle lokalen Datenbankdaten @echo "Achtung: Dieser Schritt löscht das lokale Datenbank-Volume." @read -p "Fortfahren? [j/N] " CONFIRMATION; \ if [ "$$CONFIRMATION" = "j" ] || [ "$$CONFIRMATION" = "J" ]; then \ docker compose -f $(COMPOSE_FILE) down --volumes; \ echo "Lokale Datenbankdaten wurden gelöscht."; \ else \ echo "Abgebrochen."; \ fi .PHONY: require-env require-env: ## Prüft, ob die lokale Konfiguration vorhanden ist @if [ ! -f $(ENV_FILE) ]; then \ echo "Es fehlt die Datei $(ENV_FILE). Bitte zuerst 'make dev-env' ausführen."; \ exit 1; \ fi # --------------------------------------------------------------------------- # Backend # --------------------------------------------------------------------------- .PHONY: build build: ## Baut alle Go-Binaries nach ./bin @mkdir -p $(BIN_DIR) @go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-api ./apps/api/cmd/syncova-api @go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-migrate ./apps/api/cmd/syncova-migrate @go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-admin ./apps/api/cmd/syncova-admin @go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-repo ./apps/api/cmd/syncova-repo @go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-dr ./apps/api/cmd/syncova-dr @go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-bench ./apps/api/cmd/syncova-bench @go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-agent ./apps/agent/cmd/syncova-agent @go build -ldflags "$(GO_LDFLAGS)" -o $(BIN_DIR)/syncova-proxmox ./apps/api/cmd/syncova-proxmox @echo "Binaries gebaut (Version $(BUILD_VERSION))." .PHONY: run-api run-api: require-env ## Startet den API-Dienst lokal @go run -ldflags "$(GO_LDFLAGS)" ./apps/api/cmd/syncova-api .PHONY: migrate-up migrate-up: require-env ## Wendet alle ausstehenden Datenbankmigrationen an @go run ./apps/api/cmd/syncova-migrate up .PHONY: migrate-status migrate-status: require-env ## Zeigt den aktuellen Migrationsstand @go run ./apps/api/cmd/syncova-migrate status .PHONY: migrate-down migrate-down: require-env ## Nimmt genau eine Migration zurück @go run ./apps/api/cmd/syncova-migrate down .PHONY: test test: ## Führt alle Go-Tests mit Race-Detector aus @go test -race $(GO_PACKAGES) .PHONY: test-coverage test-coverage: ## Führt die Go-Tests aus und schreibt einen Coverage-Bericht @go test -race -coverprofile=coverage.out $(GO_PACKAGES) @go tool cover -func=coverage.out | tail -1 .PHONY: lint lint: ## Prüft Formatierung und statische Analyse des Go-Codes @echo "==> gofmt" @UNFORMATTED_FILES="$$(gofmt -l $(GO_SOURCE_DIRS))"; \ if [ -n "$$UNFORMATTED_FILES" ]; then \ echo "Nicht formatierte Dateien gefunden:"; echo "$$UNFORMATTED_FILES"; exit 1; \ fi @echo "==> go vet" @go vet $(GO_PACKAGES) @echo "==> staticcheck" @go run honnef.co/go/tools/cmd/staticcheck@latest $(GO_PACKAGES) # Die Sicherheitsprüfungen laufen getrennt vom Lint, weil sie das Netz brauchen: # govulncheck gleicht gegen die Schwachstellendatenbank von Go ab. In einer # Umgebung ohne Netz soll `make lint` trotzdem durchlaufen. # Die Plattformprüfung ist keine Formalie. # # Bis Phase 5 liess sich der Agent fuer Windows **gar nicht uebersetzen** — # unix.Statfs gibt es dort nicht. Der Windows-Dienst galt als „geschrieben, aber # ungeprueft"; tatsaechlich haette er sich nicht einmal bauen lassen. Ein # Uebersetzungslauf je Zielplattform faengt das in Sekunden. .PHONY: cross-build cross-build: ## Prüft die Übersetzbarkeit für alle Zielplattformen @echo "==> windows/amd64" @GOOS=windows GOARCH=amd64 go build -o /dev/null ./apps/agent/cmd/syncova-agent @GOOS=windows GOARCH=amd64 go build -o /dev/null ./apps/api/cmd/syncova-api @GOOS=windows GOARCH=amd64 go build -o /dev/null ./apps/api/cmd/syncova-repo @echo "==> linux/amd64" @GOOS=linux GOARCH=amd64 go build -o /dev/null ./apps/agent/cmd/syncova-agent @GOOS=linux GOARCH=amd64 go build -o /dev/null ./apps/api/cmd/syncova-api @echo "==> linux/arm64" @GOOS=linux GOARCH=arm64 go build -o /dev/null ./apps/agent/cmd/syncova-agent @echo "Alle Zielplattformen übersetzen." .PHONY: security-scan security-scan: ## Prüft Abhängigkeiten auf bekannte Schwachstellen @echo "==> govulncheck" @go run golang.org/x/vuln/cmd/govulncheck@latest $(GO_PACKAGES) @echo "==> npm audit (Frontend)" @cd apps/web && npm audit --audit-level=high .PHONY: tidy tidy: ## Bereinigt die Go-Modulabhängigkeiten @go mod tidy .PHONY: generate-key generate-key: ## Erzeugt einen neuen Verschlüsselungsschlüssel @go run ./apps/api/cmd/syncova-admin generate-key .PHONY: create-admin create-admin: require-env ## Legt den ersten Administrator an (fragt nach dem Passwort) @go run ./apps/api/cmd/syncova-admin create-admin --username $(USERNAME) # --------------------------------------------------------------------------- # Frontend # --------------------------------------------------------------------------- .PHONY: web-install web-install: ## Installiert die Frontend-Abhängigkeiten @cd apps/web && npm ci .PHONY: web-dev web-dev: ## Startet den Frontend-Entwicklungsserver @cd apps/web && npm run dev .PHONY: web-build web-build: ## Baut das Frontend für die Auslieferung @cd apps/web && npm run build .PHONY: web-test web-test: ## Führt die Frontend-Tests aus @cd apps/web && npm run test .PHONY: web-lint web-lint: ## Prüft den Frontend-Code @cd apps/web && npm run lint # --------------------------------------------------------------------------- # Übergreifend # --------------------------------------------------------------------------- .PHONY: secret-scan secret-scan: ## Durchsucht den Quellbestand nach Geheimnissen @go test -count=1 -run TestRepositoryContainsNoSecrets ./packages/platform/secretscan/ .PHONY: release release: ## Baut das Auslieferungspaket nach ./dist @scripts/build-release.sh .PHONY: check check: lint cross-build test web-lint web-test ## Führt alle Prüfungen aus (wie in der CI) @echo "Alle Prüfungen bestanden."