Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ repos:
language: python
pass_filenames: false
additional_dependencies:
- "codespell[toml]>=2.4"
- tomli

- id: typecheck
Expand Down
33 changes: 30 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

<div align="justify">
Expand Down Expand Up @@ -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.
Expand All @@ -195,8 +222,8 @@ Try to follow these guidelines:

<div align="justify">

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.


Expand Down
55 changes: 29 additions & 26 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
# ---------------------
Expand All @@ -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'

Expand All @@ -53,60 +56,60 @@ 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
# ---------------------

.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
Expand All @@ -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
Expand Down Expand Up @@ -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}'
awk 'BEGIN {FS = ".PHONY: |## "}; {printf "\033[36m%-19s\033[0m %s\n", $$2, $$3}'
97 changes: 97 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -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
Loading