FossilRepo

fossilrepo / CONTRIBUTING.md
Source Blame History 138 lines
c588255… ragelink 1 # Contributing to Fossilrepo
c588255… ragelink 2
c588255… ragelink 3 Thanks for your interest in contributing. This document covers how to get set up, our coding standards, and the PR process.
c588255… ragelink 4
c588255… ragelink 5 ## Development Setup
c588255… ragelink 6
c588255… ragelink 7 ### Prerequisites
c588255… ragelink 8
c588255… ragelink 9 - Python 3.12+
c588255… ragelink 10 - Docker and Docker Compose
c588255… ragelink 11 - [uv](https://docs.astral.sh/uv/) (Python package manager)
c588255… ragelink 12 - [Ruff](https://docs.astral.sh/ruff/) (linter/formatter)
c588255… ragelink 13
c588255… ragelink 14 ### Running Locally
c588255… ragelink 15
c588255… ragelink 16 ```bash
c588255… ragelink 17 git clone https://github.com/ConflictHQ/fossilrepo.git
c588255… ragelink 18 cd fossilrepo
c588255… ragelink 19
c588255… ragelink 20 # Start infrastructure
c588255… ragelink 21 docker compose up -d postgres redis mailpit
c588255… ragelink 22
c588255… ragelink 23 # Install dependencies
c588255… ragelink 24 uv sync --all-extras
c588255… ragelink 25
c588255… ragelink 26 # Run migrations and seed data
c588255… ragelink 27 DJANGO_DEBUG=true uv run python manage.py migrate
c588255… ragelink 28 DJANGO_DEBUG=true uv run python manage.py seed
c588255… ragelink 29
c588255… ragelink 30 # Start the dev server
c588255… ragelink 31 DJANGO_DEBUG=true POSTGRES_HOST=localhost uv run python manage.py runserver
c588255… ragelink 32 ```
c588255… ragelink 33
c588255… ragelink 34 Or use Docker for everything:
c588255… ragelink 35
c588255… ragelink 36 ```bash
c588255… ragelink 37 docker compose up -d --build
c588255… ragelink 38 docker compose exec backend python manage.py migrate
c588255… ragelink 39 docker compose exec backend python manage.py seed
c588255… ragelink 40 ```
c588255… ragelink 41
c588255… ragelink 42 ### Default Users
c588255… ragelink 43
c588255… ragelink 44 - `admin` / `admin` — superuser, full access
c588255… ragelink 45 - `viewer` / `viewer` — read-only permissions
4ce269c… ragelink 46
4ce269c… ragelink 47 ## Code Style
4ce269c… ragelink 48
c588255… ragelink 49 We use **Ruff** for linting and formatting. No debates, no custom configs.
c588255… ragelink 50
c588255… ragelink 51 ```bash
c588255… ragelink 52 # Check
c588255… ragelink 53 ruff check .
c588255… ragelink 54 ruff format --check .
c588255… ragelink 55
c588255… ragelink 56 # Fix
c588255… ragelink 57 ruff check --fix .
c588255… ragelink 58 ruff format .
c588255… ragelink 59 ```
c588255… ragelink 60
c588255… ragelink 61 Key conventions:
c588255… ragelink 62
c588255… ragelink 63 - **Max line length:** 140 characters
c588255… ragelink 64 - **Imports:** sorted by Ruff (isort rules)
c588255… ragelink 65 - **Quote style:** double quotes
c588255… ragelink 66 - **Target:** Python 3.12+
c588255… ragelink 67
c588255… ragelink 68 ## Codebase Conventions
c588255… ragelink 69
c588255… ragelink 70 Read [`bootstrap.md`](bootstrap.md) before writing code. It covers:
c588255… ragelink 71
c588255… ragelink 72 - Model base classes (`Tracking`, `BaseCoreModel`)
c588255… ragelink 73 - Soft deletes (never call `.delete()`)
c588255… ragelink 74 - Permission system (`P` enum + project-level RBAC)
c588255… ragelink 75 - View patterns (HTMX partials, auth checks)
c588255… ragelink 76 - Template conventions (dark theme, Tailwind classes)
4ce269c… ragelink 77
4ce269c… ragelink 78 ## Testing
4ce269c… ragelink 79
c588255… ragelink 80 Tests run against a real PostgreSQL database. No mocked databases.
c588255… ragelink 81
c588255… ragelink 82 ```bash
c588255… ragelink 83 # Run all tests
c588255… ragelink 84 DJANGO_DEBUG=true uv run pytest
c588255… ragelink 85
c588255… ragelink 86 # Run specific test file
c588255… ragelink 87 DJANGO_DEBUG=true uv run pytest tests/test_releases.py
c588255… ragelink 88
c588255… ragelink 89 # Run with coverage
c588255… ragelink 90 DJANGO_DEBUG=true uv run pytest --cov
c588255… ragelink 91 ```
c588255… ragelink 92
c588255… ragelink 93 Every PR should:
c588255… ragelink 94
c588255… ragelink 95 - Include tests for new features (happy path + permission denied cases)
c588255… ragelink 96 - Not decrease test coverage
c588255… ragelink 97 - Pass all existing tests
c588255… ragelink 98
c588255… ragelink 99 ## Pull Request Process
c588255… ragelink 100
c588255… ragelink 101 1. **Fork and branch** from `main`. Branch naming: `feature/short-description` or `fix/short-description`.
c588255… ragelink 102
c588255… ragelink 103 2. **Write code** following the conventions in `bootstrap.md`.
c588255… ragelink 104
c588255… ragelink 105 3. **Write tests.** Both allowed and denied permission cases. Assert against database state, not just status codes.
c588255… ragelink 106
c588255… ragelink 107 4. **Lint and test locally.** CI will catch it anyway, but save yourself a round trip.
c588255… ragelink 108
c588255… ragelink 109 5. **Open a PR** with a clear description:
c588255… ragelink 110 - What changed and why
c588255… ragelink 111 - How to test it
c588255… ragelink 112 - Link to any related issues
c588255… ragelink 113
c588255… ragelink 114 6. **Address review feedback** in new commits (don't amend/squash during review).
c588255… ragelink 115
c588255… ragelink 116 7. **Merge** when CI is green and review is approved.
c588255… ragelink 117
c588255… ragelink 118 ## Reporting Issues
c588255… ragelink 119
c588255… ragelink 120 Use [GitHub Issues](https://github.com/ConflictHQ/fossilrepo/issues). Include:
c588255… ragelink 121
c588255… ragelink 122 - What you expected to happen
c588255… ragelink 123 - What actually happened
c588255… ragelink 124 - Steps to reproduce
c588255… ragelink 125 - Browser/OS/version if relevant
c588255… ragelink 126
c588255… ragelink 127 ## Architecture Decisions
c588255… ragelink 128
c588255… ragelink 129 Fossilrepo has some non-obvious design choices worth understanding:
c588255… ragelink 130
c588255… ragelink 131 - **No Fossil HTTP server.** We read `.fossil` files directly via SQLite (`FossilReader`) and use `fossil http` in CGI mode for sync. No persistent Fossil process, stateless containers.
c588255… ragelink 132 - **Django-backed forum posts** supplement Fossil's native forum because Fossil forum posts don't sync via clone/pull.
c588255… ragelink 133 - **Encrypted fields** use Fernet (AES-128-CBC + HMAC) keyed from `SECRET_KEY` for SSH keys and OAuth tokens at rest.
c588255… ragelink 134 - **Single org model.** Multi-org is possible but not implemented — fossilrepo targets self-hosted single-team deployments.
4ce269c… ragelink 135
c588255… ragelink 136 ## License
4ce269c… ragelink 137
c588255… ragelink 138 By contributing, you agree that your contributions will be licensed under the MIT License.

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button