Post Action Plugin Infrastructure - #277
Conversation
alexandraBara
left a comment
There was a problem hiding this comment.
Couple things to consider:
- currently nothing prevents the same plugin from appearing twice in post actions with diff conditions
- PluginConfig.merge() drops post-actions in pluginrecipe.py. What do we do with this? do we allow postconditions in recipes?
- This merges post_actions_plugins: PluginExecutor.merge_configs() but this one does not: PluginConfig.merge() (recipes)
| # | ||
| # MIT License | ||
| # | ||
| # Copyright (c) 2025 Advanced Micro Devices, Inc. |
There was a problem hiding this comment.
new files must have 2026
| """If set, only inspect the PluginResult whose ``source`` matches this name. | ||
| If None, all results are candidates.""" | ||
|
|
||
| status: Optional[str] = None |
There was a problem hiding this comment.
this type should be ExecutionStatus
| Accepts any :class:`~nodescraper.enums.ExecutionStatus` name | ||
| (e.g. ``"WARNING"``, ``"ERROR"``, ``"EXECUTION_FAILURE"``).""" | ||
|
|
||
| event_category: Optional[str] = None |
There was a problem hiding this comment.
this should also be EventPriority not str
There was a problem hiding this comment.
Assuming you meant event_priority with this comment, which is fixed in 3cc2d56
| """If set, only inspect the PluginResult whose ``source`` matches this name. | ||
| If None, all results are candidates.""" | ||
|
|
||
| status: Optional[str] = None |
There was a problem hiding this comment.
| status: Optional[str] = None | |
| status: Optional[ExecutionStatus] = None |
| def _matches_result(self, result: PluginResult) -> bool: | ||
| """Return True if *result* satisfies all specified fields (AND logic). | ||
|
|
||
| Each field that is not None must be satisfied; unset fields are skipped. | ||
| """ | ||
| # --- status check --- | ||
| if self.status is not None: | ||
| try: | ||
| status_threshold = ExecutionStatus[self.status.upper()] | ||
| except KeyError: | ||
| return False | ||
| if result.status < status_threshold: | ||
| return False |
There was a problem hiding this comment.
once the correct type is set for status this function can probably just be:
| def _matches_result(self, result: PluginResult) -> bool: | |
| """Return True if *result* satisfies all specified fields (AND logic). | |
| Each field that is not None must be satisfied; unset fields are skipped. | |
| """ | |
| # --- status check --- | |
| if self.status is not None: | |
| try: | |
| status_threshold = ExecutionStatus[self.status.upper()] | |
| except KeyError: | |
| return False | |
| if result.status < status_threshold: | |
| return False | |
| def _matches_result(self, result: PluginResult) -> bool: | |
| """Return True if *result* satisfies all specified fields (AND logic). | |
| if self.status is not None and result.status < self.status: | |
| return False |
| event_description_contains: Optional[str] = None | ||
| """If set, at least one event's description must contain this substring | ||
| (case-sensitive).""" | ||
|
|
There was a problem hiding this comment.
Once the types are fixed, i recommend you add these too:
@field_validator("status", mode="before")
@classmethod
def _coerce_status(cls, v):
# mirror TaskResult.validate_status
...
@field_validator("event_priority", mode="before")
@classmethod
def _coerce_priority(cls, v):
# mirror Event.validate_priority (or import shared helper)
...
| } | ||
| """ | ||
|
|
||
| plugin: str |
There was a problem hiding this comment.
i think this needs a @field_validator to sanitize input like "" or " ". Maybe something like:
@field_validator("plugin")
@classmethod
def _strip_and_require_plugin(cls, v: str) -> str:
v = v.strip()
if not v:
raise ValueError("plugin name must not be empty")
return v
For 1, I think this is fine, since users could also just specify the same plugin multiple times in their config with different For 2+3, post actions should be allowed in recipes in my opinion, and I have made the changes you suggested to allow for this, and added some tests in 3cc2d56 |
Summary
This PR adds
post-actions, which is a method of running more plugins based on the granular results of prior plugins. Post actions can be specified only through the plugin configuration JSON file. The README is updated with the specific semantics of how post actions can be configured. Any plugin can be used as a post-action plugin. This PR also adds unit tests for post actions, and updates one existing unit test.This PR also contains a bugfix that prevented OS detection during remote execution. The fix was to not make a
pydanticmodel copy ofsystem_infoinpluginexecutor.py, and instead use the pre-existing instance of the model. The copy would be update with the correct OS family, but the original, which was then passed to the plugins themselves, was not updated, which caused all plugins to not run.Test plan
pytest test/unitpytest test/functional(if applicable)pre-commit run --all-filesChecklist