mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-07-15 06:55:48 +00:00
Setup command (#9)
* block issues without templates * add setup subcommand * handle devtools config correctly
This commit is contained in:
@ -31,12 +31,8 @@ def _parser() -> argparse.ArgumentParser:
|
||||
:return: command line parser for the application
|
||||
"""
|
||||
parser = argparse.ArgumentParser(prog="ahriman", description="ArcHlinux ReposItory MANager")
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"--architecture",
|
||||
help="target architectures (can be used multiple times)",
|
||||
action="append",
|
||||
required=True)
|
||||
parser.add_argument("-a", "--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("--force", help="force run, remove file lock", action="store_true")
|
||||
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("--unsafe", help="allow to run ahriman as non-ahriman user", action="store_true")
|
||||
parser.add_argument("-v", "--version", action="version", version=version.__version__)
|
||||
|
||||
subparsers = parser.add_subparsers(title="command", help="command to run", dest="command", required=True)
|
||||
|
||||
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-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-manual",
|
||||
help="do not clear directory with manually added packages",
|
||||
action="store_true")
|
||||
clean_parser.add_argument("--no-manual", 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.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.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.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.add_argument("package", help="sign only specified packages", nargs="*")
|
||||
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.add_argument("package", help="filter check by package base", nargs="*")
|
||||
update_parser.add_argument(
|
||||
"--dry-run", help="just perform check for updates, same as check command", action="store_true")
|
||||
update_parser.add_argument("--dry-run", help="just perform check for updates, same as check command",
|
||||
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-vcs", help="do not check VCS packages", action="store_true")
|
||||
@ -110,8 +114,8 @@ def _parser() -> argparse.ArgumentParser:
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
arg_parser = _parser()
|
||||
args = arg_parser.parse_args()
|
||||
args_parser = _parser()
|
||||
args = args_parser.parse_args()
|
||||
|
||||
handler: handlers.Handler = args.handler
|
||||
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.remove import Remove
|
||||
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.status import Status
|
||||
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)
|
Reference in New Issue
Block a user