From 0094268eedd852da261a64be427ce0ef9ca0af2a Mon Sep 17 00:00:00 2001 From: Evgenii Alekseev Date: Mon, 10 Aug 2026 16:25:38 +0300 Subject: [PATCH] use local devtools configs instead of global ones --- ahriman-core/package/bin/ahriman-archbuild | 16 +++++++++++++++- .../package/share/ahriman/settings/ahriman.ini | 4 +++- .../src/ahriman/application/handlers/setup.py | 15 +++++++++++---- .../src/ahriman/core/build_tools/task.py | 12 +++++++++++- .../src/ahriman/core/configuration/schema.py | 7 +++++++ .../src/ahriman/models/repository_paths.py | 13 ++++++++++++- tests/testresources/core/ahriman.ini | 1 + 7 files changed, 60 insertions(+), 8 deletions(-) diff --git a/ahriman-core/package/bin/ahriman-archbuild b/ahriman-core/package/bin/ahriman-archbuild index e1999e35..acacb055 100755 --- a/ahriman-core/package/bin/ahriman-archbuild +++ b/ahriman-core/package/bin/ahriman-archbuild @@ -7,16 +7,19 @@ usage() { echo "Usage: $cmd [options] -- [archbuild args]" echo " -r Repository name" echo " -a Repository architecture" + echo " -c Read devtools pacman configurations from this directory" exit 1 } repository= architecture= +pacman_config_dir= -while getopts ":r:a:" arg; do +while getopts ":r:a:c:" arg; do case "$arg" in r) repository="$OPTARG" ;; a) architecture="$OPTARG" ;; + c) pacman_config_dir="$OPTARG" ;; *) usage ;; esac done @@ -28,6 +31,17 @@ fi source "/usr/share/devtools/lib/archroot.sh" check_root "SOURCE_DATE_EPOCH,SRCDEST,SRCPKGDEST,PKGDEST,LOGDEST,NPROC,MAKEFLAGS,PACKAGER,GNUPGHOME" "${BASH_SOURCE[0]}" "$@" +# because devtools doesn't allow to read configuration from custom path +# here is a workaround, which uses unshare to bind-mount directory with configuration files +# for specific process +if [[ -n $pacman_config_dir && -z ${AHRIMAN_ARCHBUILD_MOUNTED:-} ]]; then + export AHRIMAN_ARCHBUILD_MOUNTED=1 + exec unshare --mount --propagation private bash -e -c ' + mount --bind "$0" /usr/share/devtools/pacman.conf.d + exec "$@" + ' "$(readlink -f "$pacman_config_dir")" "${BASH_SOURCE[0]}" "$@" +fi + exec bash -c ' source "$1" "${@:2}" ' "${repository}-${architecture}-build" "archbuild" "${@:$OPTIND}" diff --git a/ahriman-core/package/share/ahriman/settings/ahriman.ini b/ahriman-core/package/share/ahriman/settings/ahriman.ini index 67c92b3e..2b2187d6 100644 --- a/ahriman-core/package/share/ahriman/settings/ahriman.ini +++ b/ahriman-core/package/share/ahriman/settings/ahriman.ini @@ -1,6 +1,6 @@ [settings] ; Relative path to directory with configuration files overrides. Overrides will be applied in alphabetic order. -include = ahriman.ini.d $HOME/.config/ahriman.ini.d +include = ahriman.ini.d ${repository:root}/.config/ahriman/ahriman.ini.d ; Relative path to configuration used by logging package. logging = ahriman.ini.d/logging.ini ; Perform database migrations on the application start. Do not touch this option unless you know what you are doing. @@ -34,6 +34,8 @@ retry_backoff = 1.0 [build] ; List of additional flags passed to archbuild command. ;archbuild_flags = +; Path to local directory with devtools configuration files, which will be bind-mounted for devtools. +devtools_configs = ${repository:root}/.config/ahriman/pacman.conf.d ; Path to build command. devtools_wrapper = ahriman-archbuild ; List of packages to be ignored during automatic updates. diff --git a/ahriman-core/src/ahriman/application/handlers/setup.py b/ahriman-core/src/ahriman/application/handlers/setup.py index aedbefbf..96b3269c 100644 --- a/ahriman-core/src/ahriman/application/handlers/setup.py +++ b/ahriman-core/src/ahriman/application/handlers/setup.py @@ -71,7 +71,13 @@ class Setup(Handler): # basically we create configuration here as root, but it is ok, because those files are only used for reading repository_server = f"file://{application.repository.paths.repository}" if args.server is None else args.server Setup.configuration_create_devtools( - repository_id, args.from_configuration, args.mirror, args.multilib, repository_server) + repository_id, + args.from_configuration, + configuration.repository_paths.ensure_exists(configuration.getpath("build", "devtools_configs")), + args.mirror, + args.multilib, + repository_server, + ) # finish initialization with application.repository.paths.preserve_owner(): @@ -171,8 +177,8 @@ class Setup(Handler): configuration.write(ahriman_configuration) @staticmethod - def configuration_create_devtools(repository_id: RepositoryId, source: Path, mirror: str | None, - multilib: bool, repository_server: str) -> None: + def configuration_create_devtools(repository_id: RepositoryId, source: Path, target_directory: Path, + mirror: str | None, multilib: bool, repository_server: str) -> None: """ create configuration for devtools based on ``source`` configuration @@ -182,6 +188,7 @@ class Setup(Handler): Args: repository_id(RepositoryId): repository unique identifier source(Path): path to source configuration file + target_directory(Path): path to directory where configuration files will be written mirror(str | None): link to package server mirror multilib(bool): add or do not multilib repository to the configuration repository_server(str): url of the repository @@ -216,7 +223,7 @@ class Setup(Handler): configuration.set_option(repository_id.name, "SigLevel", "Never") # we don't care configuration.set_option(repository_id.name, "Server", repository_server) - target = source.parent / f"{repository_id.name}-{repository_id.architecture}.conf" + target = target_directory / f"{repository_id.name}-{repository_id.architecture}.conf" with target.open("w", encoding="utf8") as devtools_configuration: configuration.write(devtools_configuration) diff --git a/ahriman-core/src/ahriman/core/build_tools/task.py b/ahriman-core/src/ahriman/core/build_tools/task.py index 3178a556..a5b5ebc9 100644 --- a/ahriman-core/src/ahriman/core/build_tools/task.py +++ b/ahriman-core/src/ahriman/core/build_tools/task.py @@ -38,6 +38,7 @@ class Task(LazyLogging): Attributes: archbuild_flags(list[str]): command flags for archbuild command build_command(list[str]): build command + devtools_configs(Path): path to local directory with devtools configuration files include_debug_packages(bool): whether to include debug packages or not make_flags(str): MAKEFLAGS variable for makepkg command makechrootpkg_flags(list[str]): command flags for makechrootpkg command @@ -64,6 +65,7 @@ class Task(LazyLogging): self.archbuild_flags = configuration.getlist("build", "archbuild_flags", fallback=[]) self.build_command = configuration.getlist("build", "devtools_wrapper") + self.devtools_configs = configuration.getpath("build", "devtools_configs") self._legacy_build_command = configuration.getlist("build", "build_command", fallback=[]) self.include_debug_packages = configuration.getboolean("build", "include_debug_packages", fallback=True) # even though this option is declared as list, there is no need to read it as list, @@ -116,7 +118,15 @@ class Task(LazyLogging): """ command = self._legacy_build_command[:] if not command: - command = self.build_command + ["-r", self.repository_id.name, "-a", self.repository_id.architecture, "--"] + command = self.build_command + [ + "-r", + self.repository_id.name, + "-a", + self.repository_id.architecture, + "-c", + str(self.devtools_configs), + "--", + ] command.extend(["-r", str(self.paths.chroot)] + self.archbuild_flags) # archbuild flags command.extend(["--", "-D", str(self.paths.archive)] + self.makechrootpkg_flags) # makechrootpkg flags diff --git a/ahriman-core/src/ahriman/core/configuration/schema.py b/ahriman-core/src/ahriman/core/configuration/schema.py index ca7a5bc2..95196fce 100644 --- a/ahriman-core/src/ahriman/core/configuration/schema.py +++ b/ahriman-core/src/ahriman/core/configuration/schema.py @@ -200,6 +200,13 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = { "empty": False, }, }, + "devtools_configs": { + "type": "path", + "coerce": "absolute_path", + "required": True, + "path_exists": True, + "path_type": "dir", + }, "devtools_wrapper": { "type": "list", "coerce": "list", diff --git a/ahriman-core/src/ahriman/models/repository_paths.py b/ahriman-core/src/ahriman/models/repository_paths.py index f723a58c..9585f5ef 100644 --- a/ahriman-core/src/ahriman/models/repository_paths.py +++ b/ahriman-core/src/ahriman/models/repository_paths.py @@ -103,7 +103,7 @@ class RepositoryPaths(LazyLogging): Returns: Path: path to directory in which build process is run """ - uid, _ = owner(self.root) + uid, _ = self.root_owner return self.chroot / f"{self.repository_id.name}-{self.repository_id.architecture}" / getpwuid(uid).pw_name @property @@ -127,6 +127,16 @@ class RepositoryPaths(LazyLogging): # for the chroot directory devtools will create own tree, and we don't have to specify architecture here return self.root / "chroot" / self.repository_id.name + @property + def configs(self) -> Path: + """ + get directory for local configuration files + + Returns: + Path: full path to local configuration directory + """ + return self.root / ".config" / "ahriman" + @property def packages(self) -> Path: """ @@ -323,6 +333,7 @@ class RepositoryPaths(LazyLogging): self.archive, self.cache, self.chroot, + self.configs, self.packages, self.pacman, self.repository, diff --git a/tests/testresources/core/ahriman.ini b/tests/testresources/core/ahriman.ini index b65987d6..94dd2f15 100644 --- a/tests/testresources/core/ahriman.ini +++ b/tests/testresources/core/ahriman.ini @@ -23,6 +23,7 @@ allow_read_only = no [build] archbuild_flags = +devtools_configs = . devtools_wrapper = ahriman-archbuild ignore_packages = makechrootpkg_flags =