Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.

add per-method description and timeout to shell commands#685

Merged
mangelajo merged 1 commit intojumpstarter-dev:mainfrom
michalskrivanek:shell-customization
Oct 7, 2025
Merged

add per-method description and timeout to shell commands#685
mangelajo merged 1 commit intojumpstarter-dev:mainfrom
michalskrivanek:shell-customization

Conversation

@michalskrivanek
Copy link
Contributor

@michalskrivanek michalskrivanek commented Oct 3, 2025

introducing new format in addition to the simple
methods:
method: "command"
you can now specify per-method customization with: methods:
method:
description: "This shows up in the CLI"
method: "echo Hello"
timeout: 5

Summary by CodeRabbit

  • New Features
    • Support two method configuration formats (simple string and unified per-method entries) that can be mixed; per-method command, description, and optional timeout supported. CLI shows per-command descriptions (defaults applied when absent). Runtime honors per-method timeouts and logs timeout context.
  • Documentation
    • Updated README, API and CLI docs with examples, mixed-format guidance, configuration parameters, and CLI help samples.
  • Tests
    • Expanded tests covering CLI commands, descriptions, mixed formats, exit codes, and description retrieval.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 3, 2025

Walkthrough

Adds support for two method formats (simple string or dict with command, description, timeout); exposes per-method descriptions to the client for CLI help registration at runtime; honors per-method timeouts during execution; updates README and tests to document and validate mixed-format usage.

Changes

Cohort / File(s) Summary
Docs: Config and CLI examples
packages/jumpstarter-driver-shell/README.md
Replaces single example with two formats (Format 1 simple string, Format 2 unified dict with command, description, timeout); adds Configuration Parameters, CLI Help Output, mixed-format examples, and updated CLI usage/help text.
Driver: Method formats, descriptions, timeouts
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py
Changes methods typing to `dict[str, str
Client/CLI: Runtime help registration
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py
Moves Click decorator application to runtime after retrieving descriptions via get_method_description (with fallback); sets __doc__ and applies click.argument/click.option/group registration dynamically.
Tests: Expanded coverage for CLI, descriptions, timeouts
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py
Adds/updates tests for command availability, exit codes, default/custom descriptions, unified and mixed formats; tests get_method_description RPC; adjusts CLI-related assertions to new registration behavior.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant CLI as CLI (client.py)
  participant Driver as Shell Driver (driver.py)
  participant Config as Methods Config

  rect rgb(245,248,255)
    note over CLI: Startup — register method commands
    CLI->>Config: Read methods (string or dict)
    CLI->>Driver: get_method_description(method)
    Driver-->>CLI: description (custom or default)
    CLI->>CLI: apply click decorators with help=description
  end

  User->>CLI: run command: <method> [args]
  CLI->>Driver: call_method(method, args)
  alt method has per-method timeout
    Driver->>Driver: extract command + per-method timeout
  else fallback to global timeout
    Driver->>Driver: extract command + global timeout
  end
  Driver->>Driver: _run_inline_shell_script(script, timeout)
  Driver-->>CLI: result (exit code, output)
  CLI-->>User: print result / help
Loading
sequenceDiagram
  autonumber
  participant Driver as Shell Driver
  participant Runner as Inline Shell Runner
  participant OS as Subprocess/Env

  Driver->>Runner: run(script, env, cwd, timeout)
  Runner->>OS: spawn process
  par stream stdout/stderr
    OS-->>Runner: stream data
  and monitor timeout
    Runner->>Runner: enforce timeout
  end
  alt timeout expires
    Runner-->>Driver: TimeoutExpired (per-method or global)
  else completes
    Runner-->>Driver: exit code, output
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • Update operator scripts for upstream repos jumpstarter#200 — Modifies the same shell driver package (driver, client, docs, tests); overlaps on method format and CLI registration changes.
  • jumpstarter-dev/jumpstarter#601 — Touches client._add_method_command and per-method metadata handling; directly related to dynamic descriptions and CLI setup.

Suggested reviewers

  • mangelajo
  • kirkbrauer
  • NickCao

Poem

Thump-thump on the README trail I go,
Commands in strings or boxes neatly show.
Descriptions whisper, timeouts softly chime,
I hop between formats, one carrot at a time. 🥕🐇

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately reflects the primary enhancement of the pull request by specifying the addition of per-method descriptions and timeouts to shell commands, matching the objectives and scope of the changeset. It is clear, concise, and focused on the main feature introduced without extraneous details.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 97fbefb and e94dc35.

📒 Files selected for processing (4)
  • packages/jumpstarter-driver-shell/README.md (5 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (7 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py
🧰 Additional context used
🧬 Code graph analysis (1)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (4)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
  • cli (42-57)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (2)
  • Shell (12-222)
  • client (46-47)
packages/jumpstarter/jumpstarter/common/utils.py (1)
  • serve (31-39)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (36-46)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: Redirect rules - jumpstarter-docs
  • GitHub Check: e2e
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.11)
  • GitHub Check: pytest-matrix (macos-15, 3.11)
  • GitHub Check: pytest-matrix (macos-15, 3.13)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.13)
  • GitHub Check: pytest-matrix (macos-15, 3.12)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.12)
🔇 Additional comments (22)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (10)

15-19: LGTM!

The type annotation correctly accounts for both string and dict formats, including the integer timeout field. The comments clearly document the two supported formats.


24-29: LGTM!

The method correctly handles both string and dict formats. The default "echo Hello" command for dict entries without a command key aligns with the documented behavior for placeholder methods (as shown in the README example).


31-36: LGTM!

Consistent extraction logic with sensible default descriptions for both formats.


38-43: LGTM!

Proper fallback to the global timeout when per-method timeout is not specified.


55-58: LGTM!

The method correctly exposes description retrieval to clients. Note that error handling for unknown methods was discussed in previous reviews and intentionally not included per PR #690.


70-72: LGTM!

Proper use of the helper methods to extract command and timeout. The enhanced logging provides valuable debugging context.


76-76: LGTM!

Correctly passes the per-method timeout to the execution layer.


153-153: LGTM!

The signature and docstring correctly reflect the new timeout parameter.

Also applies to: 162-162


184-186: LGTM!

Proper fallback ensures backward compatibility when timeout is not explicitly provided.


189-189: LGTM!

The runtime loop and exception handling correctly use the resolved timeout value (per-method or global fallback), ensuring the documented behavior is honored.

Also applies to: 204-204

packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (7)

104-106: LGTM!

Direct validation of CLI command structure is appropriate and straightforward.


109-128: LGTM!

Comprehensive validation that all configured methods are exposed in the CLI interface.


131-152: LGTM!

Thorough validation of exit code propagation including standard (0, 1) and custom (42) exit codes.


155-178: LGTM!

Validates that custom descriptions in the unified dict format are correctly exposed in the CLI help text.


181-199: LGTM!

Validates the default description fallback for string-format methods.


202-219: LGTM!

Comprehensive test of the new get_method_description export method covering both custom and default descriptions.


222-255: LGTM!

Excellent comprehensive test validating mixed-format support, including the default command fallback and CLI description generation for all format combinations. This ensures backward compatibility while exercising the new features.

packages/jumpstarter-driver-shell/README.md (5)

14-16: LGTM!

Clear introduction to the dual-format configuration, and the heading punctuation issue from the previous review has been addressed.


18-26: LGTM!

Clean example demonstrating the simple string format for self-descriptive commands.


28-65: LGTM!

Comprehensive and well-structured documentation covering all aspects of the unified format including multi-line commands, per-method timeouts, placeholder methods, and mixed-format usage. The examples are clear and practical.


67-84: LGTM!

Well-structured reference documentation with clear tables and explanations. The note about mixing formats is particularly helpful for users transitioning from the simple format.


118-166: LGTM!

Excellent user-facing documentation showing how configuration choices affect CLI help output. The side-by-side comparison of custom vs. default descriptions and the mixed-format example provide clear guidance on the expected behavior.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@netlify
Copy link

netlify bot commented Oct 3, 2025

Deploy Preview for jumpstarter-docs ready!

Name Link
🔨 Latest commit e94dc35
🔍 Latest deploy log https://app.netlify.com/projects/jumpstarter-docs/deploys/68e4c6bbb6ada20008eaf4f8
😎 Deploy Preview https://deploy-preview-685--jumpstarter-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6266878 and ebcdb3a.

📒 Files selected for processing (4)
  • packages/jumpstarter-driver-shell/README.md (5 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (7 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (4)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (2)
  • client (46-47)
  • Shell (12-222)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
  • cli (42-57)
packages/jumpstarter/jumpstarter/common/utils.py (1)
  • serve (31-39)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (36-46)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (36-46)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Redirect rules - jumpstarter-docs
  • GitHub Check: Header rules - jumpstarter-docs
  • GitHub Check: Pages changed - jumpstarter-docs
  • GitHub Check: e2e
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.13)
  • GitHub Check: pytest-matrix (macos-15, 3.11)
  • GitHub Check: pytest-matrix (macos-15, 3.12)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.12)
  • GitHub Check: pytest-matrix (macos-15, 3.13)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.11)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ebcdb3a and f958878.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (1 hunks)
  • packages/jumpstarter-driver-shell/README.md (5 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (7 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/jumpstarter-driver-shell/README.md
🧰 Additional context used
🧬 Code graph analysis (3)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (36-46)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (4)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (2)
  • client (46-47)
  • Shell (12-222)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
  • cli (42-57)
packages/jumpstarter/jumpstarter/common/utils.py (1)
  • serve (31-39)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (36-46)
packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (1)
packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/client.py (1)
  • cli (34-55)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Redirect rules - jumpstarter-docs
  • GitHub Check: Header rules - jumpstarter-docs
  • GitHub Check: Pages changed - jumpstarter-docs
  • GitHub Check: build
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.13)
  • GitHub Check: pytest-matrix (macos-15, 3.13)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.11)
  • GitHub Check: pytest-matrix (macos-15, 3.12)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.12)
  • GitHub Check: e2e
🔇 Additional comments (2)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)

77-91: Fallback preserves older driver compatibility.
Wrapping the RPC in a broad try/except keeps CLI generation working against pre-0.7 servers while still surfacing richer help text when available. Nicely handled.

packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (1)

130-255: Expanded tests cover new CLI metadata paths.
Great job validating exit codes, custom descriptions, default fallbacks, and mixed method formats—this suite gives strong confidence in the new configuration shape.

Comment on lines 50 to 53
for k, v in self.children.items():
if hasattr(v, "cli"):
# Check if the cli method accepts a click_group parameter
sig = inspect.signature(v.cli)
if "click_group" in sig.parameters:
base.add_command(v.cli(click_group=base), k)
else:
base.add_command(v.cli(), k)
base.add_command(v.cli(), k)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Regression: child CLIs needing the parent group now break.

Many drivers’ cli factories (e.g. jumpstarter_driver_tmt.client.ShellClient.cli(self, click_group)) still expect the parent click.Group to be passed in. Removing the signature check and calling v.cli() unconditionally now raises TypeError for every such driver, so composite CLIs stop booting. Please keep supporting both styles—detect whether the child cli expects a group parameter and pass base accordingly.

🤖 Prompt for AI Agents
In packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py
around lines 50 to 53, the loop unconditionally calls v.cli() which breaks
drivers whose cli factories expect the parent click.Group parameter; update the
code to detect whether v.cli accepts a parameter and call v.cli(base) when it
does, otherwise call v.cli() — e.g., use inspect.signature (or similar) to check
the number of parameters or try calling with base and fall back on calling
without it, then add the resulting command to base with base.add_command(...,
k).

Comment on lines 56 to 65
def test_multi_line_scripts(client):
stdout, stderr, returncode = _collect_streaming_output(client, "multi_line", {}, "a", "b", "c")
assert stdout == "a\nb\nc\n"
def test_normal_multi_line(client):
stdout, stderr, returncode = _collect_streaming_output(client, "multi_line", {}, "hello", "world", "!")
assert stdout == "hello\nworld\n!\n"
assert stderr == ""
assert returncode == 0


def test_return_codes(client):
stdout, stderr, returncode = _collect_streaming_output(client, "exit1")
assert stdout == ""
assert stderr == ""
def test_exit_code(client):
stdout, stderr, returncode = _collect_streaming_output(client, "exit1", {})
assert returncode == 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think AI is being creative here with unnecessary changes :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hehe

Comment on lines 79 to 80
client.unknown()
except AttributeError as e:
assert "method unknown not found in" in str(e)
_collect_streaming_output(client, "unknown_method", {})
except Exception as e:
assert "not found" in str(e)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this change needed?

won't a regular call to .unknown method fail in the same way?

Copy link
Member

@mangelajo mangelajo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only some nits about testing, it looks good,

only one question about test_unknown_method test.

Comment on lines +205 to +210
"method1": {
"command": "echo",
"description": "Custom description for method1"
},
"method2": "ls", # String format, should use default description
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah cool so it's backwards compatible 💯

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah it's not too ugly to keep supporting the old way as well. maybe it will still be useful for simple things like
methods:
ls: ls

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/jumpstarter-driver-shell/README.md (1)

16-16: Fix heading punctuation.

The heading "Format 1: Simple String e.g. for self-descriptive short commands)" has a stray closing parenthesis. Either add the opening parenthesis after "Simple String" or remove the trailing one.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f958878 and 8322e57.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (17)
  • packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (2 hunks)
  • packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py (1 hunks)
  • packages/jumpstarter-driver-gpiod/jumpstarter_driver_gpiod/client.py (2 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/client.py (1 hunks)
  • packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (1 hunks)
  • packages/jumpstarter-driver-power/jumpstarter_driver_power/client_test.py (1 hunks)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/client.py (1 hunks)
  • packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/client.py (1 hunks)
  • packages/jumpstarter-driver-shell/README.md (5 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (2 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (7 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (1 hunks)
  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/client.py (1 hunks)
  • packages/jumpstarter-driver-ssh/jumpstarter_driver_ssh/client.py (1 hunks)
  • packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/client.py (1 hunks)
  • packages/jumpstarter/jumpstarter/client/base.py (1 hunks)
  • packages/jumpstarter/jumpstarter/driver/base.py (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py
🧰 Additional context used
🧬 Code graph analysis (12)
packages/jumpstarter-driver-network/jumpstarter_driver_network/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • get_cli_description (92-111)
packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • get_cli_description (92-111)
packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/client.py (2)
packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (1)
  • cli (36-53)
packages/jumpstarter-driver-ssh/jumpstarter_driver_ssh/client.py (1)
  • cli (21-33)
packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • get_cli_description (92-111)
packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (2)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • get_cli_description (92-111)
packages/jumpstarter-driver-opendal/jumpstarter_driver_opendal/client.py (6)
  • base (417-418)
  • base (552-554)
  • cli (408-522)
  • cli (550-590)
  • cli (717-741)
  • cli (791-793)
packages/jumpstarter-driver-gpiod/jumpstarter_driver_gpiod/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • get_cli_description (92-111)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • get_cli_description (92-111)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client_test.py (3)
packages/jumpstarter/jumpstarter/common/utils.py (1)
  • serve (31-39)
packages/jumpstarter-driver-power/jumpstarter_driver_power/driver.py (3)
  • MockPower (39-64)
  • client (10-11)
  • client (25-26)
packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (2)
  • cli (37-59)
  • cli (66-75)
packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • get_cli_description (92-111)
packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • get_cli_description (92-111)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (4)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
  • cli (42-56)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (2)
  • Shell (12-222)
  • client (46-47)
packages/jumpstarter/jumpstarter/common/utils.py (1)
  • serve (31-39)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (36-46)
packages/jumpstarter-driver-ssh/jumpstarter_driver_ssh/client.py (2)
packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (1)
  • cli (36-53)
packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/client.py (1)
  • cli (34-55)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Redirect rules - jumpstarter-docs
  • GitHub Check: Header rules - jumpstarter-docs
  • GitHub Check: Pages changed - jumpstarter-docs
  • GitHub Check: build
  • GitHub Check: pytest-matrix (macos-15, 3.12)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.11)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.13)
  • GitHub Check: pytest-matrix (macos-15, 3.13)
  • GitHub Check: pytest-matrix (macos-15, 3.11)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.12)
  • GitHub Check: e2e
🔇 Additional comments (26)
packages/jumpstarter/jumpstarter/driver/base.py (1)

76-110: LGTM! Clean addition of driver description support.

The new description field and get_description() method provide a clean mechanism for drivers to expose custom descriptions for CLI help text. The implementation is correct:

  • Optional field with clear docstring
  • Proper use of @export decorator for RPC access
  • Returns str | None as expected by consumers
packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/client.py (1)

20-20: LGTM! Consistent use of dynamic CLI descriptions.

The CLI group now uses self.get_cli_description("SNMP power control commands") to provide dynamic help text with a sensible default fallback.

packages/jumpstarter/jumpstarter/client/base.py (1)

92-111: LGTM! Well-designed fallback mechanism.

The get_cli_description() method provides a robust way to retrieve driver descriptions with proper error handling:

  • Attempts to fetch custom description via RPC
  • Gracefully handles failures (driver may not support get_description)
  • Returns sensible default as fallback
  • Clear documentation
packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/client.py (1)

105-105: LGTM! Consistent CLI description pattern.

The storage group now uses dynamic help text via get_cli_description("RideSX storage operations").

packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py (1)

753-753: LGTM! Consistent CLI description pattern.

The base CLI group now uses dynamic help text via get_cli_description("Software-defined flasher interface").

packages/jumpstarter-driver-gpiod/jumpstarter_driver_gpiod/client.py (2)

37-37: LGTM! Consistent CLI description pattern.

The GPIO power control CLI group now uses dynamic help text.


81-81: LGTM! Consistent CLI description pattern.

The GPIO input CLI group now uses dynamic help text.

packages/jumpstarter-driver-ssh/jumpstarter_driver_ssh/client.py (1)

21-33: LGTM! Simplified CLI registration.

The SSH client now returns a command directly using @click.command(...) rather than accepting a parent group parameter. This aligns with the TMT driver pattern and simplifies the interface by removing the click_group parameter from the signature.

packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (2)

37-37: LGTM! Consistent CLI description pattern.

The composite device CLI group now uses dynamic help text via get_cli_description("Generic composite device").


49-51: All child drivers now support parameterless cli() jumpstarter-driver-opendal/client.py still defines cli(self, base=None) to preserve backward compatibility; all other drivers use a parameterless cli().

packages/jumpstarter-driver-shell/README.md (3)

28-66: LGTM! Comprehensive examples.

The unified format examples effectively demonstrate all supported configurations: custom descriptions, multi-line commands, description-only methods, custom timeouts, and format mixing. The inline comments enhance clarity.


116-166: LGTM! Clear CLI documentation.

The CLI sections effectively illustrate the difference between unified format (custom descriptions) and simple format (default descriptions), including a helpful mixed-format example.


67-84: Default command documentation matches implementation

The driver.py default of "echo Hello" aligns with the README.

packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (7)

100-107: LGTM! Safe indexing change.

Switching from .get() to direct indexing is acceptable here since the test fixture guarantees the 'echo' method exists. The assertion on line 106 confirms the command structure.


109-128: LGTM! Thorough CLI method presence test.

The test properly verifies that all configured methods are exposed as CLI commands using set equality, ensuring no methods are missing or unexpectedly added.


131-153: LGTM! Exit code validation test.

This test properly verifies that shell command exit codes are correctly propagated through the driver, covering success (0), standard failure (1), and custom exit codes (42).


155-179: LGTM! Custom description validation.

The test effectively validates that custom descriptions from the unified format are properly exposed in CLI command help text.


181-200: LGTM! Default description validation.

This test ensures backwards compatibility by verifying that simple string-format methods receive appropriate default descriptions following the established pattern.


202-220: LGTM! Export method validation.

The test properly validates the get_method_description export method for both unified format (custom description) and simple format (default description).


222-256: LGTM! Comprehensive mixed-format test.

This test thoroughly validates the core feature by mixing all supported formats (simple string, dict with command, dict with description-only) and verifying both execution and CLI help text. The test confirms that methods without a command specification can still execute successfully.

packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (6)

24-29: LGTM! Clean command extraction.

The helper correctly handles both string and dict formats, with an appropriate default command. The default "echo Hello" is simple and safe for testing.


31-36: LGTM! Consistent description extraction.

The helper properly generates default descriptions for simple formats and extracts custom descriptions from the unified format, maintaining consistency with the documented behavior.


38-43: LGTM! Proper timeout resolution.

The helper correctly implements the timeout fallback chain: per-method timeout → global timeout. This allows fine-grained control while maintaining a sensible default.


55-58: LGTM! Clean public API.

The exported method provides a clean interface for clients to retrieve method descriptions, essential for generating CLI help text at runtime.


60-89: LGTM! Proper helper integration.

The method correctly uses the new helper functions to extract command and timeout, and properly threads the per-method timeout through to the execution layer. The logging enhancement aids debugging.


152-222: LGTM! Clean timeout integration.

The timeout parameter is properly integrated into the execution loop:

  • Backwards-compatible signature with timeout=None
  • Correct fallback to global timeout
  • Proper use in timing logic and exception handling

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (1)

15-44: Broaden methods type to cover per-method timeouts

The new unified format allows timeout: int, but the annotation still constrains dict values to dict[str, str]. Static type-checkers (and IDEs) now flag every config using a numeric timeout. Please widen the type, e.g. by introducing a TypedDict with optional command, description, and timeout keys, or by extending the union to include int values.

-from dataclasses import dataclass, field
-from typing import AsyncGenerator
+from dataclasses import dataclass, field
+from typing import AsyncGenerator, TypedDict
...
-    methods: dict[str, str | dict[str, str]]
+class MethodConfig(TypedDict, total=False):
+    command: str
+    description: str
+    timeout: int
+
+
+@dataclass(kw_only=True)
+class Shell(Driver):
+    ...
+    methods: dict[str, str | MethodConfig]
🧹 Nitpick comments (1)
packages/jumpstarter-driver-shell/README.md (1)

50-56: Clarify placeholder command behavior

Documentation claims “Description-only (uses default echo Hello command)”, but the actual driver defaults to command = "echo Hello" only when command is omitted and configuration is the dict form. For this placeholder example you should either show the default command explicitly or note that omitting command causes the driver to run "echo Hello" so readers know what will execute.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8322e57 and 4e8aa05.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (24)
  • packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (2 hunks)
  • packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py (1 hunks)
  • packages/jumpstarter-driver-gpiod/jumpstarter_driver_gpiod/client.py (2 hunks)
  • packages/jumpstarter-driver-network/jumpstarter_driver_network/client.py (1 hunks)
  • packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (1 hunks)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/client.py (1 hunks)
  • packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/client.py (1 hunks)
  • packages/jumpstarter-driver-shell/README.md (5 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (2 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (7 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (1 hunks)
  • packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/client.py (1 hunks)
  • packages/jumpstarter-driver-ssh/jumpstarter_driver_ssh/client.py (1 hunks)
  • packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/client.py (1 hunks)
  • packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/driver_test.py (5 hunks)
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py (2 hunks)
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py (1 hunks)
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2_grpc.py (8 hunks)
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/kubernetes_pb2.py (1 hunks)
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/router_pb2.py (1 hunks)
  • packages/jumpstarter/jumpstarter/client/base.py (1 hunks)
  • packages/jumpstarter/jumpstarter/client/client.py (2 hunks)
  • packages/jumpstarter/jumpstarter/driver/base.py (1 hunks)
  • packages/jumpstarter/jumpstarter/exporter/session.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/v1/jumpstarter_pb2.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/jumpstarter-driver-pyserial/jumpstarter_driver_pyserial/client.py
  • packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py
  • packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py
🧰 Additional context used
🧬 Code graph analysis (7)
packages/jumpstarter-driver-ssh/jumpstarter_driver_ssh/client.py (2)
packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (1)
  • cli (36-53)
packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/client.py (1)
  • cli (34-55)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (39-49)
packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/driver_test.py (2)
packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (1)
  • cli (36-53)
packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/client.py (1)
  • cli (34-55)
packages/jumpstarter/jumpstarter/exporter/session.py (2)
packages/jumpstarter/jumpstarter/driver/base.py (2)
  • enumerate (214-225)
  • report (195-212)
packages/jumpstarter-driver-composite/jumpstarter_driver_composite/driver.py (2)
  • enumerate (40-41)
  • report (37-38)
packages/jumpstarter/jumpstarter/client/client.py (2)
packages/jumpstarter/jumpstarter/driver/base.py (1)
  • report (195-212)
packages/jumpstarter-driver-composite/jumpstarter_driver_composite/driver.py (1)
  • report (37-38)
packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/client.py (2)
packages/jumpstarter-driver-composite/jumpstarter_driver_composite/client.py (1)
  • cli (36-53)
packages/jumpstarter-driver-ssh/jumpstarter_driver_ssh/client.py (1)
  • cli (21-33)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (4)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
  • cli (42-56)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (2)
  • Shell (12-222)
  • client (46-47)
packages/jumpstarter/jumpstarter/common/utils.py (1)
  • serve (31-39)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (39-49)
🪛 GitHub Actions: documentation
packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py

[error] 34-34: ImportError: cannot import name 'common_pb2' from 'jumpstarter_protocol.jumpstarter.v1' (during Sphinx docs build)

🪛 GitHub Actions: Run Tests
packages/jumpstarter-protocol/jumpstarter_protocol/jumpstarter/client/v1/client_pb2.py

[error] 34-34: ImportError: cannot import name 'common_pb2' from 'jumpstarter_protocol.jumpstarter.v1'. This occurs while importing generated protobuf modules during test discovery.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: e2e
🔇 Additional comments (15)
packages/jumpstarter-driver-ssh/jumpstarter_driver_ssh/client.py (1)

21-22: Approve CLI signature change
No callers of SSHWrapperClient.cli() pass a group argument; removing the click_group parameter is safe and aligns with other drivers.

packages/jumpstarter/jumpstarter/driver/base.py (1)

75-77: LGTM! Clean addition of description field.

The new optional description field is well-documented and properly typed. The placement between existing fields is logical, and the default value of None ensures backward compatibility.

packages/jumpstarter-driver-power/jumpstarter_driver_power/client.py (1)

38-40: LGTM! Consistent implementation of dynamic help text.

The decorator now sources help text from self.description with a sensible fallback, aligning with the PR's objective to surface driver descriptions in CLI help.

packages/jumpstarter-driver-network/jumpstarter_driver_network/client.py (1)

23-25: LGTM! Consistent pattern applied.

The dynamic help text implementation matches the pattern established across other drivers in this PR.

packages/jumpstarter-driver-snmp/jumpstarter_driver_snmp/client.py (1)

20-22: LGTM! Appropriate help text for SNMP driver.

The help text implementation is consistent with other drivers and provides a clear description of the SNMP power control functionality.

packages/jumpstarter/jumpstarter/client/base.py (1)

36-38: LGTM! Parallel implementation for client side.

The description field on DriverClient mirrors the server-side Driver field, enabling CLI help text to be propagated from the driver through GetReport. The docstring clearly explains the data flow.

packages/jumpstarter-driver-gpiod/jumpstarter_driver_gpiod/client.py (2)

37-39: LGTM! Consistent help text for GPIO output.

The dynamic help text implementation provides appropriate context for GPIO power control operations.


81-83: LGTM! Consistent help text for GPIO input.

The dynamic help text implementation appropriately differentiates input operations from output operations.

packages/jumpstarter-driver-ridesx/jumpstarter_driver_ridesx/client.py (1)

105-107: LGTM! Descriptive help text for RideSX storage.

The help text appropriately describes the storage operations context for the RideSX driver.

packages/jumpstarter/jumpstarter/exporter/session.py (2)

118-118: LGTM! Descriptions added to GetReportResponse.

The descriptions map is properly included in the response, enabling clients to retrieve all driver descriptions in a single RPC call as documented in the comment.


104-109: Approve description collection logic. enumerate() consistently returns a 4-tuple (uuid, parent, name, instance) across driver implementations, so the filtering and mapping of instance.description is safe.

packages/jumpstarter/jumpstarter/client/client.py (2)

39-40: LGTM!

The defensive use of getattr with a default empty dict ensures backward compatibility when the descriptions field is absent from the response.


64-64: Verify client constructors accept description
Manually confirm that every *Client class in packages/jumpstarter/jumpstarter/client/ (and its base classes) defines an __init__ signature accepting the description keyword (or **kwargs) to prevent runtime errors.

packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/driver_test.py (1)

26-435: LGTM! Test updates align with CLI signature changes.

The test suite has been correctly updated to reflect the new CLI attachment model where TMT commands are invoked directly without a top-level "tmt" subcommand group. All test invocations consistently remove the "tmt" prefix from argument lists, and the test logic remains sound.

packages/jumpstarter-driver-tmt/jumpstarter_driver_tmt/client.py (1)

34-36: LGTM! CLI signature simplification aligns with the new attachment model.

Removing the click_group parameter and using @click.command directly simplifies the CLI integration and aligns with the pattern used in other drivers (e.g., SSH driver). The test suite confirms this change works correctly.

@michalskrivanek michalskrivanek force-pushed the shell-customization branch 2 times, most recently from fd403f3 to 0f229d7 Compare October 3, 2025 16:07
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)

77-81: Fallback description does not match legacy wording.

The fallback description at line 81 uses f"Execute {method_name}", but the past review comment specifically requested f"Execute the {method_name} shell method" to preserve exact legacy wording for pre-0.7 servers. This discrepancy means the help text will differ from documented behavior when talking to older servers.

Apply this diff to restore the legacy wording:

-            description = f"Execute {method_name}"
+            description = f"Execute the {method_name} shell method"
🧹 Nitpick comments (1)
packages/jumpstarter-driver-shell/README.md (1)

71-72: Call out per-method timeout in the methods table for completeness

The table row for methods mentions only command and description, so readers can miss that dict entries may also override timeout. Please surface the new field here to keep the quick-reference accurate.

-| `methods` | Dictionary of methods. Values can be:<br/>- String: just the command<br/>- Dict: `{command: "...", description: "..."}` | `dict[str, str \| dict]` | Yes | - |
+| `methods` | Dictionary of methods. Values can be:<br/>- String: just the command<br/>- Dict: `{command: "...", description: "...", timeout: ...}` | `dict[str, str \| dict]` | Yes | - |
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e8aa05 and 0f229d7.

📒 Files selected for processing (4)
  • packages/jumpstarter-driver-shell/README.md (5 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (7 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py
🧰 Additional context used
🧬 Code graph analysis (2)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (36-46)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (4)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
  • cli (42-57)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (2)
  • Shell (12-222)
  • client (46-47)
packages/jumpstarter/jumpstarter/common/utils.py (1)
  • serve (31-39)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (36-46)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Redirect rules - jumpstarter-docs
  • GitHub Check: Header rules - jumpstarter-docs
  • GitHub Check: Pages changed - jumpstarter-docs
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.12)
  • GitHub Check: pytest-matrix (macos-15, 3.12)
  • GitHub Check: pytest-matrix (macos-15, 3.11)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.11)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.13)
  • GitHub Check: build
  • GitHub Check: e2e
🔇 Additional comments (8)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)

84-91: LGTM! Dynamic decorator application is correctly implemented.

The decorator chain properly applies click decorators after retrieving the method description, and the command registration uses the retrieved description as help text. This enables runtime description resolution as intended by the PR.

packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (7)

104-106: LGTM! Direct indexing is appropriate for test assertions.

The change from .get('echo') to direct indexing ['echo'] is acceptable in test context. If the command doesn't exist, the KeyError provides a clear failure signal, which is appropriate for testing expected behavior.


109-128: LGTM! Test properly validates CLI method inclusion.

The test correctly verifies that all configured methods appear as CLI commands. The assertions are clear and the test structure is sound.


131-153: LGTM! Exit code handling is properly tested.

The test effectively validates that shell command exit codes are correctly propagated through the client interface, covering success, failure, and custom exit codes.


155-179: LGTM! Custom descriptions are properly tested.

The test effectively validates the new unified dict format for method configuration with custom descriptions. The assertions confirm that custom descriptions appear correctly in CLI help text.


181-200: LGTM! Default descriptions are properly tested.

The test correctly validates that methods using the simple string format receive default descriptions with the legacy wording "Execute the {method} shell method". This ensures backward compatibility is maintained.


202-220: LGTM! RPC method for descriptions is properly tested.

The test effectively validates the get_method_description export method, covering both custom descriptions from dict format and default descriptions from string format. The assertions correctly verify the RPC behavior.


222-255: LGTM! Mixed format support is thoroughly tested.

This comprehensive test validates that string format, dict format with custom command and description, and dict format with only description (using default command) all work correctly together. The test covers both execution and CLI description generation for all three formats, ensuring the feature is robust and backward compatible.

@michalskrivanek michalskrivanek force-pushed the shell-customization branch 2 times, most recently from cde250b to 6767fd3 Compare October 3, 2025 17:01
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/jumpstarter-driver-shell/README.md (1)

79-82: Consider clarifying per-method timeout behavior.

While the current text correctly states that per-method timeout "defaults to global timeout value", it might be clearer to explicitly mention that the global default is 300 seconds. This helps users understand what happens when they omit both global and per-method timeout.

Consider this minor clarification:

 - `timeout`: Command-specific timeout in seconds (optional, defaults to global `timeout` value)
+- `timeout`: Command-specific timeout in seconds (optional, defaults to global `timeout` value of 300 seconds)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f229d7 and 6767fd3.

📒 Files selected for processing (4)
  • packages/jumpstarter-driver-shell/README.md (5 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (7 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (36-46)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (4)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
  • cli (42-57)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (2)
  • Shell (12-222)
  • client (46-47)
packages/jumpstarter/jumpstarter/common/utils.py (1)
  • serve (31-39)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (36-46)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: pytest-matrix (macos-15, 3.13)
🔇 Additional comments (4)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)

77-91: LGTM! Backward compatibility preserved.

The try/except block correctly handles the scenario where get_method_description isn't available on pre-0.7 servers. The fallback to the legacy help text format ("Execute the {method_name} shell method") ensures consistent behavior with older versions. The dynamic decoration after description retrieval is correctly structured.

packages/jumpstarter-driver-shell/README.md (1)

118-166: LGTM! Documentation accurately reflects the CLI behavior.

The CLI usage documentation clearly demonstrates how descriptions appear in help output for unified format (custom descriptions), simple format (default descriptions), and mixed format. The examples are consistent with the implementation.

packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (1)

222-255: LGTM! Comprehensive test coverage for mixed formats.

This test thoroughly validates the mixed format feature by:

  • Testing execution of all three format variants (simple string, detailed dict, dict with description-only)
  • Verifying CLI help text for each format
  • Ensuring the default command fallback works correctly

The test coverage ensures the feature works correctly in all documented scenarios.

packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (1)

152-222: LGTM! Timeout handling correctly implemented.

The per-method timeout feature is well-integrated:

  • The timeout parameter is properly threaded through the execution path
  • Fallback to self.timeout provides a sensible default
  • Timeout enforcement uses the correct local value
  • The TimeoutExpired exception accurately reflects the timeout that was enforced

The defensive None check (lines 184-185) is good practice even though the current call path always provides a timeout.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6767fd3 and 97fbefb.

📒 Files selected for processing (4)
  • packages/jumpstarter-driver-shell/README.md (5 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (7 hunks)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py
🧰 Additional context used
🧬 Code graph analysis (1)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver_test.py (4)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/client.py (1)
  • cli (42-57)
packages/jumpstarter-driver-shell/jumpstarter_driver_shell/driver.py (2)
  • Shell (12-222)
  • client (46-47)
packages/jumpstarter/jumpstarter/common/utils.py (1)
  • serve (31-39)
packages/jumpstarter/jumpstarter/client/base.py (1)
  • call (36-46)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Redirect rules - jumpstarter-docs
  • GitHub Check: Header rules - jumpstarter-docs
  • GitHub Check: Pages changed - jumpstarter-docs
  • GitHub Check: pytest-matrix (macos-15, 3.13)
  • GitHub Check: pytest-matrix (macos-15, 3.11)
  • GitHub Check: pytest-matrix (macos-15, 3.12)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.11)
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.13)
  • GitHub Check: build
  • GitHub Check: pytest-matrix (ubuntu-24.04, 3.12)
  • GitHub Check: e2e

michalskrivanek referenced this pull request in michalskrivanek/jumpstarter Oct 7, 2025
introducing new format in addition to the simple
methods:
  method: "command"
you can now specify per-method customization with:
methods:
  method:
    description: "This shows up in the CLI"
    method: "echo Hello"
    timeout: 5
michalskrivanek referenced this pull request in michalskrivanek/jumpstarter Oct 7, 2025
michalskrivanek referenced this pull request in michalskrivanek/jumpstarter Oct 7, 2025
@mangelajo mangelajo merged commit e94dc35 into jumpstarter-dev:main Oct 7, 2025
18 checks passed
mangelajo referenced this pull request in jumpstarter-dev/jumpstarter Jan 21, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants