mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 07:17:17 +00:00
report support, readme
This commit is contained in:
parent
c45662517b
commit
088698d8e1
67
CONFIGURING.md
Normal file
67
CONFIGURING.md
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# ahriman configuration
|
||||||
|
|
||||||
|
## `settings` group
|
||||||
|
|
||||||
|
Base configuration settings:
|
||||||
|
|
||||||
|
* `include` - path to directory with configuration files overrides, string, required.
|
||||||
|
* `logging` - path to logging configuration, string, required. Check `logging.ini` for reference.
|
||||||
|
|
||||||
|
## `aur` group
|
||||||
|
|
||||||
|
AUR related configuration:
|
||||||
|
|
||||||
|
* `url` - base url for AUR, string, required.
|
||||||
|
|
||||||
|
## `build` group
|
||||||
|
|
||||||
|
Build related configuration:
|
||||||
|
|
||||||
|
* `archbuild_flags` - additional flags passed to `archbuild` command, space separated list of strings, optional.
|
||||||
|
* `build_command` - default build command, string, required.
|
||||||
|
* `makepkg_flags` - additional flags passed to `makepkg` command, space separated list of strings, optional.
|
||||||
|
* `makechrootpkg_flags` - additional flags passed to `makechrootpkg` command, space separated list of strings, optional.
|
||||||
|
|
||||||
|
## `repository` group
|
||||||
|
|
||||||
|
Base repository settings:
|
||||||
|
|
||||||
|
* `name` - repository name, string, required.
|
||||||
|
* `root` - root path for application, string, required.
|
||||||
|
|
||||||
|
## `sign` group
|
||||||
|
|
||||||
|
Settings for signing packages or repository:
|
||||||
|
|
||||||
|
* `enabled` - configuration flag to enable signing, string, required. Allowed values are `disabled`, `package` (sign each package separately), `repository` (sign repository database file).
|
||||||
|
* `key` - PGP key, string, optional.
|
||||||
|
|
||||||
|
## `report` group
|
||||||
|
|
||||||
|
Report generation settings:
|
||||||
|
|
||||||
|
* `target` - list of reports to be generated, space separated list of strings, optional. Allowed values are `html`.
|
||||||
|
|
||||||
|
### `html` group
|
||||||
|
|
||||||
|
* `path` - path to html report file, string, required.
|
||||||
|
* `css_path` - path to CSS to include in HTML, string, optional.
|
||||||
|
* `link_path` - prefix for HTML links, string, required.
|
||||||
|
|
||||||
|
## `upload` group
|
||||||
|
|
||||||
|
Remote synchronization settings:
|
||||||
|
|
||||||
|
* `target` - list of synchronizations to be used, space separated list of strings, optional. Allowed values are `rsync`, `s3`.
|
||||||
|
|
||||||
|
### `s3`
|
||||||
|
|
||||||
|
Requires `aws-cli` package to be installed. Do not forget to configure it for user `ahriman`.
|
||||||
|
|
||||||
|
* `bucket` - bucket name (e.g. `s3://bucket/path`), string, required.
|
||||||
|
|
||||||
|
### `rsync`
|
||||||
|
|
||||||
|
Requires `rsync` package to be installed. Do not forget to configure ssh for user `ahriman`.
|
||||||
|
|
||||||
|
* `remote` - remote server to rsync (e.g. `1.2.3.4:5678:path/to/sync`), string, required.
|
20
README.md
20
README.md
@ -0,0 +1,20 @@
|
|||||||
|
# ArcHlinux ReposItory MANager
|
||||||
|
|
||||||
|
Wrapper for managing custom repository inspired by [repo-scripts](https://github.com/arcan1s/repo-scripts).
|
||||||
|
|
||||||
|
## Installation and run
|
||||||
|
|
||||||
|
* Install package as usual.
|
||||||
|
* Change settings if required, see `CONFIGURING.md` for more details.
|
||||||
|
* Create `/var/lib/ahriman/.makepkg.conf` with `makepkg.conf` overrides if required (at least you might want to set `PACKAGER`).
|
||||||
|
* Configure build tools (it might be required if your package will use any custom repositories):
|
||||||
|
* create build command if required, e.g. `ln -s /usr/bin/archbuild /usr/local/bin/custom-x86_64-build` (you can choose any name for command);
|
||||||
|
* create configuration file, e.g. `cp /usr/share/devtools/pacman-{extra,custom}.conf`;
|
||||||
|
* change configuration file: add your own repository, add multilib repository;
|
||||||
|
* set `build.build_command` to point to your command.
|
||||||
|
* Start and enable `ahriman.timer` via `systemctl`.
|
||||||
|
* Add packages by using `ahriman add {package}` command.
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
* It does not manage dependencies, so you have to add them before main package.
|
@ -4,7 +4,7 @@ set -e
|
|||||||
|
|
||||||
VERSION="$1"
|
VERSION="$1"
|
||||||
ARCHIVE="ahriman"
|
ARCHIVE="ahriman"
|
||||||
FILES="COPYING README.md package src setup.py"
|
FILES="COPYING CONFIGURING.md README.md package src setup.py"
|
||||||
IGNORELIST="build .idea package/archlinux package/*src.tar.xz"
|
IGNORELIST="build .idea package/archlinux package/*src.tar.xz"
|
||||||
|
|
||||||
# set version
|
# set version
|
||||||
|
@ -6,10 +6,10 @@ logging = /etc/ahriman.ini.d/logging.ini
|
|||||||
url = https://aur.archlinux.org
|
url = https://aur.archlinux.org
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
archbuild_flags = -c
|
archbuild_flags =
|
||||||
extra_build = extra-x86_64-build
|
build_command = extra-x86_64-build
|
||||||
|
makechrootpkg_flags =
|
||||||
makepkg_flags = --skippgpcheck
|
makepkg_flags = --skippgpcheck
|
||||||
multilib_build = multilib-build
|
|
||||||
|
|
||||||
[repository]
|
[repository]
|
||||||
name = aur-clone
|
name = aur-clone
|
||||||
@ -19,8 +19,16 @@ root = /var/lib/ahriman
|
|||||||
enabled = disabled
|
enabled = disabled
|
||||||
key =
|
key =
|
||||||
|
|
||||||
|
[report]
|
||||||
|
target =
|
||||||
|
|
||||||
|
[html]
|
||||||
|
path =
|
||||||
|
css_path =
|
||||||
|
link_path =
|
||||||
|
|
||||||
[upload]
|
[upload]
|
||||||
enabled = disabled
|
target =
|
||||||
|
|
||||||
[s3]
|
[s3]
|
||||||
bucket =
|
bucket =
|
||||||
|
@ -51,12 +51,17 @@ def remove(args: argparse.Namespace) -> None:
|
|||||||
_get_app(args).remove(args.package)
|
_get_app(args).remove(args.package)
|
||||||
|
|
||||||
|
|
||||||
|
def report(args: argparse.Namespace) -> None:
|
||||||
|
_get_app(args).report(args.target)
|
||||||
|
|
||||||
|
|
||||||
def sync(args: argparse.Namespace) -> None:
|
def sync(args: argparse.Namespace) -> None:
|
||||||
_get_app(args).sync()
|
_get_app(args).sync(args.target)
|
||||||
|
|
||||||
|
|
||||||
def update(args: argparse.Namespace) -> None:
|
def update(args: argparse.Namespace) -> None:
|
||||||
_get_app(args).update(args.sync)
|
check_only = (args.command == 'check')
|
||||||
|
_get_app(args).update(check_only)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
@ -65,21 +70,28 @@ if __name__ == '__main__':
|
|||||||
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')
|
||||||
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='commands')
|
subparsers = parser.add_subparsers(title='command')
|
||||||
|
|
||||||
add_parser = subparsers.add_parser('add', description='add package')
|
add_parser = subparsers.add_parser('add', description='add package')
|
||||||
add_parser.add_argument('package', help='package name', nargs='+')
|
add_parser.add_argument('package', help='package name', nargs='+')
|
||||||
add_parser.set_defaults(fn=add)
|
add_parser.set_defaults(fn=add)
|
||||||
|
|
||||||
|
check_parser = subparsers.add_parser('check', description='check for updates')
|
||||||
|
check_parser.set_defaults(fn=update)
|
||||||
|
|
||||||
remove_parser = subparsers.add_parser('remove', description='remove package')
|
remove_parser = subparsers.add_parser('remove', description='remove package')
|
||||||
remove_parser.add_argument('package', help='package name', nargs='+')
|
remove_parser.add_argument('package', help='package name', nargs='+')
|
||||||
remove_parser.set_defaults(fn=remove)
|
remove_parser.set_defaults(fn=remove)
|
||||||
|
|
||||||
|
report_parser = subparsers.add_parser('report', description='generate report')
|
||||||
|
report_parser.add_argument('target', help='target to generate report', nargs='*')
|
||||||
|
report_parser.set_defaults(fn=report)
|
||||||
|
|
||||||
sync_parser = subparsers.add_parser('sync', description='sync packages to remote server')
|
sync_parser = subparsers.add_parser('sync', description='sync packages to remote server')
|
||||||
|
sync_parser.add_argument('target', help='target to sync', nargs='*')
|
||||||
sync_parser.set_defaults(fn=sync)
|
sync_parser.set_defaults(fn=sync)
|
||||||
|
|
||||||
update_parser = subparsers.add_parser('update', description='run updates')
|
update_parser = subparsers.add_parser('update', description='run updates')
|
||||||
update_parser.add_argument('-s', '--sync', help='sync packages to remote server', action='store_true')
|
|
||||||
update_parser.set_defaults(fn=update)
|
update_parser.set_defaults(fn=update)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
@ -17,9 +17,10 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from typing import List
|
from typing import List, Optional
|
||||||
|
|
||||||
from ahriman.core.build_tools.task import Task
|
from ahriman.core.build_tools.task import Task
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
@ -30,6 +31,7 @@ from ahriman.models.package import Package
|
|||||||
class Application:
|
class Application:
|
||||||
|
|
||||||
def __init__(self, config: Configuration) -> None:
|
def __init__(self, config: Configuration) -> None:
|
||||||
|
self.logger = logging.getLogger('root')
|
||||||
self.config = config
|
self.config = config
|
||||||
self.repository = Repository(config)
|
self.repository = Repository(config)
|
||||||
|
|
||||||
@ -42,12 +44,25 @@ class Application:
|
|||||||
def remove(self, names: List[str]) -> None:
|
def remove(self, names: List[str]) -> None:
|
||||||
self.repository.process_remove(names)
|
self.repository.process_remove(names)
|
||||||
|
|
||||||
def sync(self) -> None:
|
def report(self, target: Optional[List[str]] = None) -> None:
|
||||||
self.repository.process_sync()
|
targets = target or None
|
||||||
|
self.repository.process_report(targets)
|
||||||
|
|
||||||
def update(self, sync: bool) -> None:
|
def sync(self, target: Optional[List[str]] = None) -> None:
|
||||||
|
targets = target or None
|
||||||
|
self.repository.process_sync(targets)
|
||||||
|
|
||||||
|
def update(self, dry_run: bool) -> None:
|
||||||
updates = self.repository.updates()
|
updates = self.repository.updates()
|
||||||
|
log_fn = print if dry_run else self.logger.info
|
||||||
|
for package in updates:
|
||||||
|
log_fn(f'{package.name} = {package.version}') # type: ignore
|
||||||
|
|
||||||
|
if dry_run:
|
||||||
|
return
|
||||||
|
|
||||||
packages = self.repository.process_build(updates)
|
packages = self.repository.process_build(updates)
|
||||||
self.repository.process_update(packages)
|
self.repository.process_update(packages)
|
||||||
if sync:
|
|
||||||
|
self.report()
|
||||||
self.sync()
|
self.sync()
|
@ -25,7 +25,7 @@ from typing import List, Optional
|
|||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.exceptions import BuildFailed
|
from ahriman.core.exceptions import BuildFailed
|
||||||
from ahriman.core.util import check_output
|
from ahriman.core.util import check_output, options_list
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
@ -38,22 +38,20 @@ class Task:
|
|||||||
self.package = package
|
self.package = package
|
||||||
self.paths = paths
|
self.paths = paths
|
||||||
|
|
||||||
self.archbuild_flags = config.get('build_tools', 'archbuild_flags').split()
|
self.archbuild_flags = options_list(config, 'build', 'archbuild_flags')
|
||||||
self.extra_build = config.get('build_tools', 'extra_build')
|
self.build_command = config.get('build', 'build_command')
|
||||||
self.makepkg_flags = config.get('build_tools', 'makepkg_flags').split()
|
self.makepkg_flags = options_list(config, 'build', 'makepkg_flags')
|
||||||
self.multilib_build = config.get('build_tools', 'multilib_build')
|
self.makechrootpkg_flags = options_list(config, 'build', 'makechrootpkg_flags')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def git_path(self) -> str:
|
def git_path(self) -> str:
|
||||||
return os.path.join(self.paths.sources, self.package.name)
|
return os.path.join(self.paths.sources, self.package.name)
|
||||||
|
|
||||||
def build(self) -> List[str]:
|
def build(self) -> List[str]:
|
||||||
build_tool = self.multilib_build if self.package.is_multilib else self.extra_build
|
cmd = [self.build_command, '-r', self.paths.chroot]
|
||||||
|
|
||||||
cmd = [build_tool, '-r', self.paths.chroot]
|
|
||||||
cmd.extend(self.archbuild_flags)
|
cmd.extend(self.archbuild_flags)
|
||||||
if self.makepkg_flags:
|
cmd.extend(['--'] + self.makechrootpkg_flags)
|
||||||
cmd.extend(['--', '--'] + self.makepkg_flags)
|
cmd.extend(['--'] + self.makepkg_flags)
|
||||||
self.logger.info(f'using {cmd} for {self.package.name}')
|
self.logger.info(f'using {cmd} for {self.package.name}')
|
||||||
|
|
||||||
check_output(
|
check_output(
|
||||||
|
@ -40,6 +40,11 @@ class MissingConfiguration(Exception):
|
|||||||
Exception.__init__(self, f'No section `{name}` found')
|
Exception.__init__(self, f'No section `{name}` found')
|
||||||
|
|
||||||
|
|
||||||
|
class ReportFailed(Exception):
|
||||||
|
def __init__(self, cause: Exception) -> None:
|
||||||
|
Exception.__init__(self, f'Report failed with reason {cause}')
|
||||||
|
|
||||||
|
|
||||||
class SyncFailed(Exception):
|
class SyncFailed(Exception):
|
||||||
def __init__(self, cause: Exception) -> None:
|
def __init__(self, cause: Exception) -> None:
|
||||||
Exception.__init__(self, f'Sync failed with reason {cause}')
|
Exception.__init__(self, f'Sync failed with reason {cause}')
|
26
src/ahriman/core/report/dummy.py
Normal file
26
src/ahriman/core/report/dummy.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 Evgenii Alekseev.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
from ahriman.core.report.report import Report
|
||||||
|
|
||||||
|
|
||||||
|
class Dummy(Report):
|
||||||
|
|
||||||
|
def generate(self, path: str) -> None:
|
||||||
|
pass
|
52
src/ahriman/core/report/html.py
Normal file
52
src/ahriman/core/report/html.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 Evgenii Alekseev.
|
||||||
|
#
|
||||||
|
# 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 os
|
||||||
|
|
||||||
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.core.report.report import Report
|
||||||
|
|
||||||
|
|
||||||
|
class HTML(Report):
|
||||||
|
|
||||||
|
def __init__(self, config: Configuration) -> None:
|
||||||
|
Report.__init__(self, config)
|
||||||
|
self.report_path = config.get('html', 'path')
|
||||||
|
self.css_path = config.get('html', 'css_path')
|
||||||
|
self.link_path = config.get('html', 'link_path')
|
||||||
|
self.title = config.get('repository', 'name')
|
||||||
|
|
||||||
|
def generate(self, path: str) -> None:
|
||||||
|
# lets not use libraries here
|
||||||
|
html = f'''<html lang="en"><head><title>{self.title}</title>'''
|
||||||
|
if self.css_path:
|
||||||
|
html += f'''<link rel="stylesheet" type="text/css" href="{self.css_path}">'''
|
||||||
|
html += '''</head><body>'''
|
||||||
|
|
||||||
|
html += '''<ul>'''
|
||||||
|
for package in sorted(os.listdir(path)):
|
||||||
|
if '.pkg.' not in package:
|
||||||
|
continue
|
||||||
|
html += f'''<li><a href="{self.link_path}/{package}">{package}</a></li>'''
|
||||||
|
html += '''</ul>'''
|
||||||
|
|
||||||
|
html += '''</body></html>'''
|
||||||
|
|
||||||
|
with open(self.report_path, 'w') as out:
|
||||||
|
out.write(html)
|
49
src/ahriman/core/report/report.py
Normal file
49
src/ahriman/core/report/report.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 Evgenii Alekseev.
|
||||||
|
#
|
||||||
|
# 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 logging
|
||||||
|
|
||||||
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.core.exceptions import ReportFailed
|
||||||
|
from ahriman.models.report_settings import ReportSettings
|
||||||
|
|
||||||
|
|
||||||
|
class Report:
|
||||||
|
|
||||||
|
def __init__(self, config: Configuration) -> None:
|
||||||
|
self.config = config
|
||||||
|
self.logger = logging.getLogger('builder')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def run(config: Configuration, target: str, path: str) -> None:
|
||||||
|
provider = ReportSettings.from_option(target)
|
||||||
|
if provider == ReportSettings.HTML:
|
||||||
|
from ahriman.core.report.html import HTML
|
||||||
|
report: Report = HTML(config)
|
||||||
|
else:
|
||||||
|
from ahriman.core.report.dummy import Dummy
|
||||||
|
report = Dummy(config)
|
||||||
|
|
||||||
|
try:
|
||||||
|
report.generate(path)
|
||||||
|
except Exception as e:
|
||||||
|
raise ReportFailed(e) from e
|
||||||
|
|
||||||
|
def generate(self, path: str) -> None:
|
||||||
|
raise NotImplementedError
|
@ -21,13 +21,15 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from typing import List
|
from typing import List, Optional
|
||||||
|
|
||||||
from ahriman.core.build_tools.task import Task
|
from ahriman.core.build_tools.task import Task
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.repo.repo_wrapper import RepoWrapper
|
from ahriman.core.repo.repo_wrapper import RepoWrapper
|
||||||
from ahriman.core.sign.sign import Sign
|
from ahriman.core.report.report import Report
|
||||||
|
from ahriman.core.sign.gpg_wrapper import GPGWrapper
|
||||||
from ahriman.core.upload.uploader import Uploader
|
from ahriman.core.upload.uploader import Uploader
|
||||||
|
from ahriman.core.util import options_list
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ class Repository:
|
|||||||
self.paths = RepositoryPaths(config.get('repository', 'root'))
|
self.paths = RepositoryPaths(config.get('repository', 'root'))
|
||||||
self.paths.create_tree()
|
self.paths.create_tree()
|
||||||
|
|
||||||
self.sign = Sign(config)
|
self.sign = GPGWrapper(config)
|
||||||
self.wrapper = RepoWrapper(self.name, self.paths)
|
self.wrapper = RepoWrapper(self.name, self.paths)
|
||||||
|
|
||||||
def _clear_build(self) -> None:
|
def _clear_build(self) -> None:
|
||||||
@ -96,8 +98,17 @@ class Repository:
|
|||||||
self.sign.sign_repository(self.wrapper.repo_path)
|
self.sign.sign_repository(self.wrapper.repo_path)
|
||||||
return self.wrapper.repo_path
|
return self.wrapper.repo_path
|
||||||
|
|
||||||
def process_sync(self) -> None:
|
def process_report(self, targets: Optional[List[str]]) -> None:
|
||||||
return Uploader.run(self.config, self.paths.repository)
|
if targets is None:
|
||||||
|
targets = options_list(self.config, 'report', 'target')
|
||||||
|
for target in targets:
|
||||||
|
Report.run(self.config, target, self.paths.repository)
|
||||||
|
|
||||||
|
def process_sync(self, targets: Optional[List[str]]) -> None:
|
||||||
|
if targets is None:
|
||||||
|
targets = options_list(self.config, 'upload', 'target')
|
||||||
|
for target in targets:
|
||||||
|
Uploader.run(self.config, target, self.paths.repository)
|
||||||
|
|
||||||
def process_update(self, packages: List[str]) -> str:
|
def process_update(self, packages: List[str]) -> str:
|
||||||
for package in packages:
|
for package in packages:
|
||||||
|
@ -28,7 +28,7 @@ from ahriman.core.util import check_output
|
|||||||
from ahriman.models.sign_settings import SignSettings
|
from ahriman.models.sign_settings import SignSettings
|
||||||
|
|
||||||
|
|
||||||
class Sign:
|
class GPGWrapper:
|
||||||
|
|
||||||
def __init__(self, config: Configuration) -> None:
|
def __init__(self, config: Configuration) -> None:
|
||||||
self.logger = logging.getLogger('build_details')
|
self.logger = logging.getLogger('build_details')
|
@ -29,7 +29,7 @@ class S3(Uploader):
|
|||||||
self.bucket = self.config.get('s3', 'bucket')
|
self.bucket = self.config.get('s3', 'bucket')
|
||||||
|
|
||||||
def sync(self, path: str) -> None:
|
def sync(self, path: str) -> None:
|
||||||
# TODO rewrite to boto, but it is bs
|
# TODO rewrite to boto, but it is bullshit
|
||||||
check_output('aws', 's3', 'sync', path, self.bucket,
|
check_output('aws', 's3', 'sync', path, self.bucket,
|
||||||
exception=None,
|
exception=None,
|
||||||
logger=self.logger)
|
logger=self.logger)
|
||||||
|
@ -31,8 +31,8 @@ class Uploader:
|
|||||||
self.logger = logging.getLogger('builder')
|
self.logger = logging.getLogger('builder')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run(config: Configuration, path: str) -> None:
|
def run(config: Configuration, target: str, path: str) -> None:
|
||||||
provider = UploadSettings.from_option(config.get('upload', 'enabled'))
|
provider = UploadSettings.from_option(target)
|
||||||
if provider == UploadSettings.Rsync:
|
if provider == UploadSettings.Rsync:
|
||||||
from ahriman.core.upload.rsync import Rsync
|
from ahriman.core.upload.rsync import Rsync
|
||||||
uploader: Uploader = Rsync(config)
|
uploader: Uploader = Rsync(config)
|
||||||
@ -46,7 +46,7 @@ class Uploader:
|
|||||||
try:
|
try:
|
||||||
uploader.sync(path)
|
uploader.sync(path)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise SyncFailed from e
|
raise SyncFailed(e) from e
|
||||||
|
|
||||||
def sync(self, path: str) -> None:
|
def sync(self, path: str) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -20,7 +20,9 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from logging import Logger
|
from logging import Logger
|
||||||
from typing import Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
|
from ahriman.core.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
def check_output(*args: str, exception: Optional[Exception],
|
def check_output(*args: str, exception: Optional[Exception],
|
||||||
@ -37,3 +39,10 @@ def check_output(*args: str, exception: Optional[Exception],
|
|||||||
logger.debug(line)
|
logger.debug(line)
|
||||||
raise exception or e
|
raise exception or e
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def options_list(config: Configuration, section: str, key: str) -> List[str]:
|
||||||
|
raw = config.get(section, key, fallback=None)
|
||||||
|
if not raw: # empty string or none
|
||||||
|
return []
|
||||||
|
return raw.split()
|
@ -37,10 +37,6 @@ class Package:
|
|||||||
version: str
|
version: str
|
||||||
url: str
|
url: str
|
||||||
|
|
||||||
@property
|
|
||||||
def is_multilib(self) -> bool:
|
|
||||||
return self.name.startswith('lib32-')
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_archive(cls: Type[Package], path: str, aur_url: str) -> Package:
|
def from_archive(cls: Type[Package], path: str, aur_url: str) -> Package:
|
||||||
name, version = check_output('expac', '-p', '%n %v', path, exception=None).split()
|
name, version = check_output('expac', '-p', '%n %v', path, exception=None).split()
|
||||||
|
35
src/ahriman/models/report_settings.py
Normal file
35
src/ahriman/models/report_settings.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021 Evgenii Alekseev.
|
||||||
|
#
|
||||||
|
# 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/>.
|
||||||
|
#
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from enum import Enum, auto
|
||||||
|
from typing import Type
|
||||||
|
|
||||||
|
from ahriman.core.exceptions import InvalidOptionException
|
||||||
|
|
||||||
|
|
||||||
|
class ReportSettings(Enum):
|
||||||
|
HTML = auto()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_option(cls: Type[ReportSettings], value: str) -> ReportSettings:
|
||||||
|
if value.lower() in ('html',):
|
||||||
|
return cls.HTML
|
||||||
|
raise InvalidOptionException(value)
|
@ -26,15 +26,12 @@ from ahriman.core.exceptions import InvalidOptionException
|
|||||||
|
|
||||||
|
|
||||||
class UploadSettings(Enum):
|
class UploadSettings(Enum):
|
||||||
Disabled = auto()
|
|
||||||
Rsync = auto()
|
Rsync = auto()
|
||||||
S3 = auto()
|
S3 = auto()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_option(cls: Type[UploadSettings], value: str) -> UploadSettings:
|
def from_option(cls: Type[UploadSettings], value: str) -> UploadSettings:
|
||||||
if value.lower() in ('no', 'disabled'):
|
if value.lower() in ('rsync',):
|
||||||
return cls.Disabled
|
|
||||||
elif value.lower() in ('rsync',):
|
|
||||||
return cls.Rsync
|
return cls.Rsync
|
||||||
elif value.lower() in ('s3',):
|
elif value.lower() in ('s3',):
|
||||||
return cls.S3
|
return cls.S3
|
||||||
|
Loading…
Reference in New Issue
Block a user