write patches via gitremote push trigger

This commit is contained in:
Evgenii Alekseev 2022-12-15 01:34:52 +02:00
parent b0b37e8169
commit 72dec54c0d
5 changed files with 52 additions and 18 deletions

View File

@ -25,6 +25,9 @@ from ahriman.core.triggers import Trigger
class RemotePullTrigger(Trigger): class RemotePullTrigger(Trigger):
""" """
trigger based on pulling PKGBUILDs before the actions trigger based on pulling PKGBUILDs before the actions
Attributes:
targets(List[str]): git remote target list
""" """
def __init__(self, architecture: str, configuration: Configuration) -> None: def __init__(self, architecture: str, configuration: Configuration) -> None:

View File

@ -25,6 +25,7 @@ from typing import Generator
from ahriman.core.build_tools.sources import Sources from ahriman.core.build_tools.sources import Sources
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.exceptions import GitRemoteError from ahriman.core.exceptions import GitRemoteError
from ahriman.core.log import LazyLogging from ahriman.core.log import LazyLogging
from ahriman.models.package import Package from ahriman.models.package import Package
@ -39,17 +40,20 @@ class RemotePush(LazyLogging):
Attributes: Attributes:
commit_author(Optional[str]): optional commit author in form of git config (i.e. ``user <user@host>``) commit_author(Optional[str]): optional commit author in form of git config (i.e. ``user <user@host>``)
database(SQLite): database instance
remote_source(RemoteSource): repository remote source (remote pull url and branch) remote_source(RemoteSource): repository remote source (remote pull url and branch)
""" """
def __init__(self, configuration: Configuration, section: str) -> None: def __init__(self, configuration: Configuration, database: SQLite, section: str) -> None:
""" """
default constructor default constructor
Args: Args:
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
remote_push_trigger.py database(SQLite): database instance
section(str): settings section name
""" """
self.database = database
self.commit_author = configuration.get(section, "commit_author", fallback=None) self.commit_author = configuration.get(section, "commit_author", fallback=None)
self.remote_source = RemoteSource( self.remote_source = RemoteSource(
git_url=configuration.get(section, "push_url"), git_url=configuration.get(section, "push_url"),
@ -59,8 +63,7 @@ class RemotePush(LazyLogging):
source=PackageSource.Local, source=PackageSource.Local,
) )
@staticmethod def package_update(self, package: Package, target_dir: Path) -> str:
def package_update(package: Package, target_dir: Path) -> str:
""" """
clone specified package and update its content in cloned PKGBUILD repository clone specified package and update its content in cloned PKGBUILD repository
@ -79,11 +82,14 @@ class RemotePush(LazyLogging):
Sources.fetch(package_target_dir, package.remote) Sources.fetch(package_target_dir, package.remote)
# ...and last, but not least, we remove the dot-git directory... # ...and last, but not least, we remove the dot-git directory...
shutil.rmtree(package_target_dir / ".git", ignore_errors=True) shutil.rmtree(package_target_dir / ".git", ignore_errors=True)
# ...copy all patches...
for patch in self.database.patches_get(package.base):
filename = f"ahriman-{package.base}.patch" if patch.key is None else f"ahriman-{patch.key}.patch"
patch.write(package_target_dir / filename)
# ...and finally return path to the copied directory # ...and finally return path to the copied directory
return package.base return package.base
@staticmethod def packages_update(self, result: Result, target_dir: Path) -> Generator[str, None, None]:
def packages_update(result: Result, target_dir: Path) -> Generator[str, None, None]:
""" """
update all packages from the build result update all packages from the build result
@ -95,7 +101,7 @@ class RemotePush(LazyLogging):
str: path to updated files str: path to updated files
""" """
for package in result.success: for package in result.success:
yield RemotePush.package_update(package, target_dir) yield self.package_update(package, target_dir)
def run(self, result: Result) -> None: def run(self, result: Result) -> None:
""" """
@ -107,7 +113,7 @@ class RemotePush(LazyLogging):
try: try:
with TemporaryDirectory(ignore_cleanup_errors=True) as dir_name, (clone_dir := Path(dir_name)): with TemporaryDirectory(ignore_cleanup_errors=True) as dir_name, (clone_dir := Path(dir_name)):
Sources.fetch(clone_dir, self.remote_source) Sources.fetch(clone_dir, self.remote_source)
Sources.push(clone_dir, self.remote_source, *RemotePush.packages_update(result, clone_dir), Sources.push(clone_dir, self.remote_source, *self.packages_update(result, clone_dir),
commit_author=self.commit_author) commit_author=self.commit_author)
except Exception: except Exception:
self.logger.exception("git push failed") self.logger.exception("git push failed")

