.PHONY: help init setup build run test test-race test-verbose lint lint-fix security docs release clean include tools.versions # ── Variables ────────────────────────────────────────────────────────────────── BINARY_NAME := app BINARY_PATH := ./bin/$(BINARY_NAME) CMD_PATH := ./cmd/app # ── Default target ───────────────────────────────────────────────────────────── help: ## Show this help message @grep -E '^[a-zA-Z_-]+:.*?## .*$$' Makefile | \ awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}' | sort # ── First-time setup ─────────────────────────────────────────────────────────── init: ## First-time project init: fetch deps, configure git hooks go env -w GOPRIVATE=gitea.djmil.dev go mod tidy $(MAKE) setup @echo "Done! Run 'make build' to verify." setup: ## Configure git to use .githooks directory git config core.hooksPath .githooks chmod +x .githooks/* @echo "Git hooks configured: .githooks/" # ── Development tools ────────────────────────────────────────────────────────── tools: ## Install tool binaries to GOPATH/bin (versions from tools.versions) @echo "Installing tools..." go install github.com/go-delve/delve/cmd/dlv@$(DELVE_VERSION) go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) go install github.com/securego/gosec/v2/cmd/gosec@$(GOSEC_VERSION) go install golang.org/x/vuln/cmd/govulncheck@$(GOVULNCHECK_VERSION) go install golang.org/x/pkgsite/cmd/pkgsite@$(PKGSITE_VERSION) # ── Build ────────────────────────────────────────────────────────────────────── build: ## Compile the binary to ./bin/ go build -o $(BINARY_PATH) $(CMD_PATH) # ── Run ──────────────────────────────────────────────────────────────────────── run: ## Run the application with default flags go run $(CMD_PATH)/main.go # ── Test ─────────────────────────────────────────────────────────────────────── test: ## Run all tests go test ./... -cover test-race: ## Run all tests with race detector go test ./... -race -cover test-verbose: ## Run all tests with verbose output go test ./... -race -cover -v # ── Lint & Security ──────────────────────────────────────────────────────────── lint: ## Run go vet + golangci-lint go vet ./... go run github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) run ./... lint-fix: ## Apply go fix + golangci-lint auto-fix go fix ./... go run github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) run --fix ./... security: ## Run gosec + govulncheck @echo "--- gosec ---" go run github.com/securego/gosec/v2/cmd/gosec@$(GOSEC_VERSION) -quiet ./... @echo "--- govulncheck ---" go run golang.org/x/vuln/cmd/govulncheck@$(GOVULNCHECK_VERSION) ./... # ── Docs ─────────────────────────────────────────────────────────────────────── docs: ## Serve package documentation locally via pkgsite (http://localhost:8080) go run golang.org/x/pkgsite/cmd/pkgsite@$(PKGSITE_VERSION) -open . # ── Release ──────────────────────────────────────────────────────────────────── release: ## List releases, or tag+push a new one (usage: make release VERSION=v0.1.0) ifdef VERSION @echo "$(VERSION)" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$$' || \ (echo "VERSION must be semver: v0.1.0"; exit 1) @git diff --quiet && git diff --cached --quiet || \ (echo "Uncommitted changes — commit first"; exit 1) @git tag -l | grep -q "^$(VERSION)$$" && \ (echo "Tag $(VERSION) already exists"; exit 1) || true $(MAKE) test-race $(MAKE) lint $(MAKE) security @MSG=$$(mktemp); \ LAST=$$(git describe --tags --abbrev=0 2>/dev/null); \ echo "$(VERSION)" > $$MSG; \ echo "" >> $$MSG; \ if [ -n "$$LAST" ]; then \ echo "Changes since $$LAST:" >> $$MSG; \ git log $$LAST..HEAD --oneline >> $$MSG; \ else \ git log --oneline >> $$MSG; \ fi; \ git tag -a -e -F $$MSG $(VERSION); \ rm -f $$MSG git push origin $(VERSION) else @echo "Released versions:" @git tag -l --sort=-version:refname | grep -E '^v[0-9]' || echo " (none yet)" endif # ── Cleanup ──────────────────────────────────────────────────────────────────── clean: ## Remove build artifacts rm -rf ./bin