YAML parser
main / Explore-Gitea-Actions (push) Failing after 13s

This commit is contained in:
2026-08-04 11:53:58 +01:00
parent 8d73d5ded7
commit f807eab49c
5 changed files with 231 additions and 165 deletions
+102 -74
View File
@@ -1,13 +1,13 @@
from __future__ import annotations
from re import A
from dataclasses import dataclass
import yaml
from abc import ABC, abstractmethod
from pydantic import BaseModel
from playbook.models import ActModel, PlaybookModel, timed_run
from playbook.models import ActModel, PlaybookModel, StepModel, timed_run
from playbook.logging_models import Status, StepLogModel
from playbook.action_registry import ActionFn
from playbook.action_registry import ActionFn, ActionRegistry
class StepIF(ABC):
@@ -21,18 +21,6 @@ class StepIF(ABC):
""" Return a mapping of action roles (pre, play, post) to function names. """
pass
# class PlaybookError(Exception):
# """ Base exception for Playbook parsing and execution failures. """
# pass
# @dataclass
# class StepEntry(object):
# name: str
# step: StepIF
# class Play(object):
# def __init__(self, name: str, registries: dict[str, ActionRegistry]):
# self.name: str = name
@@ -130,76 +118,116 @@ class StepIF(ABC):
# playLog.msg = "success"
#
# return playLog
#
# def _play_steps(self, steps: list[CustomStep]) -> StepLogModel:
# playLog: StepLogModel = StepLogModel(
# step_name=self.name,
# status=Status.GOOD,
# duration_sec=0,
# msg="",
# error=[],
# substeps=[],
# )
#
# prev_ctx: dict[str, object] = {}
# for step in steps:
# log: StepLogModel = timed_run(step.run, self._context | prev_ctx)
# prev_ctx = log.pipe_ctx
#
# playLog.substeps.append(log)
#
# if log.failed:
# playLog.error.append({
# "status": "failed",
# "output": f"failed in step: {step.name}"
# })
# playLog.status = Status.BAD
# break
#
# if playLog.status == Status.GOOD:
# playLog.msg = "success"
#
# return playLog
#
# def _get_function_from_registry(self, fn_name) -> ActionFn:
# for reg in self._registries.values():
# try:
# return reg.get(fn_name, "*")
# except ValueError:
# continue
#
# raise ValueError(f"no function with name '{fn_name}' was found")
#
# def _build_custom_step(self, name, actions, ctx) -> CustomStep:
# functionlist: list[ActionFn] = []
# for f in actions:
# try:
# fn = self._get_function_from_registry(actions[f])
# functionlist.append(fn)
# except KeyError as e:
# raise PlaybookError(
# f"Step '{name}' is missing required action field: {e}") from e
#
# return CustomStep(name, functionlist, ctx)
class PlaybookYAMLParser():
@staticmethod
def _parse_registries(reg_names: list[str]) -> list[ActionRegistry]:
registries: list[ActionRegistry] = []
for reg in reg_names:
registries.extend(ActionRegistry.load_registries_from_file(reg))
return registries
@staticmethod
def _parse_steps(steps: list[dict[str, object]],
registries: list[ActionRegistry]) -> list[StepModel]:
step_list: list[StepModel] = []
for step in steps:
if not isinstance(step['name'], str):
raise ValueError(
f"name must of type `str` not `{type(step["name"])}`")
if not isinstance(step['action'], str):
raise ValueError(
f"action must of type `str` not `{type(step["action"])}`")
if not isinstance(step['context'], dict):
raise ValueError(
f"context must of type `dict` not `{type(step["context"])}`")
name: str = step['name']
action: str = step['action']
context: dict[str, object] = step['context']
found = False
fn: ActionFn
for reg in registries:
try:
fn = reg.get(action)
found = True
except:
continue
if not found:
raise ValueError(
f"Unable to find function `{action}` in any registry")
step_list.append(StepModel(name=name, action=fn, context=context))
return step_list
@staticmethod
def _parse_acts(acts_data: list[dict[str, object]],
registries: list[ActionRegistry]) -> list[ActModel]:
acts: list[ActModel] = []
for act in acts_data:
if not isinstance(act["name"], str):
raise ValueError(
f"name must of type `str` not `{type(act["name"])}`")
if not isinstance(act["steps"], list):
raise ValueError(
f"steps must of type `list` not `{type(act["steps"])}`")
name: str = act["name"]
steps: list[dict[str, object]] = act["steps"]
step_list = PlaybookYAMLParser._parse_steps(steps, registries)
modeled_act: ActModel = ActModel(name=name, steps=step_list)
acts.append(modeled_act)
return acts
@staticmethod
def from_yaml(fp: str) -> Playbook:
with open(fp, "rb") as source_file:
data = yaml.safe_load(source_file)
reg_yaml = data.get("registries", [])
registries = PlaybookYAMLParser._parse_registries(reg_yaml)
acts_yaml = data.get("acts", {})
acts: list[ActModel] = PlaybookYAMLParser._parse_acts(
acts_yaml, registries)
global_context = data.get("global_context", {})
log_dir: str = data.get("log_dir", "./")
playbook_name: str = data.get("playbook_name")
new_playbook: PlaybookModel = PlaybookModel(
playbook_name=playbook_name,
acts=acts,
log_dir=log_dir,
registries=registries,
global_context=global_context
)
return Playbook(new_playbook)
pass
class Playbook():
model: PlaybookModel
def __init__(self, model: PlaybookModel):
self.model = model
self.model = model
@property
def acts(self) -> list[ActModel]:
return self.model.acts
@classmethod
def from_yaml(cls, fp: str) -> Playbook:
try:
new_playboook = PlaybookModel.from_yaml_file(fp)
return Playbook(new_playboook)
except Exception as e:
raise e
return PlaybookYAMLParser.from_yaml(fp)
def view_playbook(self) -> str:
return self.model.model_dump_json()