Files
ljwx-deploy/scripts/knowledge/validate_state.py
T

106 lines
3.5 KiB
Python

#!/usr/bin/env python3
"""Validate committed knowledge publish records."""
from __future__ import annotations
import argparse
from pathlib import Path
try:
import yaml
except ImportError as exc:
raise SystemExit(
f"缺少依赖 PyYAML,请使用 uvx --with pyyaml --with jsonschema python <script>\n{exc}"
) from exc
from .common import (
JSONMapping,
KnowledgeContractError,
PUBLISH_RECORD_SCHEMA_RELATIVE,
knowledge_paths,
load_publish_records,
load_validator,
optional_non_empty_str,
require_non_empty_str,
validate_payload,
)
def parse_args() -> argparse.Namespace:
"""Parse CLI arguments."""
parser = argparse.ArgumentParser(description="Validate knowledge publish records")
parser.add_argument(
"--deploy-root", type=Path, default=Path("."), help="ljwx-deploy root"
)
parser.add_argument("--env", default="dev")
return parser.parse_args()
def load_platform_version(path: Path) -> JSONMapping:
"""Load release/platform-version.yaml."""
raw = yaml.safe_load(path.read_text(encoding="utf-8"))
if not isinstance(raw, dict):
raise KnowledgeContractError(f"{path} 根节点必须是 mapping")
return {str(key): value for key, value in raw.items()}
def main() -> int:
"""CLI entry point."""
args = parse_args()
deploy_root = args.deploy_root.resolve()
validator = load_validator(deploy_root / PUBLISH_RECORD_SCHEMA_RELATIVE)
records = load_publish_records(
knowledge_paths(deploy_root, args.env).publish_records_root
)
release_version = load_platform_version(
deploy_root / "release/platform-version.yaml"
)
config_versions = release_version.get("config_versions")
if not isinstance(config_versions, dict):
raise KnowledgeContractError(
"release/platform-version.yaml.config_versions 缺失"
)
publish_record_ref = optional_non_empty_str(
config_versions.get("knowledge_publish_record_schema"),
"release/platform-version.yaml.config_versions.knowledge_publish_record_schema",
)
expected_ref = f"{PUBLISH_RECORD_SCHEMA_RELATIVE.as_posix()}@0.1.0"
if publish_record_ref != expected_ref:
raise KnowledgeContractError(
"release/platform-version.yaml 中 knowledge_publish_record_schema "
f"必须等于 {expected_ref}"
)
for document_id, record in records.items():
validate_payload(validator, record, f"publish-record<{document_id}>")
artifact_ref = require_non_empty_str(
record.get("artifact_ref"), "record.artifact_ref"
)
normalized_ref = require_non_empty_str(
record.get("normalized_ref"), "record.normalized_ref"
)
classified_ref = require_non_empty_str(
record.get("classified_ref"), "record.classified_ref"
)
chunk_ref = require_non_empty_str(record.get("chunk_ref"), "record.chunk_ref")
for relative_path in (artifact_ref, normalized_ref, classified_ref, chunk_ref):
absolute_path = deploy_root / relative_path
if not absolute_path.exists():
raise KnowledgeContractError(
f"publish record 引用了不存在的文件: {absolute_path}"
)
print(f"knowledge publish record 校验通过 ({len(records)} 条)")
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except KnowledgeContractError as exc:
print(str(exc))
raise SystemExit(1) from exc