Skip to content

Add cmd_on_bind functionality to fetch_web plugin & testing plugin#899

Open
glowwserrano7 wants to merge 4 commits into
mainfrom
fetch-web-add-run-command
Open

Add cmd_on_bind functionality to fetch_web plugin & testing plugin#899
glowwserrano7 wants to merge 4 commits into
mainfrom
fetch-web-add-run-command

Conversation

@glowwserrano7

Copy link
Copy Markdown

Extends the fetch_web plugin by adding support for executing commands automatically after a web service bind event is detected. Commands can be executed on either the host or the emulated guest, making it easier to automate testing and verification.

Changes

  • Added the ability to execute commands after a web service bind event is detected, extending the fetch_web plugin for automated testing and verification:

    • Host mode: Executes commands on the host system with the working directory set to the project root.
    • Guest mode (default): Executes commands inside the emulated guest via the guest_cmd.py wrapper.
      • Requires guest_cmd: true under the core section of config.yaml.
      • Guest command output is automatically written to guest_commands_output.txt in the results directory for later analysis.
  • Added the shutdown_after_cmd option to automatically terminate the emulation after all cmd_on_bind commands have completed, similar to the existing shutdown_after_www behavior.

  • Added the fetch_web_testing plugin:

    • Added cmd_on_bind_guest_output_contains to verify expected guest command output.
    • Added cmd_wait_timeout to configure how long the test waits for cmd_on_bind commands to complete.
    • Supports validating both host marker files and guest command output.

Example

fetch_web

plugins:
  fetch_web:
    cmd_on_bind:
      - mode: host
        cmd:
          - python3 example.py
 
      - mode: guest
        cmd:
          - echo "im here" > /tmp/temp.txt && cat /tmp/temp.txt
        shutdown_after_cmd: true

Commands are executed automatically after the web service bind event is detected. Host commands execute from the project root, while guest commands execute inside the emulated guest via guest_cmd.py.

fetch_web_testing

plugins:
  fetch_web:
    outdir: results
    cmd_on_bind:
      - mode: host
        cmd:
          - touch hello.txt
      - mode: guest
        cmd:
          - echo "im here" > /tmp/temp.txt && cat /tmp/temp.txt
        shutdown_after_cmd: true

  fetch_web_testing:
    cmd_on_bind_marker: hello.txt
    cmd_on_bind_guest_output_contains:
      - here
    cmd_wait_timeout: 30

This configuration verifies that:

  • fetch_web successfully downloads content from the detected web service.
  • Host-mode commands create the expected marker file.
  • Guest-mode commands execute successfully and produce the expected output.

@glowwserrano7 glowwserrano7 requested a review from zestrada July 10, 2026 18:03

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Lintly has detected code quality issues in this pull request.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Lintly has detected code quality issues in this pull request.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Lintly has detected code quality issues in this pull request.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the existing fetch_web actuation plugin to optionally execute post-bind commands (host or guest) after a web service bind is detected, and adds a new fetch_web_testing plugin to validate both fetched web output and cmd-on-bind side effects/output.

Changes:

  • Add cmd_on_bind support to fetch_web, including host/guest execution modes and optional shutdown after commands.
  • Persist guest command output to guest_commands_output.txt for later verification.
  • Introduce fetch_web_testing plugin to verify fetch outputs, host marker files, and expected guest command output.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.

File Description
pyplugins/actuation/fetch_web.py Adds cmd-on-bind parsing/execution, host/guest modes, optional shutdown behavior, and guest-output capture.
pyplugins/testing/fetch_web_testing.py New integration-test plugin to verify fetch outputs and validate cmd-on-bind host/guest outcomes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +199 to +209
# Only trigger cmd_on_bind for 0.0.0.0 to avoid running commands
# multiple times
if self.cmd_on_bind_structured and guest_ip == "0.0.0.0":
self.logger.info(
f"Bind detected on {guest_ip}:{guest_port}, spawning cmd_on_bind thread")
t = threading.Thread(
target=self._delayed_bind_workflow, args=(guest_ip, guest_port)
)
t.daemon = True
t.start()

Comment on lines +275 to +288
# Determine working directory for host mode
if self.outdir:
cwd = os.path.abspath(
os.path.join(self.outdir, "../.."))
self.logger.info(
f"Derived project root from outdir: {cwd}")
if not os.path.isdir(cwd):
self.logger.warning(
f"Project root does not exist: {cwd}"
)
cwd = os.getcwd()
else:
cwd = os.getcwd()

Comment on lines +123 to +146
if self.cmd_on_bind is not None:
# Check if it's list of dicts with mode/cmd
if isinstance(
self.cmd_on_bind, list) and len(
self.cmd_on_bind) > 0:
if isinstance(self.cmd_on_bind[0], dict):
self.cmd_on_bind_structured = self.cmd_on_bind
self.logger.info(
"Using structured cmd_on_bind with mode specification"
)
else:
# List of strings (backward compatibility)
self.cmd_on_bind_structured = [
{"mode": "guest", "cmd": [str(c)]} for c in self.cmd_on_bind
]
self.logger.info("Converting legacy cmd_on_bind format")
elif isinstance(self.cmd_on_bind, str):
# Single string command (backward compatibility)
self.cmd_on_bind_structured = [
{"mode": "guest", "cmd": [str(self.cmd_on_bind)]}
]
self.logger.info("Converting single string cmd_on_bind")
else:
self.cmd_on_bind_structured = []
Comment on lines +33 to +36
self.cmd_on_bind_marker = self.get_arg("cmd_on_bind_marker")
self.cmd_on_bind_guest_output_contains = self.get_arg(
"cmd_on_bind_guest_output_contains")
self.cmd_wait_timeout = int(self.get_arg("cmd_wait_timeout") or 30)
Comment on lines +127 to +129
project_root = os.path.abspath(
os.path.join(self.outdir, "../.."))
marker_path = os.path.join(project_root, marker)
Comment on lines +148 to +150
# Guest-cmd must be enabled if any guest commands exist
has_guest_cmds = any(
entry.get("mode") == "guest" for entry in self.cmd_on_bind_structured)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants