Skip to content

Commit 10054d8

Browse files
authored
Refactor markdown generation and add docs tests for classes (#5597)
* refactor utils Signed-off-by: sirutBuasai <sirutbuasai27@outlook.com> * refactor support policy Signed-off-by: sirutBuasai <sirutbuasai27@outlook.com> * refactor iamgeconfig Signed-off-by: sirutBuasai <sirutbuasai27@outlook.com> * update kiro Signed-off-by: sirutBuasai <sirutbuasai27@outlook.com> * refactor generation using imageconfig Signed-off-by: sirutBuasai <sirutbuasai27@outlook.com> * remove inline imports Signed-off-by: sirutBuasai <sirutbuasai27@outlook.com> * refactor image config Signed-off-by: sirutBuasai <sirutbuasai27@outlook.com> * add comments Signed-off-by: sirutBuasai <sirutbuasai27@outlook.com> * add tests Signed-off-by: sirutBuasai <sirutbuasai27@outlook.com> --------- Signed-off-by: sirutBuasai <sirutbuasai27@outlook.com>
1 parent 2f1e2df commit 10054d8

File tree

24 files changed

+1171
-598
lines changed

24 files changed

+1171
-598
lines changed

.github/workflows/docs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Publish Documentations via GitHub Pages
22

33
on:
44
push:
5-
branches: [main, doc-poc]
5+
branches: [main]
66
paths:
77
- "**docs**"
88
workflow_dispatch:

.kiro/steering/docs.md

Lines changed: 132 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,132 @@ docs/src/
3333
│ └── ...
3434
├── legacy/ # Historical support data
3535
│ └── legacy_support.yml
36-
├── constants.py # Path constants and global variables
36+
├── constants.py # Path constants, global variables, and GLOBAL_CONFIG
3737
├── generate.py # Generation logic
3838
├── global.yml # Shared terminology and configuration
3939
├── hooks.py # MkDocs hooks
40+
├── image_config.py # ImageConfig class and image-related functions
4041
├── logger.py # Logging configuration
4142
├── macros.py # MkDocs macros
4243
├── main.py # CLI entry point
43-
└── utils.py # Reusable helper functions
44+
├── sorter.py # Sorting tiebreaker functions
45+
└── utils.py # Utility functions (file loading, table rendering, etc.)
46+
```
47+
48+
### File Responsibilities
49+
50+
- `constants.py` - Path constants, global variables, and `GLOBAL_CONFIG`
51+
- `sorter.py` - Sorting tiebreaker functions: `platform_sorter`, `accelerator_sorter`
52+
- `utils.py` - Utility functions: `load_yaml()`, `load_table_config()`, `load_jinja2()`, `render_table()`, `write_output()`, `parse_version()`, `clone_git_repository()`, `build_public_registry_note()`, `get_framework_order()`
53+
- `image_config.py` - `ImageConfig` class, image loaders (`load_repository_images`, `load_legacy_images`), `sort_by_version`, `get_latest_image`, `build_image_row`, `check_public_registry`
54+
- `generate.py` - `generate_support_policy()`, `generate_available_images()`, `generate_all()`
55+
- `macros.py` - MkDocs macros plugin integration
56+
- `hooks.py` - MkDocs hooks entry point
57+
58+
### Module Import Structure
59+
60+
The modules follow a strict import hierarchy to avoid circular imports:
61+
62+
```
63+
constants.py (no project imports)
64+
65+
utils.py (imports from constants)
66+
67+
image_config.py (imports from constants and utils)
68+
```
69+
70+
Functions that instantiate `ImageConfig` must stay in `image_config.py`. Functions that only use `GLOBAL_CONFIG` or utilities can live in `utils.py`.
71+
72+
### Global Configuration
73+
74+
The global configuration is loaded once at module import time in `constants.py` and exposed as `GLOBAL_CONFIG`. This eliminates the need to pass `global_config` to most functions.
75+
76+
```python
77+
from constants import GLOBAL_CONFIG
78+
79+
# Access any config value
80+
table_order = GLOBAL_CONFIG.get("table_order", [])
81+
display_names = GLOBAL_CONFIG["display_names"]
82+
```
83+
84+
### ImageConfig Class
85+
86+
The `ImageConfig` class provides a dynamic, config-driven interface for image data:
87+
88+
```python
89+
from image_config import ImageConfig, load_repository_images
90+
91+
# Load from YAML file
92+
img = ImageConfig.from_yaml(Path("data/pytorch-training/2.9-gpu-ec2.yml"), "pytorch-training")
93+
94+
# Access any YAML field as attribute
95+
img.version # "2.9"
96+
img.framework # "PyTorch"
97+
img.accelerator # "gpu"
98+
img.repository # "pytorch-training"
99+
img.framework_group # "pytorch" (computed from GLOBAL_CONFIG, defaults to repository)
100+
101+
# Safe access with default
102+
img.get("cuda", "-") # "cu130" or "-" if not present
103+
104+
# Properties (no parentheses)
105+
img.is_supported # True if eop >= today
106+
img.has_support_dates # True if ga and eop fields exist
107+
img.display_repository # "PyTorch Training" (uses GLOBAL_CONFIG)
108+
img.display_framework_group # "PyTorch" (uses GLOBAL_CONFIG)
109+
110+
# Display properties for table rendering
111+
img.display_framework_version # "PyTorch 2.9"
112+
img.display_example_url # formatted ECR URL
113+
img.display_platform # "EC2, ECS, EKS" (mapped from "ec2")
114+
img.display_accelerator # "GPU" (mapped from "gpu")
115+
116+
# Generic display accessor (uses display_<field> property if exists, else raw value)
117+
img.get_display("platform") # "EC2, ECS, EKS"
118+
img.get_display("python") # "py312" (no display_ property, returns raw)
119+
```
120+
121+
### Image Loading Functions
122+
123+
```python
124+
from image_config import load_repository_images, load_legacy_images
125+
126+
# Load all images for a repository
127+
images = load_repository_images("pytorch-training") # list[ImageConfig]
128+
129+
# Load legacy support policy images
130+
legacy = load_legacy_images() # dict[str, list[ImageConfig]]
131+
```
132+
133+
### Sorting Functions
134+
135+
```python
136+
from image_config import sort_by_version
137+
138+
# Sort images by version descending
139+
sorted_images = sort_by_version(images)
140+
141+
# Sort with tiebreakers (for available_images: platform, then accelerator)
142+
sorted_images = sort_by_version(
143+
images,
144+
tiebreakers=[
145+
lambda img: 0 if img.get("platform") == "sagemaker" else 1,
146+
lambda img: {"gpu": 0, "neuronx": 1, "cpu": 2}.get(img.get("accelerator", "").lower(), 3),
147+
],
148+
)
149+
```
150+
151+
### Table Building
152+
153+
```python
154+
from image_config import build_image_row
155+
from utils import render_table
156+
157+
# Build a complete row (uses img.get_display() internally)
158+
row = build_image_row(img, columns) # ["PyTorch 2.9", "py312", ...]
159+
160+
# Render markdown table
161+
table = render_table(headers, rows)
44162
```
45163

46164
### Adding a New Image
@@ -87,6 +205,9 @@ docs/src/
87205
header: "Framework"
88206
- field: python
89207
header: "Python"
208+
- field: framework
209+
data: framework_group # optional: use different data source for display
210+
header: "Framework"
90211
# ... add columns in desired order
91212
```
92213

@@ -166,9 +287,10 @@ Images in `available_images.md` are automatically sorted by:
166287
### Running Generation
167288

168289
```bash
169-
# Development
170-
cd docs && source .venv/bin/activate
171-
cd src && python main.py --verbose
290+
# Development (use venv in base directory)
291+
cd /path/to/deep-learning-containers
292+
source .venv/bin/activate
293+
cd docs/src && python main.py --verbose
172294
173295
# With MkDocs (automatic via hooks)
174296
mkdocs serve
@@ -178,7 +300,7 @@ mkdocs build
178300
### Support Policy Logic
179301

180302
- Scans all image configs for `ga` and `eop` fields
181-
- Groups by (repository, version)
303+
- Groups by (framework_group or repository, version)
182304
- Validates consistency within each group
183305
- Auto-determines supported/unsupported by comparing `eop` to current date
184306
- Uses `display_names` for Framework column
@@ -187,17 +309,10 @@ mkdocs build
187309

188310
Historical support policy data for older, unsupported images is stored in `docs/src/legacy/legacy_support.yml`.
189311

190-
#### Directory Structure
191-
192-
```
193-
docs/src/legacy/
194-
└── legacy_support.yml # Historical support data
195-
```
196-
197312
#### File Format
198313

199314
```yaml
200-
PyTorch:
315+
pytorch:
201316
- version: "2.5"
202317
ga: "2024-10-29"
203318
eop: "2025-10-29"
@@ -216,37 +331,9 @@ PyTorch:
216331

217332
- Legacy entries appear only in `support_policy.md` (unsupported section)
218333
- Images past their EOP date are automatically filtered from `available_images.md`
219-
- The `is_image_supported()` function checks if `eop >= today`
220-
221-
## Code Organization
222-
223-
### File Responsibilities
224-
225-
- `generate.py` - Contains only `generate_*` functions for documentation generation
226-
- `utils.py` - Contains all reusable helper functions
227-
- `macros.py` - MkDocs macros plugin integration
228-
- `hooks.py` - MkDocs hooks entry point
229-
- `constants.py` - All path constants and global variables
230-
231-
### utils.py Conventions
232-
233-
All functions in `utils.py` must:
234-
235-
1. Have a docstring explaining what the function does
236-
1. Be fully typed with type hints
237-
1. Document exceptions raised (if any)
238-
239-
Example:
240-
241-
```python
242-
def get_display_name(global_config: dict, repository: str) -> str:
243-
"""Get human-readable display name for a repository.
244-
245-
Raises:
246-
KeyError: If repository not found in global config display_names.
247-
"""
248-
```
334+
- The `ImageConfig.is_supported` property checks if `eop >= today`
249335

250336
## Update knowledge base
251337

252-
If there are any new changes to the documentations generation and organization, make sure to update you knowledge base in the steering/docs.md file.
338+
If there are any new changes to the documentations generation and organization, make sure to update you knowledge base in the steering/docs.md file and any runbook or update to processes should also be updated in DEVELOPMENT.md files.
339+
This is done so that developers get the most up-to-date information on the current codebase.

docs/.nav.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ nav:
1212
- Tensorflow: releasenotes/tensorflow/index.md
1313
- Tutorials: tutorials
1414
- Reference:
15+
- reference/index.md
1516
- Available Images: reference/available_images.md
1617
- Support Policy: reference/support_policy.md
1718
- Security:

docs/src/constants.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
from pathlib import Path
1616

17+
from omegaconf import OmegaConf
18+
1719
# Path constants
1820
SRC_DIR = Path(__file__).parent
1921
DOCS_DIR = SRC_DIR.parent
@@ -27,3 +29,7 @@
2729

2830
AVAILABLE_IMAGES_TABLE_HEADER = "##"
2931
TUTORIALS_REPO = "https://github.com/aws-samples/sample-aws-deep-learning-containers"
32+
33+
# Load global config once at import time
34+
global_cfg = OmegaConf.load(GLOBAL_CONFIG_PATH)
35+
GLOBAL_CONFIG = OmegaConf.to_container(global_cfg, resolve=True)

0 commit comments

Comments
 (0)