From 0cf5b540708fabd60544f05f8219c1f7f117b8d4 Mon Sep 17 00:00:00 2001 From: Jan Novak Date: Wed, 1 Jul 2026 01:08:51 +0200 Subject: [PATCH] chore: add root Makefile with namespaced targets Namespaced go-* targets (build, run, test, test-verbose, check, cover, fmt, vet, tidy, install, lint, clean) plus umbrella targets that delegate to them. help is the default. py-* targets will slot in during the Python port. Updates .gitignore with coverage artifacts. Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 4 +- CHANGELOG.md | 10 +++ Makefile | 91 ++++++++++++++++++++++++ README.md | 20 ++++++ docs/plans/2026-07-01-01-05-makefile.md | 90 ++++++++++++++++++++++++ docs/usage/makefile.md | 92 +++++++++++++++++++++++++ 6 files changed, 306 insertions(+), 1 deletion(-) create mode 100644 Makefile create mode 100644 docs/plans/2026-07-01-01-05-makefile.md create mode 100644 docs/usage/makefile.md diff --git a/.gitignore b/.gitignore index 3f9b4d2..aa8c000 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ -# Go binaries +# Go binaries and artifacts go/latprobe +go/coverage.out +go/coverage.html python/latprobe # Python diff --git a/CHANGELOG.md b/CHANGELOG.md index 678a756..d7ef10b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All completed features are logged here in reverse-chronological order. --- +## 2026-07-01 01:05 — Root Makefile + +- Namespaced targets: `go-build`, `go-run`, `go-test`, `go-test-verbose`, `go-check`, `go-cover`, `go-fmt`, `go-vet`, `go-tidy`, `go-install`, `go-lint`, `go-clean` +- Umbrella targets (`build`, `test`, `check`, `fmt`, `vet`, `clean`, `all`) delegate to Go now; `py-*` will slot in during the Python port +- `help` is the default target; auto-generated from `##` comments +- `go-run` accepts `ARGS=` for passing flags, `go-lint` guards for `golangci-lint` +- `.gitignore` updated with coverage artifacts + +--- + ## 2026-07-01 00:49 — Integration tests (Go, Step 6) - Extracted `run(args, stdout, stderr) int` from `main()` to make the CLI testable in-process diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..61fcd93 --- /dev/null +++ b/Makefile @@ -0,0 +1,91 @@ +GO_DIR := go +BINARY := latprobe +ARGS ?= + +.DEFAULT_GOAL := help + +# ── help ────────────────────────────────────────────────────────────────────── + +.PHONY: help +help: ## Show this help + @grep -E '^[a-zA-Z_-]+:.*##' $(MAKEFILE_LIST) \ + | awk 'BEGIN {FS = ":.*##"}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}' \ + | sort + +# ── umbrella targets (delegate to Go now; py-* will be added during Python port) ── + +.PHONY: all +all: check build ## Run checks then build + +.PHONY: build +build: go-build ## Build binary (delegates to go-build) + +.PHONY: test +test: go-test ## Run tests (delegates to go-test; py-test added later) + +.PHONY: check +check: go-check ## Run fmt + vet + test gate (delegates to go-check) + +.PHONY: fmt +fmt: go-fmt ## Format source code (delegates to go-fmt) + +.PHONY: vet +vet: go-vet ## Run go vet (delegates to go-vet) + +.PHONY: clean +clean: go-clean ## Remove build and coverage artifacts + +# ── Go targets ──────────────────────────────────────────────────────────────── + +.PHONY: go-build +go-build: ## go: build binary → go/latprobe + go -C $(GO_DIR) build -o $(BINARY) . + +.PHONY: go-run +go-run: ## go: build and run (pass flags via ARGS="…") + go -C $(GO_DIR) run . $(ARGS) + +.PHONY: go-test +go-test: ## go: run all tests + go -C $(GO_DIR) test ./... + +.PHONY: go-test-verbose +go-test-verbose: ## go: run all tests with per-case output + go -C $(GO_DIR) test -v ./... + +.PHONY: go-check +go-check: go-fmt go-vet go-test ## go: fmt + vet + test (pre-commit gate) + +.PHONY: go-cover +go-cover: ## go: run tests with coverage → go/coverage.html + go -C $(GO_DIR) test -coverprofile=coverage.out ./... + go -C $(GO_DIR) tool cover -html=coverage.out -o coverage.html + @echo "Coverage report: $(GO_DIR)/coverage.html" + +.PHONY: go-fmt +go-fmt: ## go: format all Go source files with gofmt + gofmt -w $(GO_DIR) + +.PHONY: go-vet +go-vet: ## go: run go vet on all packages + go -C $(GO_DIR) vet ./... + +.PHONY: go-tidy +go-tidy: ## go: run go mod tidy + go -C $(GO_DIR) mod tidy + +.PHONY: go-install +go-install: ## go: install binary to $GOBIN / $GOPATH/bin + go -C $(GO_DIR) install . + +.PHONY: go-lint +go-lint: ## go: run golangci-lint (must be installed) + @command -v golangci-lint >/dev/null 2>&1 || { \ + echo "golangci-lint not installed — see https://golangci-lint.run/usage/install/"; \ + exit 1; \ + } + cd $(GO_DIR) && golangci-lint run + +.PHONY: go-clean +go-clean: ## go: remove binary and coverage artifacts + rm -f $(GO_DIR)/$(BINARY) $(GO_DIR)/coverage.out $(GO_DIR)/coverage.html diff --git a/README.md b/README.md index d0dbf0a..f196b9e 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,26 @@ connection timings via custom socket wrap or `httpx`/`urllib3` hooks). --- +## Development + +A `Makefile` at the repo root provides all common tasks: + +```sh +make # list all targets +make build # build go/latprobe +make test # run all tests +make check # fmt + vet + test (pre-commit gate) +make go-run ARGS="https://example.com" +make go-test-verbose +make go-cover # coverage report → go/coverage.html +make go-lint # golangci-lint +make clean # remove build artifacts +``` + +See [`docs/usage/makefile.md`](docs/usage/makefile.md) for the full target reference. + +--- + ## Development Environment - Go 1.26.4 / darwin arm64 diff --git a/docs/plans/2026-07-01-01-05-makefile.md b/docs/plans/2026-07-01-01-05-makefile.md new file mode 100644 index 0000000..da11a10 --- /dev/null +++ b/docs/plans/2026-07-01-01-05-makefile.md @@ -0,0 +1,90 @@ +# Plan: Root Makefile + +## Context + +The project has grown to a multi-step Go implementation with a test suite, and a +Python port is planned. Common workflows (build, test, vet, coverage) are +currently typed by hand with `cd go && go ...`. A root `Makefile` gives a single, +discoverable entry point for these tasks and a place to hang the future Python +targets. + +Decisions confirmed with the user: +- Include **all** proposed targets: core set + `cover` + `tidy`/`install` + `lint`. +- **Namespaced** naming (`go-build`, `go-test`, …) with umbrella targets + (`build`, `test`, …) that delegate to the language-specific ones, so `py-*` + can slot in cleanly during the Python port. + +Environment: GNU Make 3.81, Go 1.26.4, `golangci-lint` installed. Go commands use +`go -C go …` (Go 1.20+ directory flag) to avoid `cd`. + +## File: `Makefile` (repo root) + +Variables: +```make +GO_DIR := go +BINARY := latprobe +ARGS ?= +.DEFAULT_GOAL := help +``` + +### Umbrella targets (delegate now to Go; Python added later) +| Target | Delegates to | Notes | +|--------|--------------|-------| +| `help` | — | Default. Auto-generated from `##` comments. | +| `build` | `go-build` | `py-build` appended during Python port | +| `test` | `go-test` | `py-test` appended later | +| `check` | `go-check` | fmt + vet + test gate | +| `fmt` | `go-fmt` | | +| `vet` | `go-vet` | | +| `clean` | `go-clean` | | +| `all` | `check build` | | + +A comment marks where `py-*` will be added (e.g. `test: go-test # + py-test later`). + +### Go targets +| Target | Command | +|--------|---------| +| `go-build` | `go -C $(GO_DIR) build -o $(BINARY) .` | +| `go-run` | `go -C $(GO_DIR) run . $(ARGS)` | +| `go-test` | `go -C $(GO_DIR) test ./...` | +| `go-test-verbose` | `go -C $(GO_DIR) test -v ./...` | +| `go-fmt` | `gofmt -w $(GO_DIR)` | +| `go-vet` | `go -C $(GO_DIR) vet ./...` | +| `go-check` | depends on `go-fmt go-vet go-test` | +| `go-cover` | `go -C $(GO_DIR) test -coverprofile=coverage.out ./...` then `go -C $(GO_DIR) tool cover -html=coverage.out -o coverage.html` | +| `go-tidy` | `go -C $(GO_DIR) mod tidy` | +| `go-install` | `go -C $(GO_DIR) install .` | +| `go-lint` | guard for `golangci-lint` presence, then `cd $(GO_DIR) && golangci-lint run` | +| `go-clean` | `rm -f $(GO_DIR)/$(BINARY) $(GO_DIR)/coverage.out $(GO_DIR)/coverage.html` | + +Details: +- `make run ARGS="https://example.com -n 3"` passes flags through. +- All targets listed in `.PHONY`. +- `help` recipe: `grep`/`awk` over `$(MAKEFILE_LIST)` printing `target ## description` + (works on GNU Make 3.81). +- `go-lint` guard: + ```make + @command -v golangci-lint >/dev/null 2>&1 || { echo "golangci-lint not installed: https://golangci-lint.run"; exit 1; } + ``` + +## Other changes +- `.gitignore`: add `go/coverage.out` and `go/coverage.html`. +- `docs/usage/makefile.md`: new user doc — target table + examples. +- `CHANGELOG.md`: timestamped entry. +- `README.md`: short "Development" note pointing at `make help`. +- `docs/plans/2026-07-01-01-05-makefile.md`: copy of this plan. + +## Verification +```sh +make help # lists all targets with descriptions +make build # produces go/latprobe +make run ARGS="https://example.com" +make test # go test ./... +make go-test-verbose # per-test PASS/FAIL output +make check # fmt + vet + test +make go-cover # writes go/coverage.html +make go-lint # runs golangci-lint (installed) +make clean # removes binary + coverage artifacts +``` +Confirm `make` with no args shows help, and that `clean` leaves the tree as +`git status` clean (no tracked files removed). diff --git a/docs/usage/makefile.md b/docs/usage/makefile.md new file mode 100644 index 0000000..666b721 --- /dev/null +++ b/docs/usage/makefile.md @@ -0,0 +1,92 @@ +# Makefile + +The root `Makefile` provides a single entry point for all common development +tasks. Targets are namespaced by language (`go-*`, `py-*` when the Python port +lands) with short umbrella targets (`build`, `test`, …) that delegate to the +language-specific ones. + +## Quick reference + +```sh +make # same as: make help +make help # list all targets with descriptions +``` + +## Umbrella targets + +| Target | Description | +|--------|-------------| +| `all` | Run `check` then `build` | +| `build` | Build the binary (→ `go-build`) | +| `test` | Run all tests (→ `go-test`) | +| `check` | Pre-commit gate: fmt + vet + test (→ `go-check`) | +| `fmt` | Format source (→ `go-fmt`) | +| `vet` | Static analysis (→ `go-vet`) | +| `clean` | Remove binary and coverage artifacts | + +## Go targets + +| Target | Description | +|--------|-------------| +| `go-build` | Compile `go/latprobe` | +| `go-run` | Build and run (pass flags via `ARGS=`) | +| `go-test` | `go test ./...` | +| `go-test-verbose` | `go test -v ./...` — per-case PASS/FAIL output | +| `go-check` | `go-fmt` + `go-vet` + `go-test` | +| `go-cover` | Coverage report → `go/coverage.html` | +| `go-fmt` | `gofmt -w go/` | +| `go-vet` | `go vet ./...` | +| `go-tidy` | `go mod tidy` | +| `go-install` | Install binary to `$GOBIN` | +| `go-lint` | `golangci-lint run` (must be installed) | +| `go-clean` | Remove `go/latprobe`, `go/coverage.out`, `go/coverage.html` | + +## Examples + +```sh +# Build and run a quick probe +make go-run ARGS="https://example.com" +make go-run ARGS="-n 5 --json https://example.com https://www.google.com" + +# Run the full test suite +make test + +# Verbose output showing each test case +make go-test-verbose + +# Pre-commit gate (format, vet, test all in one) +make check + +# Generate and open coverage report +make go-cover +open go/coverage.html # macOS + +# Lint +make go-lint + +# Clean up artifacts +make clean +``` + +## Passing arguments to `go-run` + +```sh +make go-run ARGS=" [url ...] [flags]" + +# Examples +make go-run ARGS="https://example.com" +make go-run ARGS="--timeout 2s --fail https://example.com" +make go-run ARGS="--json -n 3 https://example.com https://www.google.com" +``` + +## Adding Python targets (when the port lands) + +The umbrella targets are designed to accept Python targets alongside the Go ones. +The pattern will be: + +```make +test: go-test py-test # py-test added here during the port +``` + +`go-lint` requires `golangci-lint` to be installed. If it's missing the target +prints an install link and exits 1.