Skip to content

Contributing

sf2loki is a small project with a strict green bar — the workflow below keeps it that way.

Dev setup

Requirements: Python 3.14, uv, and just.

just setup   # uv sync — create the venv from the lockfile
just gate    # ruff + mypy --strict + pytest (the green bar; CI runs the same)

Useful extras:

just test        # pytest only
just lint        # ruff check + format check
just proto       # regenerate gRPC/protobuf stubs (only when proto/ changes)
just gen-config  # regenerate config.example.yaml + docs/config-reference.md

Ground rules

  • Tests first. Bug fixes and features come with tests, strict TDD: write a failing test, watch it fail for the right reason, write the minimal code to pass, then refactor. The repo is test-driven and CI fails on any red.
  • just gate must be green before a commitruff check, ruff format --check, mypy src (strict), and pytest. Run it, don't assert it; CI runs the identical gate.
  • Generated files are generated. config.example.yaml, docs/config-reference.md, and the proto stubs under src/sf2loki/**/_generated/ are produced from source (just gen-config / just proto) — never hand-edit them. CI has drift gates that fail the build if a generated file is out of sync with its source (the Pydantic config model, or proto/).
  • Conventional commits. Releases are cut by release-please from commit messages, so use feat:, fix:, docs:, chore:, perf:, etc. (feat!: or a BREAKING CHANGE: footer for majors). PR titles should follow the same convention — squash merges use them. See Release Process for how these map to changelog sections and version bumps.
  • No DCO / CLA. No sign-off dance — by contributing you agree your work is licensed under the project license (AGPL-3.0-only).
  • Label discipline is a feature. Anything that adds Loki stream labels or otherwise touches cardinality gets extra review scrutiny — see the architecture docs.

Reporting issues

Use GitHub issues for bugs and feature requests. For security problems, use the private process in Security instead — never a public issue.