mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
extend triggers to on_start and on_stop methods
This commit also replaces old run method to new on_result
This commit is contained in:
parent
e0b0c3caeb
commit
fc0d8387df
@ -473,7 +473,7 @@ def _set_repo_rebuild_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
parser.add_argument("--from-database",
|
parser.add_argument("--from-database",
|
||||||
help="read packages from database instead of filesystem. This feature in particular is "
|
help="read packages from database instead of filesystem. This feature in particular is "
|
||||||
"required in case if you would like to restore repository from another repository "
|
"required in case if you would like to restore repository from another repository "
|
||||||
"instance. Note however that in order to restore packages you need to have original "
|
"instance. Note, however, that in order to restore packages you need to have original "
|
||||||
"ahriman instance run with web service and have run repo-update at least once.",
|
"ahriman instance run with web service and have run repo-update at least once.",
|
||||||
action="store_true")
|
action="store_true")
|
||||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||||
|
@ -45,7 +45,7 @@ class ReportTrigger(Trigger):
|
|||||||
Trigger.__init__(self, architecture, configuration)
|
Trigger.__init__(self, architecture, configuration)
|
||||||
self.targets = configuration.getlist("report", "target")
|
self.targets = configuration.getlist("report", "target")
|
||||||
|
|
||||||
def run(self, result: Result, packages: Iterable[Package]) -> None:
|
def on_result(self, result: Result, packages: Iterable[Package]) -> None:
|
||||||
"""
|
"""
|
||||||
run trigger
|
run trigger
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ class Executor(Cleaner):
|
|||||||
Args:
|
Args:
|
||||||
result(Result): build result
|
result(Result): build result
|
||||||
"""
|
"""
|
||||||
self.triggers.process(result, self.packages())
|
self.triggers.on_result(result, self.packages())
|
||||||
|
|
||||||
def process_update(self, packages: Iterable[Path]) -> Result:
|
def process_update(self, packages: Iterable[Path]) -> Result:
|
||||||
"""
|
"""
|
||||||
|
@ -181,7 +181,7 @@ class GPG(LazyLogging):
|
|||||||
sign repository if required by configuration
|
sign repository if required by configuration
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
more likely you just want to pass ``repository_sign_args`` to repo wrapper
|
More likely you just want to pass ``repository_sign_args`` to repo wrapper
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path(Path): path to repository database
|
path(Path): path to repository database
|
||||||
|
@ -37,7 +37,7 @@ class Trigger(LazyLogging):
|
|||||||
This class must be used in order to create own extension. Basically idea is the following::
|
This class must be used in order to create own extension. Basically idea is the following::
|
||||||
|
|
||||||
>>> class CustomTrigger(Trigger):
|
>>> class CustomTrigger(Trigger):
|
||||||
>>> def run(self, result: Result, packages: Iterable[Package]) -> None:
|
>>> def on_result(self, result: Result, packages: Iterable[Package]) -> None:
|
||||||
>>> perform_some_action()
|
>>> perform_some_action()
|
||||||
|
|
||||||
Having this class you can pass it to ``configuration`` and it will be run on action::
|
Having this class you can pass it to ``configuration`` and it will be run on action::
|
||||||
@ -48,7 +48,7 @@ class Trigger(LazyLogging):
|
|||||||
>>> configuration.set_option("build", "triggers", "my.awesome.package.CustomTrigger")
|
>>> configuration.set_option("build", "triggers", "my.awesome.package.CustomTrigger")
|
||||||
>>>
|
>>>
|
||||||
>>> loader = TriggerLoader("x86_64", configuration)
|
>>> loader = TriggerLoader("x86_64", configuration)
|
||||||
>>> loader.process(Result(), [])
|
>>> loader.on_result(Result(), [])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
||||||
@ -62,15 +62,35 @@ class Trigger(LazyLogging):
|
|||||||
self.architecture = architecture
|
self.architecture = architecture
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
|
|
||||||
def run(self, result: Result, packages: Iterable[Package]) -> None:
|
def on_result(self, result: Result, packages: Iterable[Package]) -> None:
|
||||||
"""
|
"""
|
||||||
run trigger
|
trigger action which will be called after build process with process result
|
||||||
|
|
||||||
|
Args:
|
||||||
|
result(Result): build result
|
||||||
|
packages(Iterable[Package]): list of all available packages
|
||||||
|
"""
|
||||||
|
self.run(result, packages) # compatibility with old triggers
|
||||||
|
|
||||||
|
def on_start(self) -> None:
|
||||||
|
"""
|
||||||
|
trigger action which will be called at the start of the application
|
||||||
|
"""
|
||||||
|
|
||||||
|
def on_stop(self) -> None:
|
||||||
|
"""
|
||||||
|
trigger action which will be called before the stop of the application
|
||||||
|
"""
|
||||||
|
|
||||||
|
def run(self, result: Result, packages: Iterable[Package]) -> None:
|
||||||
|
"""
|
||||||
|
run trigger
|
||||||
|
|
||||||
|
Note:
|
||||||
|
This method is deprecated and will be removed in the future versions. In order to run old-style trigger
|
||||||
|
action the ``on_result`` method must be used.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
result(Result): build result
|
result(Result): build result
|
||||||
packages(Iterable[Package]): list of all available packages
|
packages(Iterable[Package]): list of all available packages
|
||||||
|
|
||||||
Raises:
|
|
||||||
NotImplementedError: not implemented method
|
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
|
||||||
|
@ -17,12 +17,14 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
import contextlib
|
||||||
import importlib
|
import importlib
|
||||||
import os
|
import os
|
||||||
|
import weakref
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
from typing import Iterable
|
from typing import Generator, Iterable
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.exceptions import InvalidExtension
|
from ahriman.core.exceptions import InvalidExtension
|
||||||
@ -54,7 +56,7 @@ class TriggerLoader(LazyLogging):
|
|||||||
|
|
||||||
After that you are free to run triggers::
|
After that you are free to run triggers::
|
||||||
|
|
||||||
>>> loader.process(Result(), [])
|
>>> loader.on_result(Result(), [])
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
def __init__(self, architecture: str, configuration: Configuration) -> None:
|
||||||
@ -73,6 +75,25 @@ class TriggerLoader(LazyLogging):
|
|||||||
for trigger in configuration.getlist("build", "triggers")
|
for trigger in configuration.getlist("build", "triggers")
|
||||||
]
|
]
|
||||||
|
|
||||||
|
self.on_start()
|
||||||
|
self._finalizer = weakref.finalize(self, self.on_stop)
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def __execute_trigger(self, trigger: Trigger) -> Generator[None, None, None]:
|
||||||
|
"""
|
||||||
|
decorator for calling triggers
|
||||||
|
|
||||||
|
Args:
|
||||||
|
trigger(Trigger): trigger instance to be called
|
||||||
|
"""
|
||||||
|
trigger_name = type(trigger).__name__
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.logger.info("executing extension %s", trigger_name)
|
||||||
|
yield
|
||||||
|
except Exception:
|
||||||
|
self.logger.exception("got exception while run trigger %s", trigger_name)
|
||||||
|
|
||||||
def _load_module_from_file(self, module_path: str, implementation: str) -> ModuleType:
|
def _load_module_from_file(self, module_path: str, implementation: str) -> ModuleType:
|
||||||
"""
|
"""
|
||||||
load module by given file path
|
load module by given file path
|
||||||
@ -149,18 +170,30 @@ class TriggerLoader(LazyLogging):
|
|||||||
|
|
||||||
return trigger
|
return trigger
|
||||||
|
|
||||||
def process(self, result: Result, packages: Iterable[Package]) -> None:
|
def on_result(self, result: Result, packages: Iterable[Package]) -> None:
|
||||||
"""
|
"""
|
||||||
run remote sync
|
run trigger with result of application run
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
result(Result): build result
|
result(Result): build result
|
||||||
packages(Iterable[Package]): list of all available packages
|
packages(Iterable[Package]): list of all available packages
|
||||||
"""
|
"""
|
||||||
for trigger in self.triggers:
|
for trigger in self.triggers:
|
||||||
trigger_name = type(trigger).__name__
|
with self.__execute_trigger(trigger):
|
||||||
try:
|
trigger.on_result(result, packages)
|
||||||
self.logger.info("executing extension %s", trigger_name)
|
|
||||||
trigger.run(result, packages)
|
def on_start(self) -> None:
|
||||||
except Exception:
|
"""
|
||||||
self.logger.exception("got exception while run trigger %s", trigger_name)
|
run triggers on load
|
||||||
|
"""
|
||||||
|
for trigger in self.triggers:
|
||||||
|
with self.__execute_trigger(trigger):
|
||||||
|
trigger.on_start()
|
||||||
|
|
||||||
|
def on_stop(self) -> None:
|
||||||
|
"""
|
||||||
|
run triggers before the application exit
|
||||||
|
"""
|
||||||
|
for trigger in self.triggers:
|
||||||
|
with self.__execute_trigger(trigger):
|
||||||
|
trigger.on_stop()
|
||||||
|
@ -45,7 +45,7 @@ class UploadTrigger(Trigger):
|
|||||||
Trigger.__init__(self, architecture, configuration)
|
Trigger.__init__(self, architecture, configuration)
|
||||||
self.targets = configuration.getlist("upload", "target")
|
self.targets = configuration.getlist("upload", "target")
|
||||||
|
|
||||||
def run(self, result: Result, packages: Iterable[Package]) -> None:
|
def on_result(self, result: Result, packages: Iterable[Package]) -> None:
|
||||||
"""
|
"""
|
||||||
run trigger
|
run trigger
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ def test_run_trigger(args: argparse.Namespace, configuration: Configuration, pac
|
|||||||
args.trigger = ["ahriman.core.report.ReportTrigger"]
|
args.trigger = ["ahriman.core.report.ReportTrigger"]
|
||||||
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
|
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
|
||||||
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||||
report_mock = mocker.patch("ahriman.core.report.ReportTrigger.run")
|
report_mock = mocker.patch("ahriman.core.report.ReportTrigger.on_result")
|
||||||
upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.run")
|
upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.on_result")
|
||||||
|
|
||||||
Triggers.run(args, "x86_64", configuration, True, False)
|
Triggers.run(args, "x86_64", configuration, True, False)
|
||||||
report_mock.assert_called_once_with(Result(), [package_ahriman])
|
report_mock.assert_called_once_with(Result(), [package_ahriman])
|
||||||
|
@ -5,7 +5,7 @@ from ahriman.core.report import ReportTrigger
|
|||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
def test_run(configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_on_result(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run report for specified targets
|
must run report for specified targets
|
||||||
"""
|
"""
|
||||||
@ -13,5 +13,5 @@ def test_run(configuration: Configuration, mocker: MockerFixture) -> None:
|
|||||||
run_mock = mocker.patch("ahriman.core.report.Report.run")
|
run_mock = mocker.patch("ahriman.core.report.Report.run")
|
||||||
|
|
||||||
trigger = ReportTrigger("x86_64", configuration)
|
trigger = ReportTrigger("x86_64", configuration)
|
||||||
trigger.run(Result(), [])
|
trigger.on_result(Result(), [])
|
||||||
run_mock.assert_called_once_with(Result(), [])
|
run_mock.assert_called_once_with(Result(), [])
|
||||||
|
@ -149,7 +149,7 @@ def test_process_triggers(executor: Executor, package_ahriman: Package, result:
|
|||||||
must process report
|
must process report
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.repository.executor.Executor.packages", return_value=[package_ahriman])
|
mocker.patch("ahriman.core.repository.executor.Executor.packages", return_value=[package_ahriman])
|
||||||
triggers_mock = mocker.patch("ahriman.core.triggers.TriggerLoader.process")
|
triggers_mock = mocker.patch("ahriman.core.triggers.TriggerLoader.on_result")
|
||||||
|
|
||||||
executor.process_triggers(result)
|
executor.process_triggers(result)
|
||||||
triggers_mock.assert_called_once_with(result, [package_ahriman])
|
triggers_mock.assert_called_once_with(result, [package_ahriman])
|
||||||
|
@ -1,12 +1,34 @@
|
|||||||
import pytest
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
from ahriman.core.triggers import Trigger
|
from ahriman.core.triggers import Trigger
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
|
def test_on_result(trigger: Trigger, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must pass execution nto run method
|
||||||
|
"""
|
||||||
|
run_mock = mocker.patch("ahriman.core.triggers.Trigger.run")
|
||||||
|
trigger.on_result(Result(), [])
|
||||||
|
run_mock.assert_called_once_with(Result(), [])
|
||||||
|
|
||||||
|
|
||||||
|
def test_on_start(trigger: Trigger) -> None:
|
||||||
|
"""
|
||||||
|
must do nothing for not implemented method on_start
|
||||||
|
"""
|
||||||
|
trigger.on_start()
|
||||||
|
|
||||||
|
|
||||||
|
def test_on_stop(trigger: Trigger) -> None:
|
||||||
|
"""
|
||||||
|
must do nothing for not implemented method on_stop
|
||||||
|
"""
|
||||||
|
trigger.on_stop()
|
||||||
|
|
||||||
|
|
||||||
def test_run(trigger: Trigger) -> None:
|
def test_run(trigger: Trigger) -> None:
|
||||||
"""
|
"""
|
||||||
must raise NotImplemented for missing rum method
|
must do nothing for not implemented method run
|
||||||
"""
|
"""
|
||||||
with pytest.raises(NotImplementedError):
|
trigger.run(Result(), [])
|
||||||
trigger.run(Result(), [])
|
|
||||||
|
@ -3,12 +3,26 @@ import pytest
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.exceptions import InvalidExtension
|
from ahriman.core.exceptions import InvalidExtension
|
||||||
from ahriman.core.triggers import TriggerLoader
|
from ahriman.core.triggers import TriggerLoader
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
|
def test_init_at_exit(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must call on_start on init and on_stop on exit
|
||||||
|
"""
|
||||||
|
on_start_mock = mocker.patch("ahriman.core.triggers.trigger_loader.TriggerLoader.on_start")
|
||||||
|
on_stop_mock = mocker.patch("ahriman.core.triggers.trigger_loader.TriggerLoader.on_stop")
|
||||||
|
|
||||||
|
trigger_loader = TriggerLoader("x86_64", configuration)
|
||||||
|
on_start_mock.assert_called_once_with()
|
||||||
|
del trigger_loader
|
||||||
|
on_stop_mock.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
def test_load_trigger_package(trigger_loader: TriggerLoader) -> None:
|
def test_load_trigger_package(trigger_loader: TriggerLoader) -> None:
|
||||||
"""
|
"""
|
||||||
must load trigger from package
|
must load trigger from package
|
||||||
@ -75,27 +89,51 @@ def test_load_trigger_path_not_found(trigger_loader: TriggerLoader) -> None:
|
|||||||
trigger_loader.load_trigger("/some/random/path.py.SomeRandomModule")
|
trigger_loader.load_trigger("/some/random/path.py.SomeRandomModule")
|
||||||
|
|
||||||
|
|
||||||
def test_process(trigger_loader: TriggerLoader, package_ahriman: Package, mocker: MockerFixture) -> None:
|
def test_on_result(trigger_loader: TriggerLoader, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run triggers
|
must run triggers
|
||||||
"""
|
"""
|
||||||
upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.run")
|
upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.on_result")
|
||||||
report_mock = mocker.patch("ahriman.core.report.ReportTrigger.run")
|
report_mock = mocker.patch("ahriman.core.report.ReportTrigger.on_result")
|
||||||
|
|
||||||
trigger_loader.process(Result(), [package_ahriman])
|
trigger_loader.on_result(Result(), [package_ahriman])
|
||||||
report_mock.assert_called_once_with(Result(), [package_ahriman])
|
report_mock.assert_called_once_with(Result(), [package_ahriman])
|
||||||
upload_mock.assert_called_once_with(Result(), [package_ahriman])
|
upload_mock.assert_called_once_with(Result(), [package_ahriman])
|
||||||
|
|
||||||
|
|
||||||
def test_process_exception(trigger_loader: TriggerLoader, package_ahriman: Package, mocker: MockerFixture) -> None:
|
def test_on_result_exception(trigger_loader: TriggerLoader, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must suppress exception during trigger run
|
must suppress exception during trigger run
|
||||||
"""
|
"""
|
||||||
upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.run", side_effect=Exception())
|
upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.on_result", side_effect=Exception())
|
||||||
report_mock = mocker.patch("ahriman.core.report.ReportTrigger.run")
|
report_mock = mocker.patch("ahriman.core.report.ReportTrigger.on_result")
|
||||||
log_mock = mocker.patch("logging.Logger.exception")
|
log_mock = mocker.patch("logging.Logger.exception")
|
||||||
|
|
||||||
trigger_loader.process(Result(), [package_ahriman])
|
trigger_loader.on_result(Result(), [package_ahriman])
|
||||||
report_mock.assert_called_once_with(Result(), [package_ahriman])
|
report_mock.assert_called_once_with(Result(), [package_ahriman])
|
||||||
upload_mock.assert_called_once_with(Result(), [package_ahriman])
|
upload_mock.assert_called_once_with(Result(), [package_ahriman])
|
||||||
log_mock.assert_called_once()
|
log_mock.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
def test_on_start(trigger_loader: TriggerLoader, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must run triggers on start
|
||||||
|
"""
|
||||||
|
upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.on_start")
|
||||||
|
report_mock = mocker.patch("ahriman.core.report.ReportTrigger.on_start")
|
||||||
|
|
||||||
|
trigger_loader.on_start()
|
||||||
|
report_mock.assert_called_once_with()
|
||||||
|
upload_mock.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
|
def test_on_stop(trigger_loader: TriggerLoader, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must run triggers on stop
|
||||||
|
"""
|
||||||
|
upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.on_stop")
|
||||||
|
report_mock = mocker.patch("ahriman.core.report.ReportTrigger.on_stop")
|
||||||
|
|
||||||
|
trigger_loader.on_stop()
|
||||||
|
report_mock.assert_called_once_with()
|
||||||
|
upload_mock.assert_called_once_with()
|
||||||
|
@ -5,7 +5,7 @@ from ahriman.core.upload import UploadTrigger
|
|||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
def test_run(configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_on_result(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run report for specified targets
|
must run report for specified targets
|
||||||
"""
|
"""
|
||||||
@ -13,5 +13,5 @@ def test_run(configuration: Configuration, mocker: MockerFixture) -> None:
|
|||||||
run_mock = mocker.patch("ahriman.core.upload.Upload.run")
|
run_mock = mocker.patch("ahriman.core.upload.Upload.run")
|
||||||
|
|
||||||
trigger = UploadTrigger("x86_64", configuration)
|
trigger = UploadTrigger("x86_64", configuration)
|
||||||
trigger.run(Result(), [])
|
trigger.on_result(Result(), [])
|
||||||
run_mock.assert_called_once_with(configuration.repository_paths.repository, [])
|
run_mock.assert_called_once_with(configuration.repository_paths.repository, [])
|
||||||
|
Loading…
Reference in New Issue
Block a user