A minimal, modern starting point for Python services. Ships with structured
JSON logging (with optional Google Cloud Logging support), a src/ layout, and
a fully wired tooling setup: uv for dependency
management, ruff for linting and formatting,
mypy for type checking, and pytest for tests.
- uv
- Python 3.13 (uv will install it automatically if missing)
uv sync # create .venv and install all dependencies
cp .env.example .env # configure environment variables
uv run python -m senscritique_cliConfiguration is read from environment variables (see .env.example):
| Variable | Description | Default |
|---|---|---|
LOG_LEVEL |
DEBUG / INFO / WARNING / ERROR / CRITICAL |
DEBUG |
LOCAL_DEV |
Truthy (1/true/yes) when running locally |
false |
GOOGLE_PROJECT_ID |
When set, logs are emitted via Google Cloud's structured handler | unset |
Common tasks are exposed through the Makefile:
make install # uv sync
make lint # ruff check
make format # ruff format
make typecheck # mypy
make test # pytest (unit)
make check # lint + typecheck + test
make run # run the appmake docker # build the Docker imagemake release version=0.2.0 # cut a releaseOr call the tools directly via uv, e.g. uv run pytest.
uv run pre-commit installThis runs ruff and a gitleaks secret scan on every commit.
Unit and integration tests live under tests/. Integration tests may require
external credentials (e.g. GOOGLE_APPLICATION_CREDENTIALS).
uv run pytest tests/unit # fast, no external dependencies
uv run pytest tests/integration # requires credentialsdocker build -t senscritique_cli:latest .
docker run --rm senscritique_cli:latestThe image uses a multi-stage uv build on python:3.13-slim and runs as a
non-root user.
make release version=0.2.0This updates the version in pyproject.toml, refreshes uv.lock, commits,
tags, and pushes. The tag push triggers
.github/workflows/release.yml, which builds
the package and publishes it to PyPI.
One-time setup on pypi.org: under the project's
Publishing settings, add a trusted publisher with the repository owner,
repository name, workflow file release.yml, and environment pypi. No API
token is needed once that is configured.