local OpenCMIS TCK runtime

This commit is contained in:
2026-05-07 23:43:21 +02:00
parent 71a917f2fb
commit 18a952aa0c
12 changed files with 791 additions and 7 deletions

View File

@@ -0,0 +1,181 @@
"""Local OpenCMIS TCK runtime bootstrap helpers."""
from __future__ import annotations
import json
import shutil
import subprocess
from datetime import datetime, timezone
from pathlib import Path
from typing import Any
TCK_COORDINATE = "org.apache.chemistry.opencmis:chemistry-opencmis-test-tck:1.1.0"
TCK_LICENSE = "Apache-2.0"
def check_runtime(
extension_root: Path,
output_path: Path | None = None,
resolve: bool = False,
timeout_seconds: int = 300,
) -> dict[str, Any]:
"""Check local Java/Maven posture and optionally resolve TCK dependencies."""
root = extension_root.resolve()
pom_path = root / "runtime" / "opencmis-tck" / "pom.xml"
java = _probe(["java", "-version"])
maven = _probe(["mvn", "-version"])
missing = [
name
for name, probe in {"java": java, "maven": maven}.items()
if not probe["available"]
]
dependency_resolution = {
"attempted": False,
"status": "not_requested",
"returncode": None,
"stdout": "",
"stderr": "",
}
if resolve and not missing:
dependency_resolution = _resolve_dependencies(pom_path, timeout_seconds)
elif resolve:
dependency_resolution["attempted"] = False
dependency_resolution["status"] = "blocked_missing_prerequisite"
status = _status(missing, dependency_resolution)
summary = {
"id": "opencmis-tck-runtime",
"status": status,
"created_at": _now(),
"tck": {
"coordinate": TCK_COORDINATE,
"license": TCK_LICENSE,
"project_status": "Apache Chemistry retired; artifact remains available from Maven Central.",
"runner_class": "org.apache.chemistry.opencmis.tck.runner.ConsoleRunner",
"runner_contract": "ConsoleRunner accepts a session parameters file and a group list file.",
},
"runtime": {
"java": java,
"maven": maven,
"pom_path": str(pom_path),
"dependency_resolution": dependency_resolution,
},
"diagnostics": _diagnostics(missing, resolve, dependency_resolution),
}
if output_path is not None:
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_text(json.dumps(summary, indent=2, sort_keys=True) + "\n", encoding="utf-8")
return summary
def default_summary_path(extension_root: Path) -> Path:
return extension_root / ".local" / "opencmis-tck" / "runtime-summary.json"
def _probe(command: list[str]) -> dict[str, Any]:
executable = shutil.which(command[0])
if executable is None:
return {
"available": False,
"path": None,
"returncode": None,
"version_output": None,
}
try:
completed = subprocess.run(
command,
capture_output=True,
text=True,
timeout=20,
check=False,
)
except (OSError, subprocess.TimeoutExpired) as exc:
return {
"available": False,
"path": executable,
"returncode": None,
"version_output": str(exc),
}
output = "\n".join(
part.strip()
for part in [completed.stdout, completed.stderr]
if part.strip()
)
return {
"available": completed.returncode == 0,
"path": executable,
"returncode": completed.returncode,
"version_output": output[:4000],
}
def _resolve_dependencies(pom_path: Path, timeout_seconds: int) -> dict[str, Any]:
completed = subprocess.run(
[
"mvn",
"-q",
"-f",
str(pom_path),
"dependency:resolve",
],
capture_output=True,
text=True,
timeout=timeout_seconds,
check=False,
)
return {
"attempted": True,
"status": "resolved" if completed.returncode == 0 else "failed",
"returncode": completed.returncode,
"stdout": completed.stdout[-4000:],
"stderr": completed.stderr[-4000:],
}
def _status(missing: list[str], dependency_resolution: dict[str, Any]) -> str:
if missing:
return "blocked"
if dependency_resolution["attempted"] and dependency_resolution["status"] != "resolved":
return "blocked"
return "ready"
def _diagnostics(
missing: list[str],
resolve: bool,
dependency_resolution: dict[str, Any],
) -> list[dict[str, str]]:
diagnostics = []
for tool in missing:
diagnostics.append(
{
"severity": "error",
"field": f"runtime.{tool}",
"message": f"{tool} is not available on PATH; install it or point the local environment at an existing toolchain.",
}
)
if resolve and dependency_resolution["status"] == "failed":
diagnostics.append(
{
"severity": "error",
"field": "runtime.dependency_resolution",
"message": "Maven could not resolve the OpenCMIS TCK runtime dependencies.",
}
)
if not resolve and not missing:
diagnostics.append(
{
"severity": "info",
"field": "runtime.dependency_resolution",
"message": "Run the bootstrap command with --resolve to download/cache Maven dependencies.",
}
)
return diagnostics
def _now() -> str:
return datetime.now(timezone.utc).isoformat()