diff --git a/tests/test_workflow_paths.py b/tests/test_workflow_paths.py index a918b695..9cf03836 100644 --- a/tests/test_workflow_paths.py +++ b/tests/test_workflow_paths.py @@ -9,6 +9,7 @@ from __future__ import annotations import ast import fnmatch +import sys import unittest from pathlib import Path @@ -85,5 +86,19 @@ class DeploySiteTriggers(unittest.TestCase): self.assertEqual(uncovered, []) +class DocumentedSteps(unittest.TestCase): + def test_the_release_page_names_every_installed_package(self): + """The page listed pyyaml and mkdocs and left out jsonschema: a + maintainer following it could not run the contract check.""" + sys.path.insert(0, str(SCRIPTS)) + from check_freshness import parse_pip_pins # noqa: PLC0415 + + workflow = (REPO_ROOT / ".github/workflows/deploy-site.yml").read_text(encoding="utf-8") + page = (REPO_ROOT / "wiki/release-process.md").read_text(encoding="utf-8") + missing = sorted(name for name in parse_pip_pins(workflow) if name not in page) + self.assertEqual(missing, []) + self.assertIn("validate_schemas.py", page) + + if __name__ == "__main__": unittest.main() diff --git a/wiki/architecture.md b/wiki/architecture.md index 0f1abbed..ccf648fe 100644 --- a/wiki/architecture.md +++ b/wiki/architecture.md @@ -13,7 +13,7 @@ platforms/ one YAML config per platform (scraped from upstream) _data_dirs.yml data directory definitions (Dolphin Sys, PPSSPP...) targets/ hardware target configs + _overrides.yml provenance/ dump-catalog snapshots (redump, no-intro, tosec) -scripts/ all tooling (Python, pyyaml only dependency) +scripts/ all tooling (Python, pyyaml; jsonschema for schema checks) scraper/ upstream scrapers (libretro, batocera, recalbox...) scraper/targets/ hardware target scrapers (retroarch, batocera, emudeck, retropie) exporter/ native format exporters (batocera, recalbox, emudeck...) diff --git a/wiki/release-process.md b/wiki/release-process.md index f6d462c3..e7c90298 100644 --- a/wiki/release-process.md +++ b/wiki/release-process.md @@ -26,32 +26,41 @@ hosted runner should rebuild and re-upload. ## deploy-site.yml - Deploy Documentation Site **Trigger.** Push to `main` when any of these paths change: `platforms/`, -`emulators/`, `provenance/`, `wiki/`, `scripts/generate_site.py`, -`scripts/generate_readme.py`, `scripts/verify.py`, `scripts/common.py`, -`database.json`, `release.json`, `mkdocs.yml`. Also manual dispatch. +`emulators/`, `provenance/`, `wiki/`, `schemas/`, `tests/`, `docs_assets/`, +`install/`, `install.py`, `database.json`, `release.json`, `mkdocs.yml`, the +workflow itself, and every script the build runs or imports. Also manual +dispatch. -The list is the set of inputs the site is generated from. Adding a new input to -`generate_site.py` means adding its path here, or the site silently goes stale. +The list is the set of inputs the site is generated from. A script that +`generate_site.py`, `generate_readme.py` or another build step starts to import +must be added to it, or the site silently goes stale; +`tests/test_workflow_paths.py` computes the import closure and fails when one +is missing. **Steps:** 1. Checkout, Python 3.12 -2. Install `pyyaml`, `mkdocs-material>=9.7.5,<10`, `pymdown-extensions>=10.14` -3. Restore large files from the `large-files` release, refresh data directories -4. Run `generate_site.py` (converts YAML data into MkDocs pages and rewrites +2. Install `pyyaml`, `jsonschema[format-nongpl]==4.26.0`, + `mkdocs-material>=9.7.5,<10`, `pymdown-extensions>=10.14` +3. Run `validate_schemas.py`: the data contracts, checked before anything is + generated (see below) +4. Restore large files from the `large-files` release, refresh data directories +5. Run `generate_site.py` (converts YAML data into MkDocs pages and rewrites `mkdocs.yml`) -5. Run `generate_readme.py` (rebuilds README.md and CONTRIBUTING.md) -6. `mkdocs build --strict` to produce the static site -7. Run `validate_site.py` on the rendered HTML (metadata, headings, image +6. Run `generate_readme.py` (rebuilds README.md and CONTRIBUTING.md) +7. `mkdocs build --strict` to produce the static site +8. Run `validate_site.py` on the rendered HTML (metadata, headings, image alternatives, duplicate ids, local links and fragments) -8. Require the committed README and CONTRIBUTING to match what the generator +9. Require the committed README and CONTRIBUTING to match what the generator just produced. `write_if_changed()` compares content with the timestamp line stripped, so a run that only moves the clock leaves the files untouched and the check stays meaningful -9. Upload artifact, deploy to GitHub Pages +10. Upload artifact, deploy to GitHub Pages -Data contracts are validated with `scripts/validate_schemas.py` before the site -is generated: `database.json`, the install and target manifests, the site API +Data contracts are validated with `scripts/validate_schemas.py` at step 3, before +the site is generated. It refuses to run without the checkers for the `date-time` +and `uri` formats the schemas declare, which `jsonschema` only has with the +`format-nongpl` extra. It covers `database.json`, the install and target manifests, the site API envelopes and the stats file, plus the semantic invariants those schemas cannot express (declared totals matching their lists, no destination both installed and omitted). diff --git a/wiki/testing-guide.md b/wiki/testing-guide.md index 818b4ad7..eb29d362 100644 --- a/wiki/testing-guide.md +++ b/wiki/testing-guide.md @@ -38,8 +38,12 @@ python -m unittest tests.test_site_exports -v python -m unittest tests.test_site_validation -v ``` -The only dependency is `pyyaml`. No test framework beyond the standard -library `unittest` module. +Running the build needs `pyyaml` alone, and so does most of the suite. The +schema contract tests also need `jsonschema[format-nongpl]`, which the CI +installs: without it they are reported as skipped, so install it before a pull +request that touches a profile, a platform file or a schema +(`pip install "jsonschema[format-nongpl]"`). No test framework beyond the +standard library `unittest` module. ## Modules at a glance diff --git a/wiki/tools.md b/wiki/tools.md index 083f47a5..2e2a85d8 100644 --- a/wiki/tools.md +++ b/wiki/tools.md @@ -1,6 +1,7 @@ # Tools - RetroBIOS -All tools are Python scripts in `scripts/`. Single dependency: `pyyaml`. +All tools are Python scripts in `scripts/`. They depend on `pyyaml`; only +`validate_schemas.py` also needs `jsonschema[format-nongpl]`. ## Pipeline