Refactor API Docs CI workflow to correct ESLint command syntax and enhance Python formatting in CI pipelines; update progress tracking documentation
Some checks failed
API Docs (Node.js Express) / test (16) (push) Failing after 5m29s
API Docs (Node.js Express) / test (18) (push) Failing after 5m25s
API Docs (Node.js Express) / test (20) (push) Failing after 1m4s
API Docs (Node.js Express) / build (push) Has been skipped
API Docs (Node.js Express) / security (push) Has been skipped
LabFusion CI/CD Pipeline / api-gateway (push) Failing after 4m52s
LabFusion CI/CD Pipeline / service-adapters (push) Failing after 5m1s
LabFusion CI/CD Pipeline / api-docs (push) Failing after 5m12s
LabFusion CI/CD Pipeline / frontend (push) Failing after 6m39s
LabFusion CI/CD Pipeline / integration-tests (push) Has been skipped
LabFusion CI/CD Pipeline / security-scan (push) Has been skipped
Docker Build and Push / build-and-push (push) Failing after 34s
Docker Build and Push / security-scan (push) Has been skipped
Integration Tests / integration-tests (push) Failing after 1m33s
Integration Tests / performance-tests (push) Has been skipped
Service Adapters (Python FastAPI) / test (3.1) (push) Failing after 35s
Service Adapters (Python FastAPI) / test (3.11) (push) Failing after 5m20s
Service Adapters (Python FastAPI) / test (3.12) (push) Failing after 5m27s
Service Adapters (Python FastAPI) / test (3.9) (push) Failing after 5m50s
Docker Build and Push / deploy-staging (push) Has been skipped
Service Adapters (Python FastAPI) / build (push) Has been skipped
Service Adapters (Python FastAPI) / security (push) Has been skipped
Docker Build and Push / deploy-production (push) Has been skipped
Some checks failed
API Docs (Node.js Express) / test (16) (push) Failing after 5m29s
API Docs (Node.js Express) / test (18) (push) Failing after 5m25s
API Docs (Node.js Express) / test (20) (push) Failing after 1m4s
API Docs (Node.js Express) / build (push) Has been skipped
API Docs (Node.js Express) / security (push) Has been skipped
LabFusion CI/CD Pipeline / api-gateway (push) Failing after 4m52s
LabFusion CI/CD Pipeline / service-adapters (push) Failing after 5m1s
LabFusion CI/CD Pipeline / api-docs (push) Failing after 5m12s
LabFusion CI/CD Pipeline / frontend (push) Failing after 6m39s
LabFusion CI/CD Pipeline / integration-tests (push) Has been skipped
LabFusion CI/CD Pipeline / security-scan (push) Has been skipped
Docker Build and Push / build-and-push (push) Failing after 34s
Docker Build and Push / security-scan (push) Has been skipped
Integration Tests / integration-tests (push) Failing after 1m33s
Integration Tests / performance-tests (push) Has been skipped
Service Adapters (Python FastAPI) / test (3.1) (push) Failing after 35s
Service Adapters (Python FastAPI) / test (3.11) (push) Failing after 5m20s
Service Adapters (Python FastAPI) / test (3.12) (push) Failing after 5m27s
Service Adapters (Python FastAPI) / test (3.9) (push) Failing after 5m50s
Docker Build and Push / deploy-staging (push) Has been skipped
Service Adapters (Python FastAPI) / build (push) Has been skipped
Service Adapters (Python FastAPI) / security (push) Has been skipped
Docker Build and Push / deploy-production (push) Has been skipped
This commit is contained in:
@@ -1,20 +1,25 @@
|
||||
from fastapi import APIRouter, HTTPException, Query, BackgroundTasks
|
||||
from models.schemas import EventData, EventResponse, EventsResponse, Event
|
||||
from services.redis_client import redis_client
|
||||
from datetime import datetime
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks, HTTPException, Query
|
||||
|
||||
from models.schemas import Event, EventData, EventResponse, EventsResponse
|
||||
from services.redis_client import redis_client
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.post("/publish-event",
|
||||
response_model=EventResponse,
|
||||
summary="Publish Event",
|
||||
description="Publish an event to the Redis message bus",
|
||||
responses={
|
||||
200: {"description": "Event published successfully"},
|
||||
500: {"description": "Failed to publish event"}
|
||||
},
|
||||
tags=["Events"])
|
||||
|
||||
@router.post(
|
||||
"/publish-event",
|
||||
response_model=EventResponse,
|
||||
summary="Publish Event",
|
||||
description="Publish an event to the Redis message bus",
|
||||
responses={
|
||||
200: {"description": "Event published successfully"},
|
||||
500: {"description": "Failed to publish event"},
|
||||
},
|
||||
tags=["Events"],
|
||||
)
|
||||
async def publish_event(event_data: EventData, background_tasks: BackgroundTasks):
|
||||
"""Publish an event to the Redis message bus for consumption by other services"""
|
||||
try:
|
||||
@@ -22,29 +27,33 @@ async def publish_event(event_data: EventData, background_tasks: BackgroundTasks
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"service": event_data.service,
|
||||
"event_type": event_data.event_type,
|
||||
"metadata": json.dumps(event_data.metadata)
|
||||
"metadata": json.dumps(event_data.metadata),
|
||||
}
|
||||
|
||||
|
||||
# Publish to Redis
|
||||
redis_client.lpush("events", json.dumps(event))
|
||||
|
||||
return EventResponse(
|
||||
status="published",
|
||||
event=event
|
||||
)
|
||||
|
||||
return EventResponse(status="published", event=event)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@router.get("/events",
|
||||
response_model=EventsResponse,
|
||||
summary="Get Events",
|
||||
description="Retrieve recent events from the message bus",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved events"},
|
||||
500: {"description": "Failed to retrieve events"}
|
||||
},
|
||||
tags=["Events"])
|
||||
async def get_events(limit: int = Query(100, ge=1, le=1000, description="Maximum number of events to retrieve")):
|
||||
|
||||
@router.get(
|
||||
"/events",
|
||||
response_model=EventsResponse,
|
||||
summary="Get Events",
|
||||
description="Retrieve recent events from the message bus",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved events"},
|
||||
500: {"description": "Failed to retrieve events"},
|
||||
},
|
||||
tags=["Events"],
|
||||
)
|
||||
async def get_events(
|
||||
limit: int = Query(
|
||||
100, ge=1, le=1000, description="Maximum number of events to retrieve"
|
||||
)
|
||||
):
|
||||
"""Get recent events from the Redis message bus"""
|
||||
try:
|
||||
events = redis_client.lrange("events", 0, limit - 1)
|
||||
@@ -55,7 +64,7 @@ async def get_events(limit: int = Query(100, ge=1, le=1000, description="Maximum
|
||||
parsed_events.append(Event(**event_data))
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
|
||||
|
||||
return EventsResponse(events=parsed_events)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@@ -1,27 +1,32 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from models.schemas import FrigateEventsResponse, FrigateEvent
|
||||
from services.config import SERVICES
|
||||
from datetime import datetime
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from models.schemas import FrigateEvent, FrigateEventsResponse
|
||||
from services.config import SERVICES
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/frigate/events",
|
||||
response_model=FrigateEventsResponse,
|
||||
summary="Get Frigate Events",
|
||||
description="Retrieve detection events from Frigate NVR",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved events"},
|
||||
503: {"description": "Frigate integration not configured"}
|
||||
},
|
||||
tags=["Frigate"])
|
||||
|
||||
@router.get(
|
||||
"/frigate/events",
|
||||
response_model=FrigateEventsResponse,
|
||||
summary="Get Frigate Events",
|
||||
description="Retrieve detection events from Frigate NVR",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved events"},
|
||||
503: {"description": "Frigate integration not configured"},
|
||||
},
|
||||
tags=["Frigate"],
|
||||
)
|
||||
async def get_frigate_events():
|
||||
"""Get Frigate detection events including person, vehicle, and object detections"""
|
||||
if not SERVICES["frigate"]["enabled"]:
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Frigate integration not configured. Please set FRIGATE_TOKEN environment variable."
|
||||
status_code=503,
|
||||
detail="Frigate integration not configured. Please set FRIGATE_TOKEN environment variable.",
|
||||
)
|
||||
|
||||
|
||||
# This would make actual API calls to Frigate
|
||||
# For now, return mock data
|
||||
return FrigateEventsResponse(
|
||||
@@ -31,33 +36,36 @@ async def get_frigate_events():
|
||||
timestamp=datetime.now().isoformat(),
|
||||
camera="front_door",
|
||||
label="person",
|
||||
confidence=0.95
|
||||
confidence=0.95,
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
@router.get("/frigate/cameras",
|
||||
summary="Get Frigate Cameras",
|
||||
description="Get list of Frigate cameras",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved cameras"},
|
||||
503: {"description": "Frigate integration not configured"}
|
||||
},
|
||||
tags=["Frigate"])
|
||||
|
||||
@router.get(
|
||||
"/frigate/cameras",
|
||||
summary="Get Frigate Cameras",
|
||||
description="Get list of Frigate cameras",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved cameras"},
|
||||
503: {"description": "Frigate integration not configured"},
|
||||
},
|
||||
tags=["Frigate"],
|
||||
)
|
||||
async def get_frigate_cameras():
|
||||
"""Get list of available Frigate cameras"""
|
||||
if not SERVICES["frigate"]["enabled"]:
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Frigate integration not configured. Please set FRIGATE_TOKEN environment variable."
|
||||
status_code=503,
|
||||
detail="Frigate integration not configured. Please set FRIGATE_TOKEN environment variable.",
|
||||
)
|
||||
|
||||
|
||||
# This would make actual API calls to Frigate
|
||||
# For now, return mock data
|
||||
return {
|
||||
"cameras": [
|
||||
{"name": "front_door", "enabled": True},
|
||||
{"name": "back_yard", "enabled": True},
|
||||
{"name": "garage", "enabled": False}
|
||||
{"name": "garage", "enabled": False},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,39 +1,44 @@
|
||||
from fastapi import APIRouter
|
||||
from datetime import datetime
|
||||
from models.schemas import RootResponse, HealthResponse, ServiceStatus
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from models.schemas import HealthResponse, RootResponse, ServiceStatus
|
||||
from services.config import SERVICES
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/",
|
||||
response_model=RootResponse,
|
||||
summary="API Root",
|
||||
description="Get basic API information",
|
||||
tags=["General"])
|
||||
|
||||
@router.get(
|
||||
"/",
|
||||
response_model=RootResponse,
|
||||
summary="API Root",
|
||||
description="Get basic API information",
|
||||
tags=["General"],
|
||||
)
|
||||
async def root():
|
||||
"""Get basic API information and version"""
|
||||
return RootResponse(
|
||||
message="LabFusion Service Adapters API",
|
||||
version="1.0.0"
|
||||
)
|
||||
return RootResponse(message="LabFusion Service Adapters API", version="1.0.0")
|
||||
|
||||
@router.get("/health",
|
||||
response_model=HealthResponse,
|
||||
summary="Health Check",
|
||||
description="Check service health status",
|
||||
tags=["General"])
|
||||
|
||||
@router.get(
|
||||
"/health",
|
||||
response_model=HealthResponse,
|
||||
summary="Health Check",
|
||||
description="Check service health status",
|
||||
tags=["General"],
|
||||
)
|
||||
async def health_check():
|
||||
"""Check the health status of the service adapters"""
|
||||
return HealthResponse(
|
||||
status="healthy",
|
||||
timestamp=datetime.now().isoformat()
|
||||
)
|
||||
return HealthResponse(status="healthy", timestamp=datetime.now().isoformat())
|
||||
|
||||
@router.get("/services",
|
||||
response_model=dict,
|
||||
summary="Get Service Status",
|
||||
description="Get status of all configured external services",
|
||||
tags=["Services"])
|
||||
|
||||
@router.get(
|
||||
"/services",
|
||||
response_model=dict,
|
||||
summary="Get Service Status",
|
||||
description="Get status of all configured external services",
|
||||
tags=["Services"],
|
||||
)
|
||||
async def get_services():
|
||||
"""Get status of all configured external services (Home Assistant, Frigate, Immich, n8n)"""
|
||||
service_status = {}
|
||||
@@ -41,6 +46,6 @@ async def get_services():
|
||||
service_status[service_name] = ServiceStatus(
|
||||
enabled=config["enabled"],
|
||||
url=config["url"],
|
||||
status="unknown" # Would check actual service status
|
||||
status="unknown", # Would check actual service status
|
||||
)
|
||||
return service_status
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
from fastapi import APIRouter, HTTPException, Path
|
||||
from models.schemas import HAEntitiesResponse, HAEntity, HAAttributes
|
||||
|
||||
from models.schemas import HAAttributes, HAEntitiesResponse, HAEntity
|
||||
from services.config import SERVICES
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/home-assistant/entities",
|
||||
response_model=HAEntitiesResponse,
|
||||
summary="Get Home Assistant Entities",
|
||||
description="Retrieve all entities from Home Assistant",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved entities"},
|
||||
503: {"description": "Home Assistant integration not configured"}
|
||||
},
|
||||
tags=["Home Assistant"])
|
||||
|
||||
@router.get(
|
||||
"/home-assistant/entities",
|
||||
response_model=HAEntitiesResponse,
|
||||
summary="Get Home Assistant Entities",
|
||||
description="Retrieve all entities from Home Assistant",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved entities"},
|
||||
503: {"description": "Home Assistant integration not configured"},
|
||||
},
|
||||
tags=["Home Assistant"],
|
||||
)
|
||||
async def get_ha_entities():
|
||||
"""Get Home Assistant entities including sensors, switches, and other devices"""
|
||||
if not SERVICES["home_assistant"]["enabled"]:
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Home Assistant integration not configured. Please set HOME_ASSISTANT_TOKEN environment variable."
|
||||
status_code=503,
|
||||
detail="Home Assistant integration not configured. Please set HOME_ASSISTANT_TOKEN environment variable.",
|
||||
)
|
||||
|
||||
|
||||
# This would make actual API calls to Home Assistant
|
||||
# For now, return mock data
|
||||
return HAEntitiesResponse(
|
||||
@@ -29,46 +33,46 @@ async def get_ha_entities():
|
||||
entity_id="sensor.cpu_usage",
|
||||
state="45.2",
|
||||
attributes=HAAttributes(
|
||||
unit_of_measurement="%",
|
||||
friendly_name="CPU Usage"
|
||||
)
|
||||
unit_of_measurement="%", friendly_name="CPU Usage"
|
||||
),
|
||||
),
|
||||
HAEntity(
|
||||
entity_id="sensor.memory_usage",
|
||||
state="2.1",
|
||||
attributes=HAAttributes(
|
||||
unit_of_measurement="GB",
|
||||
friendly_name="Memory Usage"
|
||||
)
|
||||
)
|
||||
unit_of_measurement="GB", friendly_name="Memory Usage"
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@router.get("/home-assistant/entity/{entity_id}",
|
||||
response_model=HAEntity,
|
||||
summary="Get Specific HA Entity",
|
||||
description="Get a specific Home Assistant entity by ID",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved entity"},
|
||||
404: {"description": "Entity not found"},
|
||||
503: {"description": "Home Assistant integration not configured"}
|
||||
},
|
||||
tags=["Home Assistant"])
|
||||
|
||||
@router.get(
|
||||
"/home-assistant/entity/{entity_id}",
|
||||
response_model=HAEntity,
|
||||
summary="Get Specific HA Entity",
|
||||
description="Get a specific Home Assistant entity by ID",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved entity"},
|
||||
404: {"description": "Entity not found"},
|
||||
503: {"description": "Home Assistant integration not configured"},
|
||||
},
|
||||
tags=["Home Assistant"],
|
||||
)
|
||||
async def get_ha_entity(entity_id: str = Path(..., description="Entity ID")):
|
||||
"""Get a specific Home Assistant entity by its ID"""
|
||||
if not SERVICES["home_assistant"]["enabled"]:
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Home Assistant integration not configured. Please set HOME_ASSISTANT_TOKEN environment variable."
|
||||
status_code=503,
|
||||
detail="Home Assistant integration not configured. Please set HOME_ASSISTANT_TOKEN environment variable.",
|
||||
)
|
||||
|
||||
|
||||
# This would make actual API calls to Home Assistant
|
||||
# For now, return mock data
|
||||
return HAEntity(
|
||||
entity_id=entity_id,
|
||||
state="unknown",
|
||||
attributes=HAAttributes(
|
||||
unit_of_measurement="",
|
||||
friendly_name=f"Entity {entity_id}"
|
||||
)
|
||||
unit_of_measurement="", friendly_name=f"Entity {entity_id}"
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1,27 +1,32 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from models.schemas import ImmichAssetsResponse, ImmichAsset
|
||||
from services.config import SERVICES
|
||||
from datetime import datetime
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
|
||||
from models.schemas import ImmichAsset, ImmichAssetsResponse
|
||||
from services.config import SERVICES
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@router.get("/immich/assets",
|
||||
response_model=ImmichAssetsResponse,
|
||||
summary="Get Immich Assets",
|
||||
description="Retrieve photo assets from Immich",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved assets"},
|
||||
503: {"description": "Immich integration not configured"}
|
||||
},
|
||||
tags=["Immich"])
|
||||
|
||||
@router.get(
|
||||
"/immich/assets",
|
||||
response_model=ImmichAssetsResponse,
|
||||
summary="Get Immich Assets",
|
||||
description="Retrieve photo assets from Immich",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved assets"},
|
||||
503: {"description": "Immich integration not configured"},
|
||||
},
|
||||
tags=["Immich"],
|
||||
)
|
||||
async def get_immich_assets():
|
||||
"""Get Immich photo assets including metadata, tags, and face detection results"""
|
||||
if not SERVICES["immich"]["enabled"]:
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Immich integration not configured. Please set IMMICH_API_KEY environment variable."
|
||||
status_code=503,
|
||||
detail="Immich integration not configured. Please set IMMICH_API_KEY environment variable.",
|
||||
)
|
||||
|
||||
|
||||
# This would make actual API calls to Immich
|
||||
# For now, return mock data
|
||||
return ImmichAssetsResponse(
|
||||
@@ -31,32 +36,35 @@ async def get_immich_assets():
|
||||
filename="photo_001.jpg",
|
||||
created_at=datetime.now().isoformat(),
|
||||
tags=["person", "outdoor"],
|
||||
faces=["Alice", "Bob"]
|
||||
faces=["Alice", "Bob"],
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
@router.get("/immich/albums",
|
||||
summary="Get Immich Albums",
|
||||
description="Get list of Immich albums",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved albums"},
|
||||
503: {"description": "Immich integration not configured"}
|
||||
},
|
||||
tags=["Immich"])
|
||||
|
||||
@router.get(
|
||||
"/immich/albums",
|
||||
summary="Get Immich Albums",
|
||||
description="Get list of Immich albums",
|
||||
responses={
|
||||
200: {"description": "Successfully retrieved albums"},
|
||||
503: {"description": "Immich integration not configured"},
|
||||
},
|
||||
tags=["Immich"],
|
||||
)
|
||||
async def get_immich_albums():
|
||||
"""Get list of Immich albums"""
|
||||
if not SERVICES["immich"]["enabled"]:
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
detail="Immich integration not configured. Please set IMMICH_API_KEY environment variable."
|
||||
status_code=503,
|
||||
detail="Immich integration not configured. Please set IMMICH_API_KEY environment variable.",
|
||||
)
|
||||
|
||||
|
||||
# This would make actual API calls to Immich
|
||||
# For now, return mock data
|
||||
return {
|
||||
"albums": [
|
||||
{"id": "album_1", "name": "Family Photos", "asset_count": 150},
|
||||
{"id": "album_2", "name": "Vacation 2024", "asset_count": 75}
|
||||
{"id": "album_2", "name": "Vacation 2024", "asset_count": 75},
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user