Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/scripts/ci_changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ def classify(paths):
for path in paths:
if path.startswith("docs/"):
selected.add("docs")
if path == "docs/docs/quick_start.md":
# tests/python/test_quick_start.py executes this page's Python blocks.
selected.add("python_build")
continue
if path.endswith(".md"):
continue
Expand Down
3 changes: 3 additions & 0 deletions .github/scripts/test_ci_changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ def test_docs_only_skip_builds(self):
{"docs"},
)
self.assertEqual(classify(["README.md", "sample/python/README.md"]), set())
self.assertEqual(
classify(["docs/docs/quick_start.md"]), {"docs", "python_build"}
)
self.assertEqual(
classify([".github/workflows/docs.yml"]), {"docs", "python_quality"}
)
Expand Down
2 changes: 1 addition & 1 deletion .github/scripts/test_ci_workflow_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ def test_documentation_summary_is_available_for_non_doc_prs(self):
self.assertIn("needs.changes.outputs.docs == 'true'", build["if"])
self.assertIn("needs.changes.result != 'success'", build["if"])
self.assertIn("github.event_name == 'push'", build["if"])
self.assertEqual(classify(["docs/docs/quick_start.md"]), {"docs"})
self.assertEqual(classify(["docs/docs/installation.md"]), {"docs"})


if __name__ == "__main__":
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ jobs:
run: >-
python -m pytest --tb=short -q
tests/python/test_import.py
tests/python/test_quick_start.py
tests/python/test_ivf.py::test_save_load_roundtrip
tests/python/test_hnsw.py::test_save_load_roundtrip
tests/python/test_symqg.py::test_save_load_roundtrip
Expand Down
1 change: 1 addition & 0 deletions docs/maintaining.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ only the affected job groups:
| Changes | Checks |
| --- | --- |
| Documentation and Markdown only | Documentation build for `docs/`; no C++ or Python builds; the documentation summary is always emitted |
| `docs/docs/quick_start.md` | Documentation build plus the Linux source-install job, which runs the page's Python blocks |
| Issue forms/configuration and CODEOWNERS | No C++/Python builds |
| `benchmarks/core/`, `benchmarks/hotpaths/` code/build files | Ubuntu benchmark build and bounded smoke tests; C++ formatting or Python lint as applicable, without the wheel/platform matrix for benchmark-only edits |
| `.github/workflows/test.yaml` | C++ checks, ShellCheck, Python quality (including summary-job tests), and benchmark smoke |
Expand Down
32 changes: 32 additions & 0 deletions tests/python/test_quick_start.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Run the Python code blocks from docs/docs/quick_start.md in one shared namespace.

Extracts every ```python fence from the Markdown source and executes them in
order so that any API change that breaks the page also fails CI.
"""

import re
from pathlib import Path

QUICK_START = Path(__file__).resolve().parents[2] / "docs" / "docs" / "quick_start.md"
_BLOCK_RE = re.compile(r"```python\n(.*?)```", re.DOTALL)


def _extract_blocks(path: Path) -> list[str]:
text = path.read_text(encoding="utf-8")
return _BLOCK_RE.findall(text)


def test_quick_start_blocks_run_in_order(monkeypatch, tmp_path):
"""All Python blocks in quick_start.md execute successfully in one namespace."""
blocks = _extract_blocks(QUICK_START)
assert len(blocks) == 3, (
f"Expected 3 python blocks in quick_start.md, found {len(blocks)}. "
"Update this test if the page gains or loses blocks."
)

# Run from a temp dir so a future block writing a relative path can't dirty the repo.
monkeypatch.chdir(tmp_path)

namespace: dict = {}
for i, code in enumerate(blocks, start=1):
exec(compile(code, f"quick_start.md block {i}", "exec"), namespace)
Loading