# EdgeGuard — Build-System.
# Cross-Compile für Debian 13 + Ubuntu 24.04 auf amd64 und arm64.
# CGO_ENABLED=0 (statische Binaries, keine libre2-/CGO-Abhängigkeit in v1).

GO       ?= $(shell which go || echo /usr/local/go/bin/go)
MODULE   := git.netcell-it.de/projekte/edgeguard-native
BINARIES := edgeguard-api edgeguard-scheduler edgeguard-ctl edgeguard-waf
VERSION  := $(shell cat VERSION 2>/dev/null || echo 0.0.1-dev)
LDFLAGS  := -s -w -X main.version=$(VERSION)
GOFLAGS  := -trimpath -mod=readonly
export CGO_ENABLED ?= 0

.PHONY: all help build test test-race lint golangci vulncheck release-check tidy clean ui \
        build-linux-amd64 build-linux-arm64 \
        deb deb-amd64 deb-arm64 \
        publish publish-amd64 publish-arm64

all: build

help:
	@echo "EdgeGuard build targets:"
	@echo "  build              Build all binaries for the host architecture (build/host/)"
	@echo "  build-linux-amd64  Cross-compile all binaries for linux/amd64 (build/amd64/)"
	@echo "  build-linux-arm64  Cross-compile all binaries for linux/arm64 (build/arm64/)"
	@echo "  test               go test ./..."
	@echo "  lint               go vet + staticcheck (if installed)"
	@echo "  tidy               go mod tidy"
	@echo "  ui                 Build management-ui (vite)"
	@echo "  deb-amd64          Cross-compile + build edgeguard_<ver>_amd64.deb"
	@echo "  deb-arm64          Cross-compile + build edgeguard_<ver>_arm64.deb"
	@echo "  deb                Build both amd64 and arm64 .deb packages"
	@echo "  publish-amd64      Build amd64 deb AND upload to Gitea"
	@echo "  publish-arm64      Same for arm64"
	@echo "  publish            publish-amd64 + publish-arm64"
	@echo "  clean              Remove build artifacts"

build:
	@mkdir -p build/host
	@for bin in $(BINARIES); do \
	    echo "  -> build/host/$$bin"; \
	    $(GO) build $(GOFLAGS) -ldflags '$(LDFLAGS)' \
	        -o build/host/$$bin ./cmd/$$bin || exit 1; \
	done

build-linux-amd64:
	@mkdir -p build/amd64
	@for bin in $(BINARIES); do \
	    echo "  -> build/amd64/$$bin"; \
	    GOOS=linux GOARCH=amd64 $(GO) build $(GOFLAGS) -ldflags '$(LDFLAGS)' \
	        -o build/amd64/$$bin ./cmd/$$bin || exit 1; \
	done

build-linux-arm64:
	@mkdir -p build/arm64
	@for bin in $(BINARIES); do \
	    echo "  -> build/arm64/$$bin"; \
	    GOOS=linux GOARCH=arm64 $(GO) build $(GOFLAGS) -ldflags '$(LDFLAGS)' \
	        -o build/arm64/$$bin ./cmd/$$bin || exit 1; \
	done

test:
	$(GO) test $(GOFLAGS) ./...

test-race:
	CGO_ENABLED=1 $(GO) test $(GOFLAGS) -race ./...

GOBIN := $(shell $(GO) env GOPATH)/bin
GOLANGCI_VERSION := v2.13.2
# Ziel-Go-Version aus go.mod — golangci-lint MUSS mit genau dieser Toolchain
# gebaut sein (siehe golangci-Target).
GO_VERSION := $(shell awk '/^go /{print $$2; exit}' go.mod)

lint:
	$(GO) vet ./...
	@$(MAKE) --no-print-directory golangci

