Add Development and CI wiki page
1 parent
108d0ec9e1
commit
3106654b09
1 file changed
+65
@@ -0,0 +1,65 @@
|
|||||||
|
# Development & CI
|
||||||
|
|
||||||
|
How to develop, test, and ship familiar.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
uv sync # install deps (incl. dev group)
|
||||||
|
uv run pytest # full suite; FAILS under 80% coverage
|
||||||
|
uv run pytest tests/test_market.py::test_get_market_price # a single test
|
||||||
|
uv run ruff format . # format
|
||||||
|
uv run ruff check . # lint
|
||||||
|
uv run familiar # run the MCP server over stdio
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `ruff format` and `ruff check` before committing — **CI enforces both**.
|
||||||
|
|
||||||
|
There is no separate build step; `uv build` produces the sdist + wheel (CI does this on merge).
|
||||||
|
|
||||||
|
## Project layout
|
||||||
|
|
||||||
|
- `src/familiar/` — the package. One module per tool group (see **[Architecture](Architecture)**), plus the shared `esi`, `zkill`, `sde`, `auth`, `charutil`, `config`, `writes`, and `server` modules.
|
||||||
|
- `tests/` — one test module per source module, driven by `tests/conftest.py`.
|
||||||
|
- `pyproject.toml` — deps, scripts, and tool config (ruff line length 100, pytest coverage gate).
|
||||||
|
|
||||||
|
## Testing conventions
|
||||||
|
|
||||||
|
Tests use [`tests/conftest.py`](https://git.hiddenden.cafe/Hiddenden/familiar/src/branch/main/tests/conftest.py):
|
||||||
|
|
||||||
|
- The **`mock_esi`** fixture installs a mock ESI client driven by a request handler; **`route(req, {substring: body})`** dispatches by path substring.
|
||||||
|
- Async tools are driven with `asyncio.run(...)` — there is **no async-test plugin**.
|
||||||
|
- Authenticated-tool tests **monkeypatch** `auth.list_characters` / `auth.get_auth` / `auth.resolve_character` rather than touching the real token store.
|
||||||
|
- Write tests set `FAMILIAR_DATA_DIR` to a tmp dir and toggle `FAMILIAR_ENABLE_WRITES`.
|
||||||
|
- **`make_jwt(claims)`** builds fake access tokens.
|
||||||
|
- The ESI/zKill clients and the SDE connection are swapped for mocks via `esi.set_client` / `zkill.set_client` / `sde.set_connection`.
|
||||||
|
|
||||||
|
Coverage is gated at **80%** (`--cov-fail-under=80` in `pyproject.toml` addopts), so the suite fails if coverage drops below that.
|
||||||
|
|
||||||
|
## Git workflow
|
||||||
|
|
||||||
|
- Work happens on **`dev`**. Feature branches → PR → **fast-forward** merge into `dev` → delete the branch.
|
||||||
|
- Cut a release by bumping the version in `pyproject.toml` / `src/familiar/__init__.py` and opening a **`dev → main`** fast-forward PR (which publishes the clean version).
|
||||||
|
- **`main` and `dev` are protected**: no direct pushes, **signed commits required** (the user's git auto-signs), merge via PR only.
|
||||||
|
|
||||||
|
## CI / publish pipeline
|
||||||
|
|
||||||
|
[`.gitea/workflows/ci.yml`](https://git.hiddenden.cafe/Hiddenden/familiar/src/branch/main/.gitea/workflows/ci.yml) runs on every PR and push to `main`/`dev`:
|
||||||
|
|
||||||
|
1. **lint** — `ruff check .` and `ruff format --check .`.
|
||||||
|
2. **test** — `uv run pytest` (the 80% coverage gate).
|
||||||
|
3. **publish** — only on a real **push/merge** into `main` or `dev` (never on PRs), and only after lint + test pass. It builds the sdist + wheel with `uv build` and uploads to the **Gitea PyPI registry** with twine.
|
||||||
|
|
||||||
|
Version rules in the publish job:
|
||||||
|
|
||||||
|
- **`main`** publishes the clean version from `pyproject.toml`.
|
||||||
|
- **`dev`** publishes a unique pre-release `X.Y.Z.devN` (where `N` is the run number) so merges never collide.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- Auth uses the **`REGISTRY_TOKEN`** secret (a Gitea token with package read/write scope) as the twine password.
|
||||||
|
- Gitea's PyPI registry does **not** support twine's `--skip-existing`; the workflow runs a plain upload and tolerates an "already exists"/409 conflict in the shell (which only bites a `main` re-run of an already-published release).
|
||||||
|
|
||||||
|
## A note on attribution
|
||||||
|
|
||||||
|
Commits, merges, and PRs in this repo are authored plainly by the maintainer — no AI co-author trailers or "generated with" footers. Keep messages clean.
|
||||||
Reference in new issue
Block a user