gridfleet-agent 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/CHANGELOG.md +14 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/PKG-INFO +1 -1
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/appium_process.py +36 -1
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/pyproject.toml +1 -1
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/installer/test_plan.py +3 -3
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_appium_process.py +54 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/uv.lock +1 -1
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/.gitignore +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/README.md +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/__init__.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/capabilities.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/cli.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/config.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/driver_doctor.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/host_telemetry.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/installer/__init__.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/installer/install.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/installer/plan.py +2 -2
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/installer/status.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/installer/uninstall.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/installer/update.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/main.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/observability.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/__init__.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/adapter_dispatch.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/adapter_loader.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/adapter_registry.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/adapter_types.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/adapter_utils.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/discovery.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/dispatch.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/host_identity.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/manifest.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/runtime.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/runtime_policy.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/runtime_registry.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/sidecar_supervisor.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/state.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/tarball_fetch.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/pack/version_catalog.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/plugin_manager.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/py.typed +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/registration.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/terminal_pty.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/terminal_ws.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/tool_paths.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/tool_utils.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/tools_manager.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/agent_app/version_guidance.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/__init__.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/installer/test_cli_install.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/installer/test_install.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/installer/test_status.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/installer/test_uninstall.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/installer/test_update.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/__init__.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/conftest.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_adapter_dispatch.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_adapter_loader.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_adapter_loader_cancel_path_leak.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_adapter_loader_concurrent_load.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_adapter_tarball_auth.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_adapter_utils.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_adapter_wiring.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_appium_process_integration.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_desired_manifest_features.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_feature_action_routes.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_host_identity.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_manifest_parser.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_pack_discovery_endpoint.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_pack_state.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_pack_state_client_auth.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_pack_state_sidecar_reconcile.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_runtime_github.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_runtime_isolated_failures.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_runtime_manager.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_runtime_plugins.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_runtime_policy.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_sidecar_supervisor.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_sidecar_supervisor_poll_stop_race.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_state_loop.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_state_loop_wired.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_tarball_fetch.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_tarball_fetch_concurrent_dedup.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_version_catalog.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_agent_api.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_agent_api_more.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_appium_process_port_alloc_race.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_appium_process_restart_stop_race.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_appium_process_stop_start_lock_race.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_appium_process_watch_stop_race.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_capabilities.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_capabilities_more.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_cli.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_config.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_config_runtime_root.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_driver_doctor.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_host_telemetry.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_install_script.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_no_driver_imports.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_observability.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_package_metadata.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_plugin_manager.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_plugin_manager_more.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_registration.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_terminal_pty.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_terminal_ws.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_tools_and_utilities_more.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_tools_manager.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_tools_manager_extra.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_version_guidance.py +0 -0
- {gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/uninstall.sh +0 -0
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to the GridFleet host agent (`gridfleet-agent` on PyPI) are documented here.
|
|
4
4
|
|
|
5
|
+
## [0.2.4](https://github.com/quidow/gridfleet/compare/gridfleet-agent-v0.2.3...gridfleet-agent-v0.2.4) (2026-05-03)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **agent:** trigger release for port conflict cleanup ([6a561ca](https://github.com/quidow/gridfleet/commit/6a561ca480c62b9abb2d5141fa98fc4e1a7696b6))
|
|
11
|
+
|
|
12
|
+
## [0.2.3](https://github.com/quidow/gridfleet/compare/gridfleet-agent-v0.2.2...gridfleet-agent-v0.2.3) (2026-05-03)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **agent:** prioritize node in service path ([c1d2b72](https://github.com/quidow/gridfleet/commit/c1d2b728d5d01a4a0b76f53ca48be8740de17918))
|
|
18
|
+
|
|
5
19
|
## [0.2.2](https://github.com/quidow/gridfleet/compare/gridfleet-agent-v0.2.1...gridfleet-agent-v0.2.2) (2026-05-03)
|
|
6
20
|
|
|
7
21
|
|
|
@@ -88,6 +88,10 @@ class RuntimeNotInstalledError(RuntimeError):
|
|
|
88
88
|
"""Raised when no runtime is installed for the requested pack."""
|
|
89
89
|
|
|
90
90
|
|
|
91
|
+
class AppiumPortOccupiedError(RuntimeError):
|
|
92
|
+
"""Raised when a managed Appium port is now owned by another listener."""
|
|
93
|
+
|
|
94
|
+
|
|
91
95
|
def resolve_appium_invocation_for_pack(
|
|
92
96
|
pack_id: str,
|
|
93
97
|
registry: RuntimeRegistry | None,
|
|
@@ -617,6 +621,24 @@ class AppiumProcessManager:
|
|
|
617
621
|
)
|
|
618
622
|
try:
|
|
619
623
|
restarted = await self._restart_from_launch_spec(port)
|
|
624
|
+
except AppiumPortOccupiedError:
|
|
625
|
+
self._record_restart_event(
|
|
626
|
+
process="appium",
|
|
627
|
+
kind="port_conflict",
|
|
628
|
+
port=port,
|
|
629
|
+
pid=info.pid if info is not None else None,
|
|
630
|
+
attempt=attempt_number,
|
|
631
|
+
delay_sec=None,
|
|
632
|
+
exit_code=last_exit_code,
|
|
633
|
+
will_retry=False,
|
|
634
|
+
)
|
|
635
|
+
logger.error(
|
|
636
|
+
"Appium auto-restart stopped for connection_target=%s port=%d because the port is occupied",
|
|
637
|
+
info.connection_target if info is not None else "unknown",
|
|
638
|
+
port,
|
|
639
|
+
)
|
|
640
|
+
await self._drop_failed_managed_port(port)
|
|
641
|
+
return
|
|
620
642
|
except Exception:
|
|
621
643
|
self._advance_restart_backoff(self._appium_restart_backoff_steps, port)
|
|
622
644
|
logger.exception("Appium auto-restart failed for port %d on attempt %d", port, attempt_number)
|
|
@@ -859,7 +881,7 @@ class AppiumProcessManager:
|
|
|
859
881
|
appium_cmd.extend(["--allow-insecure", ",".join(spec.insecure_features)])
|
|
860
882
|
|
|
861
883
|
if await self._can_connect_to_appium(spec.port):
|
|
862
|
-
raise
|
|
884
|
+
raise AppiumPortOccupiedError(
|
|
863
885
|
f"Port {spec.port} is already in use by another Appium listener; "
|
|
864
886
|
"stop the existing process before starting a new managed node"
|
|
865
887
|
)
|
|
@@ -1128,6 +1150,19 @@ class AppiumProcessManager:
|
|
|
1128
1150
|
with contextlib.suppress(OSError):
|
|
1129
1151
|
os.unlink(toml_path)
|
|
1130
1152
|
|
|
1153
|
+
async def _drop_failed_managed_port(self, port: int) -> None:
|
|
1154
|
+
"""Forget stale ownership for a crashed Appium process without touching an unmanaged listener."""
|
|
1155
|
+
self._cancel_task(self._appium_restart_tasks, port)
|
|
1156
|
+
self._cancel_task(self._appium_watch_tasks, port)
|
|
1157
|
+
await self._stop_grid_node_process(port)
|
|
1158
|
+
self._appium_procs.pop(port, None)
|
|
1159
|
+
self._info.pop(port, None)
|
|
1160
|
+
self._launch_specs.pop(port, None)
|
|
1161
|
+
self._appium_restart_attempts.pop(port, None)
|
|
1162
|
+
self._grid_node_restart_attempts.pop(port, None)
|
|
1163
|
+
self._appium_restart_backoff_steps.pop(port, None)
|
|
1164
|
+
self._grid_node_restart_backoff_steps.pop(port, None)
|
|
1165
|
+
|
|
1131
1166
|
async def stop(self, port: int) -> None:
|
|
1132
1167
|
async with self._start_lock:
|
|
1133
1168
|
self._intentional_stop_ports.add(port)
|
|
@@ -54,7 +54,7 @@ def test_render_config_env_includes_detected_paths_and_optional_auth() -> None:
|
|
|
54
54
|
assert "AGENT_MANAGER_AUTH_PASSWORD=secret" in rendered
|
|
55
55
|
assert "AGENT_ENABLE_WEB_TERMINAL=true" in rendered
|
|
56
56
|
assert "AGENT_TERMINAL_TOKEN=terminal-token" in rendered
|
|
57
|
-
assert "PATH=/
|
|
57
|
+
assert "PATH=/opt/node/bin:/usr/bin:" in rendered
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def test_load_installed_config_reads_persisted_agent_env(tmp_path: Path) -> None:
|
|
@@ -175,10 +175,10 @@ def test_dry_run_output_names_generated_artifacts_and_warnings() -> None:
|
|
|
175
175
|
assert "ExecStart=/opt/gridfleet-agent/venv/bin/gridfleet-agent serve" in output
|
|
176
176
|
|
|
177
177
|
|
|
178
|
-
def
|
|
178
|
+
def test_build_service_path_prioritizes_node_before_system_dirs() -> None:
|
|
179
179
|
discovery = ToolDiscovery(java_bin="/usr/lib/jvm/bin/java", node_bin_dir="/opt/node/bin", android_home="/opt/sdk")
|
|
180
180
|
|
|
181
|
-
assert build_service_path(discovery).startswith("/usr/lib/jvm/bin:/opt/
|
|
181
|
+
assert build_service_path(discovery).startswith("/opt/node/bin:/usr/lib/jvm/bin:/opt/sdk/platform-tools:")
|
|
182
182
|
|
|
183
183
|
|
|
184
184
|
def test_find_node_bin_dir_prefers_home_nvm_over_system_node(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
|
@@ -705,6 +705,60 @@ async def test_auto_restart_cap_stops_retrying_after_threshold() -> None:
|
|
|
705
705
|
assert snapshot["recent_restart_events"][0]["will_retry"] is False
|
|
706
706
|
|
|
707
707
|
|
|
708
|
+
async def test_auto_restart_drops_managed_state_when_port_is_taken_by_unmanaged_listener() -> None:
|
|
709
|
+
manager = AppiumProcessManager()
|
|
710
|
+
old_appium_proc = FakeProcess(pid=1111, returncode=1)
|
|
711
|
+
old_grid_proc = FakeProcess(pid=2222)
|
|
712
|
+
manager._appium_procs[4723] = cast("asyncio.subprocess.Process", old_appium_proc)
|
|
713
|
+
manager._node_procs[4723] = cast("asyncio.subprocess.Process", old_grid_proc)
|
|
714
|
+
manager._launch_specs[4723] = AppiumLaunchSpec(
|
|
715
|
+
connection_target="device-conflict",
|
|
716
|
+
port=4723,
|
|
717
|
+
plugins=None,
|
|
718
|
+
extra_caps=None,
|
|
719
|
+
stereotype_caps=None,
|
|
720
|
+
session_override=True,
|
|
721
|
+
device_type=None,
|
|
722
|
+
ip_address=None,
|
|
723
|
+
manage_grid_node=True,
|
|
724
|
+
pack_id="appium-uiautomator2",
|
|
725
|
+
platform_id="android_mobile",
|
|
726
|
+
)
|
|
727
|
+
manager._info[4723] = AppiumProcessInfo(
|
|
728
|
+
port=4723,
|
|
729
|
+
pid=1111,
|
|
730
|
+
connection_target="device-conflict",
|
|
731
|
+
platform_id="android_mobile",
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
real_sleep = asyncio.sleep
|
|
735
|
+
|
|
736
|
+
async def fake_sleep(_delay: float) -> None:
|
|
737
|
+
await real_sleep(0)
|
|
738
|
+
|
|
739
|
+
with (
|
|
740
|
+
patch("agent_app.appium_process.resolve_appium_invocation_for_pack", return_value=_STUB_INVOCATION),
|
|
741
|
+
patch("agent_app.appium_process._build_env", return_value={"PATH": "/usr/bin"}),
|
|
742
|
+
patch.object(manager, "_can_connect_to_appium", new_callable=AsyncMock, return_value=True),
|
|
743
|
+
patch("agent_app.appium_process.asyncio.create_subprocess_exec", new_callable=AsyncMock) as create_proc,
|
|
744
|
+
patch("agent_app.appium_process.asyncio.sleep", side_effect=fake_sleep),
|
|
745
|
+
):
|
|
746
|
+
await manager._auto_restart_appium(4723, exit_code=1)
|
|
747
|
+
|
|
748
|
+
create_proc.assert_not_awaited()
|
|
749
|
+
assert manager.list_running() == []
|
|
750
|
+
assert 4723 not in manager._launch_specs
|
|
751
|
+
assert 4723 not in manager._info
|
|
752
|
+
assert 4723 not in manager._node_procs
|
|
753
|
+
assert old_grid_proc.sent_signals
|
|
754
|
+
snapshot = manager.process_snapshot()
|
|
755
|
+
assert [event["kind"] for event in snapshot["recent_restart_events"]] == [
|
|
756
|
+
"crash_detected",
|
|
757
|
+
"port_conflict",
|
|
758
|
+
]
|
|
759
|
+
assert snapshot["recent_restart_events"][-1]["process"] == "appium"
|
|
760
|
+
|
|
761
|
+
|
|
708
762
|
async def test_successful_restart_resets_backoff_step_for_next_crash() -> None:
|
|
709
763
|
manager = AppiumProcessManager()
|
|
710
764
|
first_proc = FakeProcess(pid=1001)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -221,10 +221,10 @@ def discover_tools(
|
|
|
221
221
|
|
|
222
222
|
def build_service_path(discovery: ToolDiscovery) -> str:
|
|
223
223
|
prefixes: list[str] = []
|
|
224
|
-
if discovery.java_bin:
|
|
225
|
-
prefixes.append(str(Path(discovery.java_bin).parent))
|
|
226
224
|
if discovery.node_bin_dir:
|
|
227
225
|
prefixes.append(discovery.node_bin_dir)
|
|
226
|
+
if discovery.java_bin:
|
|
227
|
+
prefixes.append(str(Path(discovery.java_bin).parent))
|
|
228
228
|
if discovery.android_home:
|
|
229
229
|
prefixes.append(f"{discovery.android_home}/platform-tools")
|
|
230
230
|
return ":".join([*prefixes, DEFAULT_SERVICE_PATH])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_adapter_loader_cancel_path_leak.py
RENAMED
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_adapter_loader_concurrent_load.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_appium_process_integration.py
RENAMED
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_desired_manifest_features.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_pack_state_sidecar_reconcile.py
RENAMED
|
File without changes
|
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_runtime_isolated_failures.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_sidecar_supervisor_poll_stop_race.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/pack/test_tarball_fetch_concurrent_dedup.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_appium_process_port_alloc_race.py
RENAMED
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_appium_process_restart_stop_race.py
RENAMED
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_appium_process_stop_start_lock_race.py
RENAMED
|
File without changes
|
{gridfleet_agent-0.2.2 → gridfleet_agent-0.2.4}/tests/test_appium_process_watch_stop_race.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|