Merge pull request 'feat: reload' (#32) from reload into develop
Reviewed-on: https://hattori.ztsh.eu/iac/karl/pulls/32
This commit is contained in:
commit
08972266db
9 changed files with 77 additions and 8 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -14,6 +14,6 @@ uv.lock
|
||||||
**/*.kdbx*
|
**/*.kdbx*
|
||||||
.compose_repository
|
.compose_repository
|
||||||
|
|
||||||
__pycache__/
|
deployment/
|
||||||
**/dist/
|
**/dist/
|
||||||
**/*.log
|
**/*.log
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@ from starlette.responses import JSONResponse, Response
|
||||||
|
|
||||||
from karl.api.models import Request
|
from karl.api.models import Request
|
||||||
from karl.core.injects import AutowireSupport
|
from karl.core.injects import AutowireSupport
|
||||||
from karl.core.woodpecker import Woodpecker
|
from karl.model.webhook import WoodpeckerEvent, ReloadEvent
|
||||||
from karl.model.webhook import WoodpeckerEvent
|
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -21,7 +20,6 @@ async def root():
|
||||||
|
|
||||||
@cbv(router)
|
@cbv(router)
|
||||||
class APIv1:
|
class APIv1:
|
||||||
woodpecker: Woodpecker = Depends(AutowireSupport.woodpecker)
|
|
||||||
bus: EventBus = Depends(AutowireSupport.bus)
|
bus: EventBus = Depends(AutowireSupport.bus)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
@ -39,3 +37,10 @@ class APIv1:
|
||||||
async def ci(self, request: Request):
|
async def ci(self, request: Request):
|
||||||
await self.bus.dispatch(mapper.map(request))
|
await self.bus.dispatch(mapper.map(request))
|
||||||
return Response(status_code=201)
|
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)
|
||||||
|
|
|
||||||
|
|
@ -51,4 +51,8 @@ class Settings(BaseSettings):
|
||||||
|
|
||||||
@lru_cache
|
@lru_cache
|
||||||
def get_settings() -> Settings:
|
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")
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from bubus import EventBus
|
from bubus import EventBus
|
||||||
from injectable import inject
|
from injectable import inject
|
||||||
|
|
||||||
|
from karl.core.reload import ReloadService
|
||||||
from karl.core.woodpecker import Woodpecker
|
from karl.core.woodpecker import Woodpecker
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -10,6 +11,10 @@ class AutowireSupport:
|
||||||
def woodpecker():
|
def woodpecker():
|
||||||
return inject(Woodpecker)
|
return inject(Woodpecker)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def reload():
|
||||||
|
return inject(ReloadService)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def bus():
|
def bus():
|
||||||
return inject(EventBus)
|
return inject(EventBus)
|
||||||
|
|
|
||||||
34
src/karl/core/reload.py
Normal file
34
src/karl/core/reload.py
Normal 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"]
|
||||||
|
))
|
||||||
|
|
@ -3,6 +3,7 @@ import logging
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from injectable import load_injection_container
|
from injectable import load_injection_container
|
||||||
|
|
||||||
|
from core.injects import AutowireSupport
|
||||||
from karl.config import get_settings
|
from karl.config import get_settings
|
||||||
from karl.util.logging import HandlerFactory
|
from karl.util.logging import HandlerFactory
|
||||||
|
|
||||||
|
|
@ -15,7 +16,7 @@ class KarlApplication:
|
||||||
_app = FastAPI(title="Karl", version="0.1.0")
|
_app = FastAPI(title="Karl", version="0.1.0")
|
||||||
self._set_middlewares(_app)
|
self._set_middlewares(_app)
|
||||||
self._set_routes(_app)
|
self._set_routes(_app)
|
||||||
self._set_events(_app)
|
self._init_services(_app)
|
||||||
|
|
||||||
self._app = _app
|
self._app = _app
|
||||||
|
|
||||||
|
|
@ -55,8 +56,9 @@ class KarlApplication:
|
||||||
app.include_router(api_v1_router, prefix="/api/v1", tags=["v1"])
|
app.include_router(api_v1_router, prefix="/api/v1", tags=["v1"])
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _set_events(self, app: FastAPI):
|
def _init_services(self, app: FastAPI):
|
||||||
pass
|
AutowireSupport.reload()
|
||||||
|
AutowireSupport.woodpecker()
|
||||||
|
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
|
|
|
||||||
7
src/karl/model/vcs.py
Normal file
7
src/karl/model/vcs.py
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Head:
|
||||||
|
sha: str
|
||||||
|
branch: str
|
||||||
|
|
@ -10,3 +10,6 @@ class WoodpeckerEvent(BaseEvent):
|
||||||
message: str
|
message: str
|
||||||
started: int
|
started: int
|
||||||
files: List[str]
|
files: List[str]
|
||||||
|
|
||||||
|
class ReloadEvent(BaseEvent):
|
||||||
|
service: str
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ from git import Repo, Remote
|
||||||
from injectable import injectable
|
from injectable import injectable
|
||||||
|
|
||||||
from karl.config import GitConfig, get_settings
|
from karl.config import GitConfig, get_settings
|
||||||
|
from model.vcs import Head
|
||||||
|
|
||||||
|
|
||||||
@injectable(singleton=True)
|
@injectable(singleton=True)
|
||||||
|
|
@ -27,3 +28,11 @@ class GitService:
|
||||||
def checkout(self, sha: str):
|
def checkout(self, sha: str):
|
||||||
self._origin.fetch()
|
self._origin.fetch()
|
||||||
self._repo.git.checkout(sha)
|
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
|
||||||
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue