Skip to content

Commit 4730166

Browse files
committed
🔧 : add Makefile for development and build automation
The Makefile introduces targets for installing dependencies, formatting code with Black and Ruff, linting with Ruff and MyPy, running tests with Pytest (including coverage), building distributions, generating docs, cleaning artifacts, and a CI pipeline. This standardizes workflows, supports Hatch for isolated environments, and enhances productivity by reducing manual command repetition.
1 parent 83f7130 commit 4730166

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

Makefile

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# Makefile for cedarmapper
2+
# Author: principal-engineering team style
3+
4+
# ---------- Configuration & Variables ----------
5+
SHELL := /bin/bash
6+
PY ?= python3
7+
PIP ?= $(PY) -m pip
8+
HATCH ?= hatch
9+
10+
# -- Tools --
11+
BLACK ?= black
12+
RUFF ?= ruff
13+
MYPY ?= mypy
14+
PYTEST ?= pytest
15+
16+
# -- Directories --
17+
SRC_DIR := src
18+
PKG_DIR := src/cedarmapper
19+
TEST_DIR := tests
20+
BUILD_DIR := build
21+
DIST_DIR := dist
22+
COV_HTML := htmlcov
23+
24+
# -- Execution Logic (DRY) --
25+
# If HATCH is available, we use it for running commands to ensure isolation.
26+
# Otherwise, we fall back to the local python environment.
27+
ifeq (, $(shell command -v $(HATCH) 2> /dev/null))
28+
# Hatch not found
29+
RUNNER := $(PY) -m
30+
BUILD_CMD := $(PY) -m build
31+
else
32+
# Hatch found
33+
RUNNER := $(HATCH) run
34+
BUILD_CMD := $(HATCH) build
35+
endif
36+
37+
# Pytest args
38+
PYTEST_ARGS ?= -ra
39+
# Allow passing extra args via command line, e.g., make test ARGS="-k my_test"
40+
41+
# ---------- Help (Fixed) ----------
42+
define HELP_MESSAGE
43+
Makefile - tasks for development
44+
45+
Usage:
46+
make <target> [VAR=value]
47+
48+
Targets:
49+
help Show this help (default)
50+
install Install package + dev dependencies (editable)
51+
52+
# Code Quality
53+
format Auto-format code (black + ruff fix)
54+
check-format Check formatting without modifying files (for CI)
55+
lint Run static checks (ruff + mypy)
56+
57+
# Testing
58+
test Run test suite with coverage
59+
quick Run tests without coverage (faster)
60+
coverage-open Open coverage HTML report
61+
62+
# Build & Dist
63+
build Build wheel + sdist
64+
clean Remove all build artifacts and __pycache__
65+
distclean Aggressive clean (includes tool caches)
66+
67+
# Automation
68+
ci Run full CI pipeline (check-format, lint, test)
69+
endef
70+
export HELP_MESSAGE
71+
72+
.PHONY: help install dev format check-format lint test quick coverage-open build wheel sdist docs clean distclean ci
73+
74+
.DEFAULT_GOAL := help
75+
76+
help:
77+
@echo "$$HELP_MESSAGE"
78+
79+
# ---------- Installation ----------
80+
install:
81+
@echo "Installing (editable mode)..."
82+
$(PIP) install -e ".[dev]"
83+
84+
dev: install
85+
86+
# ---------- Formatting & Static Checks ----------
87+
format: ## Format code (Write)
88+
@echo "Formatting code..."
89+
$(RUNNER) $(BLACK) $(SRC_DIR) $(TEST_DIR)
90+
$(RUNNER) $(RUFF) check --fix $(SRC_DIR) $(TEST_DIR)
91+
92+
check-format: ## Check code formatting (Read-only / CI)
93+
@echo "Checking formatting..."
94+
$(RUNNER) $(BLACK) --check $(SRC_DIR) $(TEST_DIR)
95+
$(RUNNER) $(RUFF) check $(SRC_DIR) $(TEST_DIR)
96+
97+
lint: ## Run static analysis (Ruff + Mypy)
98+
@echo "Running linters..."
99+
$(RUNNER) $(RUFF) check $(SRC_DIR) $(TEST_DIR)
100+
@echo "Running type checks..."
101+
$(RUNNER) $(MYPY) $(SRC_DIR)
102+
103+
# ---------- Tests ----------
104+
test: ## Run tests with coverage
105+
@echo "Running tests (with coverage)..."
106+
$(RUNNER) $(PYTEST) --cov=$(PKG_DIR) --cov-report=html --cov-report=term $(PYTEST_ARGS) $(ARGS)
107+
108+
quick: ## Run tests (no coverage)
109+
@echo "Running quick tests..."
110+
$(RUNNER) $(PYTEST) $(PYTEST_ARGS) $(ARGS)
111+
112+
coverage-open:
113+
@$(PY) -c "import webbrowser, os; f = os.path.join(os.getcwd(), '$(COV_HTML)', 'index.html'); print('Opening:', f); webbrowser.open('file://' + f) if os.path.exists(f) else print('Run make test first.')"
114+
115+
# ---------- Build & Docs ----------
116+
build: ## Build dists
117+
@echo "Building distributions..."
118+
$(BUILD_CMD)
119+
120+
wheel: build
121+
sdist: build
122+
123+
docs:
124+
@if [ -d docs ]; then \
125+
echo "Building Docs..."; \
126+
$(RUNNER) sphinx-build -b html docs docs/_build/html; \
127+
else \
128+
echo "No docs directory found."; \
129+
fi
130+
131+
# ---------- Cleaning ----------
132+
clean: ## Clean artifacts and pycache
133+
@echo "Cleaning build artifacts..."
134+
@rm -rf $(BUILD_DIR) $(DIST_DIR) *.egg-info .pytest_cache $(COV_HTML) docs/_build
135+
@echo "Cleaning python bytecode..."
136+
@find . -type d -name "__pycache__" -exec rm -rf {} +
137+
@find . -type f -name "*.pyc" -delete
138+
139+
distclean: clean ## Clean everything including tool caches
140+
@echo "Removing tool caches..."
141+
@rm -rf .mypy_cache .ruff_cache .venv
142+
143+
# ---------- CI ----------
144+
# CI chain: check format -> static analysis -> tests
145+
ci: check-format lint test

0 commit comments

Comments
 (0)