Skip to content

Instantly share code, notes, and snippets.

@hectorcanto
Last active August 16, 2025 23:16
Show Gist options
  • Save hectorcanto/03164f25c582e1ae41b400a3e467e416 to your computer and use it in GitHub Desktop.
Save hectorcanto/03164f25c582e1ae41b400a3e467e416 to your computer and use it in GitHub Desktop.
This is a combination of several Makefiles I've been using over the last years that enhance my development experience over the terminal. This works best with other tools like bash aliases, pre-commit, IDE shortcuts and else
#!/usr/bin/make -f
# Run `make` or `make help` to get the list
# Rename or reference them at your own
# Recommendation, group them to enhace autocompletion, like `lint-something`
# Use `@` at the beggining of a line to hide it from prompting
# Most commands are configured through pyproject.toml by default or explicitly
#### Setup
PKG="src"
# Main code is expected in `src/` but you can replace to one or several other folders
PKGS="src tests"
# Some tools are launched against just src, others to tests too
CURRENT_DIR := $(shell pwd)
.DEFAULT_GOAL := help
.PHONY: *
# all targets are phony, change it if any command has a file target
help: ## Prompts help for every command, try `make`
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = "[:,##]"}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$4}'
@echo
@echo "Usage: make [target]"
@echo "Use tabs for autocomplete"
### Running and docker
setup-project: ## Run this to setup the python environment
@poetry install --with dev,docs
@poetry shell
run: ## Run the application
poetry run python3 -m src.app
dkc-build: ## Build locally with docker compose, needs private pype credentials
docker compose --env-file .private/pypi.env build app
dkc-run: ## Run project locally with dkc run
@docker compose up -d --remove-orphans dep1 dep2
@docker compose run --rm app
#### Testing
run-tests: ## Run tests, dashed options will be included ( make test -s)
pytest $(MFLAGS) -m "not integration and not instrumented"
tests-current: ## Run tests decorated with @pytest.mark.current, with prompt output and high verbosity, dashed options will be included
pytest -s -m current -vv $(MFLAGS)
tests-smoke: ## Basic tests
pytest -s -m smoke -v $(MFLAGS)
tests-unit: ## Unitary tests
pytest -s -m unit -v $(MFLAGS)
test-all: ## Run all pytest tests, included instrumented
@pytest $(MFLAGS)
test-clean: ## Clean all test artifacts
@rm -rf .reports .coverage **/
#### cleaning -----------------------------------------------
py-clean: ## Remove python compiled and temporal files
@find . -name '*.pyc' -exec rm -f {} +
@find . -name '*.pyo' -exec rm -f {} +
@find . -name '*~' -exec rm -f {} +
@find . -name '__pycache__' -exec rm -fr {} +
@find . -name '.pytest_cache' -exec rm -fr {} +
@find . -name '*.egg-info' -exec rm -fr {} +
@rm -rf build/
py-debug-clean: ## Remove python and pytest debugging artifacts
@grep -rn "breakpoint" ${PKGS} || true
@grep -rn "pytest.mark.current" tests || true
@grep -rn "print(" ${PKGS} || true
clean-python: py-clean py-debug-clean
instr-clean: ### Clean INSTR comments from templates
@find . -type f -exec sed -i '/^# INST/d' {} +
@find . -type f -exec sed -i '/<!-- INST/,/-->/d' {} +
##### Style, docstrings and linting
lint-isort: ## Run import sorting
@isort "${PKGS}"
lint-ruff: ## Run ruff linting
@ruff check ${PKGS}
@ruff format --diff ${PKGS}
spell: ## Check spelling
@codespell | sed "s#^\./#file://$(CURRENT_DIR)/#g"
format-ruff: ## Run ruff linting
@ruff check --fix ${PKGS}
@ruff format ${PKGS}
lint-black: ## Run black style
@black -l 100 -C "${PKGS}"
# TODO use pyproject config
link-flake: ## Runs flake8 style check
@flake8 "${PKGS}" --statistics --show-source \
&& echo "${GREEN}Passed Flake8 style review for: ${PKGS}.${REGULAR}" \
|| (echo "${RED}Flake8 style review failed for ${PKGS}.${REGULAR}" ; exit 1)
# workaround to show red and green prompt (useful for CI and terminal) and provide an error
link-flake-toml: ## Runs flake8 style check
@flake8 "${PKGS}" \ --toml-config pyproject.toml --statistics --show-source
lint-pylint: ## Run pylint
@pylint --rcfile setup.cfg ${PKGS} | tee .reports/pylint.txt
lint-pylint-full: ## Run pylint without any configuration
@pylint -v ${PKGS}
format: isort black flake linting
docstrings-interrogate: # Run interrogate docstrings with extra parsing
@interrogate --config=setup.cfg | sed -e "s/^| //" -e "s#[^\s]*\.py#&:1#"
lint-pyright: ## Run type-checker "pyright" for code
pyright .
# TODO add mypy sample
lint-helm: ## Run linter for Helm files
@helm lint helm-3-chart-template -f helm-chart-values.yml
interrogate: # Run interrogate docstrings with extra parsing
@interrogate --config=setup.cfg | sed -e "s/^| //" -e "s#[^\s]*\.py#&:1#"
check-licenses: ## check valid licenses with liccheck
@pipenv requirements | sed -e 's/^#.*//;/./!d;' -e 's/;.*//' -e 's/\[[^]]*\]//' -e '/^--/d' > coverage-reports/requirements.txt
@liccheck -s liccheck.ini -l cautious --rfile .coverage-reports/requirements.txt \
&& echo "${GREEN}Licenses check OK ${REGULAR}"
# pipx install bandit
sec-bandit: ## Run a mild security analysis with Bandit
@bandit -r ${PKG}
sec-safety: ## Check Python packages vulnerabilities against PyUp DB
safety check --full-report | tee ${REPORTS}/safety.txt
# TODO add interrogate
docstrings: ## Review docstrings, use doit interrogate better
@pydocstyle "${PKGS}" && echo "${GREEN}pydocstyle OK ${REGULAR}" || echo "";
@docstr-coverage "${PKGS}" -v 1; echo ""
lint-dockerfile: ## Run linter for Dockerfiles
@hadolint Dockerfile*
lint-ignored: ## List all lines where linting is ignored like noqa
@grep -rni "# noqa" ${PKG} || true
@grep -rn "# fmt:" ${PKG} || true
@grep -rn "# type: ignore" ${PKG} || true
# TODO check NOQA ruff and module ones
### Docs
docs-run: # Serve docs locally
@mkdocs serve
docs-build: # Build the documentation (in a static site)
@mkdocs build -d docs_build
docs-clean: # Remove docs-related folder
@rm -rf docs_build/
### Migrations
migrate-apply: # # Apply all migrations
poetry run alembic upgrade head
# TODO(hector): raise question if create is better than generate (see other tools like Django or Express)
migrate-generate: ## Auto generate an Alembic migration according to SQLAlchemy schemas
poetry run alembic revision --autogenerate
migrate-rollback: ## Rollback one migration
poetry run alembic downgrade -1
#### packaging
requirements: ## Generate dev requirements from Pipfile
@pipfile2req --dev Pipfile.lock | sed 's/;.*//' > requirements.txt
check-pipfile: ## List available python package updates, may request creating a password wallet
@pipenv update --dev --outdated
# TODO group with pipenv and do poetry check example
# TODO do the same for poetry from the port to poetry guide
## git
# based on https://stackoverflow.com/questions/9597410/list-all-developers-on-a-project-in-git'
git-contrib-first: ## List first time a contributor committed
git log --pretty="%an,%ae,%aI" --reverse --all | awk -F',' '!seen[$$1]++ {printf "%-25s %-15s\n", $$1, $$3}'
git-contrib-count: ## List contributors by commit count based on names
git shortlog --summary --numbered --committer
git-last-tag: ## List the last released version according to git tags
@git tag -l releases/* --sort=-v:refname | head -1
commit-semantic: ## Helper to generate a semantic commit based on the branch name PROJ-123
@echo "git commit -m \"$$(git rev-parse --abbrev-ref HEAD | sed -E 's#([^/]*)/([^/]*)/(.*)#\1(\2): \3#' | sed 's/-/ /g')\"" | sed -E 's/\((PROJ) ([0-9]+)\)/(\1-\2)/g'
## Code quality -----------------------------------------
# install radon with `pipx install radon"
qual-lines: ## Count the lines of a project
@radon raw --summary src | awk '/\*\* Total \*\*/{flag=1} flag'
# loc: lines of code, sloc: physical, lloc: logical loc
# more info in https://www.wikiwand.com/en/articles/Source_lines_of_code
qual-complexity: ## Highlight functions with high cyclomatic complexity, C is usually too high (above 10)
@radon cc -s --min B src
## templates
template-sync: ## Update against original template
copier update --trust --data-file .copier-answers.yml
template-clean-inst: ## clean INST instructions from py and md files after rendering teplate
@find . -type f -exec sed -i '/^# INST/d' {} +
@find . -type f -exec sed -i '/<!-- INST/,/-->/d' {} +
links: ## Extract links for a given slides
mdlinks ${FN} | cut -d'-' -f2- | sed -e '#^$#d' -e 's# -- #\(#' -e 's#$#\)#'
toc-readme: ## Redo the Table of Contents of README
@markdown-toc -i README.md --bullets "-"
# TODO document installation
# import from main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment