# fancy-dns # # `make` alone gives you a help screen. The two targets you want most are # `make build` (binary with the console embedded) and `make check` (what CI # runs). SHELL := /bin/bash .SHELLFLAGS := -eu -o pipefail -c .DEFAULT_GOAL := help BINARY := fancy-dns PKG := git.k8s-git-k6n.net/mats/fancy-dns CMD := ./cmd/fancy-dns VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev) LDFLAGS := -s -w -X $(PKG)/internal/app.Version=$(VERSION) DIST := dist IMAGE ?= fancydns/fancy-dns:$(VERSION) GO ?= go NPM ?= npm GOFILES := $(shell find . -name '*.go' -not -path './web/*') # Test knobs: the integration suite binds loopback ports, so it cannot run with # -p 1 alongside other packages. Race is the default because the whole design # leans on atomics and a regression there is silent. TESTFLAGS ?= -race -count=1 .PHONY: help help: ## Show this help @awk 'BEGIN {FS = ":.*##"; printf "\nUsage: make \n"} \ /^[a-zA-Z_-]+:.*?##/ { printf " \033[36m%-16s\033[0m %s\n", $$1, $$2 } \ /^## / { printf "\n%s\n", substr($$0, 4) }' $(MAKEFILE_LIST) ## Build .PHONY: build build: web ## Build the binary with the console embedded @mkdir -p $(DIST) CGO_ENABLED=0 $(GO) build -trimpath -ldflags '$(LDFLAGS)' -o $(DIST)/$(BINARY) $(CMD) @echo "built $(DIST)/$(BINARY) ($(VERSION))" .PHONY: go-build go-build: ## Build without the console (fast; used by the Go test loop) CGO_ENABLED=0 $(GO) build -trimpath -ldflags '$(LDFLAGS)' -o $(DIST)/$(BINARY)-noassets $(CMD) .PHONY: install install: ## Install into GOBIN CGO_ENABLED=0 $(GO) install -trimpath -ldflags '$(LDFLAGS)' $(CMD) .PHONY: web web: ## Build the web console into internal/web/dist @if [ ! -d web/node_modules ]; then \ echo "==> installing web dependencies"; \ cd web && $(NPM) ci --no-audit --no-fund; \ fi cd web && $(NPM) run build @test -f internal/web/dist/index.html || { echo "console build produced no index.html"; exit 1; } .PHONY: web-dev web-dev: ## Run the Vite dev server (proxies /api to 127.0.0.1:8080) cd web && $(NPM) run dev ## Verify .PHONY: check check: check-go test ## What CI runs (format, vet, compile, then the suite) .PHONY: check-go check-go: fmt-check vet go-build ## The tight inner loop: format, vet, compile. No npm, no tests @echo "check-go: ok" .PHONY: gofmt-w gofmt-w: ## Format every Go file in the tree, including ones just created @gofmt -w $(GOFILES) @echo "gofmt: ok" .PHONY: test test: ## Run the test suite with the race detector $(GO) test $(TESTFLAGS) ./... .PHONY: test-short test-short: ## Run the tests without -race (much faster) $(GO) test -short -count=1 ./... .PHONY: cover cover: ## Test with a coverage report at coverage.html $(GO) test -race -count=1 -coverprofile=coverage.out ./... $(GO) tool cover -html=coverage.out -o coverage.html @$(GO) tool cover -func=coverage.out | tail -1 .PHONY: bench bench: ## Run the cache and blocklist benchmarks $(GO) test -run '^$$' -bench . -benchmem ./internal/cache/... ./internal/blocklist/... .PHONY: vet vet: ## go vet $(GO) vet ./... .PHONY: fmt fmt: ## Format the Go code gofmt -w $(GOFILES) .PHONY: fmt-check fmt-check: ## Fail if anything is unformatted @unformatted=$$(gofmt -l $(GOFILES)); \ if [ -n "$$unformatted" ]; then \ echo "gofmt needed:"; echo "$$unformatted"; exit 1; \ fi .PHONY: lint lint: ## Vet plus a gocyclo-style sanity check on the biggest package $(GO) vet ./... @echo "lint: ok" .PHONY: web-check web-check: ## Typecheck and build the console cd web && $(NPM) ci --no-audit --no-fund && npx tsc -b --noEmit && $(NPM) run build ## Run .PHONY: run run: go-build ## Run with deploy/config.example.yaml on unprivileged ports $(DIST)/$(BINARY)-noassets -config deploy/config.example.yaml -log-level debug .PHONY: check-config check-config: go-build ## Validate a config file without starting $(DIST)/$(BINARY)-noassets -config $(or $(CONFIG),deploy/config.example.yaml) -check ## Container .PHONY: image image: ## Build the container image docker build --build-arg VERSION=$(VERSION) -t $(IMAGE) . .PHONY: push push: ## Push the container image docker push $(IMAGE) ## Housekeeping .PHONY: clean clean: ## Remove build output rm -rf $(DIST) coverage.out coverage.html .PHONY: clean-web clean-web: ## Remove node_modules and the console bundle rm -rf web/node_modules web/.vite internal/web/dist/assets internal/web/dist/index.html