be45020a5c
- Adds a --clone-into option to the container-instance command to clone repository contents into a specified path during container setup. - Fixes the devcontainer-instance sandbox strategy to ensure proper isolation, correct mount permissions, and deterministic behavior across environments. - Updates related validation and error handling to reflect the new option and sandbox changes. ISSUES CLOSED: #7555
239 lines
14 KiB
Gherkin
239 lines
14 KiB
Gherkin
Feature: Devcontainer Session Cleanup and CLI Commands
|
|
As a CleverAgents developer
|
|
I want session-scoped container cleanup and CLI stop/rebuild commands
|
|
So that containers are cleaned up when sessions end and can be managed via CLI
|
|
|
|
# ── Session cleanup ────────────────────────────────────────
|
|
|
|
Scenario: Active containers stopped on session cleanup
|
|
Given a mock devcontainer CLI runner
|
|
And an active container "01TESTLIFECYCLE0000000040" with container ID "ctr-a"
|
|
And an active container "01TESTLIFECYCLE0000000041" with container ID "ctr-b"
|
|
When I run session cleanup for session "session-001"
|
|
Then the container state for "01TESTLIFECYCLE0000000040" should be "stopped"
|
|
And the container state for "01TESTLIFECYCLE0000000041" should be "stopped"
|
|
|
|
# ── Cleanup service integration ────────────────────────────
|
|
|
|
Scenario: CleanupService stop_active_devcontainers is callable and returns list
|
|
When I call CleanupService stop_active_devcontainers with no active containers
|
|
Then the cleanup result should be an empty list
|
|
And CleanupService should have a stop_active_devcontainers method
|
|
|
|
Scenario: CleanupService stop_active_devcontainers calls handler cleanup
|
|
When I call CleanupService stop_active_devcontainers with no active containers
|
|
Then the cleanup result should be an empty list
|
|
|
|
# ── stop_all_active_containers error path ──────────────────
|
|
|
|
Scenario: Session cleanup handles stop failure gracefully
|
|
Given a mock devcontainer CLI runner
|
|
And the runner configured to raise exception on stop
|
|
And an active container "01TESTLIFECYCLE0000000130" with container ID "ctr-fail"
|
|
When I run session cleanup for session "session-err"
|
|
Then the cleanup should return 0 stopped containers
|
|
|
|
# ── CLI stop/rebuild commands (F6) ─────────────────────────
|
|
|
|
Scenario: CLI stop succeeds for active devcontainer-instance
|
|
Given a mock resource service with devcontainer "local/test-dc" id "01TESTLIFECYCLE0000000200" at "/workspace/project"
|
|
And an active container "01TESTLIFECYCLE0000000200" with container ID "ctr-cli-stop"
|
|
When I invoke CLI resource stop "local/test-dc"
|
|
Then the CLI exit code should be 0
|
|
And the CLI output should contain "Stopped"
|
|
|
|
Scenario: CLI stop rejects non-devcontainer resource type
|
|
Given a mock resource service with git-checkout "local/my-repo" id "01TESTLIFECYCLE0000000201"
|
|
When I invoke CLI resource stop "local/my-repo"
|
|
Then the devcontainer CLI exit code should be non-zero
|
|
And the CLI output should contain "not a stoppable container type"
|
|
|
|
Scenario: CLI rebuild succeeds for stopped devcontainer-instance
|
|
Given a mock resource service with devcontainer "local/test-dc-rb" id "01TESTLIFECYCLE0000000210" at "/workspace/project"
|
|
And a stopped container "01TESTLIFECYCLE0000000210"
|
|
When I invoke CLI resource rebuild "local/test-dc-rb"
|
|
Then the CLI exit code should be 0
|
|
And the CLI output should contain "Rebuilt"
|
|
|
|
Scenario: CLI rebuild rejects resource with no location
|
|
Given a mock resource service with devcontainer "local/dc-no-loc" id "01TESTLIFECYCLE0000000211" with no location
|
|
And a stopped container "01TESTLIFECYCLE0000000211"
|
|
When I invoke CLI resource rebuild "local/dc-no-loc"
|
|
Then the devcontainer CLI exit code should be non-zero
|
|
And the CLI output should contain "no location"
|
|
|
|
Scenario: CLI rebuild rejects non-devcontainer resource type
|
|
Given a mock resource service with git-checkout "local/git-rb" id "01TESTLIFECYCLE0000000212"
|
|
When I invoke CLI resource rebuild "local/git-rb"
|
|
Then the devcontainer CLI exit code should be non-zero
|
|
And the CLI output should contain "rebuild requires devcontainer"
|
|
|
|
# ── R7: CLI test mock assertions ───────────────────────────
|
|
|
|
Scenario: CLI stop calls stop_container with correct resource_id
|
|
Given a mock resource service with devcontainer "local/test-dc-r7" id "01TESTLIFECYCLE0000000220" at "/workspace/project"
|
|
And an active container "01TESTLIFECYCLE0000000220" with container ID "ctr-r7"
|
|
When I invoke CLI resource stop "local/test-dc-r7"
|
|
Then the CLI exit code should be 0
|
|
And the CLI stop mock should have been called with "01TESTLIFECYCLE0000000220"
|
|
|
|
Scenario: CLI rebuild calls rebuild_container with correct args
|
|
Given a mock resource service with devcontainer "local/test-dc-r7rb" id "01TESTLIFECYCLE0000000221" at "/workspace/project"
|
|
And a stopped container "01TESTLIFECYCLE0000000221"
|
|
When I invoke CLI resource rebuild "local/test-dc-r7rb"
|
|
Then the CLI exit code should be 0
|
|
And the CLI rebuild mock should have been called with "01TESTLIFECYCLE0000000221" and "/workspace/project"
|
|
|
|
# ── R8: DevcontainerHandler coverage ───────────────────────
|
|
|
|
Scenario: DevcontainerHandler has expected class attributes and is instantiable
|
|
Then DevcontainerHandler should have _default_strategy "snapshot"
|
|
And DevcontainerHandler should have _type_label "devcontainer"
|
|
And DevcontainerHandler should be instantiable
|
|
|
|
Scenario: DevcontainerHandler extends BaseResourceHandler and inherits resolve interface
|
|
Then DevcontainerHandler should be a subclass of BaseResourceHandler
|
|
And DevcontainerHandler instance should have a resolve method
|
|
|
|
# ── R12: CLI state precondition validation ─────────────────
|
|
|
|
Scenario: CLI stop rejects container not in running state
|
|
Given a mock resource service with devcontainer "local/dc-det" id "01TESTLIFECYCLE0000000230" at "/workspace/project"
|
|
And a lifecycle tracker for resource "01TESTLIFECYCLE0000000230"
|
|
When I invoke CLI resource stop "local/dc-det"
|
|
Then the devcontainer CLI exit code should be non-zero
|
|
And the CLI output should contain "Cannot stop"
|
|
|
|
Scenario: CLI rebuild rejects container in running state
|
|
Given a mock resource service with devcontainer "local/dc-run" id "01TESTLIFECYCLE0000000231" at "/workspace/project"
|
|
And an active container "01TESTLIFECYCLE0000000231" with container ID "ctr-rb-state"
|
|
When I invoke CLI resource rebuild "local/dc-run"
|
|
Then the devcontainer CLI exit code should be non-zero
|
|
And the CLI output should contain "Cannot rebuild"
|
|
|
|
# ── R14: stop_all return list assertion ────────────────────
|
|
|
|
Scenario: Session cleanup returns list of stopped resource IDs
|
|
Given a mock devcontainer CLI runner
|
|
And an active container "01TESTLIFECYCLE0000000250" with container ID "ctr-r14a"
|
|
And an active container "01TESTLIFECYCLE0000000251" with container ID "ctr-r14b"
|
|
When I run session cleanup for session "session-r14"
|
|
Then the cleanup stopped list should contain "01TESTLIFECYCLE0000000250"
|
|
And the cleanup stopped list should contain "01TESTLIFECYCLE0000000251"
|
|
|
|
# ── A2: Stop and rebuild accept --yes flag ─────────────────
|
|
|
|
Scenario: CLI stop with --yes skips confirmation and calls stop_container
|
|
Given a CLI-mockable running devcontainer resource "test-dc-yes-stop"
|
|
When I invoke CLI resource stop "test-dc-yes-stop"
|
|
Then the devcontainer CLI exit code should be 0
|
|
And the CLI stop mock should have been called once
|
|
|
|
Scenario: CLI rebuild with --yes skips confirmation and calls rebuild_container
|
|
Given a CLI-mockable stopped devcontainer resource "test-dc-yes-rebuild"
|
|
When I invoke CLI resource rebuild "test-dc-yes-rebuild"
|
|
Then the devcontainer CLI exit code should be 0
|
|
And the CLI rebuild mock should have been called once
|
|
|
|
# ── Issue #2588: container-instance IS stoppable via CLI ────
|
|
|
|
Scenario: CLI stop accepts container-instance type (issue #2588 fix)
|
|
Given a mock resource service with container-instance "local/ctr-stop" id "01TESTLIFECYCLE0000000370" at "/workspace/project"
|
|
And an active container "01TESTLIFECYCLE0000000370" with container ID "ctr-ci-stop"
|
|
When I invoke CLI resource stop "local/ctr-stop"
|
|
Then the CLI exit code should be 0
|
|
And the CLI output should contain "Stopped"
|
|
And the CLI stop mock should have been called with "01TESTLIFECYCLE0000000370"
|
|
|
|
# ── F6-r6: CLI handler-level error paths ────────────────────
|
|
|
|
Scenario: CLI stop handles NotFoundError from show_resource
|
|
Given a mock resource service that raises NotFoundError for "local/missing"
|
|
When I invoke CLI resource stop "local/missing"
|
|
Then the devcontainer CLI exit code should be non-zero
|
|
And the CLI output should contain "Resource not found"
|
|
|
|
Scenario: CLI rebuild handles NotFoundError from show_resource
|
|
Given a mock resource service that raises NotFoundError for "local/missing-rb"
|
|
When I invoke CLI resource rebuild "local/missing-rb"
|
|
Then the devcontainer CLI exit code should be non-zero
|
|
And the CLI output should contain "Resource not found"
|
|
|
|
Scenario: CLI stop handles RuntimeError from stop_container
|
|
Given a mock resource service with devcontainer "local/dc-rterr" id "01TESTLIFECYCLE0000000500" at "/workspace/project"
|
|
And an active container "01TESTLIFECYCLE0000000500" with container ID "ctr-rterr"
|
|
And CLI stop_container mock that raises RuntimeError
|
|
When I invoke CLI resource stop with error mock "local/dc-rterr"
|
|
Then the devcontainer CLI exit code should be non-zero
|
|
And the CLI output should contain "Stop failed"
|
|
|
|
Scenario: CLI rebuild handles RuntimeError from rebuild_container
|
|
Given a mock resource service with devcontainer "local/dc-rberr" id "01TESTLIFECYCLE0000000501" at "/workspace/project"
|
|
And a stopped container "01TESTLIFECYCLE0000000501"
|
|
And CLI rebuild_container mock that raises RuntimeError
|
|
When I invoke CLI resource rebuild with error mock "local/dc-rberr"
|
|
Then the devcontainer CLI exit code should be non-zero
|
|
And the CLI output should contain "Rebuild failed"
|
|
|
|
# ── R7-F1: Session-scoped container cleanup ────────────────
|
|
|
|
Scenario: Session cleanup only stops containers belonging to that session
|
|
Given a mock devcontainer CLI runner
|
|
And a session-scoped active container "01TESTLIFECYCLE0000000600" with ID "ctr-s1" session "sess-A"
|
|
And a session-scoped active container "01TESTLIFECYCLE0000000601" with ID "ctr-s2" session "sess-B"
|
|
When I run session cleanup for session "sess-A"
|
|
Then the container state for "01TESTLIFECYCLE0000000600" should be "stopped"
|
|
And the container state for "01TESTLIFECYCLE0000000601" should be "running"
|
|
|
|
Scenario: Session cleanup with no session_id stops all containers
|
|
Given a mock devcontainer CLI runner
|
|
And an active container "01TESTLIFECYCLE0000000610" with container ID "ctr-all1"
|
|
And an active container "01TESTLIFECYCLE0000000611" with container ID "ctr-all2"
|
|
When I run session cleanup with no session filter
|
|
Then the container state for "01TESTLIFECYCLE0000000610" should be "stopped"
|
|
And the container state for "01TESTLIFECYCLE0000000611" should be "stopped"
|
|
|
|
# ── R8-F1: Eviction wired into production cleanup ────────────
|
|
|
|
Scenario: Session cleanup triggers terminal tracker eviction
|
|
Given a mock devcontainer CLI runner
|
|
And 210 stopped container trackers in the registry
|
|
And an active container "01TESTLIFECYCLE0000000650" with container ID "ctr-evict"
|
|
When I run session cleanup for session "session-evict"
|
|
Then the container state for "01TESTLIFECYCLE0000000650" should be "stopped"
|
|
And the registry should have at most 200 terminal trackers
|
|
|
|
# ── TEST-3: Coverage gap scenarios ──────────────────────────
|
|
|
|
Scenario: list_active_containers_for_session returns only matching session
|
|
Given a mock devcontainer CLI runner
|
|
And a session-scoped active container "01TESTLIFECYCLE0000000700" with ID "ctr-ts3a" session "sess-X"
|
|
And a session-scoped active container "01TESTLIFECYCLE0000000701" with ID "ctr-ts3b" session "sess-Y"
|
|
When I list active containers for session "sess-X"
|
|
Then the session container list should contain "01TESTLIFECYCLE0000000700"
|
|
And the session container list should not contain "01TESTLIFECYCLE0000000701"
|
|
|
|
Scenario: list_active_containers_for_session with empty session returns all
|
|
Given a mock devcontainer CLI runner
|
|
And an active container "01TESTLIFECYCLE0000000710" with container ID "ctr-ts3c"
|
|
And an active container "01TESTLIFECYCLE0000000711" with container ID "ctr-ts3d"
|
|
When I list active containers for an empty session
|
|
Then the session container list should contain "01TESTLIFECYCLE0000000710"
|
|
And the session container list should contain "01TESTLIFECYCLE0000000711"
|
|
|
|
Scenario: list_active_containers_for_session includes unscoped containers
|
|
Given a mock devcontainer CLI runner
|
|
And an active container "01TESTLIFECYCLE0000000720" with container ID "ctr-unscoped"
|
|
And a session-scoped active container "01TESTLIFECYCLE0000000721" with ID "ctr-scoped" session "sess-Z"
|
|
When I list active containers for session "sess-Z"
|
|
Then the session container list should contain "01TESTLIFECYCLE0000000720"
|
|
And the session container list should contain "01TESTLIFECYCLE0000000721"
|
|
|
|
# ── R7-F4: Session close cleanup without session service ────
|
|
|
|
Scenario: Session close cleans up containers even without session service
|
|
Given a facade with no session service
|
|
And a session-scoped active container "01TESTLIFECYCLE0000000630" with no docker ID session "sess-f4"
|
|
When I close session "sess-f4" via the facade
|
|
Then the container state for "01TESTLIFECYCLE0000000630" should be "stopped"
|