# golangci-lint — HARTER Gate. Tool wird bei Bedarf auf pinned Version
# installiert; bricht ab, sobald ein Finding auftaucht (Bestand ist 0,
# Rollout abgeschlossen — siehe .golangci.yml).
# Befund 2026-09-11: golangci-lint verweigert den Dienst ("the Go language
# version used to build golangci-lint is lower than the targeted Go version"),
# sobald go.mod eine neuere Go-Version zielt als die, mit der der Linter
# gebaut wurde — und ein `go install` ohne GOTOOLCHAIN baut ihn mit der in
# SEINER go.mod geforderten (älteren) Version. Deshalb die Projekt-Toolchain
# pinnen. Der frühere `command -v`-Check hat ausserdem eine bereits
# installierte, veraltete Binary nie erneuert; jetzt entscheidet die
# tatsächliche Version + Build-Go-Version der Binary über die Neuinstallation.
golangci:
	@if ! "$(GOBIN)/golangci-lint" version 2>/dev/null | grep -q "has version $(patsubst v%,%,$(GOLANGCI_VERSION)) built with go$(GO_VERSION) "; then \
	    echo "  -> installing golangci-lint $(GOLANGCI_VERSION) (built with go$(GO_VERSION))"; \
	    GOFLAGS= GOTOOLCHAIN=go$(GO_VERSION) $(GO) install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(GOLANGCI_VERSION); \
	fi
	@PATH="$(GOBIN):$$PATH" golangci-lint run --timeout 6m

# govulncheck — Go-Vuln-DB-Scan. HARTER Release-Gate: bricht ab, wenn der
# Code eine bekannte Vulnerability tatsächlich aufruft. Tool wird bei Bedarf
# automatisch installiert.
# Gleiche Toolchain-Falle wie bei golangci-lint (Befund 2026-09-11): ein
# `go install` ohne GOTOOLCHAIN baut govulncheck mit einer aelteren Go-Version,
# die dann "package requires newer Go version" fuer jedes Paket meldet statt zu
# scannen. Reinstall, sobald die Build-Go-Version der Binary abweicht.
vulncheck:
	@if ! "$(GOBIN)/govulncheck" -version 2>/dev/null | grep -q "^Go: go$(GO_VERSION)$$"; then \
	    echo "  -> installing govulncheck (built with go$(GO_VERSION))"; \
	    GOFLAGS= GOTOOLCHAIN=go$(GO_VERSION) $(GO) install golang.org/x/vuln/cmd/govulncheck@latest; \
	fi
	@PATH="$(GOBIN):$$PATH" govulncheck ./...

# Go-Quality-Baseline — läuft automatisch vor jedem Release (deb/publish).
# Reihenfolge: vet → golangci-lint (GATE) → govulncheck (GATE) → build →
# test -race. Alle vier brechen bei jedem Fund ab. Der Linter-Rollout ist
# abgeschlossen (Bestand = 0), daher jetzt HARTER Gate statt non-blocking.
release-check:
	$(GO) vet ./...
	@$(MAKE) --no-print-directory golangci
	@$(MAKE) --no-print-directory vulncheck
	$(GO) build ./...
	CGO_ENABLED=1 $(GO) test $(GOFLAGS) -race ./...
	@echo "  ✓ Go-Quality-Baseline bestanden (vet, golangci-lint, govulncheck, build, test -race)"

tidy:
	$(GO) mod tidy

ui:
	@echo "  -> management-ui (vite build, version $(VERSION))"
	@cd management-ui && \
	    if [ -x "$$(command -v bun)" ]; then bun install --silent && bun run build; \
	    else npm install --include=dev --silent && npm run build; fi

deb-amd64: release-check build-linux-amd64 ui
	@./scripts/apt-repo/build-package.sh amd64 $(VERSION)

deb-arm64: release-check build-linux-arm64 ui
	@./scripts/apt-repo/build-package.sh arm64 $(VERSION)

deb: deb-amd64 deb-arm64

# Direktes `make publish` bleibt als Handnotbremse erhalten, veröffentlicht
# aber immer nach stable — für Testing-Releases + das Stable-Promotion-
# Gate (verify_channel_debs, Version-Bump, Git-Tag) scripts/release.sh nutzen.
publish-amd64: deb-amd64
	@./scripts/apt-repo/publish.sh $(VERSION) amd64 stable
	@echo "  -> cleanup-old (keep last $${KEEP:-10})"
	@./scripts/apt-repo/cleanup-old.sh stable

publish-arm64: deb-arm64
	@./scripts/apt-repo/publish.sh $(VERSION) arm64 stable
	@echo "  -> cleanup-old (keep last $${KEEP:-10})"
	@./scripts/apt-repo/cleanup-old.sh stable

publish: publish-amd64 publish-arm64

clean:
	rm -rf build/
