ajhahn.de
← eeco
Makefile 88 lines
# eeco — build and release entry points.
# Default target builds a single local binary; `release` cross-builds
# the published matrix via scripts/build.sh.

VERSION    ?= $(shell git describe --tags --dirty --always 2>/dev/null || echo dev)
COMMIT     ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo unknown)
BUILD_DATE ?= $(shell date -u +%Y-%m-%dT%H:%M:%SZ)

# Windows host builds need the .exe suffix so the Makefile recipes
# (which invoke ./eeco directly) work under Git Bash.
ifeq ($(OS),Windows_NT)
EXE := .exe
else
EXE :=
endif

LDFLAGS = -s -w -X main.version=$(VERSION) -X main.commit=$(COMMIT) -X main.buildDate=$(BUILD_DATE)

# golangci-lint version for `make lint`, pinned here as the single
# source of truth — CI runs the same `make lint`, so local and CI
# stay byte-identical.
GOLANGCI_LINT_VERSION ?= v2.12.2

.PHONY: all build release checksums packaging verify cover cover-check gates bench clean sync-guide lint manpage

all: build

# sync-guide refreshes the in-binary user manual mirror at
# internal/guide/usage.md from the canonical docs/USAGE.md. CI keeps
# the two byte-identical via a drift gate (TestUsageMirrorsDocs) — run
# this target whenever docs/USAGE.md changes.
sync-guide:
	cp docs/USAGE.md internal/guide/usage.md

build:
	go build -trimpath -ldflags '$(LDFLAGS)' -o eeco$(EXE) ./cmd/eeco

release: manpage
	VERSION='$(VERSION)' COMMIT='$(COMMIT)' BUILD_DATE='$(BUILD_DATE)' ./scripts/build.sh

# manpage renders dist/eeco.1 from docs/USAGE.md via go-md2man. Run as a
# prerequisite of `release` so the man page is bundled into the
# darwin/linux archives and shipped as a standalone release asset.
manpage:
	./scripts/gen-manpage.sh

checksums:
	cd dist && shasum -a 256 eeco_$(VERSION)_*.tar.gz eeco_$(VERSION)_*.zip > SHA256SUMS

packaging:
	VERSION='$(VERSION)' ./scripts/gen-packaging.sh

verify:
	go build ./...
	go vet ./...
	go test ./...

# cover writes a coverage profile to coverage.out for the codecov
# upload in CI (and local inspection via `go tool cover`).
cover:
	go test -coverprofile=coverage.out -covermode=atomic ./...

# cover-check enforces the coverage ratchet: total statement coverage must
# stay at or above the floor in scripts/check-coverage.sh (a regression
# guard, not a target). Depends on `cover` so coverage.out is fresh; CI
# gates on this and the codecov step reuses the same coverage.out.
cover-check: cover
	bash scripts/check-coverage.sh

# lint runs the golangci-lint quality bar (errcheck, gosec, govet,
# staticcheck, unused) configured in .golangci.yml. Pinned via go run
# so no separate install step is needed.
lint:
	go run github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) run ./...

gates: build
	./eeco$(EXE) run comment-hygiene
	./eeco$(EXE) run leak-guard
	./eeco$(EXE) run version-sync

bench: build
	mkdir -p dist
	go test -tags=bench -bench=. -benchtime=1x -timeout=300s -run=^$$ ./internal/workflow/...
	rm -rf dist/bench-fixture

clean:
	rm -rf dist eeco eeco.exe