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 d55211d..4472c92 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -132,6 +132,33 @@ 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 justfile commands:
+
+```
+just install
+```
+
+Or use the Makefile commands while overriding the `PIP` variable:
+
+```shell
+make install 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
@@ -170,7 +197,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.
@@ -195,8 +222,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.
diff --git a/Makefile b/Makefile
index b621f32..7233167 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,10 @@ GCP_DOCKER_VOLUME:=gcp
sources = python_app_template
+PYTHON:=python
+# Control package manager. To use `uv`, override with: make install PIP="uv pip"
+PIP:=${PYTHON} -m pip
+
# ---------------------
# DOCKER
# ---------------------
@@ -18,32 +22,31 @@ sources = python_app_template
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}
.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'
@@ -53,23 +56,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 +80,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 +121,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
@@ -157,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
new file mode 100644
index 0000000..0066f8e
--- /dev/null
+++ b/justfile
@@ -0,0 +1,97 @@
+# 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"]
+
+
+VENV_NAME := ".venv"
+PYTHON := VENV_NAME / "bin" / "python"
+PIP := "uv pip"
+
+[private]
+default:
+ just --list
+
+# 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