diff --git a/Dockerfile b/Dockerfile index 3ea34628..0cf00b26 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,7 @@ ENV AHRIMAN_PACKAGER="ahriman bot " ENV AHRIMAN_PACMAN_MIRROR="" ENV AHRIMAN_PORT="" ENV AHRIMAN_REPOSITORY="aur-clone" +ENV AHRIMAN_REPOSITORY_SERVER="" ENV AHRIMAN_REPOSITORY_ROOT="/var/lib/ahriman/ahriman" ENV AHRIMAN_UNIX_SOCKET="" ENV AHRIMAN_USER="ahriman" diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index a9b9a1c4..371989d9 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -43,6 +43,9 @@ fi if [ -n "$AHRIMAN_PORT" ]; then AHRIMAN_SETUP_ARGS+=("--web-port" "$AHRIMAN_PORT") fi +if [ -n "$AHRIMAN_REPOSITORY_SERVER" ]; then + AHRIMAN_SETUP_ARGS+=("--server" "$AHRIMAN_REPOSITORY_SERVER") +fi if [ -n "$AHRIMAN_UNIX_SOCKET" ]; then AHRIMAN_SETUP_ARGS+=("--web-unix-socket" "$AHRIMAN_UNIX_SOCKET") fi diff --git a/docs/faq.rst b/docs/faq.rst index 63e0bacd..62c3da76 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -396,6 +396,7 @@ The following environment variables are supported: * ``AHRIMAN_PACMAN_MIRROR`` - override pacman mirror server if set. * ``AHRIMAN_PORT`` - HTTP server port if any, default is empty. * ``AHRIMAN_REPOSITORY`` - repository name, default is ``aur-clone``. +* ``AHRIMAN_REPOSITORY_SERVER`` - optional override for the repository url. Useful if you would like to download packages from remote instead of local filesystem. * ``AHRIMAN_REPOSITORY_ROOT`` - repository root. Because of filesystem rights it is required to override default repository root. By default, it uses ``ahriman`` directory inside ahriman's home, which can be passed as mount volume. * ``AHRIMAN_UNIX_SOCKET`` - full path to unix socket which is used by web server, default is empty. Note that more likely you would like to put it inside ``AHRIMAN_REPOSITORY_ROOT`` directory (e.g. ``/var/lib/ahriman/ahriman/ahriman-web.sock``) or to ``/tmp``. * ``AHRIMAN_USER`` - ahriman user, usually must not be overwritten, default is ``ahriman``. @@ -855,6 +856,11 @@ In addition, the following settings are recommended for workers: [remote-call] wait_timeout = 0 +Dependency management +""""""""""""""""""""" + +By default worker nodes don't know anything about master nodes packages, thus it will try to build each dependency by its own. However, using ``AHRIMAN_REPOSITORY_SERVER`` docker variable (or ``--server`` flag for setup command), it is possible to specify address of the master node for devtools configuration. + Repository and packages signing """"""""""""""""""""""""""""""" diff --git a/src/ahriman/application/ahriman.py b/src/ahriman/application/ahriman.py index 74e87029..700ef539 100644 --- a/src/ahriman/application/ahriman.py +++ b/src/ahriman/application/ahriman.py @@ -893,6 +893,7 @@ def _set_service_setup_parser(root: SubParserAction) -> argparse.ArgumentParser: action=argparse.BooleanOptionalAction, default=True) parser.add_argument("--packager", help="packager name and email", required=True) parser.add_argument("--repository", help="repository name", required=True) + parser.add_argument("--server", help="server to be used for devtools. If none set, local files will be used") parser.add_argument("--sign-key", help="sign key id") parser.add_argument("--sign-target", help="sign options", action="append", type=SignSettings.from_option, choices=enum_values(SignSettings)) diff --git a/src/ahriman/application/handlers/setup.py b/src/ahriman/application/handlers/setup.py index 66e31cbc..3515d9cf 100644 --- a/src/ahriman/application/handlers/setup.py +++ b/src/ahriman/application/handlers/setup.py @@ -63,8 +63,9 @@ class Setup(Handler): Setup.configuration_create_makepkg(args.packager, args.makeflags_jobs, application.repository.paths) Setup.executable_create(application.repository.paths, args.build_command, architecture) + repository_server = f"file://{application.repository.paths.repository}" if args.server is None else args.server Setup.configuration_create_devtools(args.build_command, architecture, args.from_configuration, args.mirror, - args.multilib, args.repository, application.repository.paths) + args.multilib, args.repository, repository_server) Setup.configuration_create_sudo(application.repository.paths, args.build_command, architecture) application.repository.repo.init() @@ -134,7 +135,7 @@ class Setup(Handler): @staticmethod def configuration_create_devtools(prefix: str, architecture: str, source: Path, mirror: str | None, - multilib: bool, repository: str, paths: RepositoryPaths) -> None: + multilib: bool, repository: str, repository_server: str) -> None: """ create configuration for devtools based on ``source`` configuration @@ -148,7 +149,7 @@ class Setup(Handler): mirror(str | None): link to package server mirror multilib(bool): add or do not multilib repository to the configuration repository(str): repository name - paths(RepositoryPaths): repository paths instance + repository_server(str): url of the repository """ # allow_no_value=True is required because pacman uses boolean configuration in which just keys present # (e.g. NoProgressBar) which will lead to exception @@ -178,7 +179,7 @@ class Setup(Handler): # add repository itself configuration.set_option(repository, "SigLevel", "Never") # we don't care - configuration.set_option(repository, "Server", f"file://{paths.repository}") + configuration.set_option(repository, "Server", repository_server) target = source.parent / f"{prefix}-{architecture}.conf" with target.open("w") as devtools_configuration: diff --git a/tests/ahriman/application/handlers/test_handler_setup.py b/tests/ahriman/application/handlers/test_handler_setup.py index 53398825..cec5bc03 100644 --- a/tests/ahriman/application/handlers/test_handler_setup.py +++ b/tests/ahriman/application/handlers/test_handler_setup.py @@ -32,6 +32,7 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace: args.multilib = True args.packager = "John Doe " args.repository = "aur-clone" + args.server = None args.sign_key = "key" args.sign_target = [SignSettings.Packages] args.web_port = 8080 @@ -57,13 +58,34 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository: ahriman_configuration_mock.assert_called_once_with(args, "x86_64", args.repository, configuration) devtools_configuration_mock.assert_called_once_with( args.build_command, "x86_64", args.from_configuration, args.mirror, args.multilib, args.repository, - repository_paths) + f"file://{repository_paths.repository}") makepkg_configuration_mock.assert_called_once_with(args.packager, args.makeflags_jobs, repository_paths) sudo_configuration_mock.assert_called_once_with(repository_paths, args.build_command, "x86_64") executable_mock.assert_called_once_with(repository_paths, args.build_command, "x86_64") init_mock.assert_called_once_with() +def test_run_with_server(args: argparse.Namespace, configuration: Configuration, repository: Repository, + mocker: MockerFixture) -> None: + """ + must run command with server specified + """ + args = _default_args(args) + args.server = "server" + mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) + mocker.patch("ahriman.application.handlers.Setup.configuration_create_ahriman") + mocker.patch("ahriman.application.handlers.Setup.configuration_create_makepkg") + mocker.patch("ahriman.application.handlers.Setup.configuration_create_sudo") + mocker.patch("ahriman.application.handlers.Setup.executable_create") + mocker.patch("ahriman.core.alpm.repo.Repo.init") + devtools_configuration_mock = mocker.patch("ahriman.application.handlers.Setup.configuration_create_devtools") + + Setup.run(args, "x86_64", configuration, report=False) + devtools_configuration_mock.assert_called_once_with( + args.build_command, "x86_64", args.from_configuration, args.mirror, args.multilib, args.repository, + "server") + + def test_build_command(args: argparse.Namespace) -> None: """ must generate correct build command name @@ -120,8 +142,7 @@ def test_configuration_create_ahriman_no_multilib(args: argparse.Namespace, conf ]) # non-strict check called intentionally -def test_configuration_create_devtools(args: argparse.Namespace, repository_paths: RepositoryPaths, - mocker: MockerFixture) -> None: +def test_configuration_create_devtools(args: argparse.Namespace, mocker: MockerFixture) -> None: """ must create configuration for the devtools """ @@ -132,13 +153,12 @@ def test_configuration_create_devtools(args: argparse.Namespace, repository_path write_mock = mocker.patch("ahriman.core.configuration.Configuration.write") Setup.configuration_create_devtools(args.build_command, "x86_64", args.from_configuration, - None, args.multilib, args.repository, repository_paths) + None, args.multilib, args.repository, "server") add_section_mock.assert_has_calls([MockCall("multilib"), MockCall(args.repository)]) write_mock.assert_called_once_with(pytest.helpers.anyvar(int)) -def test_configuration_create_devtools_mirror(args: argparse.Namespace, repository_paths: RepositoryPaths, - mocker: MockerFixture) -> None: +def test_configuration_create_devtools_mirror(args: argparse.Namespace, mocker: MockerFixture) -> None: """ must create configuration for the devtools with mirror set explicitly """ @@ -157,14 +177,13 @@ def test_configuration_create_devtools_mirror(args: argparse.Namespace, reposito set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option") Setup.configuration_create_devtools(args.build_command, "x86_64", args.from_configuration, - args.mirror, False, args.repository, repository_paths) + args.mirror, False, args.repository, "server") get_mock.assert_has_calls([MockCall("core", "Include", fallback=None), MockCall("extra", "Include", fallback=None)]) remove_option_mock.assert_called_once_with("core", "Include") set_option_mock.assert_has_calls([MockCall("core", "Server", args.mirror)]) # non-strict check called intentionally -def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, repository_paths: RepositoryPaths, - mocker: MockerFixture) -> None: +def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, mocker: MockerFixture) -> None: """ must create configuration for the devtools without multilib """ @@ -174,7 +193,7 @@ def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, rep write_mock = mocker.patch("ahriman.core.configuration.Configuration.write") Setup.configuration_create_devtools(args.build_command, "x86_64", args.from_configuration, - None, False, args.repository, repository_paths) + None, False, args.repository, "server") write_mock.assert_called_once_with(pytest.helpers.anyvar(int))