python-docs-mcp-server 0.1.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- python_docs_mcp_server-0.1.2/.cursorignore +1 -0
- python_docs_mcp_server-0.1.2/.github/INTEGRATION-TEST.md +149 -0
- python_docs_mcp_server-0.1.2/.github/RELEASE.md +198 -0
- python_docs_mcp_server-0.1.2/.github/workflows/ci.yml +56 -0
- python_docs_mcp_server-0.1.2/.github/workflows/e2e.yml +57 -0
- python_docs_mcp_server-0.1.2/.github/workflows/release.yml +119 -0
- python_docs_mcp_server-0.1.2/.gitignore +205 -0
- python_docs_mcp_server-0.1.2/.planning/FULL-CODEBASE-REVIEW.md +318 -0
- python_docs_mcp_server-0.1.2/.planning/PROJECT.md +121 -0
- python_docs_mcp_server-0.1.2/.planning/REQUIREMENTS.md +342 -0
- python_docs_mcp_server-0.1.2/.planning/ROADMAP.md +144 -0
- python_docs_mcp_server-0.1.2/.planning/STATE.md +105 -0
- python_docs_mcp_server-0.1.2/.planning/config.json +51 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-01-PLAN.md +217 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-01-SUMMARY.md +18 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-02-PLAN.md +255 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-02-SUMMARY.md +14 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-03-PLAN.md +435 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-03-SUMMARY.md +17 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-04-PLAN.md +434 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-04-SUMMARY.md +20 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-05-PLAN.md +419 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-05-SUMMARY.md +15 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-CONTEXT.md +87 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-DISCUSSION-LOG.md +108 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-RESEARCH.md +217 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-REVIEW-FIX.md +85 -0
- python_docs_mcp_server-0.1.2/.planning/phases/01-foundation-stdio-hygiene-symbol-slice/01-REVIEW.md +176 -0
- python_docs_mcp_server-0.1.2/.planning/phases/02-schema-storage/02-A-PLAN.md +216 -0
- python_docs_mcp_server-0.1.2/.planning/phases/02-schema-storage/02-A-SUMMARY.md +32 -0
- python_docs_mcp_server-0.1.2/.planning/phases/02-schema-storage/02-B-PLAN.md +99 -0
- python_docs_mcp_server-0.1.2/.planning/phases/02-schema-storage/02-B-SUMMARY.md +32 -0
- python_docs_mcp_server-0.1.2/.planning/phases/02-schema-storage/02-C-PLAN.md +410 -0
- python_docs_mcp_server-0.1.2/.planning/phases/02-schema-storage/02-C-SUMMARY.md +31 -0
- python_docs_mcp_server-0.1.2/.planning/phases/02-schema-storage/02-CONTEXT.md +60 -0
- python_docs_mcp_server-0.1.2/.planning/phases/02-schema-storage/02-RESEARCH.md +212 -0
- python_docs_mcp_server-0.1.2/.planning/phases/02-schema-storage/02-REVIEW-FIX.md +50 -0
- python_docs_mcp_server-0.1.2/.planning/phases/02-schema-storage/02-REVIEW.md +101 -0
- python_docs_mcp_server-0.1.2/.planning/phases/02-schema-storage/02-VERIFICATION.md +67 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-A-PLAN.md +181 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-A-SUMMARY.md +29 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-B-PLAN.md +205 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-B-SUMMARY.md +26 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-C-PLAN.md +175 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-C-SUMMARY.md +24 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-CONTEXT.md +76 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-D-PLAN.md +201 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-D-SUMMARY.md +27 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-RESEARCH.md +299 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-REVIEW-FIX.md +56 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-REVIEW.md +148 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-VALIDATION.md +83 -0
- python_docs_mcp_server-0.1.2/.planning/phases/03-retrieval-layer/03-VERIFICATION.md +64 -0
- python_docs_mcp_server-0.1.2/.planning/phases/04-sphinx-json-ingestion-atomic-swap-publishing/04-A-PLAN.md +182 -0
- python_docs_mcp_server-0.1.2/.planning/phases/04-sphinx-json-ingestion-atomic-swap-publishing/04-B-PLAN.md +153 -0
- python_docs_mcp_server-0.1.2/.planning/phases/04-sphinx-json-ingestion-atomic-swap-publishing/04-C-PLAN.md +225 -0
- python_docs_mcp_server-0.1.2/.planning/phases/04-sphinx-json-ingestion-atomic-swap-publishing/04-CONTEXT.md +78 -0
- python_docs_mcp_server-0.1.2/.planning/phases/04-sphinx-json-ingestion-atomic-swap-publishing/04-D-PLAN.md +555 -0
- python_docs_mcp_server-0.1.2/.planning/phases/04-sphinx-json-ingestion-atomic-swap-publishing/04-DISCUSSION-LOG.md +46 -0
- python_docs_mcp_server-0.1.2/.planning/phases/04-sphinx-json-ingestion-atomic-swap-publishing/04-PATTERNS.md +66 -0
- python_docs_mcp_server-0.1.2/.planning/phases/04-sphinx-json-ingestion-atomic-swap-publishing/04-RESEARCH.md +189 -0
- python_docs_mcp_server-0.1.2/.planning/phases/04-sphinx-json-ingestion-atomic-swap-publishing/04-REVIEW-FIX.md +62 -0
- python_docs_mcp_server-0.1.2/.planning/phases/04-sphinx-json-ingestion-atomic-swap-publishing/04-REVIEW.md +139 -0
- python_docs_mcp_server-0.1.2/.planning/phases/04-sphinx-json-ingestion-atomic-swap-publishing/04-VALIDATION.md +83 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-A-PLAN.md +389 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-B-PLAN.md +248 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-C-PLAN.md +279 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-CONTEXT.md +64 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-D-PLAN.md +262 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-E-PLAN.md +114 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-F-PLAN.md +403 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-PATTERNS.md +103 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-RESEARCH.md +140 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-REVIEW-FIX.md +80 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-REVIEW.md +175 -0
- python_docs_mcp_server-0.1.2/.planning/phases/05-services-tool-polish-caching/05-VALIDATION.md +79 -0
- python_docs_mcp_server-0.1.2/.planning/phases/06-multi-version-packaging-correctness/06-CONTEXT.md +60 -0
- python_docs_mcp_server-0.1.2/.planning/phases/06-multi-version-packaging-correctness/06-REVIEW-FIX.md +59 -0
- python_docs_mcp_server-0.1.2/.planning/phases/06-multi-version-packaging-correctness/06-REVIEW.md +104 -0
- python_docs_mcp_server-0.1.2/.planning/phases/06-multi-version-packaging-correctness/06-SUMMARY.md +58 -0
- python_docs_mcp_server-0.1.2/.planning/phases/06-multi-version-packaging-correctness/06a-PLAN.md +411 -0
- python_docs_mcp_server-0.1.2/.planning/phases/06-multi-version-packaging-correctness/06b-PLAN.md +212 -0
- python_docs_mcp_server-0.1.2/.planning/phases/06-multi-version-packaging-correctness/06c-PLAN.md +246 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07-CONTEXT.md +63 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07-REVIEW-FIX.md +49 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07-REVIEW.md +116 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07-VERIFICATION.md +65 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07a-PLAN.md +170 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07a-SUMMARY.md +33 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07b-PLAN.md +179 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07b-SUMMARY.md +39 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07c-PLAN.md +217 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07c-SUMMARY.md +29 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07d-PLAN.md +337 -0
- python_docs_mcp_server-0.1.2/.planning/phases/07-stability-tests-release-polish/07d-SUMMARY.md +38 -0
- python_docs_mcp_server-0.1.2/.planning/phases/08-ship/08-CONTEXT.md +68 -0
- python_docs_mcp_server-0.1.2/.planning/phases/08-ship/08-REVIEW-FIX.md +66 -0
- python_docs_mcp_server-0.1.2/.planning/phases/08-ship/08-REVIEW.md +134 -0
- python_docs_mcp_server-0.1.2/.planning/phases/08-ship/08-VERIFICATION.md +49 -0
- python_docs_mcp_server-0.1.2/.planning/phases/08-ship/08a-PLAN.md +180 -0
- python_docs_mcp_server-0.1.2/.planning/phases/08-ship/08a-SUMMARY.md +33 -0
- python_docs_mcp_server-0.1.2/.planning/phases/08-ship/08b-PLAN.md +205 -0
- python_docs_mcp_server-0.1.2/.planning/phases/08-ship/08b-SUMMARY.md +31 -0
- python_docs_mcp_server-0.1.2/.planning/phases/08-ship/08c-PLAN.md +161 -0
- python_docs_mcp_server-0.1.2/.planning/phases/08-ship/08c-SUMMARY.md +32 -0
- python_docs_mcp_server-0.1.2/.planning/research/ARCHITECTURE.md +946 -0
- python_docs_mcp_server-0.1.2/.planning/research/FEATURES.md +435 -0
- python_docs_mcp_server-0.1.2/.planning/research/PITFALLS.md +843 -0
- python_docs_mcp_server-0.1.2/.planning/research/STACK.md +344 -0
- python_docs_mcp_server-0.1.2/.planning/research/SUMMARY.md +277 -0
- python_docs_mcp_server-0.1.2/.planning/v0.1.0-MILESTONE-AUDIT.md +120 -0
- python_docs_mcp_server-0.1.2/AGENTS.md +97 -0
- python_docs_mcp_server-0.1.2/CLAUDE.md +16 -0
- python_docs_mcp_server-0.1.2/CONTRIBUTING.md +82 -0
- python_docs_mcp_server-0.1.2/LICENSE +21 -0
- python_docs_mcp_server-0.1.2/PKG-INFO +528 -0
- python_docs_mcp_server-0.1.2/PR9_MCP_TEST_PLAN.md +393 -0
- python_docs_mcp_server-0.1.2/PR9_SMOKE_FAILURE_FIX_PLAN.md +445 -0
- python_docs_mcp_server-0.1.2/README.md +500 -0
- python_docs_mcp_server-0.1.2/docs/launch/reddit-posts.md +110 -0
- python_docs_mcp_server-0.1.2/docs/launch/show-hn.md +89 -0
- python_docs_mcp_server-0.1.2/docs/superpowers/plans/2026-05-11-pr22-coherence-fixes.md +864 -0
- python_docs_mcp_server-0.1.2/pyproject.toml +67 -0
- python_docs_mcp_server-0.1.2/server.json +24 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/__init__.py +17 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/__main__.py +574 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/app_context.py +33 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/data/synonyms.yaml +194 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/detection.py +82 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/diagnostics.py +74 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/errors.py +33 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/ingestion/__init__.py +1 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/ingestion/cpython_versions.py +32 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/ingestion/inventory.py +178 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/ingestion/publish.py +504 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/ingestion/sphinx_json.py +617 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/models.py +216 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/py.typed +0 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/retrieval/__init__.py +31 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/retrieval/budget.py +63 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/retrieval/query.py +183 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/retrieval/ranker.py +369 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/server.py +329 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/services/__init__.py +7 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/services/cache.py +111 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/services/content.py +155 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/services/observability.py +130 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/services/package_docs.py +161 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/services/persistent_cache.py +147 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/services/search.py +111 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/services/version.py +47 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/services/version_resolution.py +79 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/storage/__init__.py +1 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/storage/db.py +146 -0
- python_docs_mcp_server-0.1.2/src/mcp_server_python_docs/storage/schema.sql +136 -0
- python_docs_mcp_server-0.1.2/tests/__init__.py +0 -0
- python_docs_mcp_server-0.1.2/tests/conftest.py +227 -0
- python_docs_mcp_server-0.1.2/tests/fixtures/retrieval_regression_cases.json +129 -0
- python_docs_mcp_server-0.1.2/tests/fixtures/sample_broken.fjson +1 -0
- python_docs_mcp_server-0.1.2/tests/fixtures/sample_library.fjson +12 -0
- python_docs_mcp_server-0.1.2/tests/fixtures/schema-get_docs-input.json +57 -0
- python_docs_mcp_server-0.1.2/tests/fixtures/schema-get_docs-output.json +71 -0
- python_docs_mcp_server-0.1.2/tests/fixtures/schema-list_versions-output.json +59 -0
- python_docs_mcp_server-0.1.2/tests/fixtures/schema-search_docs-input.json +50 -0
- python_docs_mcp_server-0.1.2/tests/fixtures/schema-search_docs-output.json +94 -0
- python_docs_mcp_server-0.1.2/tests/test_ci_workflows.py +30 -0
- python_docs_mcp_server-0.1.2/tests/test_doctor.py +178 -0
- python_docs_mcp_server-0.1.2/tests/test_ingestion.py +505 -0
- python_docs_mcp_server-0.1.2/tests/test_mcp_get_docs_cache_smoke.py +208 -0
- python_docs_mcp_server-0.1.2/tests/test_multi_version.py +322 -0
- python_docs_mcp_server-0.1.2/tests/test_package_docs.py +165 -0
- python_docs_mcp_server-0.1.2/tests/test_packaging.py +241 -0
- python_docs_mcp_server-0.1.2/tests/test_persistent_docs_cache.py +263 -0
- python_docs_mcp_server-0.1.2/tests/test_phase1_integration.py +120 -0
- python_docs_mcp_server-0.1.2/tests/test_publish.py +579 -0
- python_docs_mcp_server-0.1.2/tests/test_retrieval.py +769 -0
- python_docs_mcp_server-0.1.2/tests/test_retrieval_regression.py +214 -0
- python_docs_mcp_server-0.1.2/tests/test_schema.py +399 -0
- python_docs_mcp_server-0.1.2/tests/test_schema_snapshot.py +53 -0
- python_docs_mcp_server-0.1.2/tests/test_services.py +553 -0
- python_docs_mcp_server-0.1.2/tests/test_stability.py +159 -0
- python_docs_mcp_server-0.1.2/tests/test_stdio_hygiene.py +101 -0
- python_docs_mcp_server-0.1.2/tests/test_stdio_smoke.py +306 -0
- python_docs_mcp_server-0.1.2/tests/test_synonyms.py +78 -0
- python_docs_mcp_server-0.1.2/uv.lock +882 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.planning/
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Manual MCP QA Runbook
|
|
2
|
+
|
|
3
|
+
Use this document for manual MCP validation during development and before a
|
|
4
|
+
release. The goal is to verify real client behavior after the automated test
|
|
5
|
+
suite passes.
|
|
6
|
+
|
|
7
|
+
Release-specific sign-off still lives in [`.github/RELEASE.md`](RELEASE.md).
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
- CI or local checks are green:
|
|
12
|
+
- `uv run ruff check src/ tests/`
|
|
13
|
+
- `uv run pyright src/`
|
|
14
|
+
- `uv run pytest --tb=short -q`
|
|
15
|
+
- Local index build completed:
|
|
16
|
+
- `uv run python-docs-mcp-server build-index --versions 3.10,3.11,3.12,3.13,3.14`
|
|
17
|
+
- Doctor passes:
|
|
18
|
+
- `uv run python-docs-mcp-server doctor`
|
|
19
|
+
- Slow E2E workflow passes when preparing a release:
|
|
20
|
+
- GitHub Actions: `Slow E2E`
|
|
21
|
+
- Expected: Python 3.13 and 3.14 jobs both complete `build-index`, `doctor`,
|
|
22
|
+
and `validate-corpus` from an installed wheel
|
|
23
|
+
- If `uv` is not on `PATH`, use `python -m uv ...` instead
|
|
24
|
+
|
|
25
|
+
## Test 1: MCP Inspector quick loop
|
|
26
|
+
|
|
27
|
+
Use Inspector for fast local iteration before checking real clients.
|
|
28
|
+
|
|
29
|
+
### Start Inspector
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx @modelcontextprotocol/inspector uv --directory . run python-docs-mcp-server
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Verify
|
|
36
|
+
|
|
37
|
+
- [ ] Connect successfully over stdio
|
|
38
|
+
- [ ] Confirm the tool list includes:
|
|
39
|
+
- `search_docs`
|
|
40
|
+
- `get_docs`
|
|
41
|
+
- `list_versions`
|
|
42
|
+
- `detect_python_version`
|
|
43
|
+
- [ ] Call `search_docs` with query `asyncio.TaskGroup`, `kind="symbol"`, `version="3.13"`
|
|
44
|
+
- Expected: exact symbol hit with `library/asyncio-task.html`
|
|
45
|
+
- [ ] Call `get_docs` for the returned slug and anchor
|
|
46
|
+
- Expected: section-level documentation, not an unrelated page dump
|
|
47
|
+
- [ ] Call `list_versions`
|
|
48
|
+
- Expected: indexed versions appear with the configured default version
|
|
49
|
+
- [ ] Call `detect_python_version`
|
|
50
|
+
- Expected: returns local interpreter information without breaking the session
|
|
51
|
+
- [ ] Observe no protocol corruption or unexplained disconnects in Inspector
|
|
52
|
+
|
|
53
|
+
## Test 2: Claude Desktop integration
|
|
54
|
+
|
|
55
|
+
### Setup
|
|
56
|
+
|
|
57
|
+
1. Open Claude Desktop settings
|
|
58
|
+
2. Add this server config:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"mcpServers": {
|
|
63
|
+
"python-docs": {
|
|
64
|
+
"command": "uvx",
|
|
65
|
+
"args": ["python-docs-mcp-server"]
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
3. Fully restart Claude Desktop
|
|
72
|
+
4. Verify the MCP server appears in the chat UI
|
|
73
|
+
|
|
74
|
+
### Checks
|
|
75
|
+
|
|
76
|
+
- [ ] Ask: `what is asyncio.TaskGroup`
|
|
77
|
+
- Expected: response uses stdlib documentation, not only model prior knowledge
|
|
78
|
+
- [ ] Ask: `how do I use pathlib.Path.glob`
|
|
79
|
+
- Expected: response cites the right docs section
|
|
80
|
+
- [ ] Ask: `search for json parsing in Python`
|
|
81
|
+
- Expected: response surfaces `json` docs results
|
|
82
|
+
- [ ] Check the Claude developer console
|
|
83
|
+
- Expected: no protocol errors or repeated reconnect loops
|
|
84
|
+
|
|
85
|
+
## Test 3: Cursor integration
|
|
86
|
+
|
|
87
|
+
### Setup
|
|
88
|
+
|
|
89
|
+
1. Open Cursor MCP settings
|
|
90
|
+
2. Add a server:
|
|
91
|
+
- Name: `python-docs`
|
|
92
|
+
- Command: `uvx`
|
|
93
|
+
- Args: `python-docs-mcp-server`
|
|
94
|
+
3. Confirm the server shows as connected
|
|
95
|
+
|
|
96
|
+
### Checks
|
|
97
|
+
|
|
98
|
+
- [ ] Ask: `what is asyncio.TaskGroup`
|
|
99
|
+
- Expected: MCP tool usage is visible and the answer references the right docs
|
|
100
|
+
- [ ] Ask: `show me the docs for collections.OrderedDict`
|
|
101
|
+
- Expected: response includes the relevant documentation section
|
|
102
|
+
- [ ] Ask a second or third follow-up query
|
|
103
|
+
- Expected: the server stays connected across multiple calls
|
|
104
|
+
|
|
105
|
+
## Test 4: Fresh install verification
|
|
106
|
+
|
|
107
|
+
Use this when validating the published package or a clean local environment.
|
|
108
|
+
|
|
109
|
+
On Windows, close the MCP client before rebuilding if the live index file is
|
|
110
|
+
locked.
|
|
111
|
+
|
|
112
|
+
### Checks
|
|
113
|
+
|
|
114
|
+
- [ ] `uvx python-docs-mcp-server --version`
|
|
115
|
+
- Expected: prints the current package version
|
|
116
|
+
- [ ] `uvx python-docs-mcp-server build-index --versions 3.10,3.11,3.12,3.13,3.14`
|
|
117
|
+
- Expected: index build completes successfully
|
|
118
|
+
- [ ] `uvx python-docs-mcp-server doctor`
|
|
119
|
+
- Expected: all required checks pass
|
|
120
|
+
- [ ] Follow the README from scratch
|
|
121
|
+
- Expected: a new user can get to a working client configuration without using `.planning/`
|
|
122
|
+
|
|
123
|
+
## Test 5: Slow E2E workflow
|
|
124
|
+
|
|
125
|
+
Run this before a release and after changes to ingestion, publishing, packaging,
|
|
126
|
+
or supported Python versions.
|
|
127
|
+
|
|
128
|
+
### Checks
|
|
129
|
+
|
|
130
|
+
- [ ] Start the `Slow E2E` workflow from GitHub Actions
|
|
131
|
+
- Expected: both Python 3.13 and Python 3.14 jobs start
|
|
132
|
+
- [ ] Confirm each job installs the built wheel into a clean virtual environment
|
|
133
|
+
- Expected: the command path is the installed `python-docs-mcp-server`, not editable source
|
|
134
|
+
- [ ] Confirm `build-index --versions 3.10,3.11,3.12,3.13,3.14` passes
|
|
135
|
+
- Expected: all five versions produce content, not symbol-only fallback
|
|
136
|
+
- [ ] Confirm `doctor` and `validate-corpus` pass
|
|
137
|
+
- Expected: corpus smoke checks include requested versions and the default version
|
|
138
|
+
- [ ] Inspect uploaded logs if a job fails
|
|
139
|
+
- Expected: Sphinx/build logs are available as workflow artifacts
|
|
140
|
+
|
|
141
|
+
## Evidence log
|
|
142
|
+
|
|
143
|
+
| Test | Pass/Fail | Tester | Date | Notes |
|
|
144
|
+
|------|-----------|--------|------|-------|
|
|
145
|
+
| Inspector quick loop | | | | |
|
|
146
|
+
| Claude Desktop | | | | |
|
|
147
|
+
| Cursor | | | | |
|
|
148
|
+
| Fresh install | | | | |
|
|
149
|
+
| Slow E2E workflow | | | | |
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Release Process
|
|
2
|
+
|
|
3
|
+
## One-Time Setup: PyPI Trusted Publishing
|
|
4
|
+
|
|
5
|
+
Before the first release, configure PyPI Trusted Publishing:
|
|
6
|
+
|
|
7
|
+
1. Go to https://pypi.org/manage/account/publishing/
|
|
8
|
+
2. Add a new pending publisher:
|
|
9
|
+
- **PyPI project name**: `python-docs-mcp-server`
|
|
10
|
+
- **Owner**: your GitHub username or org
|
|
11
|
+
- **Repository**: `python-docs-mcp-server`
|
|
12
|
+
- **Workflow name**: `release.yml`
|
|
13
|
+
- **Environment name**: `pypi`
|
|
14
|
+
3. In the GitHub repo, go to Settings > Environments
|
|
15
|
+
4. Create an environment named `pypi`
|
|
16
|
+
5. (Optional) Add environment protection rules:
|
|
17
|
+
- Required reviewers (recommended for first release)
|
|
18
|
+
- Deployment branches: only `main` tags
|
|
19
|
+
|
|
20
|
+
## Notes
|
|
21
|
+
|
|
22
|
+
**Runtime coverage:** The release workflow builds and tests against Python 3.13 only.
|
|
23
|
+
Python 3.12 is covered by the CI workflow (`ci.yml`) which runs a 2x2 matrix
|
|
24
|
+
(3.12/3.13 x ubuntu/macos) on every push to `main`. Since tags are created
|
|
25
|
+
from commits that have already passed CI, 3.12 compatibility is verified before
|
|
26
|
+
the release workflow runs. This is an accepted trade-off to keep the release
|
|
27
|
+
artifact pipeline simple (single Python version produces the wheel).
|
|
28
|
+
|
|
29
|
+
**Documentation coverage:** The full docs index target is Python documentation
|
|
30
|
+
versions 3.10 through 3.14.
|
|
31
|
+
|
|
32
|
+
## Creating a Release
|
|
33
|
+
|
|
34
|
+
1. Ensure all tests pass on main:
|
|
35
|
+
```bash
|
|
36
|
+
uv run pytest --tb=short -q
|
|
37
|
+
uv run ruff check src/ tests/
|
|
38
|
+
uv run pyright src/
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
2. Verify the version in `pyproject.toml` is correct:
|
|
42
|
+
```bash
|
|
43
|
+
grep '^version' pyproject.toml
|
|
44
|
+
# Should show: version = "0.1.2"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
3. Create and push the tag:
|
|
48
|
+
```bash
|
|
49
|
+
git tag -a v0.1.2 -m "Release v0.1.2"
|
|
50
|
+
git push origin v0.1.2
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
4. Monitor the release workflow at:
|
|
54
|
+
https://github.com/<owner>/python-docs-mcp-server/actions/workflows/release.yml
|
|
55
|
+
|
|
56
|
+
5. Verify the package on PyPI:
|
|
57
|
+
https://pypi.org/project/python-docs-mcp-server/0.1.2/
|
|
58
|
+
|
|
59
|
+
## Post-Release Verification
|
|
60
|
+
|
|
61
|
+
After the package is published:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# In a fresh environment:
|
|
65
|
+
uvx python-docs-mcp-server --version
|
|
66
|
+
# Should print: 0.1.1
|
|
67
|
+
|
|
68
|
+
# Or via pipx:
|
|
69
|
+
pipx run python-docs-mcp-server --version
|
|
70
|
+
# Should print: 0.1.1
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## v0.1.1 Release Checklist
|
|
74
|
+
|
|
75
|
+
Complete these steps in order. Each step has a checkbox -- do not skip ahead.
|
|
76
|
+
|
|
77
|
+
### Pre-Release Verification
|
|
78
|
+
|
|
79
|
+
- [ ] All CI tests green on main: check https://github.com/<owner>/python-docs-mcp-server/actions/workflows/ci.yml
|
|
80
|
+
- [ ] Local test suite passes:
|
|
81
|
+
```bash
|
|
82
|
+
uv run pytest --tb=short -q
|
|
83
|
+
```
|
|
84
|
+
- [ ] Version in `pyproject.toml` is `0.1.1`:
|
|
85
|
+
```bash
|
|
86
|
+
grep '^version' pyproject.toml
|
|
87
|
+
```
|
|
88
|
+
- [ ] Integration tests from `.github/INTEGRATION-TEST.md` are complete and signed off
|
|
89
|
+
- [ ] Doctor subcommand passes:
|
|
90
|
+
```bash
|
|
91
|
+
uv run python-docs-mcp-server doctor
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### PyPI Trusted Publishing Setup (one-time)
|
|
95
|
+
|
|
96
|
+
- [ ] PyPI pending publisher configured at https://pypi.org/manage/account/publishing/:
|
|
97
|
+
- PyPI project name: `python-docs-mcp-server`
|
|
98
|
+
- Owner: `<your-github-username>`
|
|
99
|
+
- Repository: `python-docs-mcp-server`
|
|
100
|
+
- Workflow name: `release.yml`
|
|
101
|
+
- Environment name: `pypi`
|
|
102
|
+
- [ ] GitHub environment `pypi` created in repo Settings > Environments
|
|
103
|
+
|
|
104
|
+
### Tag and Release
|
|
105
|
+
|
|
106
|
+
- [ ] Create the annotated tag:
|
|
107
|
+
```bash
|
|
108
|
+
git tag -a v0.1.1 -m "Release v0.1.1
|
|
109
|
+
|
|
110
|
+
First public release of python-docs-mcp-server.
|
|
111
|
+
|
|
112
|
+
A read-only, version-aware MCP retrieval server over Python
|
|
113
|
+
standard library documentation (3.10 through 3.14).
|
|
114
|
+
|
|
115
|
+
Installable via: uvx python-docs-mcp-server"
|
|
116
|
+
```
|
|
117
|
+
- [ ] Push the tag to trigger the release workflow:
|
|
118
|
+
```bash
|
|
119
|
+
git push origin v0.1.1
|
|
120
|
+
```
|
|
121
|
+
- [ ] Monitor the workflow run: https://github.com/<owner>/python-docs-mcp-server/actions/workflows/release.yml
|
|
122
|
+
- [ ] Verify all three jobs pass: `build` -> `publish` -> `github-release`
|
|
123
|
+
|
|
124
|
+
### Post-Release Verification (SHIP-06)
|
|
125
|
+
|
|
126
|
+
- [ ] Package visible on PyPI: https://pypi.org/project/python-docs-mcp-server/0.1.2/
|
|
127
|
+
- [ ] Attestation visible on PyPI package page (look for "Provenance" badge)
|
|
128
|
+
- [ ] Fresh install test:
|
|
129
|
+
```bash
|
|
130
|
+
# Clear any cached version
|
|
131
|
+
uv cache clean python-docs-mcp-server 2>/dev/null || true
|
|
132
|
+
|
|
133
|
+
# Install and verify version
|
|
134
|
+
uvx python-docs-mcp-server --version
|
|
135
|
+
# Expected output: 0.1.1
|
|
136
|
+
```
|
|
137
|
+
- [ ] Full README flow test (from a clean environment):
|
|
138
|
+
```bash
|
|
139
|
+
# Step 1: Install
|
|
140
|
+
uvx python-docs-mcp-server --version
|
|
141
|
+
# Should print 0.1.1
|
|
142
|
+
|
|
143
|
+
# Step 2: Build index
|
|
144
|
+
uvx python-docs-mcp-server build-index --versions 3.10,3.11,3.12,3.13,3.14
|
|
145
|
+
# Should complete successfully
|
|
146
|
+
|
|
147
|
+
# Step 3: Doctor check
|
|
148
|
+
uvx python-docs-mcp-server doctor
|
|
149
|
+
# All checks should PASS
|
|
150
|
+
```
|
|
151
|
+
- [ ] Slow E2E workflow passes:
|
|
152
|
+
- Run GitHub Actions workflow `Slow E2E`
|
|
153
|
+
- Confirm Python 3.13 and Python 3.14 jobs both pass
|
|
154
|
+
- Confirm each job installs the built wheel, runs
|
|
155
|
+
`build-index --versions 3.10,3.11,3.12,3.13,3.14`, `doctor`, and
|
|
156
|
+
`validate-corpus`
|
|
157
|
+
|
|
158
|
+
### Post-PyPI Launch Pack Cleanup
|
|
159
|
+
|
|
160
|
+
- [ ] Remove every temporary PyPI pre-release block from `README.md`:
|
|
161
|
+
- Mechanical pass: delete every region from `<!-- PRE-PYPI:` to `<!-- /PRE-PYPI -->` (inclusive). Each block now encloses its surrounding heading + lead-in sentence + code, so a single pass produces a clean README.
|
|
162
|
+
- Reference command:
|
|
163
|
+
`perl -0777 -i -pe 's/<!-- PRE-PYPI:.*?<!-- \/PRE-PYPI -->\n*//gs' README.md`
|
|
164
|
+
- Make the published package commands (`uvx python-docs-mcp-server ...`) the
|
|
165
|
+
primary install, build-index, MCP client, `doctor`, and `validate-corpus`
|
|
166
|
+
examples
|
|
167
|
+
- [ ] Verify `README.md` has no temporary pre-release install artifacts:
|
|
168
|
+
```bash
|
|
169
|
+
rg -n 'PRE[-]PYPI|Before PyPI publishing|Until the first PyPI|After PyPI publishing|git\\+https://github.com/.*/python-docs-mcp-server' README.md
|
|
170
|
+
```
|
|
171
|
+
The command should return no output.
|
|
172
|
+
- [ ] Review `docs/launch/` so no public launch copy still asks users to install
|
|
173
|
+
from GitHub source after the PyPI package is available. Intentional historical
|
|
174
|
+
pre-release drafts may remain, but they must stay clearly labeled as
|
|
175
|
+
pre-PyPI-only.
|
|
176
|
+
- [ ] Submit `server.json` to https://registry.modelcontextprotocol.io/ via the
|
|
177
|
+
`mcp-publisher` CLI after the PyPI smoke test passes; verify the registry
|
|
178
|
+
listing appears and points at version 0.1.1
|
|
179
|
+
- [ ] Use the post-PyPI draft in `docs/launch/show-hn.md` for the HN submission
|
|
180
|
+
- [ ] Use `docs/launch/reddit-posts.md` for the r/Python and r/LocalLLaMA
|
|
181
|
+
submissions after the PyPI release smoke test passes
|
|
182
|
+
- [ ] Commit and push the README cleanup before public launch posts go out
|
|
183
|
+
|
|
184
|
+
- [ ] Claude Desktop test with published package:
|
|
185
|
+
Configure `mcpServers` with `uvx python-docs-mcp-server` and verify
|
|
186
|
+
"what is asyncio.TaskGroup" returns a correct hit
|
|
187
|
+
|
|
188
|
+
### Release Complete
|
|
189
|
+
|
|
190
|
+
- [ ] GitHub Release exists with attached artifacts
|
|
191
|
+
- [ ] PyPI page shows 0.1.1 with attestation
|
|
192
|
+
- [ ] README install instructions verified end-to-end
|
|
193
|
+
- [ ] README no longer contains temporary pre-PyPI GitHub-source install blocks
|
|
194
|
+
- [ ] Slow E2E workflow passed for the release candidate
|
|
195
|
+
- [ ] Tag v0.1.1 exists in git
|
|
196
|
+
|
|
197
|
+
**Release date**: _______________
|
|
198
|
+
**Released by**: _______________
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
os: [ubuntu-latest, macos-latest]
|
|
15
|
+
python-version: ["3.12", "3.13"]
|
|
16
|
+
|
|
17
|
+
runs-on: ${{ matrix.os }}
|
|
18
|
+
name: Test (Python ${{ matrix.python-version }}, ${{ matrix.os }})
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Install uv
|
|
24
|
+
uses: astral-sh/setup-uv@v4
|
|
25
|
+
|
|
26
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
27
|
+
run: uv python install ${{ matrix.python-version }}
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: uv sync --dev
|
|
31
|
+
|
|
32
|
+
- name: Run linter
|
|
33
|
+
run: uv run ruff check src/ tests/
|
|
34
|
+
|
|
35
|
+
- name: Run type checker
|
|
36
|
+
run: uv run pyright src/
|
|
37
|
+
|
|
38
|
+
- name: Run tests
|
|
39
|
+
run: uv run pytest --tb=short -q
|
|
40
|
+
|
|
41
|
+
- name: Verify wheel contents
|
|
42
|
+
run: |
|
|
43
|
+
uv build
|
|
44
|
+
uv run python -c "
|
|
45
|
+
import zipfile, glob, sys
|
|
46
|
+
wheels = glob.glob('dist/*.whl')
|
|
47
|
+
if not wheels:
|
|
48
|
+
print('No wheel found')
|
|
49
|
+
sys.exit(1)
|
|
50
|
+
with zipfile.ZipFile(wheels[0]) as zf:
|
|
51
|
+
names = zf.namelist()
|
|
52
|
+
if not any('synonyms.yaml' in n for n in names):
|
|
53
|
+
print('synonyms.yaml not found in wheel')
|
|
54
|
+
sys.exit(1)
|
|
55
|
+
print('Wheel contents OK')
|
|
56
|
+
"
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Slow E2E
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
schedule:
|
|
6
|
+
- cron: "17 4 * * 1"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
installed-build-index:
|
|
10
|
+
name: Installed build-index (Python ${{ matrix.python-version }})
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
timeout-minutes: 120
|
|
13
|
+
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ["3.13", "3.14"]
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
|
|
22
|
+
- name: Install uv
|
|
23
|
+
uses: astral-sh/setup-uv@v4
|
|
24
|
+
|
|
25
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
26
|
+
run: uv python install ${{ matrix.python-version }}
|
|
27
|
+
|
|
28
|
+
- name: Build package
|
|
29
|
+
run: uv build
|
|
30
|
+
|
|
31
|
+
- name: Install wheel in clean virtual environment
|
|
32
|
+
run: |
|
|
33
|
+
uv run --python ${{ matrix.python-version }} python -m venv .e2e-venv
|
|
34
|
+
.e2e-venv/bin/python -m pip install --upgrade pip
|
|
35
|
+
.e2e-venv/bin/python -m pip install dist/*.whl
|
|
36
|
+
.e2e-venv/bin/python-docs-mcp-server --version
|
|
37
|
+
|
|
38
|
+
- name: Build and validate full docs index
|
|
39
|
+
env:
|
|
40
|
+
HOME: ${{ runner.temp }}/mcp-python-docs-home
|
|
41
|
+
XDG_CACHE_HOME: ${{ runner.temp }}/mcp-python-docs-cache
|
|
42
|
+
run: |
|
|
43
|
+
set -o pipefail
|
|
44
|
+
.e2e-venv/bin/python-docs-mcp-server build-index --versions 3.10,3.11,3.12,3.13,3.14 \
|
|
45
|
+
2>&1 | tee "${RUNNER_TEMP}/build-index-${{ matrix.python-version }}.log"
|
|
46
|
+
.e2e-venv/bin/python-docs-mcp-server doctor
|
|
47
|
+
.e2e-venv/bin/python-docs-mcp-server validate-corpus
|
|
48
|
+
|
|
49
|
+
- name: Upload E2E logs and cache artifacts
|
|
50
|
+
if: always()
|
|
51
|
+
uses: actions/upload-artifact@v4
|
|
52
|
+
with:
|
|
53
|
+
name: e2e-python-${{ matrix.python-version }}
|
|
54
|
+
path: |
|
|
55
|
+
${{ runner.temp }}/build-index-${{ matrix.python-version }}.log
|
|
56
|
+
${{ runner.temp }}/mcp-python-docs-cache
|
|
57
|
+
retention-days: 7
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: release-${{ github.ref_name }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
name: Build & Test
|
|
16
|
+
timeout-minutes: 15
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Install uv
|
|
22
|
+
uses: astral-sh/setup-uv@v4
|
|
23
|
+
|
|
24
|
+
- name: Set up Python 3.13
|
|
25
|
+
run: uv python install 3.13
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: uv sync --dev
|
|
29
|
+
|
|
30
|
+
- name: Verify tag matches package version
|
|
31
|
+
run: |
|
|
32
|
+
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
|
33
|
+
PKG_VERSION=$(uv run python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
34
|
+
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
|
|
35
|
+
echo "::error::Tag ${GITHUB_REF_NAME} does not match pyproject.toml version ${PKG_VERSION}"
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
echo "Version check passed: ${PKG_VERSION}"
|
|
39
|
+
|
|
40
|
+
- name: Run linter
|
|
41
|
+
run: uv run ruff check src/ tests/
|
|
42
|
+
|
|
43
|
+
- name: Run type checker
|
|
44
|
+
run: uv run pyright src/
|
|
45
|
+
|
|
46
|
+
- name: Run tests
|
|
47
|
+
run: uv run pytest --tb=short -q
|
|
48
|
+
|
|
49
|
+
- name: Build package
|
|
50
|
+
run: uv build
|
|
51
|
+
|
|
52
|
+
- name: Verify wheel contents
|
|
53
|
+
run: |
|
|
54
|
+
uv run python -c "
|
|
55
|
+
import zipfile, glob, sys
|
|
56
|
+
wheels = glob.glob('dist/*.whl')
|
|
57
|
+
if not wheels:
|
|
58
|
+
print('No wheel found')
|
|
59
|
+
sys.exit(1)
|
|
60
|
+
with zipfile.ZipFile(wheels[0]) as zf:
|
|
61
|
+
names = zf.namelist()
|
|
62
|
+
if not any('synonyms.yaml' in n for n in names):
|
|
63
|
+
print('synonyms.yaml not found in wheel')
|
|
64
|
+
sys.exit(1)
|
|
65
|
+
print('Wheel contents OK')
|
|
66
|
+
"
|
|
67
|
+
|
|
68
|
+
- name: Upload dist artifacts
|
|
69
|
+
uses: actions/upload-artifact@v4
|
|
70
|
+
with:
|
|
71
|
+
name: dist
|
|
72
|
+
path: dist/
|
|
73
|
+
|
|
74
|
+
publish:
|
|
75
|
+
needs: build
|
|
76
|
+
runs-on: ubuntu-latest
|
|
77
|
+
name: Publish to PyPI
|
|
78
|
+
timeout-minutes: 10
|
|
79
|
+
environment: pypi
|
|
80
|
+
permissions:
|
|
81
|
+
id-token: write
|
|
82
|
+
contents: read
|
|
83
|
+
attestations: write
|
|
84
|
+
|
|
85
|
+
steps:
|
|
86
|
+
- name: Download dist artifacts
|
|
87
|
+
uses: actions/download-artifact@v4
|
|
88
|
+
with:
|
|
89
|
+
name: dist
|
|
90
|
+
path: dist/
|
|
91
|
+
|
|
92
|
+
- name: Generate artifact attestation
|
|
93
|
+
uses: actions/attest-build-provenance@v2
|
|
94
|
+
with:
|
|
95
|
+
subject-path: 'dist/*'
|
|
96
|
+
|
|
97
|
+
- name: Publish to PyPI
|
|
98
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
99
|
+
|
|
100
|
+
github-release:
|
|
101
|
+
needs: publish
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
name: Create GitHub Release
|
|
104
|
+
timeout-minutes: 10
|
|
105
|
+
permissions:
|
|
106
|
+
contents: write
|
|
107
|
+
|
|
108
|
+
steps:
|
|
109
|
+
- name: Download dist artifacts
|
|
110
|
+
uses: actions/download-artifact@v4
|
|
111
|
+
with:
|
|
112
|
+
name: dist
|
|
113
|
+
path: dist/
|
|
114
|
+
|
|
115
|
+
- name: Create GitHub Release
|
|
116
|
+
uses: softprops/action-gh-release@v2
|
|
117
|
+
with:
|
|
118
|
+
files: dist/*
|
|
119
|
+
generate_release_notes: true
|