mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
Setup command (#9)
* block issues without templates * add setup subcommand * handle devtools config correctly
This commit is contained in:
parent
80a1f37c85
commit
10e4f3b629
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
blank_issues_enabled: false
|
@ -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.
|
||||||
|
@ -31,12 +31,8 @@ def _parser() -> argparse.ArgumentParser:
|
|||||||
:return: command line parser for the application
|
:return: command line parser for the application
|
||||||
"""
|
"""
|
||||||
parser = argparse.ArgumentParser(prog="ahriman", description="ArcHlinux ReposItory MANager")
|
parser = argparse.ArgumentParser(prog="ahriman", description="ArcHlinux ReposItory MANager")
|
||||||
parser.add_argument(
|
parser.add_argument("-a", "--architecture", help="target architectures (can be used multiple times)",
|
||||||
"-a",
|
action="append", required=True)
|
||||||
"--architecture",
|
|
||||||
help="target architectures (can be used multiple times)",
|
|
||||||
action="append",
|
|
||||||
required=True)
|
|
||||||
parser.add_argument("-c", "--config", help="configuration path", default="/etc/ahriman.ini")
|
parser.add_argument("-c", "--config", help="configuration path", default="/etc/ahriman.ini")
|
||||||
parser.add_argument("--force", help="force run, remove file lock", action="store_true")
|
parser.add_argument("--force", help="force run, remove file lock", action="store_true")
|
||||||
parser.add_argument("--lock", help="lock file", default="/tmp/ahriman.lock")
|
parser.add_argument("--lock", help="lock file", default="/tmp/ahriman.lock")
|
||||||
@ -44,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")
|
||||||
@ -60,12 +57,10 @@ def _parser() -> argparse.ArgumentParser:
|
|||||||
clean_parser.add_argument("--no-build", help="do not clear directory with package sources", action="store_true")
|
clean_parser.add_argument("--no-build", help="do not clear directory with package sources", action="store_true")
|
||||||
clean_parser.add_argument("--no-cache", help="do not clear directory with package caches", action="store_true")
|
clean_parser.add_argument("--no-cache", help="do not clear directory with package caches", action="store_true")
|
||||||
clean_parser.add_argument("--no-chroot", help="do not clear build chroot", action="store_true")
|
clean_parser.add_argument("--no-chroot", help="do not clear build chroot", action="store_true")
|
||||||
clean_parser.add_argument(
|
clean_parser.add_argument("--no-manual", help="do not clear directory with manually added packages",
|
||||||
"--no-manual",
|
action="store_true")
|
||||||
help="do not clear directory with manually added packages",
|
|
||||||
action="store_true")
|
|
||||||
clean_parser.add_argument("--no-packages", help="do not clear directory with built packages", action="store_true")
|
clean_parser.add_argument("--no-packages", help="do not clear directory with built packages", action="store_true")
|
||||||
clean_parser.set_defaults(handler=handlers.Clean)
|
clean_parser.set_defaults(handler=handlers.Clean, unsafe=True)
|
||||||
|
|
||||||
config_parser = subparsers.add_parser("config", description="dump configuration for specified architecture")
|
config_parser = subparsers.add_parser("config", description="dump configuration for specified architecture")
|
||||||
config_parser.set_defaults(handler=handlers.Dump, lock=None, no_report=True, unsafe=True)
|
config_parser.set_defaults(handler=handlers.Dump, lock=None, no_report=True, unsafe=True)
|
||||||
@ -81,6 +76,15 @@ def _parser() -> argparse.ArgumentParser:
|
|||||||
report_parser.add_argument("target", help="target to generate report", nargs="*")
|
report_parser.add_argument("target", help="target to generate report", nargs="*")
|
||||||
report_parser.set_defaults(handler=handlers.Report)
|
report_parser.set_defaults(handler=handlers.Report)
|
||||||
|
|
||||||
|
setup_parser = subparsers.add_parser("setup", description="create initial service configuration, requires root")
|
||||||
|
setup_parser.add_argument("--build-command", help="build command prefix", default="ahriman")
|
||||||
|
setup_parser.add_argument("--from-config", help="path to default devtools pacman configuration",
|
||||||
|
default="/usr/share/devtools/pacman-extra.conf")
|
||||||
|
setup_parser.add_argument("--no-multilib", help="do not add multilib repository", action="store_true")
|
||||||
|
setup_parser.add_argument("--packager", help="packager name and email", required=True)
|
||||||
|
setup_parser.add_argument("--repository", help="repository name", default="aur-clone")
|
||||||
|
setup_parser.set_defaults(handler=handlers.Setup, lock=None, no_report=True, unsafe=True)
|
||||||
|
|
||||||
sign_parser = subparsers.add_parser("sign", description="(re-)sign packages and repository database")
|
sign_parser = subparsers.add_parser("sign", description="(re-)sign packages and repository database")
|
||||||
sign_parser.add_argument("package", help="sign only specified packages", nargs="*")
|
sign_parser.add_argument("package", help="sign only specified packages", nargs="*")
|
||||||
sign_parser.set_defaults(handler=handlers.Sign)
|
sign_parser.set_defaults(handler=handlers.Sign)
|
||||||
@ -96,8 +100,8 @@ def _parser() -> argparse.ArgumentParser:
|
|||||||
|
|
||||||
update_parser = subparsers.add_parser("update", description="run updates")
|
update_parser = subparsers.add_parser("update", description="run updates")
|
||||||
update_parser.add_argument("package", help="filter check by package base", nargs="*")
|
update_parser.add_argument("package", help="filter check by package base", nargs="*")
|
||||||
update_parser.add_argument(
|
update_parser.add_argument("--dry-run", help="just perform check for updates, same as check command",
|
||||||
"--dry-run", help="just perform check for updates, same as check command", action="store_true")
|
action="store_true")
|
||||||
update_parser.add_argument("--no-aur", help="do not check for AUR updates. Implies --no-vcs", action="store_true")
|
update_parser.add_argument("--no-aur", help="do not check for AUR updates. Implies --no-vcs", action="store_true")
|
||||||
update_parser.add_argument("--no-manual", help="do not include manual updates", action="store_true")
|
update_parser.add_argument("--no-manual", help="do not include manual updates", action="store_true")
|
||||||
update_parser.add_argument("--no-vcs", help="do not check VCS packages", action="store_true")
|
update_parser.add_argument("--no-vcs", help="do not check VCS packages", action="store_true")
|
||||||
@ -110,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)
|
||||||
|
@ -25,6 +25,7 @@ from ahriman.application.handlers.dump import Dump
|
|||||||
from ahriman.application.handlers.rebuild import Rebuild
|
from ahriman.application.handlers.rebuild import Rebuild
|
||||||
from ahriman.application.handlers.remove import Remove
|
from ahriman.application.handlers.remove import Remove
|
||||||
from ahriman.application.handlers.report import Report
|
from ahriman.application.handlers.report import Report
|
||||||
|
from ahriman.application.handlers.setup import Setup
|
||||||
from ahriman.application.handlers.sign import Sign
|
from ahriman.application.handlers.sign import Sign
|
||||||
from ahriman.application.handlers.status import Status
|
from ahriman.application.handlers.status import Status
|
||||||
from ahriman.application.handlers.sync import Sync
|
from ahriman.application.handlers.sync import Sync
|
||||||
|
160
src/ahriman/application/handlers/setup.py
Normal file
160
src/ahriman/application/handlers/setup.py
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
import argparse
|
||||||
|
import configparser
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from ahriman.application.application import Application
|
||||||
|
from ahriman.application.handlers.handler import Handler
|
||||||
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
|
class Setup(Handler):
|
||||||
|
"""
|
||||||
|
setup handler
|
||||||
|
:cvar ARCHBUILD_COMMAND_PATH: default devtools command
|
||||||
|
:cvar BIN_DIR_PATH: directory for custom binaries
|
||||||
|
:cvar MIRRORLIST_PATH: path to pacman default mirrorlist (used by multilib repository)
|
||||||
|
:cvar SUDOERS_PATH: path to sudoers.d include configuration
|
||||||
|
"""
|
||||||
|
|
||||||
|
ARCHBUILD_COMMAND_PATH = Path("/usr/bin/archbuild")
|
||||||
|
BIN_DIR_PATH = Path("/usr/local/bin")
|
||||||
|
MIRRORLIST_PATH = Path("/etc/pacman.d/mirrorlist")
|
||||||
|
SUDOERS_PATH = Path("/etc/sudoers.d/ahriman")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, config: Configuration) -> None:
|
||||||
|
"""
|
||||||
|
callback for command line
|
||||||
|
:param args: command line args
|
||||||
|
:param architecture: repository architecture
|
||||||
|
:param config: configuration instance
|
||||||
|
"""
|
||||||
|
application = Application(architecture, config)
|
||||||
|
Setup.create_makepkg_configuration(args.packager, application.repository.paths)
|
||||||
|
Setup.create_executable(args.build_command, architecture)
|
||||||
|
Setup.create_devtools_configuration(args.build_command, architecture, Path(args.from_config), args.no_multilib,
|
||||||
|
args.repository, application.repository.paths)
|
||||||
|
Setup.create_ahriman_configuration(args.build_command, architecture, args.repository, config.include)
|
||||||
|
Setup.create_sudo_configuration(args.build_command, architecture)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def build_command(prefix: str, architecture: str) -> Path:
|
||||||
|
"""
|
||||||
|
generate build command name
|
||||||
|
:param prefix: command prefix in {prefix}-{architecture}-build
|
||||||
|
:param architecture: repository architecture
|
||||||
|
:return: valid devtools command name
|
||||||
|
"""
|
||||||
|
return Setup.BIN_DIR_PATH / f"{prefix}-{architecture}-build"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_ahriman_configuration(prefix: str, architecture: str, repository: str, include_path: Path) -> None:
|
||||||
|
"""
|
||||||
|
create service specific configuration
|
||||||
|
:param prefix: command prefix in {prefix}-{architecture}-build
|
||||||
|
:param architecture: repository architecture
|
||||||
|
:param repository: repository name
|
||||||
|
:param include_path: path to directory with configuration includes
|
||||||
|
"""
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
|
||||||
|
config.add_section("build")
|
||||||
|
config.set("build", "build_command", str(Setup.build_command(prefix, architecture)))
|
||||||
|
|
||||||
|
config.add_section("repository")
|
||||||
|
config.set("repository", "name", repository)
|
||||||
|
|
||||||
|
target = include_path / "build-overrides.ini"
|
||||||
|
with target.open("w") as ahriman_config:
|
||||||
|
config.write(ahriman_config)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_devtools_configuration(prefix: str, architecture: str, source: Path,
|
||||||
|
no_multilib: bool, repository: str, paths: RepositoryPaths) -> None:
|
||||||
|
"""
|
||||||
|
create configuration for devtools based on `source` configuration
|
||||||
|
:param prefix: command prefix in {prefix}-{architecture}-build
|
||||||
|
:param architecture: repository architecture
|
||||||
|
:param source: path to source configuration file
|
||||||
|
:param no_multilib: do not add multilib repository
|
||||||
|
:param repository: repository name
|
||||||
|
:param paths: repository paths instance
|
||||||
|
"""
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
# preserve case
|
||||||
|
# stupid mypy thinks that it is impossible
|
||||||
|
config.optionxform = lambda key: key # type: ignore
|
||||||
|
|
||||||
|
# load default configuration first
|
||||||
|
# we cannot use Include here because it will be copied to new chroot, thus no includes there
|
||||||
|
config.read(source)
|
||||||
|
|
||||||
|
# set our architecture now
|
||||||
|
config.set("options", "Architecture", architecture)
|
||||||
|
|
||||||
|
# add multilib
|
||||||
|
if not no_multilib:
|
||||||
|
config.add_section("multilib")
|
||||||
|
config.set("multilib", "Include", str(Setup.MIRRORLIST_PATH))
|
||||||
|
|
||||||
|
# add repository itself
|
||||||
|
config.add_section(repository)
|
||||||
|
config.set(repository, "SigLevel", "Optional TrustAll") # we don't care
|
||||||
|
config.set(repository, "Server", f"file://{paths.repository}")
|
||||||
|
|
||||||
|
target = source.parent / f"pacman-{prefix}.conf"
|
||||||
|
with target.open("w") as devtools_config:
|
||||||
|
config.write(devtools_config)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_makepkg_configuration(packager: str, paths: RepositoryPaths) -> None:
|
||||||
|
"""
|
||||||
|
create configuration for makepkg
|
||||||
|
:param packager: packager identifier (e.g. name, email)
|
||||||
|
:param paths: repository paths instance
|
||||||
|
"""
|
||||||
|
(paths.root / ".makepkg.conf").write_text(f"PACKAGER='{packager}'\n")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_sudo_configuration(prefix: str, architecture: str) -> None:
|
||||||
|
"""
|
||||||
|
create configuration to run build command with sudo without password
|
||||||
|
:param prefix: command prefix in {prefix}-{architecture}-build
|
||||||
|
:param architecture: repository architecture
|
||||||
|
"""
|
||||||
|
command = Setup.build_command(prefix, architecture)
|
||||||
|
Setup.SUDOERS_PATH.write_text(f"ahriman ALL=(ALL) NOPASSWD: {command} *\n")
|
||||||
|
Setup.SUDOERS_PATH.chmod(0o400) # security!
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def create_executable(prefix: str, architecture: str) -> None:
|
||||||
|
"""
|
||||||
|
create executable for the service
|
||||||
|
:param prefix: command prefix in {prefix}-{architecture}-build
|
||||||
|
:param architecture: repository architecture
|
||||||
|
"""
|
||||||
|
command = Setup.build_command(prefix, architecture)
|
||||||
|
command.unlink(missing_ok=True)
|
||||||
|
command.symlink_to(Setup.ARCHBUILD_COMMAND_PATH)
|
@ -6,12 +6,17 @@ from ahriman.application.handlers import Add
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
|
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||||
|
args.package = []
|
||||||
|
args.without_dependencies = False
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run command
|
must run command
|
||||||
"""
|
"""
|
||||||
args.package = []
|
args = _default_args(args)
|
||||||
args.without_dependencies = False
|
|
||||||
mocker.patch("pathlib.Path.mkdir")
|
mocker.patch("pathlib.Path.mkdir")
|
||||||
application_mock = mocker.patch("ahriman.application.application.Application.add")
|
application_mock = mocker.patch("ahriman.application.application.Application.add")
|
||||||
|
|
||||||
|
@ -6,15 +6,20 @@ from ahriman.application.handlers import Clean
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||||
"""
|
|
||||||
must run command
|
|
||||||
"""
|
|
||||||
args.no_build = False
|
args.no_build = False
|
||||||
args.no_cache = False
|
args.no_cache = False
|
||||||
args.no_chroot = False
|
args.no_chroot = False
|
||||||
args.no_manual = False
|
args.no_manual = False
|
||||||
args.no_packages = False
|
args.no_packages = False
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must run command
|
||||||
|
"""
|
||||||
|
args = _default_args(args)
|
||||||
mocker.patch("pathlib.Path.mkdir")
|
mocker.patch("pathlib.Path.mkdir")
|
||||||
application_mock = mocker.patch("ahriman.application.application.Application.clean")
|
application_mock = mocker.patch("ahriman.application.application.Application.clean")
|
||||||
|
|
||||||
|
@ -6,11 +6,16 @@ from ahriman.application.handlers import Remove
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
|
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||||
|
args.package = []
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run command
|
must run command
|
||||||
"""
|
"""
|
||||||
args.package = []
|
args = _default_args(args)
|
||||||
mocker.patch("pathlib.Path.mkdir")
|
mocker.patch("pathlib.Path.mkdir")
|
||||||
application_mock = mocker.patch("ahriman.application.application.Application.remove")
|
application_mock = mocker.patch("ahriman.application.application.Application.remove")
|
||||||
|
|
||||||
|
@ -6,11 +6,16 @@ from ahriman.application.handlers import Report
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
|
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||||
|
args.target = []
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run command
|
must run command
|
||||||
"""
|
"""
|
||||||
args.target = []
|
args = _default_args(args)
|
||||||
mocker.patch("pathlib.Path.mkdir")
|
mocker.patch("pathlib.Path.mkdir")
|
||||||
application_mock = mocker.patch("ahriman.application.application.Application.report")
|
application_mock = mocker.patch("ahriman.application.application.Application.report")
|
||||||
|
|
||||||
|
145
tests/ahriman/application/handlers/test_handler_setup.py
Normal file
145
tests/ahriman/application/handlers/test_handler_setup.py
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from pytest_mock import MockerFixture
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
from ahriman.application.handlers import Setup
|
||||||
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
|
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||||
|
args.build_command = "ahriman"
|
||||||
|
args.from_config = "/usr/share/devtools/pacman-extra.conf"
|
||||||
|
args.no_multilib = False
|
||||||
|
args.packager = "John Doe <john@doe.com>"
|
||||||
|
args.repository = "aur-clone"
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must run command
|
||||||
|
"""
|
||||||
|
args = _default_args(args)
|
||||||
|
mocker.patch("pathlib.Path.mkdir")
|
||||||
|
ahriman_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.create_ahriman_configuration")
|
||||||
|
devtools_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.create_devtools_configuration")
|
||||||
|
makepkg_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.create_makepkg_configuration")
|
||||||
|
sudo_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.create_sudo_configuration")
|
||||||
|
executable_mock = mocker.patch("ahriman.application.handlers.setup.Setup.create_executable")
|
||||||
|
|
||||||
|
Setup.run(args, "x86_64", configuration)
|
||||||
|
ahriman_configuration_mock.assert_called_once()
|
||||||
|
devtools_configuration_mock.assert_called_once()
|
||||||
|
makepkg_configuration_mock.assert_called_once()
|
||||||
|
sudo_configuration_mock.assert_called_once()
|
||||||
|
executable_mock.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
def test_build_command(args: argparse.Namespace) -> None:
|
||||||
|
"""
|
||||||
|
must generate correct build command name
|
||||||
|
"""
|
||||||
|
args = _default_args(args)
|
||||||
|
assert Setup.build_command(args.build_command, "x86_64").name == f"{args.build_command}-x86_64-build"
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_ahriman_configuration(args: argparse.Namespace, configuration: Configuration,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must create configuration for the service
|
||||||
|
"""
|
||||||
|
args = _default_args(args)
|
||||||
|
mocker.patch("pathlib.Path.open")
|
||||||
|
add_section_mock = mocker.patch("configparser.RawConfigParser.add_section")
|
||||||
|
set_mock = mocker.patch("configparser.RawConfigParser.set")
|
||||||
|
write_mock = mocker.patch("configparser.RawConfigParser.write")
|
||||||
|
|
||||||
|
command = Setup.build_command(args.build_command, "x86_64")
|
||||||
|
Setup.create_ahriman_configuration(args.build_command, "x86_64", args.repository, configuration.include)
|
||||||
|
add_section_mock.assert_has_calls([
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_devtools_configuration(args: argparse.Namespace, repository_paths: RepositoryPaths,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must create configuration for the devtools
|
||||||
|
"""
|
||||||
|
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), args.no_multilib,
|
||||||
|
args.repository, repository_paths)
|
||||||
|
add_section_mock.assert_has_calls([
|
||||||
|
mock.call("multilib"),
|
||||||
|
mock.call(args.repository)
|
||||||
|
])
|
||||||
|
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,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must create makepkg configuration
|
||||||
|
"""
|
||||||
|
args = _default_args(args)
|
||||||
|
write_text_mock = mocker.patch("pathlib.Path.write_text")
|
||||||
|
|
||||||
|
Setup.create_makepkg_configuration(args.packager, repository_paths)
|
||||||
|
write_text_mock.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_sudo_configuration(args: argparse.Namespace, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must create sudo configuration
|
||||||
|
"""
|
||||||
|
args = _default_args(args)
|
||||||
|
chmod_text_mock = mocker.patch("pathlib.Path.chmod")
|
||||||
|
write_text_mock = mocker.patch("pathlib.Path.write_text")
|
||||||
|
|
||||||
|
Setup.create_sudo_configuration(args.build_command, "x86_64")
|
||||||
|
chmod_text_mock.assert_called_with(0o400)
|
||||||
|
write_text_mock.assert_called_once()
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_executable(args: argparse.Namespace, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must create executable
|
||||||
|
"""
|
||||||
|
args = _default_args(args)
|
||||||
|
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")
|
||||||
|
symlink_text_mock.assert_called_once()
|
||||||
|
unlink_text_mock.assert_called_once()
|
@ -6,11 +6,16 @@ from ahriman.application.handlers import Sign
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
|
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||||
|
args.package = []
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run command
|
must run command
|
||||||
"""
|
"""
|
||||||
args.package = []
|
args = _default_args(args)
|
||||||
mocker.patch("pathlib.Path.mkdir")
|
mocker.patch("pathlib.Path.mkdir")
|
||||||
application_mock = mocker.patch("ahriman.application.application.Application.sign")
|
application_mock = mocker.patch("ahriman.application.application.Application.sign")
|
||||||
|
|
||||||
|
@ -6,13 +6,17 @@ from ahriman.application.handlers import Status
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
|
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||||
|
args.ahriman = True
|
||||||
|
args.package = []
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run command
|
must run command
|
||||||
"""
|
"""
|
||||||
args.ahriman = True
|
args = _default_args(args)
|
||||||
args.package = []
|
|
||||||
args.without_dependencies = False
|
|
||||||
mocker.patch("pathlib.Path.mkdir")
|
mocker.patch("pathlib.Path.mkdir")
|
||||||
application_mock = mocker.patch("ahriman.core.status.client.Client.get_self")
|
application_mock = mocker.patch("ahriman.core.status.client.Client.get_self")
|
||||||
packages_mock = mocker.patch("ahriman.core.status.client.Client.get")
|
packages_mock = mocker.patch("ahriman.core.status.client.Client.get")
|
||||||
|
@ -6,11 +6,16 @@ from ahriman.application.handlers import Sync
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
|
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||||
|
args.target = []
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run command
|
must run command
|
||||||
"""
|
"""
|
||||||
args.target = []
|
args = _default_args(args)
|
||||||
mocker.patch("pathlib.Path.mkdir")
|
mocker.patch("pathlib.Path.mkdir")
|
||||||
application_mock = mocker.patch("ahriman.application.application.Application.sync")
|
application_mock = mocker.patch("ahriman.application.application.Application.sync")
|
||||||
|
|
||||||
|
@ -6,15 +6,20 @@ from ahriman.application.handlers import Update
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
|
||||||
"""
|
|
||||||
must run command
|
|
||||||
"""
|
|
||||||
args.package = []
|
args.package = []
|
||||||
args.dry_run = False
|
args.dry_run = False
|
||||||
args.no_aur = False
|
args.no_aur = False
|
||||||
args.no_manual = False
|
args.no_manual = False
|
||||||
args.no_vcs = False
|
args.no_vcs = False
|
||||||
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must run command
|
||||||
|
"""
|
||||||
|
args = _default_args(args)
|
||||||
mocker.patch("pathlib.Path.mkdir")
|
mocker.patch("pathlib.Path.mkdir")
|
||||||
application_mock = mocker.patch("ahriman.application.application.Application.update")
|
application_mock = mocker.patch("ahriman.application.application.Application.update")
|
||||||
updates_mock = mocker.patch("ahriman.application.application.Application.get_updates")
|
updates_mock = mocker.patch("ahriman.application.application.Application.get_updates")
|
||||||
@ -28,11 +33,8 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, moc
|
|||||||
"""
|
"""
|
||||||
must run simplified command
|
must run simplified command
|
||||||
"""
|
"""
|
||||||
args.package = []
|
args = _default_args(args)
|
||||||
args.dry_run = True
|
args.dry_run = True
|
||||||
args.no_aur = False
|
|
||||||
args.no_manual = False
|
|
||||||
args.no_vcs = False
|
|
||||||
mocker.patch("pathlib.Path.mkdir")
|
mocker.patch("pathlib.Path.mkdir")
|
||||||
updates_mock = mocker.patch("ahriman.application.application.Application.get_updates")
|
updates_mock = mocker.patch("ahriman.application.application.Application.get_updates")
|
||||||
|
|
||||||
|
@ -26,6 +26,14 @@ def test_subparsers_check(parser: argparse.ArgumentParser) -> None:
|
|||||||
assert args.dry_run
|
assert args.dry_run
|
||||||
|
|
||||||
|
|
||||||
|
def test_subparsers_clean(parser: argparse.ArgumentParser) -> None:
|
||||||
|
"""
|
||||||
|
clean command must imply unsafe
|
||||||
|
"""
|
||||||
|
args = parser.parse_args(["-a", "x86_64", "clean"])
|
||||||
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_config(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_config(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
config command must imply lock, no_report and unsafe
|
config command must imply lock, no_report and unsafe
|
||||||
@ -36,6 +44,16 @@ def test_subparsers_config(parser: argparse.ArgumentParser) -> None:
|
|||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
|
def test_subparsers_setup(parser: argparse.ArgumentParser) -> None:
|
||||||
|
"""
|
||||||
|
setup command must imply lock, no_report and unsafe
|
||||||
|
"""
|
||||||
|
args = parser.parse_args(["-a", "x86_64", "setup", "--packager", "John Doe <john@doe.com>"])
|
||||||
|
assert args.lock is None
|
||||||
|
assert args.no_report
|
||||||
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_status(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_status(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
status command must imply lock, no_report and unsafe
|
status command must imply lock, no_report and unsafe
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
[settings]
|
[settings]
|
||||||
|
include = .
|
||||||
logging = logging.ini
|
logging = logging.ini
|
||||||
|
|
||||||
[alpm]
|
[alpm]
|
||||||
|
Loading…
Reference in New Issue
Block a user