Last active
October 17, 2022 23:22
-
-
Save ajcerejeira/c043a441f9078ce996b5a09cb98c130c to your computer and use it in GitHub Desktop.
(Ab)using Makefiles in Django projects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Lightning talk @ DjangoCon EU 2022 | |
# Afonso Cerejeira <github.com/ajcerejeira> | |
# Intro | |
# ===== | |
# | |
# - Makefiles are a set of rules for building targets based on prerequisites; | |
# - Usually both targets and prerequisites represent filenames; | |
# - Makefiles define dependency graphs; | |
# Project setup | |
# ============= | |
VENV := .venv | |
PYTHON := $(VENV)/bin/python | |
$(PYTHON): | |
python -m venv $(VENV) | |
.PHONY: install | |
install: $(VENV)/.install | |
$(VENV)/.install: $(PYTHON) requirements.txt | |
$(PYTHON) -m pip install -r requirements.txt | |
touch $@ # file name of the target of the rule, in this case '.venv/.install' | |
# Usage: | |
# | |
# $ make install | |
# python -m venv .venv | |
# .venv/bin/python -m pip install -r requirements.txt | |
# ... | |
# touch .venv/.install | |
# | |
# make only runs install when requirements.txt is updated: | |
# Automatically installing Python programs | |
# ======================================== | |
# Special rule to automatically install binary targets, (e.g, dev tools) | |
# - '%' is a placeholder to be substituted in the target | |
# - '$@' expands to the name of the target (i.e, '$(VENV)/bin/...') | |
# - 'notdir' is function that extracts the basename of a file | |
$(VENV)/bin/%: $(PYTHON) | |
$(PYTHON) -m pip install $(notdir $@) | |
# Usage: | |
# $ make .venv/bin/pylint | |
# python -m venv .venv | |
# .venv/bin/python -m pip install pylint | |
# Collecting pylint | |
# Linting and formatting | |
# ====================== | |
BLACK := $(VENV)/bin/black | |
ISORT := $(VENV)/bin/isort | |
DJHTML := $(VENV)/bin/djhtml | |
PYLINT := $(VENV)/bin/pylint | |
.PHONY: format | |
format: $(BLACK) $(ISORT) $(DJHTML) | |
$(BLACK) . | |
$(ISORT) . | |
$(DJHTML) -i templates/ | |
.PHONY: lint | |
lint: $(PYLINT) | |
$(PYLINT) . | |
# Testing | |
# ======= | |
COVERAGE := $(VENV)/bin/coverage | |
.PHONY: test | |
test: install $(COVERAGE) | |
$(COVERAGE) run manage.py test | |
$(COVERAGE) report | |
$(COVERAGE) html | |
# Automating Docker workflows | |
# =========================== | |
.ONESHELL: docker | |
.SILENT: docker | |
docker: .SHELLFLAGS = run --rm --entrypoint /bin/bash ubuntu -c | |
docker: SHELL := docker | |
docker: | |
echo "hello, container world!" | |
# Embedding Python scripts in the Makefile | |
# ======================================== | |
# Generate secret key | |
# Run all the commands of target 'secretkey' in a single shell | |
.ONESHELL: secretkey | |
# Do not print the command names to STDOUT | |
.SILENT: secretkey | |
# This target does not generate a file | |
.PHONY: secretkey | |
# Use the current virtual environment Python shell | |
secretkey: SHELL = $(PYTHON) | |
secretkey: | |
from django.core.management.utils import get_random_secret_key | |
print(get_random_secret_key()) | |
# Catch-all target for manage.py script | |
# ===================================== | |
# Default rule to call 'manage.py' script | |
.DEFAULT: | |
@$(PYTHON) manage.py "$@" | |
# Final thoughts | |
# ============== | |
# - make is very powerful and has a steep learning curve, so it is advised | |
# to read its manual: https://www.gnu.org/software/make/manual. | |
# - Or not, just use tox, nox or pyinvoke. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment