devops-bot-sdk 1.4.143__tar.gz → 1.4.145__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.
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/PKG-INFO +1 -1
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/devops_bot_sdk.egg-info/PKG-INFO +1 -1
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/devops_bot_sdk.egg-info/SOURCES.txt +2 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/__init__.py +2 -2
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/client.py +16 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/api.py +32 -0
- devops_bot_sdk-1.4.145/sdk/ui/health.py +80 -0
- devops_bot_sdk-1.4.145/tests/test_health.py +53 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/README.md +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/devops_bot_sdk.egg-info/dependency_links.txt +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/devops_bot_sdk.egg-info/entry_points.txt +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/devops_bot_sdk.egg-info/requires.txt +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/devops_bot_sdk.egg-info/top_level.txt +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/pyproject.toml +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agentd.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/__init__.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/builder.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/chat.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/connectors.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/engines/__init__.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/engines/claude_code.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/engines/http.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/engines/mcp.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/engines/n8n.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/engines/shell.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/integrations.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/inventory.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/library/__init__.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/manifest.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/prompt_studio.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/prompt_template.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/prompt_vars.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/run_log.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/secrets.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/usage.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/agents/varstore.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/cli.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/collectors/__init__.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/collectors/files.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/collectors/process.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/collectors/screenshot.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/config.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/crucial.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/design_verify/__init__.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/design_verify/assets.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/design_verify/bootstrap.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/design_verify/browser.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/design_verify/compare.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/design_verify/loop.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/exceptions.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/git_ops.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/graphify.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/hooks/__init__.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/hooks/crucial_guard.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ipc/__init__.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ipc/electron_bridge.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ipc/handlers.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/local_exec.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/models/__init__.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/models/envelope.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/models/requests.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/models/responses.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/models/snapshots.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/platform_compat.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/py.typed +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/run_auto.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/sse.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/test.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/test_pipeline.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/__init__.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/dashboard.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/ip_allowlist.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/jobs.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/models.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/runner.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/security.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/server.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/service.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/setup_manager.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/static/agents.html +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/static/app.js +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/static/custom-agents.html +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/static/default-agents.html +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/static/index.html +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/static/runs.html +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/static/setup.html +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/static/styles.css +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/ui/static/tickets.html +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/sdk/updater.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/setup.cfg +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/tests/test_agent_chat_features.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/tests/test_agent_prompt_models.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/tests/test_agents_connectors_builder.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/tests/test_git_action.py +0 -0
- {devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/tests/test_updater_extras.py +0 -0
|
@@ -67,6 +67,7 @@ sdk/models/snapshots.py
|
|
|
67
67
|
sdk/ui/__init__.py
|
|
68
68
|
sdk/ui/api.py
|
|
69
69
|
sdk/ui/dashboard.py
|
|
70
|
+
sdk/ui/health.py
|
|
70
71
|
sdk/ui/ip_allowlist.py
|
|
71
72
|
sdk/ui/jobs.py
|
|
72
73
|
sdk/ui/models.py
|
|
@@ -88,4 +89,5 @@ tests/test_agent_chat_features.py
|
|
|
88
89
|
tests/test_agent_prompt_models.py
|
|
89
90
|
tests/test_agents_connectors_builder.py
|
|
90
91
|
tests/test_git_action.py
|
|
92
|
+
tests/test_health.py
|
|
91
93
|
tests/test_updater_extras.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""AgentOS Desktop SDK — thin HTTPS/SSE client for the Electron app.
|
|
2
2
|
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.145
|
|
4
4
|
|
|
5
5
|
Public surface:
|
|
6
6
|
BackendClient.from_config() — create client from ~/.agentos/config.toml
|
|
@@ -30,7 +30,7 @@ Rules:
|
|
|
30
30
|
- All data egress through submit_webhook only
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
|
-
__version__ = "1.4.
|
|
33
|
+
__version__ = "1.4.145" # SINGLE SOURCE OF TRUTH — bump on every change; pyproject,
|
|
34
34
|
__author__ = "AgentOS" # sdk.client.SDK_VERSION and the UI server version all read this.
|
|
35
35
|
|
|
36
36
|
from sdk.client import BackendClient
|
|
@@ -1227,6 +1227,22 @@ class BackendClient:
|
|
|
1227
1227
|
_check_status(resp.status_code, self._base_url)
|
|
1228
1228
|
return resp.json().get("agents", [])
|
|
1229
1229
|
|
|
1230
|
+
async def list_product_agents(self, product_id: str) -> dict:
|
|
1231
|
+
"""GET /api/v1/product/agents?product_id=… — a product's custom agents.
|
|
1232
|
+
|
|
1233
|
+
The backend resolves the product's VPS IP from ``product_id`` and proxies
|
|
1234
|
+
to the product's ``/orchestrator/agents`` endpoint, returning the purified
|
|
1235
|
+
``{response, product_id}`` shape. Used by the product-mode agents page.
|
|
1236
|
+
"""
|
|
1237
|
+
async with httpx.AsyncClient(timeout=30.0) as client:
|
|
1238
|
+
resp = await client.get(
|
|
1239
|
+
self._url("/api/v1/product/agents"),
|
|
1240
|
+
params={"product_id": product_id},
|
|
1241
|
+
headers=self._headers,
|
|
1242
|
+
)
|
|
1243
|
+
_check_status(resp.status_code, self._base_url)
|
|
1244
|
+
return resp.json()
|
|
1245
|
+
|
|
1230
1246
|
async def get_custom_agents(self) -> list[CustomAgent]:
|
|
1231
1247
|
"""GET /api/v1/agents → parsed :class:`CustomAgent` rows.
|
|
1232
1248
|
|
|
@@ -94,6 +94,20 @@ async def status() -> dict:
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
|
|
97
|
+
@router.get("/health", dependencies=[_auth])
|
|
98
|
+
async def health() -> dict:
|
|
99
|
+
"""VPS health snapshot — live CPU/RAM/disk/uptime + auto-loop state + version.
|
|
100
|
+
|
|
101
|
+
The backend pings this (``GET /api/v1/vps/health`` → this endpoint) to report
|
|
102
|
+
on each VPS. Resource metrics need the ``[process]`` extra (psutil); without
|
|
103
|
+
it ``resources.available`` is False rather than an error. Token-gated + IP-
|
|
104
|
+
allowlisted like every other ``/api/ui/*`` route.
|
|
105
|
+
"""
|
|
106
|
+
from sdk.ui.health import collect_health
|
|
107
|
+
|
|
108
|
+
return collect_health()
|
|
109
|
+
|
|
110
|
+
|
|
97
111
|
# ── IP allowlist management ─────────────────────────────────────────────────
|
|
98
112
|
# Whitelist a client IP for THIS SDK. A whitelisted IP passes the IP gate for
|
|
99
113
|
# EVERY path (all /api/ui/* endpoints + the UI + /docs); data endpoints still
|
|
@@ -314,6 +328,24 @@ async def connectors() -> dict:
|
|
|
314
328
|
}
|
|
315
329
|
|
|
316
330
|
|
|
331
|
+
@router.get("/product-agents", dependencies=[_auth])
|
|
332
|
+
async def product_agents(product_id: str = Query(...)) -> dict:
|
|
333
|
+
"""A product's custom agents, for the product-mode agents page.
|
|
334
|
+
|
|
335
|
+
Given ``product_id``, the backend resolves the product's VPS IP (from
|
|
336
|
+
``products_vps``) and proxies to the product's ``/orchestrator/agents``,
|
|
337
|
+
returning ``{response, product_id}`` (``response`` holds the agents). Product
|
|
338
|
+
mode is the either/or alternative to the custom+default page — never both.
|
|
339
|
+
Best-effort: on backend error returns ``{response: [], product_id, error}``.
|
|
340
|
+
"""
|
|
341
|
+
from sdk.client import BackendClient
|
|
342
|
+
|
|
343
|
+
try:
|
|
344
|
+
return await BackendClient.from_config().list_product_agents(product_id)
|
|
345
|
+
except Exception as exc: # noqa: BLE001 — degrade to empty, surface the reason
|
|
346
|
+
return {"response": [], "product_id": product_id, "error": str(exc)}
|
|
347
|
+
|
|
348
|
+
|
|
317
349
|
@router.get("/agents", dependencies=[_auth])
|
|
318
350
|
async def agents() -> dict:
|
|
319
351
|
"""The caller's custom agents (``relation_type=person``) from the backend.
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""VPS health snapshot for ``GET /api/ui/health``.
|
|
2
|
+
|
|
3
|
+
Gathers live host metrics (CPU / RAM / disk / uptime) plus the auto-loop state and
|
|
4
|
+
SDK version, so the backend can ping each VPS for reporting/monitoring. Resource
|
|
5
|
+
metrics use ``psutil`` when available (the ``[process]`` extra) and degrade
|
|
6
|
+
gracefully — ``resources.available=False`` — when it isn't, rather than erroring.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import platform
|
|
11
|
+
import socket
|
|
12
|
+
import time
|
|
13
|
+
from datetime import datetime, timezone
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def _resources() -> dict:
|
|
17
|
+
"""CPU/RAM/disk/uptime via psutil; ``{"available": False}`` when psutil absent."""
|
|
18
|
+
try:
|
|
19
|
+
import psutil
|
|
20
|
+
except Exception: # noqa: BLE001 — psutil optional ([process] extra)
|
|
21
|
+
return {"available": False, "reason": "psutil not installed (pip install 'devops-bot-sdk[process]')"}
|
|
22
|
+
|
|
23
|
+
out: dict = {"available": True}
|
|
24
|
+
try:
|
|
25
|
+
out["cpu_percent"] = round(float(psutil.cpu_percent(interval=0.1)), 2)
|
|
26
|
+
except Exception: # noqa: BLE001
|
|
27
|
+
out["cpu_percent"] = None
|
|
28
|
+
try:
|
|
29
|
+
vm = psutil.virtual_memory()
|
|
30
|
+
out["ram"] = {
|
|
31
|
+
"used_mb": round(vm.used / 1048576, 1),
|
|
32
|
+
"total_mb": round(vm.total / 1048576, 1),
|
|
33
|
+
"percent": round(float(vm.percent), 2),
|
|
34
|
+
}
|
|
35
|
+
except Exception: # noqa: BLE001
|
|
36
|
+
out["ram"] = None
|
|
37
|
+
try:
|
|
38
|
+
du = psutil.disk_usage("/")
|
|
39
|
+
out["disk"] = {
|
|
40
|
+
"used_gb": round(du.used / 1073741824, 2),
|
|
41
|
+
"total_gb": round(du.total / 1073741824, 2),
|
|
42
|
+
"percent": round(float(du.percent), 2),
|
|
43
|
+
}
|
|
44
|
+
except Exception: # noqa: BLE001
|
|
45
|
+
out["disk"] = None
|
|
46
|
+
try:
|
|
47
|
+
out["uptime_seconds"] = int(time.time() - psutil.boot_time())
|
|
48
|
+
except Exception: # noqa: BLE001
|
|
49
|
+
out["uptime_seconds"] = None
|
|
50
|
+
return out
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def collect_health() -> dict:
|
|
54
|
+
"""Full health snapshot: host, live resources, auto-loop state, SDK version."""
|
|
55
|
+
import sdk as _sdk
|
|
56
|
+
|
|
57
|
+
# Loop state — best-effort (never fail the health probe on it).
|
|
58
|
+
try:
|
|
59
|
+
from sdk.ui.runner import loop_state
|
|
60
|
+
loop = loop_state()
|
|
61
|
+
except Exception as exc: # noqa: BLE001
|
|
62
|
+
loop = {"error": str(exc)}
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
hostname = socket.gethostname()
|
|
66
|
+
except Exception: # noqa: BLE001
|
|
67
|
+
hostname = ""
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
"status": "ok",
|
|
71
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
72
|
+
"sdk_version": getattr(_sdk, "__version__", "0.0.0"),
|
|
73
|
+
"host": {
|
|
74
|
+
"hostname": hostname,
|
|
75
|
+
"os": platform.platform(),
|
|
76
|
+
"python": platform.python_version(),
|
|
77
|
+
},
|
|
78
|
+
"resources": _resources(),
|
|
79
|
+
"loop": loop,
|
|
80
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""SDK VPS health — collect_health() + GET /api/ui/health.
|
|
2
|
+
|
|
3
|
+
Resource metrics degrade gracefully when psutil is absent (resources.available
|
|
4
|
+
False), and the route is token-gated like every /api/ui/* endpoint.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
from unittest.mock import patch
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
from sdk.ui.health import collect_health
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TestCollectHealth:
|
|
17
|
+
def test_shape(self):
|
|
18
|
+
h = collect_health()
|
|
19
|
+
assert h["status"] == "ok"
|
|
20
|
+
assert h["sdk_version"] and "host" in h and "resources" in h and "loop" in h
|
|
21
|
+
assert "os" in h["host"] and "python" in h["host"]
|
|
22
|
+
|
|
23
|
+
def test_resources_degrade_without_psutil(self):
|
|
24
|
+
# Simulate psutil missing → resources.available False, no crash.
|
|
25
|
+
with patch.dict(sys.modules, {"psutil": None}):
|
|
26
|
+
h = collect_health()
|
|
27
|
+
assert h["resources"]["available"] is False
|
|
28
|
+
|
|
29
|
+
def test_loop_never_breaks_probe(self):
|
|
30
|
+
with patch("sdk.ui.runner.loop_state", side_effect=RuntimeError("boom")):
|
|
31
|
+
h = collect_health()
|
|
32
|
+
assert "error" in h["loop"]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
fastapi = pytest.importorskip("fastapi")
|
|
36
|
+
from fastapi.testclient import TestClient # noqa: E402
|
|
37
|
+
|
|
38
|
+
from sdk.ui.api import require_token, router # noqa: E402
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _client():
|
|
42
|
+
app = fastapi.FastAPI()
|
|
43
|
+
app.include_router(router)
|
|
44
|
+
app.dependency_overrides[require_token] = lambda: None
|
|
45
|
+
return TestClient(app)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TestHealthRoute:
|
|
49
|
+
def test_returns_health(self):
|
|
50
|
+
resp = _client().get("/api/ui/health")
|
|
51
|
+
assert resp.status_code == 200
|
|
52
|
+
body = resp.json()
|
|
53
|
+
assert body["status"] == "ok" and "resources" in body and "loop" in body
|
|
File without changes
|
{devops_bot_sdk-1.4.143 → devops_bot_sdk-1.4.145}/devops_bot_sdk.egg-info/dependency_links.txt
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
|
|
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
|
|
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
|