fix(cli): implement --mount flag on resource add container-instance #1134

Merged
hamza.khyari merged 1 commit from bugfix/m8-container-mount-flag into master 2026-03-27 13:26:27 +00:00
Member

Summary

Implements --mount flag on resource add container-instance per spec WF17.

Mount Formats

  • Resource-reference: --mount local/api-repo:/workspace (type=resource, mode=rw)
  • Host-path: --mount /var/config:/config:ro (type=bind, mode=rw|ro)
  • Multiple --mount flags supported on a single command

Changes

  • _parse_mount_spec() parses both formats with validation
  • Mounts stored as JSON string in properties["mounts"]
  • _format_properties() renders mounts in human-readable format for resource show
  • Added mount to container-instance cli_args metadata
  • 6 Behave BDD scenarios
  • Updated CHANGELOG

Example

agents resource add container-instance local/ctr --image node:18 \
    --mount local/api-repo:/workspace \
    --mount /var/shared/config:/config:ro

ISSUES CLOSED: #1078

## Summary Implements `--mount` flag on `resource add container-instance` per spec WF17. ## Mount Formats - Resource-reference: `--mount local/api-repo:/workspace` (type=resource, mode=rw) - Host-path: `--mount /var/config:/config:ro` (type=bind, mode=rw|ro) - Multiple `--mount` flags supported on a single command ## Changes - `_parse_mount_spec()` parses both formats with validation - Mounts stored as JSON string in `properties["mounts"]` - `_format_properties()` renders mounts in human-readable format for `resource show` - Added `mount` to container-instance `cli_args` metadata - 6 Behave BDD scenarios - Updated CHANGELOG ## Example ```bash agents resource add container-instance local/ctr --image node:18 \ --mount local/api-repo:/workspace \ --mount /var/shared/config:/config:ro ``` ISSUES CLOSED: #1078
freemo approved these changes 2026-03-24 15:25:20 +00:00
Dismissed
freemo left a comment

Review: APPROVED with Comments

Well-structured PR with clean implementation of mount parsing, good error handling via typer.BadParameter, and 6 BDD scenarios. The code follows existing project patterns. Approving, but please address the following items (some are important).

Issues to Address

  1. Logic bug in _parse_mount_spec()/ heuristic for type inference. At the 2-part parsing branch, the code uses "/" in parts[0] to determine type: "resource" vs type: "bind". This means --mount /data:/app (a valid 2-part absolute host-path) will be misclassified as type: "resource" because /data contains /. A resource name like local/api-repo also contains /, so the heuristic is ambiguous. Consider: parts[0].startswith("/") → bind; else → resource. Or require 3-part format for host paths.

  2. No milestone assigned. The branch is prefixed bugfix/m8-*, strongly suggesting it belongs to Milestone 8. Per CONTRIBUTING.md requirement #11, a milestone is mandatory. Please assign before merge.

  3. Merge conflicts. mergeable: false — needs a rebase against master.

  4. Metadata mismatch. _resource_registry_data.py adds a single mount field (singular, type string) in cli_args, but the CLI stores mounts (plural) as a JSON array in properties. The metadata key and the actual property key are inconsistent.

Minor Notes

  1. No test for the / heuristic ambiguity — e.g., --mount /data:/app (2-part host path) is never tested, so the misclassification goes undetected. Adding this test case would catch the bug in item #1.

  2. _NoClose wrapper in test steps is clever but opaque. A docstring comment explaining why session.close() is suppressed (to keep in-memory SQLite alive) would help future readers.

  3. Mounts stored as a JSON string inside a dict value is a serialization-within-serialization pattern. If properties is itself JSON-serialized to the DB, this results in double-encoded JSON. Worth considering a cleaner schema in a future iteration.

