From 5870e54e939ed1c3b6d4513a45660fdef24b7565 Mon Sep 17 00:00:00 2001 From: Fernando Cagua Date: Tue, 16 Dec 2025 09:27:22 +1300 Subject: [PATCH 1/6] feat: Add PYTHON and PIP variables to Makefile for UV support - Add PYTHON variable pointing to venv python binary - Add PIP variable defaulting to '${PYTHON} -m pip' for consistency - Allow override with 'uv pip' for faster dependency management - Update all recipes to use ${PYTHON} and ${PIP} variables - Enables optional use of uv in local development without Docker Documentation: - Add UV package manager section to CONTRIBUTING.md - Emphasize UV is for local development only, Docker uses pip by default - Include installation instructions and usage examples --- CONTRIBUTING.md | 22 ++++++++++++++++++++++ Makefile | 40 ++++++++++++++++++++++------------------ 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d55211d..ce468b3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -132,6 +132,28 @@ make reqs-upgrade > Remember that if you change the [requirements.txt], you need to rebuild the docker image (`make docker-build`) in order to use it locally. +### Using UV for faster local development (Optional) + +**This is for local development only.** Docker builds use pip by default. + +If you prefer faster dependency resolution and installation during local development, +you can optionally use [uv](https://docs.astral.sh/uv/) instead of pip. + +Install `uv`: +```shell +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +Then, use it with the Makefile commands by overriding the `PIP` variable: +```shell +make install PIP="uv pip" +make reqs PIP="uv pip" +make reqs-upgrade PIP="uv pip" +``` + +This will use `uv pip` for faster resolution while maintaining the same functionality. +Docker and CI/CD pipelines will continue to use standard pip. + ## Git Workflow
diff --git a/Makefile b/Makefile index b621f32..a08420a 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,10 @@ GCP_DOCKER_VOLUME:=gcp sources = python_app_template +PYTHON:=${VENV_NAME}/bin/python +# Control package manager. To use `uv`, override with: make install PIP="uv pip" +PIP:=${PYTHON} -m pip + # --------------------- # DOCKER # --------------------- @@ -53,23 +57,23 @@ reqs-upgrade: .PHONY: venv ## Creates virtual environment. venv: - python -m venv ${VENV_NAME} + ${PYTHON} -m venv ${VENV_NAME} .PHONY: upgrade-pip ## Upgrades pip. upgrade-pip: - python -m pip install pip==25.2 + ${PIP} install pip==25.2 .PHONY: install-test ## Install and only test dependencies. install-test: upgrade-pip - python -m pip install -r requirements-test.txt + ${PIP} install -r requirements-test.txt .PHONY: install ## Install the package in editable mode & all dependencies for local development. install: upgrade-pip - python -m pip install -e .[lint,dev,build,test] + ${PIP} install -e .[lint,dev,build,test] .PHONY: test ## Run all unit tests exporting coverage.xml report. test: - python -m pytest -m "not integration" --cov-report term --cov-report=xml --cov=$(sources) + ${PYTHON} -m pytest -m "not integration" --cov-report term --cov-report=xml --cov=$(sources) # --------------------- # QUALITY CHECKS @@ -77,36 +81,36 @@ test: .PHONY: hooks ## Install and pre-commit hooks. hooks: - python -m pre_commit install --install-hooks - python -m pre_commit install --hook-type commit-msg + ${PYTHON} -m pre_commit install --install-hooks + ${PYTHON} -m pre_commit install --hook-type commit-msg .PHONY: format ## Auto-format python source files according with PEP8. format: - python -m black $(sources) - python -m ruff check --fix $(sources) - python -m ruff format $(sources) + ${PYTHON} -m black $(sources) + ${PYTHON} -m ruff check --fix $(sources) + ${PYTHON} -m ruff format $(sources) .PHONY: lint ## Lint python source files. lint: - python -m ruff check $(sources) - python -m ruff format --check $(sources) - python -m black $(sources) --check --diff + ${PYTHON} -m ruff check $(sources) + ${PYTHON} -m ruff format --check $(sources) + ${PYTHON} -m black $(sources) --check --diff .PHONY: codespell ## Use Codespell to do spell checking. codespell: - python -m codespell_lib + ${PYTHON} -m codespell_lib .PHONY: typecheck ## Perform type-checking. typecheck: - python -m mypy + ${PYTHON} -m mypy .PHONY: audit ## Use pip-audit to scan for known vulnerabilities. audit: - python -m pip_audit . + ${PYTHON} -m pip_audit . .PHONY: pre-commit ## Run all pre-commit hooks. pre-commit: - python -m pre_commit run --all-files + ${PYTHON} -m pre_commit run --all-files .PHONY: all ## Run the standard set of checks performed in CI. all: lint codespell typecheck audit test @@ -118,7 +122,7 @@ all: lint codespell typecheck audit test .PHONY: build ## Build a source distribution and a wheel distribution. build: all clean - python -m build + ${PYTHON} -m build .PHONY: publish ## Publish the distribution to PyPI. publish: build From 332bd9f950c7ebf83e63c4fd9c5149263f9b5c2d Mon Sep 17 00:00:00 2001 From: Fernando Cagua Date: Tue, 16 Dec 2025 09:29:23 +1300 Subject: [PATCH 2/6] fix: Add docker-volume dependency to docker-compose recipes - Add docker-volume as dependency to docker-gcp, docker-ci-test, docker-shell, reqs, and reqs-upgrade - Replace 'make docker-volume' call with Make dependency in docker-gcp - Prevents 'external volume not found' errors when recipes run without volume creation - Users no longer need to manually run 'make docker-volume' first - Volume is automatically created when any docker-compose recipe is invoked --- Makefile | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index a08420a..3c750e9 100644 --- a/Makefile +++ b/Makefile @@ -27,27 +27,26 @@ docker-volume: docker volume create --name ${GCP_DOCKER_VOLUME} .PHONY: docker-gcp ## gcp: Authenticates to google cloud and configure the project. -docker-gcp: - make docker-volume +docker-gcp: docker-volume docker compose run gcloud auth application-default login docker compose run gcloud config set project ${GCP_PROJECT} docker compose run gcloud auth application-default set-quota-project ${GCP_PROJECT} .PHONY: docker-ci-test ## Runs tests using prod image, exporting coverage.xml report. -docker-ci-test: +docker-ci-test: docker-volume docker compose run --rm ${DOCKER_CI_TEST_SERVICE} .PHONY: docker-shell ## Enters to docker container shell. -docker-shell: +docker-shell: docker-volume docker compose run --rm -it ${DOCKER_DEV_SERVICE} .PHONY: reqs ## Compiles requirements.txt with pip-tools. -reqs: +reqs: docker-volume docker compose run --rm ${DOCKER_DEV_SERVICE} -c \ 'pip-compile -o ${REQS_PROD} -v' .PHONY: reqs-upgrade ## Upgrades requirements.txt with pip-tools. -reqs-upgrade: +reqs-upgrade: docker-volume docker compose run --rm ${DOCKER_DEV_SERVICE} -c \ 'pip-compile -o ${REQS_PROD} -U -v' From c817bf35a42da370d6bff5ae7b0f02b2cd336227 Mon Sep 17 00:00:00 2001 From: Fernando Cagua Date: Tue, 16 Dec 2025 10:11:58 +1300 Subject: [PATCH 3/6] feat: Add justfile for local development - Thin wrapper that calls Make recipes with venv PYTHON and PIP variables - Sets PYTHON=.venv/bin/python and PIP='.venv/bin/python -m pip' - Allows seamless local development without modifying Makefile - Docker and CI/CD continue using Makefile directly with system python - Default recipe is 'list' to show available commands - Example: 'just install', 'just test', 'just reqs' --- justfile | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 justfile diff --git a/justfile b/justfile new file mode 100644 index 0000000..0b7081e --- /dev/null +++ b/justfile @@ -0,0 +1,93 @@ +# Justfile - Thin wrapper for local development +# Adjusts PYTHON and PIP variables for venv, then calls Make recipes +# Use: `just install`, `just test`, `just reqs`, etc. + +set shell := ["bash", "-c"] +set default-recipe := "list" + +VENV_NAME := ".venv" +PYTHON := VENV_NAME / "bin" / "python" +PIP := PYTHON + " -m pip" + +# Create virtual environment +venv: + make venv + +# Upgrade pip +upgrade-pip: + make upgrade-pip PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Install and only test dependencies +install-test: upgrade-pip + make install-test PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Install the package in editable mode & all dependencies for local development +install: upgrade-pip + make install PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Run all unit tests exporting coverage.xml report +test: + make test PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Install and pre-commit hooks +hooks: + make hooks PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Auto-format python source files according with PEP8 +format: + make format PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Lint python source files +lint: + make lint PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Use Codespell to do spell checking +codespell: + make codespell PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Perform type-checking +typecheck: + make typecheck PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Use pip-audit to scan for known vulnerabilities +audit: + make audit PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Run all pre-commit hooks +pre-commit: + make pre-commit PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Run the standard set of checks performed in CI +all: lint codespell typecheck audit test + +# Compile requirements.txt with pip-tools +reqs: + make reqs PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Upgrade requirements.txt with pip-tools +reqs-upgrade: + make reqs-upgrade PYTHON="{{ PYTHON }}" PIP="{{ PIP }}" + +# Docker: Build docker images +docker-build: + make docker-build + +# Docker: Create the docker volume for GCP +docker-volume: + make docker-volume + +# Docker: Authenticate to google cloud and configure the project +docker-gcp: + make docker-gcp + +# Docker: Run tests using prod image, exporting coverage.xml report +docker-ci-test: + make docker-ci-test + +# Docker: Enter interactive dev container shell +docker-shell: + make docker-shell + +# Clean local caches and build artifacts +clean: + make clean From 0413beee0ac4bdca45d4ac55b95920052d8a7d92 Mon Sep 17 00:00:00 2001 From: Fernando Cagua Date: Tue, 16 Dec 2025 10:20:15 +1300 Subject: [PATCH 4/6] fix: Minor fixes to Makefile and justfile --- Makefile | 6 +++--- justfile | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 3c750e9..7233167 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ GCP_DOCKER_VOLUME:=gcp sources = python_app_template -PYTHON:=${VENV_NAME}/bin/python +PYTHON:=python # Control package manager. To use `uv`, override with: make install PIP="uv pip" PIP:=${PYTHON} -m pip @@ -22,7 +22,7 @@ PIP:=${PYTHON} -m pip docker-build: docker compose build -.PHONY: docker-volume ## Creates the docker volume for GCP. +.PHONY: docker-volume ## Creates the docker volume for GCP. docker-volume: docker volume create --name ${GCP_DOCKER_VOLUME} @@ -160,4 +160,4 @@ clean: help: @grep -E \ '^.PHONY: .*?## .*$$' $(MAKEFILE_LIST) | \ - awk 'BEGIN {FS = ".PHONY: |## "}; {printf "\033[36m%-19s\033[0m %s\n", $$2, $$3}' \ No newline at end of file + awk 'BEGIN {FS = ".PHONY: |## "}; {printf "\033[36m%-19s\033[0m %s\n", $$2, $$3}' diff --git a/justfile b/justfile index 0b7081e..0066f8e 100644 --- a/justfile +++ b/justfile @@ -3,11 +3,15 @@ # Use: `just install`, `just test`, `just reqs`, etc. set shell := ["bash", "-c"] -set default-recipe := "list" + VENV_NAME := ".venv" PYTHON := VENV_NAME / "bin" / "python" -PIP := PYTHON + " -m pip" +PIP := "uv pip" + +[private] +default: + just --list # Create virtual environment venv: From 166605a335e0cd00804d1f1813c5e632c762f13d Mon Sep 17 00:00:00 2001 From: Fernando Cagua Date: Tue, 16 Dec 2025 10:29:03 +1300 Subject: [PATCH 5/6] fix: Add codespell to pre-commit hook dependencies --- .pre-commit-config.yaml | 1 + CONTRIBUTING.md | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 768c280..d860096 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,6 +32,7 @@ repos: language: python pass_filenames: false additional_dependencies: + - "codespell[toml]>=2.4" - tomli - id: typecheck diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ce468b3..4382ab9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -145,10 +145,9 @@ curl -LsSf https://astral.sh/uv/install.sh | sh ``` Then, use it with the Makefile commands by overriding the `PIP` variable: + ```shell make install PIP="uv pip" -make reqs PIP="uv pip" -make reqs-upgrade PIP="uv pip" ``` This will use `uv pip` for faster resolution while maintaining the same functionality. @@ -192,7 +191,7 @@ Try to follow these guidelines: - Maintain a clean commit history in your feature branch. Use interactive rebase (`git rebase -i`) to squash, reorder, or edit commits.[^1] - + - If you are not using [pre-commit] hooks, use the provided [Makefile] commands (`format`, `lint`, `codespell`, `typecheck`) as much as possible to maintain code quality. @@ -217,8 +216,8 @@ Try to follow these guidelines:
-A Google Cloud build that publishes a Docker image is triggered in the following cases: -- When a commit is merged into `main` or `develop`. +A Google Cloud build that publishes a Docker image is triggered in the following cases: +- When a commit is merged into `main` or `develop`. - When a new tag is created. From 6e3cdfc95c27db667e21ddfbab4f1396a9a13a0a Mon Sep 17 00:00:00 2001 From: Fernando Cagua Date: Tue, 16 Dec 2025 10:37:11 +1300 Subject: [PATCH 6/6] docs: Update CONTRIBUTING.md to clarify usage of justfile commands --- CONTRIBUTING.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4382ab9..4472c92 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -144,7 +144,13 @@ Install `uv`: curl -LsSf https://astral.sh/uv/install.sh | sh ``` -Then, use it with the Makefile commands by overriding the `PIP` variable: +Then, use it with the justfile commands: + +``` +just install +``` + +Or use the Makefile commands while overriding the `PIP` variable: ```shell make install PIP="uv pip"