handle devtools config correctly

This commit is contained in:
Evgenii Alekseev 2021-03-29 03:20:45 +03:00
parent 9b9c045f79
commit c9cebab2df
4 changed files with 59 additions and 20 deletions

View File

@ -19,14 +19,14 @@ Wrapper for managing custom repository inspired by [repo-scripts](https://github
* Create `/var/lib/ahriman/.makepkg.conf` with `makepkg.conf` overrides if required (at least you might want to set `PACKAGER`): * Create `/var/lib/ahriman/.makepkg.conf` with `makepkg.conf` overrides if required (at least you might want to set `PACKAGER`):
```shell ```shell
echo 'PACKAGES="John Doe <john@doe.com>"' | sudo -u ahriman tee -a /var/lib/ahriman/.makepkg.conf echo 'PACKAGER="John Doe <john@doe.com>"' | sudo -u ahriman tee -a /var/lib/ahriman/.makepkg.conf
``` ```
* Configure build tools (it is required for correct dependency management system): * Configure build tools (it is required for correct dependency management system):
* create build command, e.g. `ln -s /usr/bin/archbuild /usr/local/bin/ahriman-x86_64-build` (you can choose any name for command, basically it should be `{name}-{arch}-build`); * create build command, e.g. `ln -s /usr/bin/archbuild /usr/local/bin/ahriman-x86_64-build` (you can choose any name for command, basically it should be `{name}-{arch}-build`);
* create configuration file, e.g. `cp /usr/share/devtools/pacman-{extra,ahriman}.conf` (same as previous `pacman-{name}.conf`); * create configuration file, e.g. `cp /usr/share/devtools/pacman-{extra,ahriman}.conf` (same as previous `pacman-{name}.conf`);
* change configuration file, add your own repository, add multilib repository etc. Hint: you can use `Include` option as well; * change configuration file, add your own repository, add multilib repository etc;
* set `build_command` option to point to your command; * set `build_command` option to point to your command;
* configure `/etc/sudoers.d/ahriman` to allow running command without a password. * configure `/etc/sudoers.d/ahriman` to allow running command without a password.
@ -66,3 +66,5 @@ Wrapper for managing custom repository inspired by [repo-scripts](https://github
```shell ```shell
sudo -u ahriman ahriman -a x86_64 add yay sudo -u ahriman ahriman -a x86_64 add yay
``` ```
Note that initial service configuration can be done by running `ahriman setup` with specific arguments.

View File

@ -40,6 +40,7 @@ def _parser() -> argparse.ArgumentParser:
parser.add_argument("--no-report", help="force disable reporting to web service", action="store_true") parser.add_argument("--no-report", help="force disable reporting to web service", action="store_true")
parser.add_argument("--unsafe", help="allow to run ahriman as non-ahriman user", action="store_true") parser.add_argument("--unsafe", help="allow to run ahriman as non-ahriman user", action="store_true")
parser.add_argument("-v", "--version", action="version", version=version.__version__) parser.add_argument("-v", "--version", action="version", version=version.__version__)
subparsers = parser.add_subparsers(title="command", help="command to run", dest="command", required=True) subparsers = parser.add_subparsers(title="command", help="command to run", dest="command", required=True)
add_parser = subparsers.add_parser("add", description="add package") add_parser = subparsers.add_parser("add", description="add package")
@ -113,8 +114,8 @@ def _parser() -> argparse.ArgumentParser:
if __name__ == "__main__": if __name__ == "__main__":
arg_parser = _parser() args_parser = _parser()
args = arg_parser.parse_args() args = args_parser.parse_args()
handler: handlers.Handler = args.handler handler: handlers.Handler = args.handler
status = handler.execute(args) status = handler.execute(args)

View File

@ -55,8 +55,8 @@ class Setup(Handler):
Setup.create_makepkg_configuration(args.packager, application.repository.paths) Setup.create_makepkg_configuration(args.packager, application.repository.paths)
Setup.create_executable(args.build_command, architecture) Setup.create_executable(args.build_command, architecture)
Setup.create_devtools_configuration(args.build_command, architecture, Path(args.from_config), args.no_multilib, Setup.create_devtools_configuration(args.build_command, architecture, Path(args.from_config), args.no_multilib,
application.repository.name, application.repository.paths) args.repository, application.repository.paths)
Setup.create_ahriman_configuration(args.build_command, architecture, config.include) Setup.create_ahriman_configuration(args.build_command, architecture, args.repository, config.include)
Setup.create_sudo_configuration(args.build_command, architecture) Setup.create_sudo_configuration(args.build_command, architecture)
@staticmethod @staticmethod
@ -70,18 +70,23 @@ class Setup(Handler):
return Setup.BIN_DIR_PATH / f"{prefix}-{architecture}-build" return Setup.BIN_DIR_PATH / f"{prefix}-{architecture}-build"
@staticmethod @staticmethod
def create_ahriman_configuration(prefix: str, architecture: str, include_path: Path) -> None: def create_ahriman_configuration(prefix: str, architecture: str, repository: str, include_path: Path) -> None:
""" """
create service specific configuration create service specific configuration
:param prefix: command prefix in {prefix}-{architecture}-build :param prefix: command prefix in {prefix}-{architecture}-build
:param architecture: repository architecture :param architecture: repository architecture
:param repository: repository name
:param include_path: path to directory with configuration includes :param include_path: path to directory with configuration includes
""" """
config = configparser.RawConfigParser() config = configparser.ConfigParser()
config.add_section("build") config.add_section("build")
config.set("build", "build_command", str(Setup.build_command(prefix, architecture))) config.set("build", "build_command", str(Setup.build_command(prefix, architecture)))
target = include_path / "build.ini" config.add_section("repository")
config.set("repository", "name", repository)
target = include_path / "build-overrides.ini"
with target.open("w") as ahriman_config: with target.open("w") as ahriman_config:
config.write(ahriman_config) config.write(ahriman_config)
@ -97,11 +102,16 @@ class Setup(Handler):
:param repository: repository name :param repository: repository name
:param paths: repository paths instance :param paths: repository paths instance
""" """
config = configparser.RawConfigParser() config = configparser.ConfigParser()
# preserve case
# stupid mypy thinks that it is impossible
config.optionxform = lambda key: key # type: ignore
# include base configuration # load default configuration first
config.add_section("options") # we cannot use Include here because it will be copied to new chroot, thus no includes there
config.set("options", "Include", str(source)) config.read(source)
# set our architecture now
config.set("options", "Architecture", architecture) config.set("options", "Architecture", architecture)
# add multilib # add multilib
@ -145,4 +155,6 @@ class Setup(Handler):
:param prefix: command prefix in {prefix}-{architecture}-build :param prefix: command prefix in {prefix}-{architecture}-build
:param architecture: repository architecture :param architecture: repository architecture
""" """
Setup.build_command(prefix, architecture).symlink_to(Setup.BIN_DIR_PATH) command = Setup.build_command(prefix, architecture)
command.unlink(missing_ok=True)
command.symlink_to(Setup.ARCHBUILD_COMMAND_PATH)

View File

@ -58,16 +58,22 @@ def test_create_ahriman_configuration(args: argparse.Namespace, configuration: C
write_mock = mocker.patch("configparser.RawConfigParser.write") write_mock = mocker.patch("configparser.RawConfigParser.write")
command = Setup.build_command(args.build_command, "x86_64") command = Setup.build_command(args.build_command, "x86_64")
Setup.create_ahriman_configuration(args.build_command, "x86_64", configuration.include) Setup.create_ahriman_configuration(args.build_command, "x86_64", args.repository, configuration.include)
add_section_mock.assert_called_once() add_section_mock.assert_has_calls([
set_mock.assert_called_with("build", "build_command", str(command)) mock.call("build"),
mock.call("repository"),
])
set_mock.assert_has_calls([
mock.call("build", "build_command", str(command)),
mock.call("repository", "name", args.repository),
])
write_mock.assert_called_once() write_mock.assert_called_once()
def test_create_devtools_configuration(args: argparse.Namespace, repository_paths: RepositoryPaths, def test_create_devtools_configuration(args: argparse.Namespace, repository_paths: RepositoryPaths,
mocker: MockerFixture) -> None: mocker: MockerFixture) -> None:
""" """
must create configuration for the service must create configuration for the devtools
""" """
args = _default_args(args) args = _default_args(args)
mocker.patch("pathlib.Path.open") mocker.patch("pathlib.Path.open")
@ -78,13 +84,29 @@ def test_create_devtools_configuration(args: argparse.Namespace, repository_path
Setup.create_devtools_configuration(args.build_command, "x86_64", Path(args.from_config), args.no_multilib, Setup.create_devtools_configuration(args.build_command, "x86_64", Path(args.from_config), args.no_multilib,
args.repository, repository_paths) args.repository, repository_paths)
add_section_mock.assert_has_calls([ add_section_mock.assert_has_calls([
mock.call("options"),
mock.call("multilib"), mock.call("multilib"),
mock.call(args.repository) mock.call(args.repository)
]) ])
write_mock.assert_called_once() write_mock.assert_called_once()
def test_create_devtools_configuration_no_multilib(args: argparse.Namespace, repository_paths: RepositoryPaths,
mocker: MockerFixture) -> None:
"""
must create configuration for the devtools without multilib
"""
args = _default_args(args)
mocker.patch("pathlib.Path.open")
mocker.patch("configparser.RawConfigParser.set")
add_section_mock = mocker.patch("configparser.RawConfigParser.add_section")
write_mock = mocker.patch("configparser.RawConfigParser.write")
Setup.create_devtools_configuration(args.build_command, "x86_64", Path(args.from_config), True,
args.repository, repository_paths)
add_section_mock.assert_called_once()
write_mock.assert_called_once()
def test_create_makepkg_configuration(args: argparse.Namespace, repository_paths: RepositoryPaths, def test_create_makepkg_configuration(args: argparse.Namespace, repository_paths: RepositoryPaths,
mocker: MockerFixture) -> None: mocker: MockerFixture) -> None:
""" """
@ -112,10 +134,12 @@ def test_create_sudo_configuration(args: argparse.Namespace, mocker: MockerFixtu
def test_create_executable(args: argparse.Namespace, mocker: MockerFixture) -> None: def test_create_executable(args: argparse.Namespace, mocker: MockerFixture) -> None:
""" """
must create sudo configuration must create executable
""" """
args = _default_args(args) args = _default_args(args)
symlink_text_mock = mocker.patch("pathlib.Path.symlink_to") symlink_text_mock = mocker.patch("pathlib.Path.symlink_to")
unlink_text_mock = mocker.patch("pathlib.Path.unlink")
Setup.create_executable(args.build_command, "x86_64") Setup.create_executable(args.build_command, "x86_64")
symlink_text_mock.assert_called_once() symlink_text_mock.assert_called_once()
unlink_text_mock.assert_called_once()