106 lines
3.5 KiB
Python
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
|