docker: categorize AMD/domain notebooks and wire the feature validation into CI

unsloth_nb_view.parse_readme only reset the folder section on level-3
(###) headings. The notebooks README carries level-1 domain headers
(# AMD Notebooks, # Kaggle Notebooks) with their own nb/*.ipynb link
tables and no intervening ###, so those notebooks were mis-filed under
the previous stale section (all 148 AMD notebooks landed in Other
Notebooks on an --amd build). Reset on any heading level and strip a
leading emoji/symbol run so the domain notebooks get their own clean
folder.

Also run tests/validate_studio_features.py explicitly in the repo CPU
job. It is named validate_* (not test_*) so pytest never collected it,
which meant a regression in the notebook view, Colab compat, strip,
JupyterLab defaults or login branding failed CI only when run by hand.
This commit is contained in:
Daniel Han 2026-07-05 14:09:48 +00:00
commit 5d41a03b40
2 changed files with 16 additions and 1 deletions

View file

@ -238,3 +238,9 @@ jobs:
echo "::endgroup::"
done
- name: Docker JupyterLab/notebook feature validation
# Named validate_studio_features.py (not test_*.py) so pytest's default
# discovery skips it; run it explicitly here so a regression in the
# notebook view, Colab compat, strip, JupyterLab defaults or login
# branding fails CI instead of only when someone runs it by hand.
run: python tests/validate_studio_features.py

View file

@ -51,6 +51,10 @@ def clean_section(title):
# Drop a trailing run of '#', surrounding whitespace and any emoji/symbols
# that sometimes lead a header; keep ASCII text, digits and a few separators.
title = title.strip().strip("#").strip()
# Strip a leading run of emoji / symbols / punctuation that some domain
# headers lead with (e.g. "🐧 AMD Notebooks", "📒 Kaggle Notebooks") so the
# folder label is clean text.
title = re.sub(r"^[^\w]+", "", title)
title = title.replace("-", " ").replace("/", " ")
title = re.sub(r"\s+", " ", title).strip()
return title
@ -74,8 +78,13 @@ def parse_readme(readme_path):
rows = []
seen_pairs = set() # (section, filename) already emitted
section = None
# Reset on ANY markdown heading, not just `###`. The catalog uses `#`/`##`
# domain headers (e.g. "# AMD Notebooks", "# Kaggle Notebooks") that carry
# their own `nb/*.ipynb` link tables directly, with no intervening `###`.
# Matching only `###` left `section` stale, so those links were mis-filed
# under the previous section instead of getting their own folder.
for line in text.splitlines():
m = re.match(r"^###\s+(.*)$", line)
m = re.match(r"^#{1,6}\s+(.*)$", line)
if m:
section = clean_section(m.group(1))
continue