generated from coulomb/repo-seed
local OpenCMIS TCK runtime
This commit is contained in:
181
src/open_cmis_tck/bootstrap.py
Normal file
181
src/open_cmis_tck/bootstrap.py
Normal 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()
|
||||
Reference in New Issue
Block a user