generated from coulomb/repo-seed
feat(cli): add open-reuse validate and register portfolio integrations
Some checks failed
ci / validate-registry (push) Has been cancelled
Some checks failed
ci / validate-registry (push) Has been cancelled
Implement Integration Definition validator CLI with schema and index checks, pytest suite, and CI workflow. Register open-cmis-tck and issue-core-gitea in the integration index. Closes OPEN-WP-0003 and OPEN-WP-0004.
This commit is contained in:
91
open_reuse/registry.py
Normal file
91
open_reuse/registry.py
Normal file
@@ -0,0 +1,91 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import yaml
|
||||
|
||||
PACKAGE_ROOT = Path(__file__).resolve().parent.parent
|
||||
|
||||
INDEX_REQUIRED_FIELDS = (
|
||||
"id",
|
||||
"name",
|
||||
"status",
|
||||
"owner",
|
||||
"reuse_mode",
|
||||
"path",
|
||||
"repo",
|
||||
"upstream",
|
||||
)
|
||||
|
||||
|
||||
def resolve_repo_root(root: Path | None = None) -> Path:
|
||||
if root is not None:
|
||||
return root.resolve()
|
||||
candidate = PACKAGE_ROOT
|
||||
markers = (
|
||||
candidate / "schemas" / "integration.schema.yaml",
|
||||
candidate / "registry" / "indexes" / "integrations.yaml",
|
||||
)
|
||||
if all(path.exists() for path in markers):
|
||||
return candidate
|
||||
raise FileNotFoundError(
|
||||
"Could not resolve open-reuse repo root; pass --root explicitly."
|
||||
)
|
||||
|
||||
|
||||
def registry_paths(repo_root: Path) -> dict[str, Path]:
|
||||
registry = repo_root / "registry"
|
||||
return {
|
||||
"registry": registry,
|
||||
"integrations": registry / "integrations",
|
||||
"index": registry / "indexes" / "integrations.yaml",
|
||||
"schema": repo_root / "schemas" / "integration.schema.yaml",
|
||||
}
|
||||
|
||||
|
||||
def load_schema(repo_root: Path) -> dict[str, Any]:
|
||||
schema_path = registry_paths(repo_root)["schema"]
|
||||
with schema_path.open(encoding="utf-8") as handle:
|
||||
return yaml.safe_load(handle)
|
||||
|
||||
|
||||
def load_yaml(path: Path) -> dict[str, Any]:
|
||||
with path.open(encoding="utf-8") as handle:
|
||||
data = yaml.safe_load(handle)
|
||||
if not isinstance(data, dict):
|
||||
raise ValueError(f"{path}: expected YAML mapping at root")
|
||||
return data
|
||||
|
||||
|
||||
def load_index(repo_root: Path) -> dict[str, Any]:
|
||||
index_path = registry_paths(repo_root)["index"]
|
||||
if not index_path.exists():
|
||||
return {"integrations": []}
|
||||
return load_yaml(index_path)
|
||||
|
||||
|
||||
def integration_paths(repo_root: Path, targets: list[Path] | None = None) -> list[Path]:
|
||||
if targets:
|
||||
return [path.resolve() for path in targets]
|
||||
integrations_dir = registry_paths(repo_root)["integrations"]
|
||||
if not integrations_dir.exists():
|
||||
return []
|
||||
return sorted(
|
||||
path
|
||||
for path in integrations_dir.glob("*.integration.yaml")
|
||||
if path.is_file()
|
||||
)
|
||||
|
||||
|
||||
def resolve_external_definition(
|
||||
repo_slug: str,
|
||||
relative_path: str,
|
||||
repos_base: Path | None,
|
||||
) -> Path | None:
|
||||
if repos_base is None:
|
||||
return None
|
||||
candidate = (repos_base / repo_slug / relative_path).resolve()
|
||||
if candidate.is_file():
|
||||
return candidate
|
||||
return None
|
||||
Reference in New Issue
Block a user