diff --git a/packages/cli/src/managed-python-command.test.ts b/packages/cli/src/managed-python-command.test.ts index eabaaa4a..91244f53 100644 --- a/packages/cli/src/managed-python-command.test.ts +++ b/packages/cli/src/managed-python-command.test.ts @@ -44,6 +44,9 @@ function layout(): ManagedPythonRuntimeLayout { assetManifestPath: '/assets/python/manifest.json', pythonPath: '/runtime/0.2.0/.venv/bin/python', daemonPath: '/runtime/0.2.0/.venv/bin/ktx-daemon', + daemonStatePath: '/runtime/0.2.0/daemon.json', + daemonStdoutPath: '/runtime/0.2.0/daemon.stdout.log', + daemonStderrPath: '/runtime/0.2.0/daemon.stderr.log', }; } diff --git a/packages/cli/src/managed-python-runtime.test.ts b/packages/cli/src/managed-python-runtime.test.ts index 8f6b1c9c..35691e51 100644 --- a/packages/cli/src/managed-python-runtime.test.ts +++ b/packages/cli/src/managed-python-runtime.test.ts @@ -58,6 +58,15 @@ describe('managedPythonRuntimeLayout', () => { expect(layout.daemonPath).toBe( '/Users/alex/Library/Application Support/kaelio/ktx/runtime/0.2.0/.venv/bin/ktx-daemon', ); + expect(layout.daemonStatePath).toBe( + '/Users/alex/Library/Application Support/kaelio/ktx/runtime/0.2.0/daemon.json', + ); + expect(layout.daemonStdoutPath).toBe( + '/Users/alex/Library/Application Support/kaelio/ktx/runtime/0.2.0/daemon.stdout.log', + ); + expect(layout.daemonStderrPath).toBe( + '/Users/alex/Library/Application Support/kaelio/ktx/runtime/0.2.0/daemon.stderr.log', + ); expect(layout.assetManifestPath).toBe('/repo/packages/cli/assets/python/manifest.json'); }); diff --git a/packages/cli/src/managed-python-runtime.ts b/packages/cli/src/managed-python-runtime.ts index 47aea1e4..155b44e4 100644 --- a/packages/cli/src/managed-python-runtime.ts +++ b/packages/cli/src/managed-python-runtime.ts @@ -61,6 +61,9 @@ export interface ManagedPythonRuntimeLayout { assetManifestPath: string; pythonPath: string; daemonPath: string; + daemonStatePath: string; + daemonStdoutPath: string; + daemonStderrPath: string; } export interface ManagedRuntimeAsset { @@ -152,6 +155,9 @@ export function managedPythonRuntimeLayout(options: ManagedPythonRuntimeLayoutOp assetManifestPath: join(assetDir, 'manifest.json'), pythonPath: executablePath(venvDir, platform, 'python'), daemonPath: executablePath(venvDir, platform, 'ktx-daemon'), + daemonStatePath: join(versionDir, 'daemon.json'), + daemonStdoutPath: join(versionDir, 'daemon.stdout.log'), + daemonStderrPath: join(versionDir, 'daemon.stderr.log'), }; } diff --git a/packages/cli/src/runtime.test.ts b/packages/cli/src/runtime.test.ts index 69506216..54de630c 100644 --- a/packages/cli/src/runtime.test.ts +++ b/packages/cli/src/runtime.test.ts @@ -44,6 +44,9 @@ describe('runKtxRuntime', () => { assetManifestPath: '/assets/python/manifest.json', pythonPath: '/runtime/0.2.0/.venv/bin/python', daemonPath: '/runtime/0.2.0/.venv/bin/ktx-daemon', + daemonStatePath: '/runtime/0.2.0/daemon.json', + daemonStdoutPath: '/runtime/0.2.0/daemon.stdout.log', + daemonStderrPath: '/runtime/0.2.0/daemon.stderr.log', }, asset: { wheelPath: '/assets/python/kaelio_ktx-0.1.0-py3-none-any.whl', @@ -120,6 +123,9 @@ describe('runKtxRuntime', () => { assetManifestPath: '/assets/python/manifest.json', pythonPath: '/runtime/0.2.0/.venv/bin/python', daemonPath: '/runtime/0.2.0/.venv/bin/ktx-daemon', + daemonStatePath: '/runtime/0.2.0/daemon.json', + daemonStdoutPath: '/runtime/0.2.0/daemon.stdout.log', + daemonStderrPath: '/runtime/0.2.0/daemon.stderr.log', }, })), }; @@ -187,6 +193,9 @@ describe('runKtxRuntime', () => { assetManifestPath: '/assets/python/manifest.json', pythonPath: '/runtime/0.2.0/.venv/bin/python', daemonPath: '/runtime/0.2.0/.venv/bin/ktx-daemon', + daemonStatePath: '/runtime/0.2.0/daemon.json', + daemonStdoutPath: '/runtime/0.2.0/daemon.stdout.log', + daemonStderrPath: '/runtime/0.2.0/daemon.stderr.log', }, })), pruneRuntime: vi.fn(async () => ({ diff --git a/python/ktx-daemon/src/ktx_daemon/app.py b/python/ktx-daemon/src/ktx_daemon/app.py index 73220227..272b0c24 100644 --- a/python/ktx-daemon/src/ktx_daemon/app.py +++ b/python/ktx-daemon/src/ktx_daemon/app.py @@ -3,6 +3,7 @@ from __future__ import annotations import logging +import os from collections.abc import Callable from typing import Any @@ -80,7 +81,11 @@ def create_app( @app.get("/health") async def health() -> dict[str, str]: - return {"status": "healthy"} + response = {"status": "healthy"} + version = os.environ.get("KTX_DAEMON_VERSION") + if version: + response["version"] = version + return response @app.post("/database/introspect", response_model=DatabaseIntrospectionResponse) async def database_introspect( diff --git a/python/ktx-daemon/tests/test_app.py b/python/ktx-daemon/tests/test_app.py index fe3c1e4d..cd5c4f16 100644 --- a/python/ktx-daemon/tests/test_app.py +++ b/python/ktx-daemon/tests/test_app.py @@ -69,6 +69,16 @@ def test_health_endpoint_returns_healthy() -> None: assert response.json() == {"status": "healthy"} +def test_health_endpoint_returns_managed_runtime_version(monkeypatch) -> None: + monkeypatch.setenv("KTX_DAEMON_VERSION", "0.2.0") + client = TestClient(create_app()) + + response = client.get("/health") + + assert response.status_code == 200 + assert response.json() == {"status": "healthy", "version": "0.2.0"} + + def test_database_introspect_endpoint_returns_snapshot() -> None: calls = []