## Review: APPROVED with Comments Well-structured PR with clean implementation of mount parsing, good error handling via `typer.BadParameter`, and 6 BDD scenarios. The code follows existing project patterns. Approving, but please address the following items (some are important). ### Issues to Address 1. **Logic bug in `_parse_mount_spec()` — `/` heuristic for type inference.** At the 2-part parsing branch, the code uses `"/" in parts[0]` to determine `type: "resource"` vs `type: "bind"`. This means `--mount /data:/app` (a valid 2-part absolute host-path) will be misclassified as `type: "resource"` because `/data` contains `/`. A resource name like `local/api-repo` also contains `/`, so the heuristic is ambiguous. Consider: `parts[0].startswith("/")` → bind; else → resource. Or require 3-part format for host paths. 2. **No milestone assigned.** The branch is prefixed `bugfix/m8-*`, strongly suggesting it belongs to Milestone 8. Per CONTRIBUTING.md requirement #11, a milestone is mandatory. Please assign before merge. 3. **Merge conflicts.** `mergeable: false` — needs a rebase against master. 4. **Metadata mismatch.** `_resource_registry_data.py` adds a single `mount` field (singular, type `string`) in `cli_args`, but the CLI stores `mounts` (plural) as a JSON array in properties. The metadata key and the actual property key are inconsistent. ### Minor Notes 5. No test for the `/` heuristic ambiguity — e.g., `--mount /data:/app` (2-part host path) is never tested, so the misclassification goes undetected. Adding this test case would catch the bug in item #1. 6. `_NoClose` wrapper in test steps is clever but opaque. A docstring comment explaining *why* `session.close()` is suppressed (to keep in-memory SQLite alive) would help future readers. 7. Mounts stored as a JSON string inside a dict value is a serialization-within-serialization pattern. If `properties` is itself JSON-serialized to the DB, this results in double-encoded JSON. Worth considering a cleaner schema in a future iteration.
hamza.khyari force-pushed bugfix/m8-container-mount-flag from 1afb374e76
Some checks failed
CI / build (pull_request) Successful in 32s
CI / lint (pull_request) Successful in 3m19s
CI / quality (pull_request) Successful in 3m49s
CI / typecheck (pull_request) Successful in 3m53s
CI / integration_tests (pull_request) Successful in 6m49s
CI / benchmark-publish (pull_request) Has been skipped
CI / e2e_tests (pull_request) Failing after 14m19s
CI / unit_tests (pull_request) Failing after 14m57s
CI / security (pull_request) Failing after 14m59s
CI / coverage (pull_request) Successful in 12m41s
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 1s
CI / benchmark-regression (pull_request) Successful in 1h1m14s
to 3a58763750
Some checks failed
CI / build (pull_request) Successful in 21s
CI / lint (pull_request) Successful in 3m20s
CI / quality (pull_request) Successful in 3m49s
CI / typecheck (pull_request) Successful in 3m55s
CI / security (pull_request) Successful in 4m3s
CI / integration_tests (pull_request) Successful in 7m52s
CI / unit_tests (pull_request) Successful in 8m20s
CI / docker (pull_request) Successful in 1m16s
CI / e2e_tests (pull_request) Has been cancelled
CI / benchmark-regression (pull_request) Has been cancelled
CI / coverage (pull_request) Has been cancelled
CI / benchmark-publish (pull_request) Has been cancelled
CI / status-check (pull_request) Has been cancelled
2026-03-27 11:31:14 +00:00
Compare
hamza.khyari dismissed freemo's review 2026-03-27 11:31:14 +00:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

hamza.khyari added this to the v3.5.0 milestone 2026-03-27 11:32:29 +00:00
hamza.khyari force-pushed bugfix/m8-container-mount-flag from 3a58763750
Some checks failed
CI / build (pull_request) Successful in 21s
CI / lint (pull_request) Successful in 3m20s
CI / quality (pull_request) Successful in 3m49s
CI / typecheck (pull_request) Successful in 3m55s
CI / security (pull_request) Successful in 4m3s
CI / integration_tests (pull_request) Successful in 7m52s
CI / unit_tests (pull_request) Successful in 8m20s
CI / docker (pull_request) Successful in 1m16s
CI / e2e_tests (pull_request) Has been cancelled
CI / benchmark-regression (pull_request) Has been cancelled
CI / coverage (pull_request) Has been cancelled
CI / benchmark-publish (pull_request) Has been cancelled
CI / status-check (pull_request) Has been cancelled
to f5b4032854
Some checks failed
CI / build (pull_request) Successful in 20s
CI / security (pull_request) Successful in 1m2s
CI / quality (pull_request) Successful in 3m47s
CI / typecheck (pull_request) Successful in 4m14s
CI / integration_tests (pull_request) Successful in 7m7s
CI / e2e_tests (pull_request) Successful in 11m47s
CI / lint (pull_request) Successful in 3m18s
CI / benchmark-publish (pull_request) Has been skipped
CI / unit_tests (pull_request) Successful in 7m10s
CI / docker (pull_request) Successful in 1m13s
CI / coverage (pull_request) Successful in 11m39s
CI / status-check (pull_request) Successful in 2s
CI / benchmark-regression (pull_request) Has been cancelled
2026-03-27 11:42:05 +00:00
Compare
Author
Member

