mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-12-16 02:05:48 -07:00
Resolved User-Created Script Execution Issues
This commit is contained in:
@@ -14,8 +14,9 @@ import datetime as _dt
|
|||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
from typing import Any, Dict, List, Mapping, Optional, Union
|
from typing import Any, Dict, Iterable, List, Mapping, Optional, Set, Union
|
||||||
|
|
||||||
from ...assembly_management.bootstrap import AssemblyCache
|
from ...assembly_management.bootstrap import AssemblyCache
|
||||||
from ...assembly_management.models import AssemblyDomain, AssemblyRecord, CachedAssembly, PayloadType
|
from ...assembly_management.models import AssemblyDomain, AssemblyRecord, CachedAssembly, PayloadType
|
||||||
@@ -80,10 +81,7 @@ class AssemblyRuntimeService:
|
|||||||
except Exception:
|
except Exception:
|
||||||
entries = []
|
entries = []
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
metadata = entry.record.metadata or {}
|
for candidate in _iter_source_paths(entry.record):
|
||||||
candidate = _normalize_source_path(metadata.get("source_path"))
|
|
||||||
if not candidate:
|
|
||||||
continue
|
|
||||||
if candidate.lower() != lookup_key:
|
if candidate.lower() != lookup_key:
|
||||||
continue
|
continue
|
||||||
payload_text = self._read_payload_text(entry.record.assembly_guid) if include_payload else None
|
payload_text = self._read_payload_text(entry.record.assembly_guid) if include_payload else None
|
||||||
@@ -376,6 +374,77 @@ def _normalize_source_path(value: Any) -> str:
|
|||||||
return "/".join(segments)
|
return "/".join(segments)
|
||||||
|
|
||||||
|
|
||||||
|
def _iter_source_paths(record: AssemblyRecord) -> Iterable[str]:
|
||||||
|
"""Yield canonical source paths for the provided assembly record."""
|
||||||
|
|
||||||
|
metadata = record.metadata or {}
|
||||||
|
seen: Set[str] = set()
|
||||||
|
for key in (
|
||||||
|
"source_path",
|
||||||
|
"rel_path",
|
||||||
|
"legacy_path",
|
||||||
|
"legacy_rel_path",
|
||||||
|
"path",
|
||||||
|
"relative_path",
|
||||||
|
"script_path",
|
||||||
|
"playbook_path",
|
||||||
|
"workflow_path",
|
||||||
|
):
|
||||||
|
candidate = _normalize_source_path(metadata.get(key))
|
||||||
|
if not candidate:
|
||||||
|
continue
|
||||||
|
lowered = candidate.lower()
|
||||||
|
if lowered in seen:
|
||||||
|
continue
|
||||||
|
seen.add(lowered)
|
||||||
|
yield candidate
|
||||||
|
|
||||||
|
fallback = _fallback_source_path(record)
|
||||||
|
if fallback:
|
||||||
|
lowered = fallback.lower()
|
||||||
|
if lowered not in seen:
|
||||||
|
seen.add(lowered)
|
||||||
|
yield fallback
|
||||||
|
|
||||||
|
|
||||||
|
def _fallback_source_path(record: AssemblyRecord) -> str:
|
||||||
|
metadata = record.metadata or {}
|
||||||
|
prefix = _kind_prefix(record.assembly_kind, record.assembly_type)
|
||||||
|
fallback_name = (
|
||||||
|
metadata.get("display_name")
|
||||||
|
or record.display_name
|
||||||
|
or metadata.get("name")
|
||||||
|
or record.summary
|
||||||
|
or record.assembly_guid
|
||||||
|
or "Assembly"
|
||||||
|
)
|
||||||
|
safe_name = _sanitize_name_for_path(fallback_name)
|
||||||
|
candidate = f"{prefix}/{safe_name}"
|
||||||
|
return _normalize_source_path(candidate)
|
||||||
|
|
||||||
|
|
||||||
|
def _kind_prefix(kind: Optional[str], assembly_type: Optional[str]) -> str:
|
||||||
|
key = (kind or "").strip().lower()
|
||||||
|
type_key = (assembly_type or "").strip().lower()
|
||||||
|
if key == "ansible" or type_key == "ansible":
|
||||||
|
return "Ansible_Playbooks"
|
||||||
|
if key == "workflow" or type_key == "workflow":
|
||||||
|
return "Workflows"
|
||||||
|
return "Scripts"
|
||||||
|
|
||||||
|
|
||||||
|
_PATH_SANITIZE_PATTERN = re.compile(r"[^A-Za-z0-9._-]+")
|
||||||
|
|
||||||
|
|
||||||
|
def _sanitize_name_for_path(value: Any, fallback: str = "Assembly") -> str:
|
||||||
|
text = str(value or "").strip()
|
||||||
|
if not text:
|
||||||
|
return fallback
|
||||||
|
sanitized = _PATH_SANITIZE_PATTERN.sub("_", text)
|
||||||
|
sanitized = sanitized.strip()
|
||||||
|
return sanitized or fallback
|
||||||
|
|
||||||
|
|
||||||
def _serialize_payload(value: Any) -> str:
|
def _serialize_payload(value: Any) -> str:
|
||||||
if isinstance(value, (dict, list)):
|
if isinstance(value, (dict, list)):
|
||||||
return json.dumps(value, indent=2, sort_keys=True)
|
return json.dumps(value, indent=2, sort_keys=True)
|
||||||
|
|||||||
@@ -150,3 +150,13 @@ def test_cache_flush_waits_for_locked_database(assembly_runtime) -> None:
|
|||||||
records = db_manager.load_all(AssemblyDomain.USER)
|
records = db_manager.load_all(AssemblyDomain.USER)
|
||||||
summaries = {entry.assembly_guid: entry.summary for entry in records}
|
summaries = {entry.assembly_guid: entry.summary for entry in records}
|
||||||
assert summaries[guid] == "Updated summary after lock."
|
assert summaries[guid] == "Updated summary after lock."
|
||||||
|
|
||||||
|
|
||||||
|
def test_resolve_document_matches_virtual_path(assembly_runtime) -> None:
|
||||||
|
service, _cache, _db_manager = assembly_runtime
|
||||||
|
payload = _script_payload(display_name="User Created Script")
|
||||||
|
record = service.create_assembly(payload)
|
||||||
|
|
||||||
|
resolved = service.resolve_document_by_source_path("Scripts/User_Created_Script")
|
||||||
|
assert resolved is not None
|
||||||
|
assert resolved["assembly_guid"] == record["assembly_guid"]
|
||||||
|
|||||||
Reference in New Issue
Block a user