diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 780a8037..d6d195a1 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -173,8 +173,10 @@ jobs: 3.8 3.12 + # markdown: the site validation test renders a wiki line to prove the + # heading guard's premise, and skipped on every run without it. - name: Install dependencies - run: pip install pyyaml "jsonschema[format-nongpl]==4.26.0" + run: pip install pyyaml "jsonschema[format-nongpl]==4.26.0" "markdown==3.10.2" # The exporter fidelity cases compare what we hand back against the # file each platform publishes, so they need those files. They skip diff --git a/pyproject.toml b/pyproject.toml index 0e73c027..6e588335 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ dependencies = [ [project.optional-dependencies] dev = [ "jsonschema[format-nongpl]>=4.23", + "markdown>=3.7", ] # The site build the repo generates and documents. Both were hard # requirements of deploy-site.yml and of wiki/release-process.md while being diff --git a/tests/test_site_validation.py b/tests/test_site_validation.py index b2f3f940..9c6622df 100644 --- a/tests/test_site_validation.py +++ b/tests/test_site_validation.py @@ -163,5 +163,44 @@ class RenderedSiteValidation(unittest.TestCase): self.assertTrue(any("duplicate description" in issue for issue in issues)) + +class EveryTestDependencyIsInstalledInCi(unittest.TestCase): + """The markdown rendering test skipped on every CI run: the test job + installed pyyaml and jsonschema only. A test that skips where it is + meant to run guards nothing.""" + + PACKAGES = {"yaml": "pyyaml", "jsonschema": "jsonschema", "markdown": "markdown"} + + def test_the_test_job_installs_what_the_tests_import(self): + import ast + + root = Path(__file__).resolve().parents[1] + local = ( + {p.stem for p in (root / "scripts").rglob("*.py")} + | {p.name for p in (root / "scripts").iterdir() if p.is_dir()} + | {p.stem for p in (root / "tests").glob("*.py")} + | {"scripts", "tests", "install"} + ) + imported: set[str] = set() + for path in (root / "tests").glob("*.py"): + for node in ast.walk(ast.parse(path.read_text(encoding="utf-8"))): + if isinstance(node, ast.Import): + imported.update(a.name.split(".")[0] for a in node.names) + elif isinstance(node, ast.ImportFrom) and node.level == 0 and node.module: + imported.add(node.module.split(".")[0]) + third_party = { + m for m in imported if m not in sys.stdlib_module_names and m not in local + } + workflow = (root / ".github" / "workflows" / "validate.yml").read_text() + job = workflow[workflow.index("run-tests:"):] + install_line = next( + line for line in job.splitlines() if "pip install" in line + ) + missing = sorted( + m for m in third_party if self.PACKAGES.get(m, m) not in install_line + ) + self.assertEqual(missing, []) + + if __name__ == "__main__": unittest.main()