mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-08 19:13:47 -06:00
fix: redeploy the site on any script it imports
This commit is contained in:
1 parent
240a30f1d7
commit
d3e02c8c5e
2 files changed
+129
-5
No files matched your search
@@ -8,11 +8,47 @@ on:
|
|||||||
- "emulators/**"
|
- "emulators/**"
|
||||||
- "provenance/**"
|
- "provenance/**"
|
||||||
- "wiki/**"
|
- "wiki/**"
|
||||||
- "scripts/generate_site.py"
|
# Every script the build runs or imports (tests/test_workflow_paths.py).
|
||||||
- "scripts/generate_readme.py"
|
- "scripts/artifacts.py"
|
||||||
- "scripts/validate_site.py"
|
- "scripts/auto_fetch.py"
|
||||||
- "scripts/verify.py"
|
|
||||||
- "scripts/common.py"
|
- "scripts/common.py"
|
||||||
|
- "scripts/cross_reference.py"
|
||||||
|
- "scripts/crypto_verify.py"
|
||||||
|
- "scripts/deterministic_zip.py"
|
||||||
|
- "scripts/dumpcatalog.py"
|
||||||
|
- "scripts/generate_pack.py"
|
||||||
|
- "scripts/generate_readme.py"
|
||||||
|
- "scripts/generate_site.py"
|
||||||
|
- "scripts/hashing.py"
|
||||||
|
- "scripts/largefiles.py"
|
||||||
|
- "scripts/list_platforms.py"
|
||||||
|
- "scripts/nativemode.py"
|
||||||
|
- "scripts/packextras.py"
|
||||||
|
- "scripts/packpaths.py"
|
||||||
|
- "scripts/packreadme.py"
|
||||||
|
- "scripts/packresolve.py"
|
||||||
|
- "scripts/packverify.py"
|
||||||
|
- "scripts/profile_sync.py"
|
||||||
|
- "scripts/provenance_report.py"
|
||||||
|
- "scripts/refresh_data_dirs.py"
|
||||||
|
- "scripts/region.py"
|
||||||
|
- "scripts/release_record.py"
|
||||||
|
- "scripts/restore_large_files.py"
|
||||||
|
- "scripts/safeparse.py"
|
||||||
|
- "scripts/sect233r1.py"
|
||||||
|
- "scripts/siterender.py"
|
||||||
|
- "scripts/sitesources.py"
|
||||||
|
- "scripts/sitewrite.py"
|
||||||
|
- "scripts/slot.py"
|
||||||
|
- "scripts/slots.py"
|
||||||
|
- "scripts/split_pack.py"
|
||||||
|
- "scripts/truth.py"
|
||||||
|
- "scripts/upstream.py"
|
||||||
|
- "scripts/validate_schemas.py"
|
||||||
|
- "scripts/validate_site.py"
|
||||||
|
- "scripts/validation.py"
|
||||||
|
- "scripts/verify.py"
|
||||||
|
- "scripts/ziptools.py"
|
||||||
- "schemas/**"
|
- "schemas/**"
|
||||||
- "tests/**"
|
- "tests/**"
|
||||||
- "docs_assets/**"
|
- "docs_assets/**"
|
||||||
@@ -20,7 +56,6 @@ on:
|
|||||||
- "install.py"
|
- "install.py"
|
||||||
- "database.json"
|
- "database.json"
|
||||||
- "release.json"
|
- "release.json"
|
||||||
- "scripts/release_record.py"
|
|
||||||
- "mkdocs.yml"
|
- "mkdocs.yml"
|
||||||
- ".github/workflows/deploy-site.yml"
|
- ".github/workflows/deploy-site.yml"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|||||||
@@ -0,0 +1,89 @@
|
|||||||
|
"""The site redeploys whenever a script it runs changes.
|
||||||
|
|
||||||
|
Deploy Site listed five scripts by hand while the build imports forty:
|
||||||
|
a change to siterender.py, which writes every page, published nothing
|
||||||
|
until some unrelated file moved.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import ast
|
||||||
|
import fnmatch
|
||||||
|
import unittest
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
SCRIPTS = REPO_ROOT / "scripts"
|
||||||
|
|
||||||
|
|
||||||
|
def _module_file(name: str) -> Path | None:
|
||||||
|
name = name.removeprefix("scripts.")
|
||||||
|
for candidate in (
|
||||||
|
SCRIPTS / (name.replace(".", "/") + ".py"),
|
||||||
|
SCRIPTS / name.replace(".", "/") / "__init__.py",
|
||||||
|
):
|
||||||
|
if candidate.exists():
|
||||||
|
return candidate
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _imports(path: Path) -> set[Path]:
|
||||||
|
found: set[Path] = set()
|
||||||
|
for node in ast.walk(ast.parse(path.read_text(encoding="utf-8"))):
|
||||||
|
if isinstance(node, ast.Import):
|
||||||
|
names = [alias.name for alias in node.names]
|
||||||
|
elif isinstance(node, ast.ImportFrom) and node.level == 0 and node.module:
|
||||||
|
names = [node.module, *(f"{node.module}.{a.name}" for a in node.names)]
|
||||||
|
elif isinstance(node, ast.ImportFrom):
|
||||||
|
base = path.parent / (node.module or "").replace(".", "/")
|
||||||
|
candidates = [base / f"{a.name}.py" for a in node.names]
|
||||||
|
candidates += [base.with_suffix(".py"), base / "__init__.py"]
|
||||||
|
found.update(c for c in candidates if c.is_file())
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
found.update(f for f in map(_module_file, names) if f)
|
||||||
|
return found
|
||||||
|
|
||||||
|
|
||||||
|
def closure(entry_points: list[str]) -> set[str]:
|
||||||
|
seen: set[Path] = set()
|
||||||
|
stack = [SCRIPTS / name for name in entry_points]
|
||||||
|
while stack:
|
||||||
|
path = stack.pop()
|
||||||
|
if path not in seen:
|
||||||
|
seen.add(path)
|
||||||
|
stack.extend(_imports(path))
|
||||||
|
return {str(p.relative_to(REPO_ROOT)) for p in seen}
|
||||||
|
|
||||||
|
|
||||||
|
class DeploySiteTriggers(unittest.TestCase):
|
||||||
|
def test_every_script_the_build_imports_triggers_it(self):
|
||||||
|
workflow = yaml.safe_load(
|
||||||
|
(REPO_ROOT / ".github/workflows/deploy-site.yml").read_text(encoding="utf-8")
|
||||||
|
)
|
||||||
|
on = workflow.get("on", workflow.get(True))
|
||||||
|
patterns = on["push"]["paths"]
|
||||||
|
run = "\n".join(
|
||||||
|
step.get("run", "") for job in workflow["jobs"].values() for step in job["steps"]
|
||||||
|
)
|
||||||
|
entry_points = sorted(
|
||||||
|
{
|
||||||
|
word.removeprefix("scripts/")
|
||||||
|
for word in run.split()
|
||||||
|
if word.startswith("scripts/") and word.endswith(".py")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertIn("generate_site.py", entry_points)
|
||||||
|
uncovered = sorted(
|
||||||
|
path
|
||||||
|
for path in closure(entry_points)
|
||||||
|
if not any(fnmatch.fnmatch(path, p.replace("**", "*")) for p in patterns)
|
||||||
|
)
|
||||||
|
self.assertEqual(uncovered, [])
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Reference in new issue
Block a user