mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-11 14:03:23 -05:00
fix: redeploy the site on any script it imports
This commit is contained in:
1 parent
d02672c17b
commit
cd90f46937
2 files changed
+129
-5
No files matched your search
@@ -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