mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-11 12:33:53 -06:00
102 lines
3.7 KiB
Python
102 lines
3.7 KiB
Python
#!/usr/bin/env python3
|
|
"""Run the checks validate.yml runs on a pull request, in its order.
|
|
|
|
Usage:
|
|
python scripts/pr_checks.py
|
|
python scripts/pr_checks.py --list
|
|
|
|
Each step runs even when an earlier one failed, as CI runs them, and the
|
|
summary names every step that failed or could not run. A step whose tool is
|
|
absent (npm, python3.8, vermin) is reported as not run, with what provides it.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Step:
|
|
command: str
|
|
why: str
|
|
needs: str = ""
|
|
provider: str = ""
|
|
env: dict[str, str] = field(default_factory=dict)
|
|
|
|
|
|
# The order of validate.yml: data fetched, site generated and built, then the
|
|
# suite, its 3.8 run and the built-site check.
|
|
STEPS: tuple[Step, ...] = (
|
|
Step("python scripts/validate_pr.py --changed", "the BIOS files the branch adds"),
|
|
Step("python scripts/validate_schemas.py --source-only", "profiles and platform files"),
|
|
Step("python scripts/profile_sync.py --added --strict", "each profile the branch adds"),
|
|
Step("vermin --no-tips -t=3.8- --violations install.py", "install.py stays on Python 3.8",
|
|
needs="vermin", provider="the pip line of CONTRIBUTING.md"),
|
|
Step("python scripts/export_native.py --all --fetch --output-dir tmp/native",
|
|
"files the exporter tests compare with"),
|
|
Step("python scripts/refresh_data_dirs.py", "data directories the pack-building tests read"),
|
|
Step("python scripts/generate_site.py", "the pages the site tests read"),
|
|
Step("npm ci --prefix website", "the site's packages, Node 24",
|
|
needs="npm", provider="Node 24"),
|
|
Step("npm run build --prefix website", "the built site",
|
|
needs="npm", provider="Node 24"),
|
|
Step("python -m unittest discover -s tests -t .", "the suite",
|
|
env={"RETROBIOS_OFFLINE": "1"}),
|
|
Step("python3.8 -m unittest tests.test_install_tui", "the full screen on the installer's floor",
|
|
needs="python3.8", provider="a Python 3.8 with pyte",
|
|
env={"RETROBIOS_OFFLINE": "1"}),
|
|
Step("python scripts/validate_site.py --site-dir website/dist", "links and page budgets"),
|
|
)
|
|
|
|
|
|
def argv(step: Step) -> list[str]:
|
|
"""The command, with `python` run by the interpreter running this script."""
|
|
words = step.command.split()
|
|
return [sys.executable, *words[1:]] if words[0] == "python" else words
|
|
|
|
|
|
def run(steps: tuple[Step, ...] = STEPS) -> int:
|
|
failed: list[str] = []
|
|
not_run: list[str] = []
|
|
for step in steps:
|
|
print(f"\n== {step.command}", flush=True)
|
|
if step.needs and shutil.which(step.needs) is None:
|
|
print(f"not run: {step.needs} is not installed ({step.provider})")
|
|
not_run.append(f"{step.command} ({step.needs}: {step.provider})")
|
|
continue
|
|
code = subprocess.run(argv(step), cwd=ROOT, env={**os.environ, **step.env}).returncode
|
|
if code:
|
|
failed.append(f"{step.command} (exit {code})")
|
|
print()
|
|
for line in failed:
|
|
print(f"FAILED {line}")
|
|
for line in not_run:
|
|
print(f"NOT RUN {line}")
|
|
print(f"{len(steps) - len(failed) - len(not_run)}/{len(steps)} checks passed")
|
|
return 1 if failed else 0
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__.splitlines()[0])
|
|
parser.add_argument("--list", action="store_true", help="print the steps and exit")
|
|
args = parser.parse_args()
|
|
if args.list:
|
|
for step in STEPS:
|
|
print(step.command)
|
|
return 0
|
|
return run()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
from common import run_cli
|
|
|
|
run_cli(main)
|