92e2585358
CI / lint (pull_request) Successful in 39s
CI / helm (pull_request) Successful in 32s
CI / build (pull_request) Successful in 32s
CI / push-validation (pull_request) Successful in 31s
CI / quality (pull_request) Successful in 1m0s
CI / security (pull_request) Successful in 1m2s
CI / typecheck (pull_request) Successful in 1m40s
CI / unit_tests (pull_request) Successful in 6m25s
CI / docker (pull_request) Successful in 1m27s
CI / coverage (pull_request) Successful in 10m51s
CI / integration_tests (pull_request) Successful in 22m36s
CI / status-check (pull_request) Successful in 3s
Add the missing workflow validation example and keep the #1039 TDD regression active by removing the expected-fail tag and updating scenario narrative.\n\nTo satisfy the required full quality gates, stabilize flaky integration behavior encountered during this issue run: use a shared SQLAlchemy session in resource DAG scripts, isolate RxPY validation temp paths per test run, extend transient subprocess timeouts/retry behavior, and clear stale pabot worker artifacts before integration runs so repeated nox executions are reliable.\n\nISSUES CLOSED: #1039
125 lines
10 KiB
Plaintext
125 lines
10 KiB
Plaintext
*** Settings ***
|
|
Documentation Resource DAG Linking and Discovery Tests
|
|
Library Process
|
|
Library OperatingSystem
|
|
|
|
*** Test Cases ***
|
|
Link Child And Verify Tree
|
|
[Documentation] Link a child resource and verify it appears in children list
|
|
${script}= Catenate SEPARATOR=\n
|
|
... import json
|
|
... from datetime import datetime, UTC
|
|
... from sqlalchemy import create_engine, event
|
|
... from sqlalchemy.pool import StaticPool
|
|
... from sqlalchemy.orm import sessionmaker
|
|
... from sqlalchemy.pool import StaticPool
|
|
... from cleveragents.infrastructure.database.models import Base
|
|
... from cleveragents.infrastructure.database.repositories import ResourceTypeRepository, ResourceRepository
|
|
... from cleveragents.domain.models.core.resource_type import ResourceTypeSpec, ResourceKind, SandboxStrategy
|
|
... from cleveragents.domain.models.core.resource import Resource, PhysVirt, ResourceCapabilities
|
|
... engine = create_engine("sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool)
|
|
... @event.listens_for(engine, "connect")
|
|
... def _fk(conn, _): conn.cursor().execute("PRAGMA foreign_keys=ON")
|
|
... Base.metadata.create_all(engine)
|
|
... factory = sessionmaker(bind=engine)
|
|
... shared_session = factory()
|
|
... rt_repo = ResourceTypeRepository(lambda: shared_session)
|
|
... res_repo = ResourceRepository(lambda: shared_session)
|
|
... parent_spec = ResourceTypeSpec(name="robot/dag-parent", description="Parent", resource_kind=ResourceKind.PHYSICAL, sandbox_strategy=SandboxStrategy.NONE, user_addable=True, cli_args=[], parent_types=[], child_types=["robot/dag-child"], auto_discovery=None, equivalence=None, handler=None, capabilities={"read": True, "write": True, "sandbox": True, "checkpoint": False}, built_in=False)
|
|
... child_spec = ResourceTypeSpec(name="robot/dag-child", description="Child", resource_kind=ResourceKind.PHYSICAL, sandbox_strategy=SandboxStrategy.NONE, user_addable=True, cli_args=[], parent_types=[], child_types=[], auto_discovery=None, equivalence=None, handler=None, capabilities={"read": True, "write": True, "sandbox": True, "checkpoint": False}, built_in=False)
|
|
... rt_repo.create(parent_spec)
|
|
... rt_repo.create(child_spec)
|
|
... p = Resource(resource_id="01HDAGR0B0T0000000PARENT01", name=None, resource_type_name="robot/dag-parent", classification=PhysVirt.PHYSICAL, properties={}, location=None, capabilities=ResourceCapabilities(), created_at=datetime.now(tz=UTC), updated_at=datetime.now(tz=UTC))
|
|
... c = Resource(resource_id="01HDAGR0B0T00000CHXND00001", name=None, resource_type_name="robot/dag-child", classification=PhysVirt.PHYSICAL, properties={}, location=None, capabilities=ResourceCapabilities(), created_at=datetime.now(tz=UTC), updated_at=datetime.now(tz=UTC))
|
|
... res_repo.create(p)
|
|
... res_repo.create(c)
|
|
... res_repo.link_child("01HDAGR0B0T0000000PARENT01", "01HDAGR0B0T00000CHXND00001")
|
|
... children = res_repo.get_children("01HDAGR0B0T0000000PARENT01")
|
|
... assert len(children) == 1, f"Expected 1 child, got {len(children)}"
|
|
... assert children[0].resource_id == "01HDAGR0B0T00000CHXND00001"
|
|
... shared_session.close()
|
|
... print("Link child and verify tree passed")
|
|
${result}= Run Process ${PYTHON} -c ${script} timeout=60s on_timeout=kill
|
|
Should Be Equal As Integers ${result.rc} 0 Link test failed: ${result.stderr}
|
|
Should Contain ${result.stdout} Link child and verify tree passed
|
|
|
|
Cycle Detection Rejects A To B To A
|
|
[Documentation] Linking A->B then B->A should raise CycleDetectedError
|
|
${script}= Catenate SEPARATOR=\n
|
|
... from datetime import datetime, UTC
|
|
... from sqlalchemy import create_engine, event
|
|
... from sqlalchemy.pool import StaticPool
|
|
... from sqlalchemy.orm import sessionmaker
|
|
... from sqlalchemy.pool import StaticPool
|
|
... from cleveragents.infrastructure.database.models import Base
|
|
... from cleveragents.infrastructure.database.repositories import ResourceTypeRepository, ResourceRepository, CycleDetectedError
|
|
... from cleveragents.domain.models.core.resource_type import ResourceTypeSpec, ResourceKind, SandboxStrategy
|
|
... from cleveragents.domain.models.core.resource import Resource, PhysVirt, ResourceCapabilities
|
|
... engine = create_engine("sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool)
|
|
... @event.listens_for(engine, "connect")
|
|
... def _fk(conn, _): conn.cursor().execute("PRAGMA foreign_keys=ON")
|
|
... Base.metadata.create_all(engine)
|
|
... factory = sessionmaker(bind=engine)
|
|
... shared_session = factory()
|
|
... rt_repo = ResourceTypeRepository(lambda: shared_session)
|
|
... res_repo = ResourceRepository(lambda: shared_session)
|
|
... spec_a = ResourceTypeSpec(name="robot/cycle-a", description="Cycle A", resource_kind=ResourceKind.PHYSICAL, sandbox_strategy=SandboxStrategy.NONE, user_addable=True, cli_args=[], parent_types=[], child_types=["robot/cycle-b"], auto_discovery=None, equivalence=None, handler=None, capabilities={"read": True, "write": True, "sandbox": True, "checkpoint": False}, built_in=False)
|
|
... spec_b = ResourceTypeSpec(name="robot/cycle-b", description="Cycle B", resource_kind=ResourceKind.PHYSICAL, sandbox_strategy=SandboxStrategy.NONE, user_addable=True, cli_args=[], parent_types=[], child_types=["robot/cycle-a"], auto_discovery=None, equivalence=None, handler=None, capabilities={"read": True, "write": True, "sandbox": True, "checkpoint": False}, built_in=False)
|
|
... rt_repo.create(spec_a)
|
|
... rt_repo.create(spec_b)
|
|
... a = Resource(resource_id="01HDAGCYC000000000000000A1", name=None, resource_type_name="robot/cycle-a", classification=PhysVirt.PHYSICAL, properties={}, location=None, capabilities=ResourceCapabilities(), created_at=datetime.now(tz=UTC), updated_at=datetime.now(tz=UTC))
|
|
... b = Resource(resource_id="01HDAGCYC000000000000000B1", name=None, resource_type_name="robot/cycle-b", classification=PhysVirt.PHYSICAL, properties={}, location=None, capabilities=ResourceCapabilities(), created_at=datetime.now(tz=UTC), updated_at=datetime.now(tz=UTC))
|
|
... res_repo.create(a)
|
|
... res_repo.create(b)
|
|
... res_repo.link_child("01HDAGCYC000000000000000A1", "01HDAGCYC000000000000000B1")
|
|
... try:
|
|
... ${SPACE * 4}res_repo.link_child("01HDAGCYC000000000000000B1", "01HDAGCYC000000000000000A1")
|
|
... ${SPACE * 4}assert False, "Should have raised CycleDetectedError"
|
|
... except CycleDetectedError:
|
|
... ${SPACE * 4}print("Cycle detection passed")
|
|
... finally:
|
|
... ${SPACE * 4}shared_session.close()
|
|
${result}= Run Process ${PYTHON} -c ${script} timeout=60s on_timeout=kill
|
|
Should Be Equal As Integers ${result.rc} 0 Cycle test failed: ${result.stderr}
|
|
Should Contain ${result.stdout} Cycle detection passed
|
|
|
|
Auto Discover Children
|
|
[Documentation] Auto-discover creates child resources per type rules
|
|
${script}= Catenate SEPARATOR=\n
|
|
... import json
|
|
... from datetime import datetime, UTC
|
|
... from sqlalchemy import create_engine, event
|
|
... from sqlalchemy.pool import StaticPool
|
|
... from sqlalchemy.orm import sessionmaker
|
|
... from sqlalchemy.pool import StaticPool
|
|
... from cleveragents.infrastructure.database.models import Base
|
|
... from cleveragents.infrastructure.database.repositories import ResourceTypeRepository, ResourceRepository
|
|
... from cleveragents.domain.models.core.resource_type import ResourceTypeSpec, ResourceKind, SandboxStrategy
|
|
... from cleveragents.domain.models.core.resource import Resource, PhysVirt, ResourceCapabilities
|
|
... engine = create_engine("sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool)
|
|
... @event.listens_for(engine, "connect")
|
|
... def _fk(conn, _): conn.cursor().execute("PRAGMA foreign_keys=ON")
|
|
... Base.metadata.create_all(engine)
|
|
... factory = sessionmaker(bind=engine)
|
|
... shared_session = factory()
|
|
... rt_repo = ResourceTypeRepository(lambda: shared_session)
|
|
... res_repo = ResourceRepository(lambda: shared_session)
|
|
... parent_spec = ResourceTypeSpec(name="robot/disc-parent", description="Discoverer", resource_kind=ResourceKind.PHYSICAL, sandbox_strategy=SandboxStrategy.NONE, user_addable=True, cli_args=[], parent_types=[], child_types=["robot/disc-child"], auto_discovery={"enabled": True, "rules": [{"type": "robot/disc-child", "pattern": "*"}]}, equivalence=None, handler=None, capabilities={"read": True, "write": True, "sandbox": True, "checkpoint": False}, built_in=False)
|
|
... child_spec = ResourceTypeSpec(name="robot/disc-child", description="Discovered", resource_kind=ResourceKind.PHYSICAL, sandbox_strategy=SandboxStrategy.NONE, user_addable=True, cli_args=[], parent_types=[], child_types=[], auto_discovery=None, equivalence=None, handler=None, capabilities={"read": True, "write": True, "sandbox": True, "checkpoint": False}, built_in=False)
|
|
... rt_repo.create(parent_spec)
|
|
... rt_repo.create(child_spec)
|
|
... p = Resource(resource_id="01HDAGR0B0TDSC00PARENT0001", name=None, resource_type_name="robot/disc-parent", classification=PhysVirt.PHYSICAL, properties={}, location=None, capabilities=ResourceCapabilities(), created_at=datetime.now(tz=UTC), updated_at=datetime.now(tz=UTC))
|
|
... res_repo.create(p)
|
|
... created = res_repo.auto_discover_children("01HDAGR0B0TDSC00PARENT0001")
|
|
... assert len(created) >= 1, f"Expected >=1 children, got {len(created)}"
|
|
... assert created[0].resource_type_name == "robot/disc-child"
|
|
... children = res_repo.get_children("01HDAGR0B0TDSC00PARENT0001")
|
|
... assert len(children) >= 1, f"Expected >=1 linked children, got {len(children)}"
|
|
... shared_session.close()
|
|
... print("Auto discover children passed")
|
|
${result}= Run Process ${PYTHON} -c ${script} timeout=60s on_timeout=kill
|
|
Should Be Equal As Integers ${result.rc} 0 Auto discover test failed: ${result.stderr}
|
|
Should Contain ${result.stdout} Auto discover children passed
|
|
|
|
*** Keywords ***
|