Compare commits

..

12 commits

9 changed files with 77 additions and 8 deletions

2
.gitignore vendored
View file

@ -14,6 +14,6 @@ uv.lock
**/*.kdbx*
.compose_repository
__pycache__/
deployment/
**/dist/
**/*.log

View file

@ -8,8 +8,7 @@ from starlette.responses import JSONResponse, Response
from karl.api.models import Request
from karl.core.injects import AutowireSupport
from karl.core.woodpecker import Woodpecker
from karl.model.webhook import WoodpeckerEvent
from karl.model.webhook import WoodpeckerEvent, ReloadEvent
router = APIRouter()
logger = logging.getLogger(__name__)
@ -21,7 +20,6 @@ async def root():
@cbv(router)
class APIv1:
woodpecker: Woodpecker = Depends(AutowireSupport.woodpecker)
bus: EventBus = Depends(AutowireSupport.bus)
def __init__(self):
@ -39,3 +37,10 @@ class APIv1:
async def ci(self, request: Request):
await self.bus.dispatch(mapper.map(request))
return Response(status_code=201)
@router.get("/reload", summary="Manual service reload")
async def reload(self, service: str = None) -> Response:
if service is None:
return Response(status_code=400)
await self.bus.dispatch(ReloadEvent(service=service))
return Response(status_code=201)

View file

@ -51,4 +51,8 @@ class Settings(BaseSettings):
@lru_cache
def get_settings() -> Settings:
return Settings.from_yaml()
paths = ['deployment/config.yaml', 'config/config.yaml']
for path in paths:
if Path(path).exists():
return Settings.from_yaml(path)
raise Exception("Config file not found")

View file

@ -1,6 +1,7 @@
from bubus import EventBus
from injectable import inject
from karl.core.reload import ReloadService
from karl.core.woodpecker import Woodpecker
@ -10,6 +11,10 @@ class AutowireSupport:
def woodpecker():
return inject(Woodpecker)
@staticmethod
def reload():
return inject(ReloadService)
@staticmethod
def bus():
return inject(EventBus)

34
src/karl/core/reload.py Normal file
View file

@ -0,0 +1,34 @@
import logging
from datetime import datetime
from typing import Annotated
from bubus import EventBus
from injectable import injectable, autowired, Autowired
from model.webhook import ReloadEvent, WoodpeckerEvent
from services import GitService
logger = logging.getLogger(__name__)
@injectable(singleton=True)
class ReloadService:
@autowired
def __init__(self, bus: Annotated[EventBus, Autowired]):
self._bus = bus
self._git = GitService()
bus.on(ReloadEvent, self.on_reload)
logger.info("ReloadService initialized.")
async def on_reload(self, event: ReloadEvent):
logger.info(f"Received ReloadEvent: {event.service}")
head = self._git.get_head()
await self._bus.dispatch(WoodpeckerEvent(
_id=-1,
commit=head.sha,
ref=head.branch,
message=f"Manual reload of {event.service}",
started=int(datetime.now().timestamp()),
files=[f"compose/{event.service}/docker-compose.yml"]
))

View file

@ -3,6 +3,7 @@ import logging
from fastapi import FastAPI
from injectable import load_injection_container
from core.injects import AutowireSupport
from karl.config import get_settings
from karl.util.logging import HandlerFactory
@ -15,7 +16,7 @@ class KarlApplication:
_app = FastAPI(title="Karl", version="0.1.0")
self._set_middlewares(_app)
self._set_routes(_app)
self._set_events(_app)
self._init_services(_app)
self._app = _app
@ -55,8 +56,9 @@ class KarlApplication:
app.include_router(api_v1_router, prefix="/api/v1", tags=["v1"])
pass
def _set_events(self, app: FastAPI):
pass
def _init_services(self, app: FastAPI):
AutowireSupport.reload()
AutowireSupport.woodpecker()
def run():

7
src/karl/model/vcs.py Normal file
View file

@ -0,0 +1,7 @@
from dataclasses import dataclass
@dataclass
class Head:
sha: str
branch: str

View file

@ -10,3 +10,6 @@ class WoodpeckerEvent(BaseEvent):
message: str
started: int
files: List[str]
class ReloadEvent(BaseEvent):
service: str

View file

@ -2,6 +2,7 @@ from git import Repo, Remote
from injectable import injectable
from karl.config import GitConfig, get_settings
from model.vcs import Head
@injectable(singleton=True)
@ -27,3 +28,11 @@ class GitService:
def checkout(self, sha: str):
self._origin.fetch()
self._repo.git.checkout(sha)
def get_head(self) -> Head:
if self._repo.head.is_detached:
return Head(self._repo.head.object.hexsha, "detached")
return Head(
self._repo.active_branch.commit.hexsha,
self._repo.active_branch.name
)