View File

@ -20,6 +20,7 @@
from typing import Iterable from typing import Iterable
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.gitremote.remote_push import RemotePush from ahriman.core.gitremote.remote_push import RemotePush
from ahriman.core.triggers import Trigger from ahriman.core.triggers import Trigger
from ahriman.models.package import Package from ahriman.models.package import Package
@ -29,6 +30,10 @@ from ahriman.models.result import Result
class RemotePushTrigger(Trigger): class RemotePushTrigger(Trigger):
""" """
trigger for syncing PKGBUILDs to remote repository trigger for syncing PKGBUILDs to remote repository
Attributes:
database(SQLite): database instance
targets(List[str]): git remote target list
""" """
def __init__(self, architecture: str, configuration: Configuration) -> None: def __init__(self, architecture: str, configuration: Configuration) -> None:
@ -40,6 +45,7 @@ class RemotePushTrigger(Trigger):
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
""" """
Trigger.__init__(self, architecture, configuration) Trigger.__init__(self, architecture, configuration)
self.database = SQLite.load(configuration)
self.targets = configuration.getlist("remote-push", "target", fallback=["gitremote"]) self.targets = configuration.getlist("remote-push", "target", fallback=["gitremote"])
def on_result(self, result: Result, packages: Iterable[Package]) -> None: def on_result(self, result: Result, packages: Iterable[Package]) -> None:
@ -52,5 +58,5 @@ class RemotePushTrigger(Trigger):
""" """
for target in self.targets: for target in self.targets:
section, _ = self.configuration.gettype(target, self.architecture) section, _ = self.configuration.gettype(target, self.architecture)
runner = RemotePush(self.configuration, section) runner = RemotePush(self.configuration, self.database, section)
runner.run(result) runner.run(result)

View File

