Files
planet/scripts/check_earth_boundary_production_ready.py
linkong 93eb41a9f7
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / delivery (push) Has been cancelled
release / images (push) Has been cancelled
release: bump version to 0.58.0
Release 0.58.0 includes the Earth high-precision boundary PMTiles/MVT pipeline, standardized Earth boundary source collectors, China POV boundary configuration templates, and removal of the legacy low-precision GeoJSON fallback. It also adds Earth news target-location queueing/archive support, fixes datasource task status visibility, documents the Earth surface depth-spacing rules that prevent far-zoom z-fighting snow/black blocks, and updates bilingual operations/developer docs.
2026-05-15 17:40:07 +08:00

75 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""Check whether the Earth boundary pipeline is ready for PMTiles production.
This is intentionally a verifier, not a fake builder. It fails when the repo is
still using seed data or when the external MVT/PMTiles toolchain is absent.
"""
from __future__ import annotations
import argparse
import json
import shutil
import sys
from pathlib import Path
from typing import Any
DEFAULT_CONFIG = Path("config/earth-boundary-sources.example.json")
DEFAULT_ARTIFACT = Path("frontend/public/earth/data/boundaries/earth-boundaries-china-pov-v1.pmtiles")
def load_json(path: Path) -> dict[str, Any]:
with path.open("r", encoding="utf-8") as f:
payload = json.load(f)
if not isinstance(payload, dict):
raise ValueError(f"{path} must contain a JSON object")
return payload
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--config", type=Path, default=DEFAULT_CONFIG)
parser.add_argument("--artifact", type=Path, default=DEFAULT_ARTIFACT)
args = parser.parse_args()
config = load_json(args.config)
policy = config.get("policy") or {}
collector_configs = config.get("collectorConfigs") or {}
failures: list[str] = []
warnings: list[str] = []
if policy.get("productionTileFormat") != "pmtiles+mvt":
failures.append("policy.productionTileFormat must be pmtiles+mvt")
if not policy.get("povPolicyPath"):
failures.append("policy.povPolicyPath is required")
required_kinds = {"admin0-boundaries", "coastline", "claim-lines"}
configured_kinds = {str(source.get("sourceKind")) for source in collector_configs.values()}
missing_kinds = sorted(required_kinds - configured_kinds)
if missing_kinds:
failures.append(f"missing production source kind(s): {', '.join(missing_kinds)}")
for collector_name, source in collector_configs.items():
endpoint = str(source.get("endpoint") or "")
if not endpoint or endpoint.startswith("https://example.com/"):
failures.append(f"{collector_name} endpoint must be configured to an audited production source")
for tool in ("tippecanoe", "pmtiles"):
if shutil.which(tool) is None:
failures.append(f"external tool not found in PATH: {tool}")
if not args.artifact.exists():
warnings.append(f"PMTiles artifact does not exist yet: {args.artifact}")
result = {
"ready": not failures,
"failures": failures,
"warnings": warnings,
"artifact": str(args.artifact),
}
print(json.dumps(result, ensure_ascii=False, sort_keys=True))
return 0 if not failures else 2
if __name__ == "__main__":
sys.exit(main())