From 0e493ad8d17cdabbe7da3df1fb4664b08f216a8d Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Tue, 24 Mar 2026 15:31:42 -0400 Subject: [PATCH] Add CLAUDE.md and /release command Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/commands/release.md | 42 +++++++++++++++++++++++++++++++++++ CLAUDE.md | 44 +++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 .claude/commands/release.md create mode 100644 CLAUDE.md diff --git a/.claude/commands/release.md b/.claude/commands/release.md new file mode 100644 index 0000000..def4ccf --- /dev/null +++ b/.claude/commands/release.md @@ -0,0 +1,42 @@ +Release a new version of responder to PyPI and GitHub. + +Usage: /release (e.g. /release 3.6.0) + +If no version is provided, ask the user what version to release. + +## Steps + +1. **Verify clean state**: Run `git status` and ensure the working tree is clean. If not, stop and ask the user. + +2. **Run tests**: Run `uv run pytest -x --no-header -q`. If any fail, stop and report. + +3. **Bump version**: Update `responder/__version__.py` to the new version. + +4. **Update changelog**: + - Run `git log --oneline $(git describe --tags --abbrev=0)..HEAD` to get commits since last release. + - Add a new section in `CHANGELOG.md` under `## [Unreleased]` with the date, categorized into Added/Changed/Fixed/Removed. + - Update the compare links at the bottom of the file. + +5. **Lock deps**: Run `uv lock`. + +6. **Commit**: Stage `responder/__version__.py`, `CHANGELOG.md`, and `uv.lock`. Commit with message `Bump version to X.Y.Z and update changelog`. + +7. **Push and tag**: + ``` + git push + git tag vX.Y.Z + git push origin vX.Y.Z + ``` + +8. **GitHub release**: Create a release with `gh release create` including highlights and a link to the full changelog. + +9. **Build and publish**: + ``` + uv build + uvx twine upload dist/responder-X.Y.Z* + ``` + Note: This requires a PyPI token. If twine fails due to auth, tell the user to set `TWINE_USERNAME=__token__` and `TWINE_PASSWORD` and re-run, or run `! uvx twine upload dist/responder-X.Y.Z*` interactively. + +10. **Update GitHub release**: Edit the release to add a link to the PyPI page: `https://pypi.org/project/responder/X.Y.Z/` + +11. **Report**: Print a summary with links to the GitHub release and PyPI page. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..27e9723 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,44 @@ +# Responder + +A familiar HTTP Service Framework for Python, by Kenneth Reitz. + +## Commands + +- **Tests**: `uv run pytest` (runs full suite with coverage) +- **Single test**: `uv run pytest tests/test_responder.py::test_name -xvs` +- **Lint**: `uv run ruff check .` +- **Type check**: `uv run mypy` +- **Build docs**: `cd docs && uv run make html` +- **Build package**: `uv build` +- **Lock deps**: `uv lock` + +## Architecture + +- `responder/api.py` — Main `API` class, the entry point for all apps +- `responder/routes.py` — `Router`, `Route`, `WebSocketRoute` dispatch +- `responder/models.py` — `Request` and `Response` wrappers around Starlette +- `responder/ext/` — Extensions: CLI, GraphQL, OpenAPI, rate limiting +- `responder/background.py` — Background task queue +- `responder/formats.py` — Content negotiation (JSON, YAML, msgpack) +- `responder/__version__.py` — Single source of truth for version string + +## Conventions + +- Python 3.10+ only. Use `from __future__ import annotations` where present. +- Use `inspect.iscoroutinefunction` (not `asyncio.iscoroutinefunction`). +- Tests use `api.requests` (Starlette TestClient) with `allowed_hosts=[";"]` or `["localhost"]`. +- Werkzeug 3.1.7+ rejects invalid Host headers — use `localhost` when mounting WSGI apps in tests. +- Version is in `responder/__version__.py`, bump it there. +- Changelog follows [Keep a Changelog](https://keepachangelog.com/) format in `CHANGELOG.md`. +- Compare links at the bottom of CHANGELOG.md must be updated when adding a release. +- All deps managed via `uv`. Lock file (`uv.lock`) is committed. + +## Release Process + +1. Bump version in `responder/__version__.py` +2. Add changelog entry in `CHANGELOG.md` (update compare links too) +3. `uv lock` to refresh the lock file +4. Commit: `Bump version to X.Y.Z and update changelog` +5. `git tag vX.Y.Z && git push && git push origin vX.Y.Z` +6. `gh release create vX.Y.Z --title "vX.Y.Z" --notes "..."` +7. `uv build && uvx twine upload dist/responder-X.Y.Z*`