From 3a67ba031b178b7de8d8ec7aaeee0ae41fa8aab0 Mon Sep 17 00:00:00 2001 From: Snider Date: Mon, 3 Nov 2025 19:33:28 +0000 Subject: [PATCH] Add maintainer Makefile for local CI parity and update .gitignore and CI configuration --- .github/workflows/ci.yml | 11 +++- .gitignore | 3 +- .golangci.yml | 12 +---- Makefile | 108 +++++++++++++++++++++++++++++++++++++++ README.md | 103 +++++++++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 12 deletions(-) create mode 100644 Makefile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb824c2..ffabb87 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,16 @@ jobs: run: go test -race -coverprofile=coverage.out -covermode=atomic ./... - name: Fuzz (10s) - run: go test -run=NONE -fuzz=Fuzz -fuzztime=10s ./... + run: | + set -e + for pkg in $(go list ./...); do + if go test -list '^Fuzz' "$pkg" | grep -q '^Fuzz'; then + echo "==> Fuzzing $pkg for 10s" + go test -run=NONE -fuzz=Fuzz -fuzztime=10s "$pkg" + else + echo "==> Skipping $pkg (no fuzz targets)" + fi + done - name: Upload coverage artifact if: always() diff --git a/.gitignore b/.gitignore index 1921ae5..47f4b46 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,8 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out - +bench.txt +coverage.html # Dependency directories (remove the comment below to include it) vendor/ diff --git a/.golangci.yml b/.golangci.yml index c5e57df..2fc3e88 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,29 +1,21 @@ +version: "2" run: timeout: 5m linters: enable: - govet - - gosimple - staticcheck - ineffassign - - gofmt - - revive + - misspell - errcheck issues: - exclude-use-default: false max-issues-per-linter: 0 max-same-issues: 0 exclude-rules: - # Errcheck is noisy in examples and doc tests; ignore *_test.go for errcheck only. - path: _test\.go linters: - errcheck linters-settings: - revive: - severity: warning - rules: - - name: exported - arguments: ["disable"] # keep comments pragmatic; we have pkg docs and key API docs errcheck: # Be pragmatic: don't require checking of Close for defer patterns in tests/examples. # (Keep defaults; exclusions above handle test files.) diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..07789e0 --- /dev/null +++ b/Makefile @@ -0,0 +1,108 @@ +# Maintainer Makefile for Poindexter +# Usage: `make ` +# Many targets are CI-parity helpers for local use. + +# Tools (override with env if needed) +GO ?= go +GOLANGCI_LINT?= golangci-lint +GORELEASER ?= goreleaser +MKDOCS ?= mkdocs + +# Params +FUZZTIME ?= 10s +BENCHOUT ?= bench.txt +COVEROUT ?= coverage.out +COVERHTML?= coverage.html + +.PHONY: help all +all: help +help: ## List available targets + @awk 'BEGIN {FS = ":.*##"}; /^[a-zA-Z0-9_.-]+:.*##/ {printf "\033[36m%-22s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort + +.PHONY: tidy +tidy: ## Run `go mod tidy` + $(GO) mod tidy + +.PHONY: tidy-check +tidy-check: ## Run tidy and ensure go.mod/go.sum unchanged + $(GO) mod tidy + @git diff --exit-code -- go.mod go.sum + +.PHONY: fmt +fmt: ## Format code with go fmt + $(GO) fmt ./... + +.PHONY: vet +vet: ## Run go vet + $(GO) vet ./... + +.PHONY: build +build: ## Build all packages + $(GO) build ./... + +.PHONY: examples +examples: ## Build all example programs under examples/ + @if [ -d examples ]; then $(GO) build ./examples/...; else echo "No examples/ directory"; fi + +.PHONY: test +test: ## Run unit tests + $(GO) test ./... + +.PHONY: race +race: ## Run tests with race detector + $(GO) test -race ./... + +.PHONY: cover +cover: ## Run tests with race + coverage and summarize + $(GO) test -race -coverprofile=$(COVEROUT) -covermode=atomic ./... + @$(GO) tool cover -func=$(COVEROUT) | tail -n 1 + +.PHONY: coverhtml +coverhtml: cover ## Generate HTML coverage report at $(COVERHTML) + @$(GO) tool cover -html=$(COVEROUT) -o $(COVERHTML) + @echo "Wrote $(COVERHTML)" + +.PHONY: fuzz +fuzz: ## Run Go fuzz tests for $(FUZZTIME) + @set -e; \ + PKGS="$$( $(GO) list ./... )"; \ + for pkg in $$PKGS; do \ + if $(GO) test -list '^Fuzz' $$pkg | grep -q '^Fuzz'; then \ + echo "==> Fuzzing $$pkg for $(FUZZTIME)"; \ + $(GO) test -run=NONE -fuzz=Fuzz -fuzztime=$(FUZZTIME) $$pkg; \ + else \ + echo "==> Skipping $$pkg (no fuzz targets)"; \ + fi; \ + done + +.PHONY: bench +bench: ## Run benchmarks and write $(BENCHOUT) + $(GO) test -bench . -benchmem -run=^$$ ./... | tee $(BENCHOUT) + +.PHONY: lint +lint: ## Run golangci-lint (requires it installed) + $(GOLANGCI_LINT) run + +.PHONY: vuln +vuln: ## Run govulncheck (requires it installed) + govulncheck ./... + +.PHONY: ci +ci: tidy-check build vet cover examples bench lint vuln ## CI-parity local run + @echo "CI-like checks completed" + +.PHONY: release +release: ## Run GoReleaser to publish a tagged release (requires tag and permissions) + $(GORELEASER) release --clean --config .goreleaser.yaml + +.PHONY: snapshot +snapshot: ## Run GoReleaser in snapshot mode (no publish) + $(GORELEASER) release --skip=publish --clean --config .goreleaser.yaml + +.PHONY: docs-serve +docs-serve: ## Serve MkDocs locally (requires mkdocs-material) + $(MKDOCS) serve -a 127.0.0.1:8000 + +.PHONY: docs-build +docs-build: ## Build MkDocs site into site/ + $(MKDOCS) build diff --git a/README.md b/README.md index bb72420..e36b89c 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,109 @@ Explore runnable examples in the repository: See the multi-dimensional KDTree docs for end-to-end examples and weighting/normalization helpers: [Multi-Dimensional KDTree (DHT)](docs/kdtree-multidimensional.md). +## Maintainer Makefile + +The repository includes a maintainer-friendly `Makefile` that mirrors CI tasks and speeds up local workflows. + +- help — list available targets +- tidy / tidy-check — run `go mod tidy`, optionally verify no diffs +- fmt — format code (`go fmt ./...`) +- vet — `go vet ./...` +- build — `go build ./...` +- examples — build all programs under `examples/` (if present) +- test — run unit tests +- race — run tests with the race detector +- cover — run tests with race + coverage (writes `coverage.out` and prints summary) +- coverhtml — render HTML coverage report to `coverage.html` +- fuzz — run Go fuzzing for a configurable time (default 10s) matching CI +- bench — run benchmarks with `-benchmem` (writes `bench.txt`) +- lint — run `golangci-lint` (if installed) +- vuln — run `govulncheck` (if installed) +- ci — CI-parity aggregate: tidy-check, build, vet, cover, examples, bench, lint, vuln +- release — run GoReleaser with the canonical `.goreleaser.yaml` (for tagged releases) +- snapshot — GoReleaser snapshot (no publish) +- docs-serve — serve MkDocs locally on 127.0.0.1:8000 +- docs-build — build MkDocs site into `site/` + +Quick usage: + +- See all targets: + +```bash +make help +``` + +- Fast local cycle: + +```bash +make fmt +make vet +make test +``` + +- CI-parity run (what GitHub Actions does, locally): + +```bash +make ci +``` + +- Coverage summary: + +```bash +make cover +``` + +- Generate HTML coverage report (writes coverage.html): + +```bash +make coverhtml +``` + +- Fuzz for 10 seconds (default): + +```bash +make fuzz +``` + +- Fuzz with a custom time (e.g., 30s): + +```bash +make fuzz FUZZTIME=30s +``` + +- Run benchmarks (writes bench.txt): + +```bash +make bench +``` + +- Build examples (if any under ./examples): + +```bash +make examples +``` + +- Serve docs locally (requires mkdocs-material): + +```bash +make docs-serve +``` + +Configurable variables: + +- `FUZZTIME` (default `10s`) — e.g. `make fuzz FUZZTIME=30s` +- `BENCHOUT` (default `bench.txt`), `COVEROUT` (default `coverage.out`), `COVERHTML` (default `coverage.html`) +- Tool commands are overridable via env: `GO`, `GOLANGCI_LINT`, `GORELEASER`, `MKDOCS` + +Requirements for optional targets: + +- `golangci-lint` for `make lint` +- `golang.org/x/vuln/cmd/govulncheck` for `make vuln` +- `goreleaser` for `make release` / `make snapshot` +- `mkdocs` + `mkdocs-material` for `make docs-serve` / `make docs-build` + +See the full Makefile at the repo root for authoritative target definitions. + ## License This project is licensed under the European Union Public Licence v1.2 (EUPL-1.2). See [LICENSE](LICENSE) for details.