Response to @freemo Review

All 7 findings addressed in f5b40328. 8 scenarios passing (was 6).

# Finding Fix
1 / heuristic misclassifies /data:/app as resource type Changed to parts[0].startswith("/") — absolute paths are bind mounts, everything else is resource-reference
2 --mount accepted on all types Added type_name != "container-instance" guard with typer.Abort()
3 Metadata key mismatch (mount vs mounts) Renamed cli_args from mount to mounts with description explaining JSON array format
4 No test for /data:/app Added scenario: "Absolute host path 2-part mount is bind type" — verifies type: bind, mode: rw
5 No test for type validation Added scenario: "Mount rejected on non-container type"
6 _NoClose lacks docstring Added docstring explaining in-memory SQLite session keepalive
7 Double-encoded JSON Acknowledged — matches existing properties serialization pattern. Cleaner schema tracked for future iteration.

Process: Milestone v3.5.0 assigned. Rebased onto master (Mergeable: true).

## Response to @freemo Review All 7 findings addressed in `f5b40328`. 8 scenarios passing (was 6). | # | Finding | Fix | |---|---------|-----| | **1** | `/` heuristic misclassifies `/data:/app` as resource type | Changed to `parts[0].startswith("/")` — absolute paths are bind mounts, everything else is resource-reference | | **2** | `--mount` accepted on all types | Added `type_name != "container-instance"` guard with `typer.Abort()` | | **3** | Metadata key mismatch (`mount` vs `mounts`) | Renamed cli_args from `mount` to `mounts` with description explaining JSON array format | | **4** | No test for `/data:/app` | Added scenario: "Absolute host path 2-part mount is bind type" — verifies `type: bind`, `mode: rw` | | **5** | No test for type validation | Added scenario: "Mount rejected on non-container type" | | **6** | `_NoClose` lacks docstring | Added docstring explaining in-memory SQLite session keepalive | | **7** | Double-encoded JSON | Acknowledged — matches existing `properties` serialization pattern. Cleaner schema tracked for future iteration. | **Process:** Milestone v3.5.0 assigned. Rebased onto master (`Mergeable: true`).
hamza.khyari force-pushed bugfix/m8-container-mount-flag from f5b4032854
Some checks failed
CI / build (pull_request) Successful in 20s
CI / security (pull_request) Successful in 1m2s
CI / quality (pull_request) Successful in 3m47s
CI / typecheck (pull_request) Successful in 4m14s
CI / integration_tests (pull_request) Successful in 7m7s
CI / e2e_tests (pull_request) Successful in 11m47s
CI / lint (pull_request) Successful in 3m18s
CI / benchmark-publish (pull_request) Has been skipped
CI / unit_tests (pull_request) Successful in 7m10s
CI / docker (pull_request) Successful in 1m13s
CI / coverage (pull_request) Successful in 11m39s
CI / status-check (pull_request) Successful in 2s
CI / benchmark-regression (pull_request) Has been cancelled
to ebafe8cddd
Some checks failed
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 28s
CI / build (pull_request) Successful in 26s
CI / typecheck (pull_request) Successful in 3m57s
CI / security (pull_request) Successful in 4m3s
CI / quality (pull_request) Successful in 4m6s
CI / integration_tests (pull_request) Successful in 9m11s
CI / unit_tests (pull_request) Successful in 9m22s
CI / docker (pull_request) Successful in 1m0s
CI / coverage (pull_request) Successful in 12m22s
CI / status-check (pull_request) Successful in 1s
CI / benchmark-regression (pull_request) Has been cancelled
CI / e2e_tests (pull_request) Successful in 11m40s
2026-03-27 12:57:06 +00:00
Compare
hamza.khyari scheduled this pull request to auto merge when all checks succeed 2026-03-27 12:58:08 +00:00
hamza.khyari deleted branch bugfix/m8-container-mount-flag 2026-03-27 13:30:34 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core!1134
No description provided.