Skip to content

Commit c1153d8

Browse files
authored
feat: api reference docs pipeline (#30)
* feat: add pydoc-markdown configuration for documentation generation Signed-off-by: James Ding <jamesding365@gmail.com> * feat: add GitHub Actions workflow for automatic API documentation updates Signed-off-by: James Ding <jamesding365@gmail.com> * feat: update GitHub Actions workflow to remove main branch trigger (temporary) Signed-off-by: James Ding <jamesding365@gmail.com> * feat: remove sign-commits option from API documentation update workflow Signed-off-by: James Ding <jamesding365@gmail.com> * feat: remove legacy SDK references from documentation and configuration Signed-off-by: James Ding <jamesding365@gmail.com> * feat: add script to copy generated documentation files to the docs repository Signed-off-by: James Ding <jamesding365@gmail.com> * feat: migrate doc script to new docs structure * fix: ensure newline at end of file in copy_docs.py * feat: simplify job name in docs.yml for clarity * feat: restore main branch trigger to workflow in docs.yml --------- Signed-off-by: James Ding <jamesding365@gmail.com>
1 parent 54bc101 commit c1153d8

4 files changed

Lines changed: 993 additions & 0 deletions

File tree

.github/workflows/docs.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: Documentation
2+
3+
on:
4+
push:
5+
branches: [main]
6+
workflow_dispatch:
7+
8+
jobs:
9+
update-docs:
10+
name: Generate Docs
11+
runs-on: ubuntu-latest
12+
environment: docs
13+
steps:
14+
- name: Checkout fish-audio-python
15+
uses: actions/checkout@v4
16+
with:
17+
path: sdk
18+
19+
- name: Install uv
20+
uses: astral-sh/setup-uv@v4
21+
22+
- name: Install dependencies
23+
working-directory: sdk
24+
run: uv sync
25+
26+
- name: Generate API documentation
27+
working-directory: sdk
28+
run: uv run pydoc-markdown
29+
30+
- name: Checkout docs
31+
uses: actions/checkout@v4
32+
with:
33+
repository: ${{ vars.DOCS_REPO }}
34+
path: docs
35+
36+
- name: Copy generated documentation
37+
run: uv run python sdk/scripts/copy_docs.py sdk docs
38+
39+
- name: Create Pull Request
40+
uses: peter-evans/create-pull-request@v6
41+
with:
42+
token: ${{ secrets.DOCS_TOKEN }}
43+
path: docs
44+
commit-message: |
45+
chore: update Python SDK API reference
46+
47+
Auto-generated from fishaudio/fish-audio-python@${{ github.sha }}
48+
branch: auto/python-api-docs
49+
delete-branch: true
50+
title: "Update Python SDK API Reference"
51+
body: |
52+
Auto-generated API documentation update from [fish-audio-python@${{ github.sha }}](https://github.com/fishaudio/fish-audio-python/commit/${{ github.sha }})
53+
54+
## Changes
55+
- Updated API reference documentation for Python SDK
56+
- Generated from latest docstrings in the codebase
57+
58+
labels: |
59+
python

pyproject.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,26 @@ asyncio_mode = "auto"
5656
[dependency-groups]
5757
dev = [
5858
"mypy>=1.14.1",
59+
"pydoc-markdown>=4.8.2",
5960
"pytest>=8.3.5",
6061
"pytest-asyncio>=0.24.0",
6162
"pytest-cov>=5.0.0",
6263
"python-dotenv>=1.0.1",
6364
"ruff>=0.14.3",
6465
]
66+
67+
[[tool.pydoc-markdown.loaders]]
68+
type = "python"
69+
packages = ["fishaudio", "fish_audio_sdk"]
70+
71+
[tool.pydoc-markdown.renderer]
72+
type = "mkdocs"
73+
pages = [
74+
{title = "Fish Audio SDK", name="index", source = "README.md"},
75+
{title = "Client", name="fishaudio/client", contents = ["fishaudio.client.*"] },
76+
{title = "Resources", name="fishaudio/resources", contents = ["fishaudio.resources.*"] },
77+
{title = "Types", name="fishaudio/types", contents = ["fishaudio.types.*"] },
78+
{title = "Core", name="fishaudio/core", contents = ["fishaudio.core.*"] },
79+
{title = "Utils", name="fishaudio/utils", contents = ["fishaudio.utils.*"] },
80+
{title = "Exceptions", name="fishaudio/exceptions", contents = ["fishaudio.exceptions.*"] },
81+
]

scripts/copy_docs.py

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Script to copy generated documentation files to the docs repository.
4+
5+
Usage:
6+
python scripts/copy_docs.py <sdk_root> <docs_root>
7+
8+
Example:
9+
python scripts/copy_docs.py . ../docs
10+
python scripts/copy_docs.py sdk docs # In CI context
11+
"""
12+
13+
import argparse
14+
import shutil
15+
from pathlib import Path
16+
from typing import Callable
17+
18+
19+
def add_frontmatter(content: str, title: str, description: str, icon: str) -> str:
20+
"""
21+
Add Mintlify frontmatter to markdown content.
22+
23+
Args:
24+
content: Original markdown content
25+
title: Page title
26+
description: Page description
27+
icon: Icon name
28+
29+
Returns:
30+
Content with frontmatter prepended
31+
"""
32+
frontmatter = f"""---
33+
title: "{title}"
34+
description: "{description}"
35+
icon: "{icon}"
36+
---
37+
38+
"""
39+
return frontmatter + content
40+
41+
42+
def copy_file_with_extension_change(
43+
source: Path, dest_dir: Path, new_extension: str = ".mdx"
44+
) -> None:
45+
"""
46+
Copy a single file to destination directory with extension change.
47+
48+
Args:
49+
source: Source file path
50+
dest_dir: Destination directory
51+
new_extension: New file extension (default: .mdx)
52+
"""
53+
if not source.exists():
54+
print(f"Warning: {source} does not exist")
55+
return
56+
57+
dest = dest_dir / source.with_suffix(new_extension).name
58+
shutil.copy2(source, dest)
59+
print(f" ✓ {source.name} -> {dest.name}")
60+
61+
62+
def copy_files_from_directory(
63+
source_dir: Path, dest_dir: Path, pattern: str = "*.md", new_extension: str = ".mdx"
64+
) -> None:
65+
"""
66+
Copy all files matching pattern from source directory to destination with extension change.
67+
68+
Args:
69+
source_dir: Source directory
70+
dest_dir: Destination directory
71+
pattern: File pattern to match (default: *.md)
72+
new_extension: New file extension (default: .mdx)
73+
"""
74+
if not source_dir.exists():
75+
print(f"Warning: {source_dir} does not exist")
76+
return
77+
78+
print(f"Copying files from {source_dir} to {dest_dir}")
79+
for file in source_dir.glob(pattern):
80+
dest = dest_dir / file.with_suffix(new_extension).name
81+
shutil.copy2(file, dest)
82+
print(f" ✓ {file.name} -> {dest.name}")
83+
84+
85+
def copy_file_with_transformation(
86+
source: Path,
87+
dest_dir: Path,
88+
transform_fn: Callable[[str], str],
89+
new_extension: str = ".mdx",
90+
dest_filename: str | None = None,
91+
) -> None:
92+
"""
93+
Copy a file with content transformation.
94+
95+
Args:
96+
source: Source file path
97+
dest_dir: Destination directory
98+
transform_fn: Function to transform file content
99+
new_extension: New file extension (default: .mdx)
100+
dest_filename: Optional custom destination filename (without extension)
101+
"""
102+
if not source.exists():
103+
print(f"Warning: {source} does not exist")
104+
return
105+
106+
if dest_filename:
107+
dest = dest_dir / f"{dest_filename}{new_extension}"
108+
else:
109+
dest = dest_dir / source.with_suffix(new_extension).name
110+
111+
content = source.read_text(encoding="utf-8")
112+
transformed_content = transform_fn(content)
113+
dest.write_text(transformed_content, encoding="utf-8")
114+
print(f" ✓ {source.name} -> {dest.name} (transformed)")
115+
116+
117+
def copy_docs(sdk_root: Path, docs_root: Path) -> None:
118+
"""
119+
Copy generated documentation files to the docs repository.
120+
121+
Args:
122+
sdk_root: Root directory of the fish-audio-python SDK
123+
docs_root: Root directory of the docs repository
124+
"""
125+
# Source paths
126+
build_dir = sdk_root / "build" / "docs" / "content"
127+
fishaudio_dir = build_dir / "fishaudio"
128+
index_file = build_dir / "index.md"
129+
130+
# Destination path (flat structure - all files go to the same directory)
131+
python_sdk_dir = docs_root / "api-reference" / "sdk" / "python"
132+
133+
# Create destination directory
134+
python_sdk_dir.mkdir(parents=True, exist_ok=True)
135+
136+
# Copy fishaudio module reference files
137+
copy_files_from_directory(fishaudio_dir, python_sdk_dir)
138+
139+
# Copy index.md to python directory as overview.mdx with frontmatter
140+
copy_file_with_transformation(
141+
index_file,
142+
python_sdk_dir,
143+
lambda content: add_frontmatter(
144+
content,
145+
title="Python SDK",
146+
description="Fish Audio Python SDK for text-to-speech and voice cloning",
147+
icon="python",
148+
),
149+
dest_filename="overview",
150+
)
151+
152+
print("\nDocumentation copy completed successfully!")
153+
154+
155+
def main() -> None:
156+
parser = argparse.ArgumentParser(
157+
description="Copy generated documentation files to the docs repository"
158+
)
159+
parser.add_argument(
160+
"sdk_root",
161+
type=Path,
162+
help="Root directory of the fish-audio-python SDK",
163+
)
164+
parser.add_argument(
165+
"docs_root",
166+
type=Path,
167+
help="Root directory of the docs repository",
168+
)
169+
170+
args = parser.parse_args()
171+
172+
# Validate paths
173+
if not args.sdk_root.exists():
174+
parser.error(f"SDK root directory does not exist: {args.sdk_root}")
175+
176+
if not args.docs_root.exists():
177+
parser.error(f"Docs root directory does not exist: {args.docs_root}")
178+
179+
copy_docs(args.sdk_root, args.docs_root)
180+
181+
182+
if __name__ == "__main__":
183+
main()

0 commit comments

Comments
 (0)