@ -5,48 +5,65 @@ from pytest_mock import MockerFixture
from unittest.mock import call as MockCall from unittest.mock import call as MockCall
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.exceptions import GitRemoteError from ahriman.core.exceptions import GitRemoteError
from ahriman.core.gitremote.remote_push import RemotePush from ahriman.core.gitremote.remote_push import RemotePush
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.pkgbuild_patch import PkgbuildPatch
from ahriman.models.result import Result from ahriman.models.result import Result
def test_package_update(package_ahriman: Package, mocker: MockerFixture) -> None: def test_package_update(database: SQLite, configuration: Configuration, package_ahriman: Package,
mocker: MockerFixture) -> None:
""" """
must update single package must update single package
""" """
patch1 = PkgbuildPatch(None, "patch")
patch2 = PkgbuildPatch("key", "value")
rmtree_mock = mocker.patch("shutil.rmtree") rmtree_mock = mocker.patch("shutil.rmtree")
fetch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.fetch") fetch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
patches_mock = mocker.patch("ahriman.core.database.SQLite.patches_get", return_value=[patch1, patch2])
patches_write_mock = mocker.patch("ahriman.models.pkgbuild_patch.PkgbuildPatch.write")
runner = RemotePush(configuration, database, "gitremote")
local = Path("local") local = Path("local")
RemotePush.package_update(package_ahriman, local) assert runner.package_update(package_ahriman, local) == package_ahriman.base
rmtree_mock.assert_has_calls([ rmtree_mock.assert_has_calls([
MockCall(local / package_ahriman.base, ignore_errors=True), MockCall(local / package_ahriman.base, ignore_errors=True),
MockCall(local / package_ahriman.base / ".git", ignore_errors=True), MockCall(local / package_ahriman.base / ".git", ignore_errors=True),
]) ])
fetch_mock.assert_called_once_with(pytest.helpers.anyvar(int), package_ahriman.remote) fetch_mock.assert_called_once_with(pytest.helpers.anyvar(int), package_ahriman.remote)
patches_mock.assert_called_once_with(package_ahriman.base)
patches_write_mock.assert_has_calls([
MockCall(local / package_ahriman.base / f"ahriman-{package_ahriman.base}.patch"),
MockCall(local / package_ahriman.base / f"ahriman-{patch2.key}.patch"),
])
def test_packages_update(result: Result, package_ahriman: Package, mocker: MockerFixture) -> None: def test_packages_update(database: SQLite, configuration: Configuration, result: Result, package_ahriman: Package,
mocker: MockerFixture) -> None:
""" """
must generate packages update must generate packages update
""" """
update_mock = mocker.patch("ahriman.core.gitremote.remote_push.RemotePush.package_update", update_mock = mocker.patch("ahriman.core.gitremote.remote_push.RemotePush.package_update",
return_value=[package_ahriman.base]) return_value=[package_ahriman.base])
runner = RemotePush(configuration, database, "gitremote")
local = Path("local") local = Path("local")
assert list(RemotePush.packages_update(result, local)) assert list(runner.packages_update(result, local))
update_mock.assert_called_once_with(package_ahriman, local) update_mock.assert_called_once_with(package_ahriman, local)
def test_run(configuration: Configuration, result: Result, package_ahriman: Package, mocker: MockerFixture) -> None: def test_run(database: SQLite, configuration: Configuration, result: Result, package_ahriman: Package,
mocker: MockerFixture) -> None:
""" """
must push changes on result must push changes on result
""" """
mocker.patch("ahriman.core.gitremote.remote_push.RemotePush.packages_update", return_value=[package_ahriman.base]) mocker.patch("ahriman.core.gitremote.remote_push.RemotePush.packages_update", return_value=[package_ahriman.base])
fetch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.fetch") fetch_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.fetch")
push_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.push") push_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.push")
runner = RemotePush(configuration, "gitremote") runner = RemotePush(configuration, database, "gitremote")
runner.run(result) runner.run(result)
fetch_mock.assert_called_once_with(pytest.helpers.anyvar(int), runner.remote_source) fetch_mock.assert_called_once_with(pytest.helpers.anyvar(int), runner.remote_source)
@ -55,12 +72,12 @@ def test_run(configuration: Configuration, result: Result, package_ahriman: Pack
) )
def test_run_failed(configuration: Configuration, result: Result, mocker: MockerFixture) -> None: def test_run_failed(database: SQLite, configuration: Configuration, result: Result, mocker: MockerFixture) -> None:
""" """
must reraise exception on error occurred must reraise exception on error occurred
""" """
mocker.patch("ahriman.core.build_tools.sources.Sources.fetch", side_effect=Exception()) mocker.patch("ahriman.core.build_tools.sources.Sources.fetch", side_effect=Exception())
runner = RemotePush(configuration, "gitremote") runner = RemotePush(configuration, database, "gitremote")
with pytest.raises(GitRemoteError): with pytest.raises(GitRemoteError):
runner.run(result) runner.run(result)

View File

@ -1,16 +1,18 @@
from pytest_mock import MockerFixture from pytest_mock import MockerFixture
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.gitremote import RemotePushTrigger from ahriman.core.gitremote import RemotePushTrigger
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_on_result(configuration: Configuration, result: Result, package_ahriman: Package, def test_on_result(configuration: Configuration, result: Result, package_ahriman: Package,
mocker: MockerFixture) -> None: database: SQLite, mocker: MockerFixture) -> None:
""" """
must push changes on result must push changes on result
""" """
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
run_mock = mocker.patch("ahriman.core.gitremote.remote_push.RemotePush.run") run_mock = mocker.patch("ahriman.core.gitremote.remote_push.RemotePush.run")
trigger = RemotePushTrigger("x86_64", configuration) trigger = RemotePushTrigger("x86_64", configuration)