lint / go (push) Canceled after 0s
lint / go_mod (push) Canceled after 0s
lint / conf (push) Canceled after 0s
lint / docslinks (push) Canceled after 0s
lint / docsorder (push) Canceled after 0s
lint / apidocs (push) Canceled after 0s
lint / other (push) Canceled after 0s
test / test_64 (push) Canceled after 0s
test / test_32 (push) Canceled after 0s
test / test_e2e (push) Canceled after 0s
127 lines
4.5 KiB
Python
127 lines
4.5 KiB
Python
"""Project-specific DevHarness entry point for the MediaMTX customization fork."""
|
||
|
||
from __future__ import annotations
|
||
|
||
import argparse
|
||
import json
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
from wiki_docs import WikiClient, WikiDocsError, load_config, parse_mirror, sync_all
|
||
|
||
|
||
ROOT = Path(__file__).resolve().parents[1]
|
||
CONFIG = ROOT / "wiki-docs.json"
|
||
REQUIRED_FILES = (
|
||
"AGENTS.md",
|
||
"CLAUDE.md",
|
||
".gitea/issue_template/epic.md",
|
||
".gitea/issue_template/mvp.md",
|
||
".gitea/issue_template/task.md",
|
||
"wiki-docs.json",
|
||
"dev_scripts/harness.py",
|
||
"dev_scripts/wiki_docs.py",
|
||
"tests/test_harness.py",
|
||
)
|
||
EXPECTED_MAPPINGS = {
|
||
"Home": "docs/maintainer/README.md",
|
||
"Project-Profile": "docs/maintainer/1-project-profile.md",
|
||
"Development-Workflow": "docs/maintainer/2-development-workflow.md",
|
||
"Architecture-and-Code-Map": "docs/maintainer/3-architecture-and-code-map.md",
|
||
"Product-Requirements-Overview": "docs/maintainer/4-product-requirements-overview.md",
|
||
"Local-Development-and-Verification": "docs/maintainer/5-local-development-and-verification.md",
|
||
"Common-Changes": "docs/maintainer/6-common-changes.md",
|
||
"Troubleshooting": "docs/maintainer/7-troubleshooting.md",
|
||
}
|
||
|
||
|
||
def check(strict: bool) -> list[str]:
|
||
errors: list[str] = []
|
||
for relative in REQUIRED_FILES:
|
||
if not (ROOT / relative).is_file():
|
||
errors.append(f"缺少文件:{relative}")
|
||
|
||
if "ip_camera.env" not in (ROOT / ".gitignore").read_text(encoding="utf-8"):
|
||
errors.append(".gitignore 未忽略 ip_camera.env")
|
||
|
||
try:
|
||
raw = json.loads(CONFIG.read_text(encoding="utf-8"))
|
||
actual = {item["page"]: item["path"] for item in raw.get("mappings", [])}
|
||
if actual != EXPECTED_MAPPINGS:
|
||
errors.append("wiki-docs.json 的核心映射与项目约定不一致")
|
||
except (OSError, ValueError, KeyError, TypeError) as exc:
|
||
errors.append(f"无法读取 wiki-docs.json:{exc}")
|
||
|
||
agents = (ROOT / "AGENTS.md").read_text(encoding="utf-8") if (ROOT / "AGENTS.md").is_file() else ""
|
||
for phrase in ("Gitea 单元工单", "docs/maintainer/", "ip_camera.env", "upstream"):
|
||
if phrase not in agents:
|
||
errors.append(f"AGENTS.md 缺少项目规则:{phrase}")
|
||
|
||
if strict:
|
||
for path in EXPECTED_MAPPINGS.values():
|
||
target = ROOT / path
|
||
if not target.is_file():
|
||
errors.append(f"缺少 Wiki 镜像:{path}")
|
||
continue
|
||
try:
|
||
metadata, _ = parse_mirror(target.read_text(encoding="utf-8"))
|
||
except WikiDocsError as exc:
|
||
errors.append(f"Wiki 镜像无效 {path}:{exc}")
|
||
continue
|
||
if not metadata.get("wiki_revision"):
|
||
errors.append(f"Wiki 镜像缺少 revision:{path}")
|
||
|
||
return errors
|
||
|
||
|
||
def run_check(args: argparse.Namespace) -> int:
|
||
errors = check(args.strict)
|
||
if errors:
|
||
for error in errors:
|
||
print(f"错误:{error}")
|
||
return 1
|
||
print("MediaMTX DevHarness 检查通过")
|
||
return 0
|
||
|
||
|
||
def run_sync(args: argparse.Namespace) -> int:
|
||
try:
|
||
config = load_config(Path(args.config))
|
||
for message in sync_all(config, WikiClient(config), check=args.check):
|
||
print(message)
|
||
except WikiDocsError as exc:
|
||
print(f"错误:{exc}", file=sys.stderr)
|
||
return 1
|
||
if args.verify:
|
||
errors = check(True)
|
||
if errors:
|
||
for error in errors:
|
||
print(f"错误:{error}")
|
||
return 1
|
||
try:
|
||
for message in sync_all(config, WikiClient(config), check=True):
|
||
print(message)
|
||
except WikiDocsError as exc:
|
||
print(f"错误:{exc}", file=sys.stderr)
|
||
return 1
|
||
return 0
|
||
|
||
|
||
def main() -> int:
|
||
parser = argparse.ArgumentParser(description="MediaMTX 定制版 DevHarness")
|
||
sub = parser.add_subparsers(dest="command", required=True)
|
||
check_parser = sub.add_parser("check", help="检查项目 Harness 结构")
|
||
check_parser.add_argument("--strict", action="store_true")
|
||
check_parser.set_defaults(handler=run_check)
|
||
sync_parser = sub.add_parser("sync", help="从 Gitea Wiki 单向同步维护文档")
|
||
sync_parser.add_argument("--config", default=str(CONFIG))
|
||
sync_parser.add_argument("--check", action="store_true")
|
||
sync_parser.add_argument("--verify", action="store_true")
|
||
sync_parser.set_defaults(handler=run_sync)
|
||
args = parser.parse_args()
|
||
return args.handler(args)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
raise SystemExit(main())
|