Compare commits

...

465 Commits

Author SHA1 Message Date
969352d842 Release 2.11.0 2023-08-27 02:12:21 +03:00
a1db4dc8b8 add ability to partition tree before calculationn 2023-08-27 01:55:57 +03:00
f6081507c0 small improvements on code smell
* fix some grammar/typo errors
* change some statements to be more clear
* use pattern matching for enum processing
2023-08-25 04:15:10 +03:00
477c473187 force rtd theme
Since Aug, 22 rtd doesn't force its theme anymore, leaving it as default
2023-08-23 15:27:51 +03:00
33e68a59e2 use http client class for all http requests 2023-08-23 03:27:42 +03:00
6dfe1b92f2 bump pylintrc 2023-08-21 02:55:08 +03:00
5dc6df11c5 verbose subprocess exception handle annd quite git 2023-08-21 01:35:43 +03:00
d3f6ca24c8 review exception raise
In some cases for better readability of logs, exceptions are now raised
without parent exception stacktrace. Also updated docs and contributing
guidelines
2023-08-20 17:03:46 +03:00
c26a13c562
Remote call trigger support (#105)
* add support of remote task tracking
* add remote call trigger implementation
* docs update
* add cross-service upload
* add notes about user
* add more ability to control upload
* multipart upload with signatures as well as safe file save
* configuration reference update
* rename watcher methods
* erase logs based on current package version

Old implementation has used process id instead, but it leads to log
removal in case of remote process trigger

* add --server flag for setup command
* restore behavior of the httploghandler
2023-08-20 03:44:31 +03:00
9ea3a911f7 update gh actions install script 2023-08-17 16:33:02 +03:00
ca60317750 add dummy type fields for pkgbuild generators
This field is required in order to pass config validation in case if
section name differs from default one. Also by default keyring_generator
and mirrorlist_generator have been renamed to keyring-generator and
mirrorlist-generator respectively for consistence
2023-08-17 16:02:15 +03:00
1384efb31d close descriptor after uploading archive on github 2023-08-15 02:31:46 +03:00
8c6486c233 contributing guide update 2023-08-14 02:51:14 +03:00
a1d0e993a8 resoolve dependencies by using local cache too (#107) 2023-08-14 02:31:24 +03:00
572880eb73 add ability to read values from environment variables
It makes sense to read some values from environment. In particular this
feature is useful in case of running application in containers in ci/cd

See #108 for more details
2023-08-14 01:48:08 +03:00
d9eaf17a11 remove unused absolute path validator (#106)
Extracted path is always absolute, so there is no need to check it
2023-08-13 20:48:07 +03:00
95e29d16bb Local packages support improvements (#104)
* handle git author correctly
* make remote source required argument
2023-08-13 15:45:53 +03:00
1f2d56e605 make auth.salt parameter optional
Used implementation of the hasher includes salt itself, thus additional
salt is optional and can be safely (in terms of security) treat as empty
string
2023-08-11 16:31:47 +03:00
1baf04998d full support of pep517
Since llast upgrade build is broken. Lets fully migrate to
pyproject.toml. Note for maintaners: because data_files option is
deprectated (see https://github.com/pypa/setuptools/discussions/2648)
you will have to install files manually inside your packaging process
2023-08-11 03:55:31 +03:00
3a88d00db0 automatically bump pkgrel on version duplicates
The new --(no-)increment flag has been added to add, update and rebuild
subcommands. In case if it is true and package version is the same as in
repository, it will automatically bump pkgrel appending (increasing)
minor part of it (e.g. 1.0.0-1 -> 1.0.0-1.1).

Inn order to implement this, the shadow (e.g. it will not store it in
database) patch for pkgrel will be created
2023-08-08 03:14:47 +03:00
b58d8d96ff Release 2.10.2 2023-08-08 02:54:23 +03:00
4abe3b8963 remove napoleon contrib dependency 2023-08-08 02:53:08 +03:00
237fec3f85 fix issues with remote pull triggers (see #103)
* The issue appears when repository contains PKGBUILD in root. In this
  case it will copy tree with loosing package information, because
  the repository will be cloned to temporary path with random generated
  name
* The issue appears when branch which is different from master is used
  for any reposittory with git files (e.g. single-pkgbuild repo or repo
  with submodules)
2023-08-08 02:34:44 +03:00
bd0f850d25 Release 2.10.1 2023-07-28 03:21:19 +03:00
5904727da2 do not create application in shell handler
The main reason for having shell handler is to be able to fix if
something (e.g. migrations) goes wrong. In this way we need to reduce
actions inside this wrapper
2023-07-28 03:06:28 +03:00
263c53bac5 rase 405 error in case if GET login method is used whereas no aioauth
library installed
2023-07-23 03:01:25 +03:00
6743f1d62a optimize schemas import 2023-07-23 02:24:39 +03:00
931ff9bd98 Release 2.10.0 2023-07-22 05:28:57 +03:00
6b3fc3a6a0
add support of table filter controls (#101) 2023-07-21 02:10:26 +03:00
b7852f55c8 remove unsafe flag from handlers
This flag became reduntant there and tree creation has been moved to
lock
2023-07-07 03:25:05 +03:00
721b447767 fix code block in docs 2023-07-06 19:17:11 +03:00
b80ea80e9d add salt generator to setup command instead 2023-07-06 19:16:49 +03:00
8e9da5baab register dependency package before build
If package has been added as dependency, the service miss remote as well
as causes some 400 errors in reporter
2023-07-06 03:11:19 +03:00
a443abb94e handle packages load from aur by package name also
In general package names array may not contain package base, thus it
leads to inability to load packages from aur by its base during update
process
2023-07-01 15:55:04 +03:00
61c565ab0d explicitly pass user agent for the arch linux sites requests 2023-06-26 02:52:08 +03:00
10100b20e1 print configuration paths in dump command 2023-06-11 15:11:34 +03:00
2922bb9d72 remove salt generation from users handler
It causes issues, because users handler is operating with service user,
but writtinng salt requires root privileges
2023-06-05 05:25:10 +03:00
17f5f41e36 complitely disable signature check for local repository in devtools
It appears that with optional level pacman still tries to validate the
key, which can lead to errors whille processing in docker container
2023-06-05 04:41:03 +03:00
c22ddd71d9 packager documentation update 2023-06-05 03:40:02 +03:00
4b984afb64
packagers support (#100) 2023-06-05 02:37:19 +03:00
d495163fdd use autodoc_mock_imports instead of custom mocking for docs 2023-05-31 19:17:16 +03:00
041e9536bf use cached property instead of custom __getattr__ implementation 2023-05-31 19:17:16 +03:00
1625fddccd support check dependencies 2023-05-31 19:17:16 +03:00
8f2c33fe5d
mimic parent arguments during spawn process (#99) 2023-05-30 18:09:35 +03:00
d064e46af6 do not terminate child process explicitly
This feature sometimes causes the main process termination. Since the
child process has been already terminated (or going to) there is no need
to terminate it manually
2023-05-29 17:27:04 +03:00
5627c9cca0 fix case where it was impossible to create session if user and password
are required

Issue appears if auth is enabled and unix socket is disabled and caused
by 7f5e541120
2023-05-29 17:23:57 +03:00
8731cee8ea runtime logger handler selector 2023-05-29 03:41:11 +03:00
01a4d68ce6 add repod reference to faq 2023-05-26 12:58:25 +03:00
8f0a6cf6b5 allow to filter packages for rebuild by their statuses 2023-05-25 17:41:54 +03:00
d96e3c97db fix documentation error 2023-05-25 16:31:47 +03:00
1cf027cb55
Support type triggers (#96)
* implement mirrorlist package generator

* implement keyring package generator

* docs update

* do not skip empty lines

* fill remote source for local packages

* faq update
2023-05-25 16:27:16 +03:00
8e0e57e193 switch to explicit journald logger instead of syslog 2023-05-25 04:44:38 +03:00
f855e645cc update optional dependencies list 2023-05-24 15:39:36 +03:00
8ab0df2bed bump rtd image 2023-05-24 03:58:14 +03:00
840921f585 update packaging files
also remove makedependencies after installation in docker
2023-05-22 18:23:06 +03:00
6f566b0c6c Release 2.9.0 2023-05-22 17:04:32 +03:00
d06399db2c update models index 2023-05-22 17:02:55 +03:00
70e9e3e822 migrate to the latest devtools & archlinux git changes
This migration includes
* removal of community repository as it is no more
* fixed paths for devtools configurations
* migration of archlinux packaging git url
2023-05-22 16:51:27 +03:00
8c55438140 disable debugpanel for now 2023-05-04 14:30:27 +03:00
277d40d231 do not assign path in context manager as it is deprectated 2023-05-04 14:29:39 +03:00
2ff56965d9
PEP-673 use Self as return type for classmethods (#94)
* PEP-673 use Self as return type for classmethods

* add dummy test file

* remove python3.10 compat
2023-05-04 03:28:08 +03:00
9dc6d56a8d fix flapping tests for oauth
Original implementation sends requests to httpbin which sometimes might
not be available. With proposed changes we are blocking redirects and
just check request itself
2023-05-03 14:53:35 +03:00
d59a0629c5 PEP-561 complaint: add py.typed marker 2023-04-17 18:56:49 +03:00
31f47b8069 fix some pycharm warnings 2023-04-17 02:23:50 +03:00
e42ca95789 suppress status errors also if option is set 2023-04-15 05:05:55 +03:00
ff917281a2 add referencne to api docs to docs 2023-04-14 05:06:53 +03:00
f7e260e1f4 add reference to api documentation from main page 2023-04-12 04:22:49 +03:00
abf29083c4
PEP-585 complaint: remove type aliases (#93) 2023-04-12 04:09:28 +03:00
54d36ccf36 docs update 2023-04-10 21:13:43 +03:00
2cd61b0a20 Release 2.8.0 2023-04-09 13:06:54 +03:00
9503a9f2ae try to remove unknown packages from api 2023-04-06 18:14:36 +03:00
39fde7cd5f hide cookie key and salt from config output 2023-04-06 00:31:50 +03:00
58379e7bf3 optimize imports 2023-04-06 00:24:39 +03:00
3c068edf4f argument annootation update 2023-04-06 00:24:39 +03:00
1106ff6482 fix license url 2023-04-06 00:24:39 +03:00
e08ab2db10 extract schemas automatically from views 2023-04-06 00:24:39 +03:00
8f4a2547e8 use api generated docs instead of comments (#92) 2023-04-06 00:24:39 +03:00
7f5e541120 execute request in context methods instead of handling them each time
manually
2023-03-23 12:43:04 +02:00
ec0550a275 Release 2.7.1 2023-03-06 01:15:47 +02:00
df23be9269 gracefully terminate web server
In previous revisions server was terminated by itself, thus no lock or
socket was removed. In new version, graceful termination of the queue
has been added as well as server now handles singals
2023-03-06 01:13:41 +02:00
a8c40a6b87 replace InitializeException with InitializeError in docs 2023-03-02 11:07:59 +02:00
a274f91677 simplify login ttl processing 2023-02-24 16:52:55 +02:00
13faf66bdb add more validation rules 2023-02-23 15:18:56 +02:00
4fb9335df9 add ability to read cookie secret from config 2023-02-22 18:47:56 +02:00
d517d8bfbb Release 2.7.0 2023-02-20 03:05:08 +02:00
37e57c13c8
update dependencies before build (#91)
Old implementation has used add step in order to fetch dependencies,
which could lead to build errors in case if dependency list was updated.

New solution uses dependencies which are declared at current version and
fetch them (if required and if enabled) before update process.

Closes #90
2023-02-12 06:02:30 +03:00
19bb19e9f5 handle .gitignore file correctly in remote push trigger 2023-02-11 04:41:24 +02:00
3a4e8f4d97 mask mypy warning
The newest mypy produces the following warning:

src/ahriman/application/handlers/search.py:43: error: Non-overlapping identity check (left operand type: "Union[_DefaultFactory[Any], Literal[_MISSING_TYPE.MISSING]]", right operand type: "Type[List[Any]]")  [comparison-overlap]

which is more likely caused by updated dataclass models to protoocol (however decorators are still calllable). This commit masks problematic line from checking
2023-02-09 22:46:08 +02:00
4db8ad8e8d hide passwords and secrets from repo-config subcommand by default 2023-02-05 16:44:48 +02:00
117f096d41 note about local database update (see #85) 2023-01-31 14:47:58 +02:00
917ec48be5 handle architecture specific fields for dependencies
This change requires srcinfo at least 0.1.2 version. Unfortunatelly aur
api don't support architecture specific arrays for now, so we just leave
it as is

Closes #82
2023-01-31 14:34:09 +02:00
0a2ba4ae07 filter empty packages from database
In some cases (e.g. during addition of the package to build queue) we don't have
full information about package inself; in these cases we produce lines
with empty architecture, which duplicates normal ones.

This commit changes architecture column type to required and also
filters packages which don't have architecture set yet.

Closes #83
2023-01-30 17:57:13 +02:00
9d7f63e549 trim version from provides list
Closes #87
2023-01-30 17:27:34 +02:00
25eee9ca5e add ability to suppress http logging errors (#86) 2023-01-30 17:19:01 +02:00
5af84955ac
calculate dependencies based on package information (#89) 2023-01-30 17:28:05 +03:00
d3ad4c3c08 remove debug line 2023-01-27 16:41:41 +02:00
5bbb9d269b Release 2.6.1 2023-01-25 15:28:27 +02:00
17466d8d37 make oauth client trully optional (#84)
Same old song, after migraiton to packages some optional modules are
being imported globally which lead to making hard dependency
2023-01-25 15:25:42 +02:00
9e4e3b701b enable lock for web service 2023-01-18 01:39:55 +02:00
c6555cf2c7 Release 2.6.0 2023-01-16 01:35:12 +02:00
85baad6a41 add notes about non-x86_64 architecture setup 2023-01-15 18:16:29 +02:00
616a1950ae add ability to override pacman mirror in devtools configuration
This commit also extends configuration of the multilib option, adding
the ability to exlcude multilib repository from repositories list

Note, that in order to support repository list and mirror correctly,
alpm configuration section is now architectture specific
2023-01-15 18:05:15 +02:00
30b9bcb45a add note about other authroization options to gitremote triggers 2023-01-13 17:27:19 +02:00
d7356926c4 consider vcs flag and vcs_allowed_age during local packages update 2023-01-12 15:37:05 +02:00
43a7d09cab add ability to check for service updates 2023-01-12 15:37:05 +02:00
77954b988b subcommand review
Some commands have been moved to another group and thus having another
default name (old subcommands are still available...for now):

* daemon -> repo-daemon
* key-import -> service-key-import
* repo-clean -> service-clean
* repo-config -> service-config
* repo-config-validate -> service-config-validate
* repo-setup -> service-setup
* repo-shell -> service-shell
* version -> help-version
2023-01-12 15:37:05 +02:00
0239fb50b6 expose trigger configuration schema
Note that this commit contains the following breaking changes:

* remote pull and remote push triggers are now enabled by default (with
  empty target list)
* remote pull and remote push triggers now require target option to be
  set (old behaviour had fallback on `gitremote`)
* validation is now considered to be stable, so it is enabled by default
  in docker image (can be disabled however)
2023-01-10 03:33:52 +02:00
d942a70272
add config validator subcommand (#80)
* add config validator subcommand

* add --exit-code flag

* docs & faq update
2023-01-09 18:22:29 +03:00
1f07a89316 sort unsafe commands response 2023-01-04 18:00:10 +02:00
014007ade3 review unsafe commands access
Some commands were made unsafe in old versions, but nowadays they can be
run without having special privileges.

There was also a bug in which status commands were not available if you
are not ahriman user and unix socket is used. It has been fixed by
switching to manual socket creation (see also
https://github.com/aio-libs/aiohttp/issues/4155)
2023-01-04 17:45:44 +02:00
730f3ca0c9 copyright update 2023-01-04 03:43:10 +02:00
42c13b5d4b Release 2.5.4 2023-01-03 01:59:25 +02:00
04e5a263b7 add notes about documentation and methods inside class
Because I always forget which way I used before
2023-01-03 01:53:10 +02:00
caca1576c8 Correct way to allow setting context with existing
This reverts commit 5c4d3eeffd.

Original solution has introduced special workaround (strict flag) which
contradicts the concept of immutable context. Moreover, it introduces
possible side-effects, because child process will use the one set by
parent instead of having own one.

The correct solution is to re-create context in process entry point

Sorry, it was Jan 1 and I was drunk :(
2023-01-03 00:48:14 +02:00
98f2f19d5b Release 2.5.3 2023-01-02 03:24:11 +02:00
5c4d3eeffd allow setting context with existing
In case of running command from web interface, it will raise exception
because context has been copied with subprocesses
2023-01-02 03:21:15 +02:00
84d4523e85 Release 2.5.2 2023-01-02 01:57:09 +02:00
2c2eae2334 remote all gitfiles in git remote trigger
In case if there is .gitignore file with asterics, the pkgbuild upload
would not appear
2023-01-02 01:45:50 +02:00
214d6d7fdd Release 2.5.1 2022-12-31 14:58:37 +02:00
e9512e9a6a remote log for calculate version as it cleans logs 2022-12-31 14:48:21 +02:00
f984ea75d0 fully lazy handle load
In case of immediate handle load it would try to sync databases (or at
least to create database files), which is not possible in case if
command is run as non-ahriman user. This commit makes handle load lazy
and allows to run some commands as non-ahriman user
2022-12-31 14:48:21 +02:00
b44e5c3a3d Release 2.5.0 2022-12-31 02:02:37 +02:00
1891d6c944 force upgrade sphinx documentation 2022-12-30 22:58:13 +02:00
08d68258ca add completion files generated by shtab 2022-12-30 21:19:23 +02:00
cd3d12a754 allow 3 symbols for package search 2022-12-30 21:19:23 +02:00
81d9526054 improve VCS packages checks
* Unlike older version, currently service will always try to pull AUR
  package to check version. Previously if no-vcs flag is set, it would
  ignore VCS packages completelly
* Introduce build.vcs_allowed_age option. If set, it will skip version
  calculation if package age (now - build_date) is less than this value
2022-12-30 21:19:23 +02:00
c7447f19f0 change another boolean info option to boolean action 2022-12-29 03:15:48 +02:00
7de94a8daa add repo-structure subcommand
This commit also changes Tree class, replacing load method by resolve
2022-12-27 10:35:03 +02:00
aa1a59d0a3 fix property description in docs 2022-12-26 02:32:14 +02:00
8864855c14
write patches via gitremote push trigger (#79)
* write patches via gitremote push trigger

* implement context variables intead of custom database class
2022-12-25 02:10:38 +03:00
b0b37e8169 Release 2.4.1 2022-12-11 05:17:10 +02:00
7df4adfc9d replace alert bodals with toasts 2022-12-09 11:33:19 +02:00
2d5b73c6dc remove badges from status page 2022-12-09 00:58:03 +02:00
1c8aed4a97 check that package has been created during setup workflow 2022-12-06 11:09:56 +02:00
2e059023f3 Release 2.4.0 2022-12-05 00:25:53 +02:00
da5d97788a do not update database via pacman, use ahriman's own databses 2022-12-04 23:45:10 +02:00
0e839fbbf2 Some minor documentation related fixes
* Improve some wording (again)
* Change default type for refresh option to False (does not affect
  behavior)
* Update docstrings to reflect last changes
* Configuration.__convert_path has been replaced by shlex
* aiosecurity functions support kwargs now
2022-12-04 02:10:46 +02:00
262462d3c3 improve wording in documentation 2022-12-02 15:45:01 +02:00
7aa91f9e2e do not trigger update on sign command 2022-12-02 01:41:23 +02:00
01eda513cf improve setup command by --makeflags-jobs argument and fix repository sign on creation 2022-12-02 01:41:23 +02:00
0161617e36 implement support of unix socket for server
This feature can be used for unauthorized access to apis - e.g. for
reporting service if it is run on the same machine. Since now it becomes
recommended way for the interprocess communication, thus some options
(e.g. creating user with as-service flag) are no longer available now
2022-12-02 01:41:23 +02:00
4811dec759 do not invoke configuration write in case if no salt or user was written 2022-12-02 01:41:23 +02:00
09623c20d5 add rebuild implementation to interface 2022-12-02 01:41:23 +02:00
eba247b759 make package actions as dropdown 2022-12-02 01:41:23 +02:00
5073c80af1 add key-import button to interface 2022-12-02 01:41:23 +02:00
766081d212 add demos links 2022-11-24 02:38:33 +02:00
896cd0bd71 add security notes 2022-11-24 02:38:33 +02:00
ce1bd2f2db add curl examples to web views 2022-11-24 02:38:33 +02:00
6ba96d838d build docs together with web views 2022-11-24 02:38:33 +02:00
df9e03f495 change respone for service requests 2022-11-24 02:38:33 +02:00
89944eb2b6 add fallback for copying to clipboard 2022-11-24 02:38:33 +02:00
336784519b add show/hide password button 2022-11-24 02:38:33 +02:00
f3341ec7cd update web preview picture 2022-11-24 02:38:33 +02:00
d36e851a29 render httpunauthorized as html in plain http requests 2022-11-22 23:40:27 +02:00
28bd5f2095 allow scrolling with fixed copy button position 2022-11-22 22:20:21 +02:00
011b4e2e31 change logging module imports 2022-11-22 22:20:21 +02:00
15609ba044 change wording for package actions 2022-11-22 15:46:49 +02:00
6d4f9981f7 fix login and logout buttons decorations 2022-11-22 11:17:59 +02:00
bbb97d1cdd add more notes about docker 2022-11-22 10:49:46 +02:00
3bca780bdd check log record in handler instead of client 2022-11-22 02:30:37 +02:00
78e6b48c24 ask users to repeat password
In case if password is asked via getpass, it is possible to make typo
and user will not see the mistake. In order to avoid it, additional
confirmation has been added
2022-11-22 02:19:37 +02:00
137d62e2f8
Extended package status page (#76)
* implement log storage at backend
* handle process id during removal. During one process we can write logs from different packages in different times (e.g. check and update later) and we would like to store all logs belong to the same process
* set package context in main functions
* implement logs support in interface
* filter out logs posting http logs
* add timestamp to log records
* hide getting logs under reporter permission

List of breaking changes:

* `ahriman.core.lazy_logging.LazyLogging` has been renamed to `ahriman.core.log.LazyLogging`
* `ahriman.core.configuration.Configuration.from_path` does not have `quiet` attribute now
* `ahriman.core.configuration.Configuration` class does not have `load_logging` method now
* `ahriman.core.status.client.Client.load` requires `report` argument now
2022-11-22 02:58:22 +03:00
8a6854c867 Release 2.3.0 2022-11-16 00:53:48 +02:00
299732181c remote threadname from logging
Since application is mostly singlethreaded it makes no sense to log it
2022-11-14 23:21:06 +02:00
84c1b4d82d Release 2.3.0rc4 2022-11-14 01:02:27 +02:00
cdd66ee780 fix case when no files were commited in remote push trigger
The issue appears together with --intent-to-add flag for adding new
files. Original testing has been performed by having already added new
files, thus it passed all checks.

This commit also adds `commit_author` option which will allow to
overwrite the author.
2022-11-14 00:59:43 +02:00
b2ed383de0 Release 2.3.0rc3 2022-11-11 21:20:55 +02:00
551ee670bf rollback cwd parameter for clone 2022-11-11 21:19:27 +02:00
5d4bd9e459 Release 2.3.0rc2 2022-11-11 17:25:11 +02:00
4f21eb6fe6 Fix issue when there is no cached source directory yet (closes #75) 2022-11-11 17:23:15 +02:00
9a008ddafa Release 2.3.0rc1 2022-11-11 16:36:13 +02:00
0cd07afa0f use intersection of from_database and depends_on filters for the rebuild subcommand
Old logic used OR condition, i.e. if set from-database, it would ignore
the --depends-on flag. In new logic it calculates dependencies based on
the package list, which can be retrieved from database
2022-11-11 16:02:19 +02:00
f590136197 limit max module size and improve some help messages 2022-11-11 16:01:54 +02:00
1855e513a8 speedup docker build command by adding dockerignore listing 2022-11-11 12:47:31 +02:00
233dda8420 man update 2022-11-10 20:10:07 +02:00
9556779ee2 add exec to shell subcommand 2022-11-10 18:52:55 +02:00
8b32bd43db make exception optional argument for check_output method 2022-11-10 18:05:32 +02:00
0eadef597a
replace several store_true keys to booleanoptionalaction alternative (#74) 2022-11-10 18:34:01 +03:00
e58ccdc8ad write .makepkg.conf to home dir instead of repository root (#72) 2022-11-08 17:02:13 +02:00
2a07356d24
add ability to use ahriman pacman database instead of system one (#71)
By default this feature is enabled. On the first run it will copy (if
exists) databases from filesystem to local cache (one per each
architecture). Later it will use this cache for all alpm operations. In
order to update this cache, some commands (mainly package building)
provide `-y`/`--refresh` option which has same semantics as pacman -Sy
does.

Note however that due to extending `Pacman` class some methods were
renamed in order to be more descriptive:
* `Pacman.all_packages` -> `Pacman.packages`
* `Pacman.get` -> `Pacman.package_get`

This commit also adds multilib repository to the default docker image
which was missed.
2022-11-08 17:26:51 +03:00
43c553a3db improve repo-setup command
* Move devtools executable to ahriman home, because we don't really
  need to use executable inside root
* Use named sudoers file instead of single file. It will allow easily to
  remove file as well as use setup command for several
  repositories/architectures
2022-11-06 14:25:44 +02:00
0d1a890bd0 fix case in which if no source PKGBUILDs were updated, an exception will occur 2022-11-03 03:39:54 +02:00
3aeaa8ce2c faq update 2022-11-02 17:15:17 +02:00
7cee859f19 docs update 2022-11-02 04:17:26 +02:00
fb6b22cdd7 change gitremote api to be same as report and upload
These changes are keeping fallback to old settings, but will allow to
run multiple git targets with different settings
2022-11-02 04:09:42 +02:00
4f35ec6542 fix update handler tests
If daemon tests are run before the update handler it causes test
failure, because there are other calls
2022-10-31 11:51:12 +02:00
d98211e5e5 add possibility to run full update
In case if packages are not set from web, the spawner will run full
repository update
2022-10-31 02:41:24 +02:00
b97c8928e1 add daemon subcommand
This command emulates default systemd timer and can be useful in docker
container in order to run 24/7
2022-10-31 01:38:01 +02:00
649df81aa5
implement single-function patches (#69) 2022-10-30 03:11:03 +03:00
ad7cdb7d95 drop ahriman.core.triggers.Trigger.run method
In order to force new triggers to use on_result method, the old method
has been removed. However, default on_result method still checks if the
old method exists and tries to run it
2022-10-19 20:07:31 +03:00
4bb598d2eb fix rtd docs building
Commit 6633766cc3 introduced kw_only
dataclasess which require python 3.10+
2022-10-18 02:24:18 +03:00
f47be6cab0 disallow no values in configuration
This option could lead to missing warnings about missing or invalid
configuration values because code usually expects that values are exists
and not empty unless it is explicitly specified.

However, pacman configuration still requires this option in order to be
able to deal with boolean values
2022-10-18 02:13:01 +03:00
342b3cb652
Add gitremote triggers (#68)
* add gitremote pull trigger

* add push gitremote trigger

* docs update
2022-10-18 01:46:27 +03:00
fc0d8387df extend triggers to on_start and on_stop methods
This commit also replaces old run method to new on_result
2022-09-26 01:22:54 +03:00
e0b0c3caeb add minimal install step to workflow 2022-09-17 14:52:08 +03:00
61969dd682 make sqlite import consistent 2022-09-17 14:32:21 +03:00
e441d93a56 Release 2.2.2 2022-09-17 04:05:06 +03:00
664b6369bb skip architecture list patching in case if any architecture is set 2022-09-17 04:04:28 +03:00
4f6bd29ff4 Release 2.2.1 2022-09-14 04:49:08 +03:00
f6d9ea480a docs update 2022-09-14 04:48:11 +03:00
08f62842ba Release 2.2.0 2022-09-14 03:28:28 +03:00
1912790ccc Make optional dependencies trully optional (#67)
The issue appears when there is no boto, jinja and some other libraries
are not installed because the classes which use these libraries are
still being imported inside the package file. The fix removes those
imports from package root, because they should not be here, in fact,
content of report and upload packages must be imported only inside the
trigger class and only if they are actually required

This commit also adds setuptools as required dependency since it is used
for some parsers (previously it was provided dependency)
2022-09-11 01:44:06 +03:00
cf3c48ffeb
patch architecture list in runtime (#66) 2022-08-09 15:18:20 +03:00
6633766cc3 frozen dataclasses 2022-07-26 14:40:28 +03:00
f73d1eb424 reduce docker image size a bit 2022-07-18 11:42:26 +03:00
87ab3683ad Release 2.1.0 2022-07-02 15:42:39 +03:00
9c2f73af8c simplify tmpdir method 2022-06-28 19:11:38 +03:00
31f551bdf2 review loggers once more
This commit makes loggers like java.util.logging with fully qualified
logger name which is created by LazyLogging trait
2022-06-28 11:00:45 +03:00
cbbe2b01e4 fix case with package name which cannot be downloaded
(without special settings)

The issue appears if file or its version contains one of special URI
characters, e.g. +. Theu will be interpreted as query parameters by
(some) servers (e.g. S3 works in this way). In this commit we rename
archive to the one with safe name.
2022-06-27 18:53:48 +03:00
cd361a483d review loggers once more
This commit makes loggers like java.util.logging with fully qualified
logger name which is created by LazyLogging trait
2022-06-27 01:41:49 +03:00
cee4fd4cce bump web libraries
also encode strings for the views
2022-06-24 12:03:38 +03:00
18daecaac7 review loggers 2022-06-21 11:48:42 +03:00
03c298c762 replace if with while for telelgram reporting 2022-06-10 12:02:00 +03:00
79d4a488a0 Release 2.0.0 2022-06-05 20:46:32 +03:00
22847aac68 small docs update 2022-06-04 15:24:14 +03:00
75b9a96798 do not pass timestamp to pretty_datetime functioon 2022-05-31 21:26:39 +03:00
a0cfb7561d rewrite api under single /api endpoint 2022-05-29 17:15:49 +03:00
f4131b8cd7 add shell and version parser 2022-05-27 18:34:07 +03:00
9f134e37b6 update readme 2022-05-22 16:00:24 +03:00
07b7689701 do not bump timestamp on empty updates 2022-05-21 04:19:04 +03:00
47de715d7d
dynamic html load (#63)
* dynamic html load
* split by classes
2022-05-20 22:29:36 +03:00
5674b7b388 add ability to run only speicifed triggers from command line
This commit also restores repo-report and repo-sync subcommands
2022-05-12 18:43:36 +03:00
f6e57a411c fix case when provided trigger path is directory
If trigger is directory and we have permissions to read it, the loaded
will try to load this from it and will fail with IsADirectoryError
2022-05-12 07:22:50 +03:00
38e48b1571 add not about pacman database update 2022-05-11 04:30:24 +03:00
d492c968ea add contribution guide 2022-05-11 03:17:37 +03:00
a11fd188a2 Release 2.0.0rc11 2022-05-10 06:03:33 +03:00
2431d5de0e fix bug with checking file
The bug appear when the file exists or doesn't, but we don't have
permissions to read it. This one must be treated as missed permission
2022-05-10 06:01:41 +03:00
88f71b240d Release 2.0.0rc10 2022-05-09 21:51:35 +03:00
99874845b5 triggers implementation (#62) 2022-05-09 20:00:20 +03:00
d98cfa3732 Release 2.0.0rc9 2022-05-08 03:58:53 +03:00
b6db2a8035 fix error with missing sources
In case if package has local cache it will fail to load because no
remote source set. Particially this case can be observed during tree
load
2022-05-08 03:56:54 +03:00
47c578ea08 Release 2.0.0rc8 2022-05-06 20:55:54 +03:00
98910240dd shorten public imports 2022-05-06 04:08:05 +03:00
33e9fea47c Docs update (#61)
* Improve sphinx documentation

* update faq formatting

* fix setup doc

* fix docs according to the generated htmls
2022-05-06 02:54:37 +03:00
304690e0d0 correct archllinux wording in readme 2022-05-06 02:54:37 +03:00
3d9fae5415 add __all__ attribute 2022-05-06 02:54:37 +03:00
b7dca2d797 add note about ahriman to index page 2022-05-06 02:54:37 +03:00
b7debddaea
Complete official repository support (#59) 2022-05-03 00:49:32 +03:00
1cfc751d21 rename classes in order to make documentation reference work 2022-04-18 05:30:02 +03:00
6ebbb04504 readthedoc integration 2022-04-18 04:39:40 +03:00
c9ee470ee2 move documentation to tox 2022-04-18 01:48:36 +03:00
a2610504e5 apply data migration in the same transaction block with schema migration 2022-04-18 01:19:38 +03:00
36b8b0f46a fix target naming 2022-04-18 01:19:20 +03:00
d90f417cae
Docstring update (#58)
* migrate docstrings from reST to google format

* add raises note

Also change behaviour of the `from_option` method to fallback to
disabled instead of raising exception on unknown option

* fix part of warnings for sphinx

* make identation a bit more readable

* review fixes

* add verbose description for properties to make them parsed by sphinx extenstion

* add demo sphinx generator
2022-04-17 20:25:28 +03:00
0db619136d Release 2.0.0rc7 2022-04-11 00:48:08 +03:00
208a9b920d docs update 2022-04-11 00:46:46 +03:00
cb63bc08ff add backup and restore subcommands 2022-04-10 21:34:34 +03:00
6551c8d983 merge restore to rebuild commannd 2022-04-10 01:51:12 +03:00
a6c8d64053 Release 2.0.0rc6 2022-04-09 17:34:23 +03:00
fd78f2b5e2 do not render failed packages in jinja (#57)
basic templates require package info which is unavailable if package
wasn't built
2022-04-09 17:31:13 +03:00
900907cdaa Release 2.0.0rc5 2022-04-08 04:42:05 +03:00
5ff2f43506 change telegram default index to telegram-index 2022-04-08 04:32:34 +03:00
dd521b49b5 force git run from the same dir to clone 2022-04-08 04:04:06 +03:00
5b1f5a8473 fix users migration 2022-04-08 03:45:17 +03:00
86af13f09e add telegram integraion 2022-04-08 03:41:07 +03:00
733c014229 Release 2.0.0rc4 2022-04-08 01:14:35 +03:00
783c16b2ed trim versions before dependency list calculation
When dependencies list contains same package with version it tries to
find packages which don't exists
2022-04-07 20:32:55 +03:00
2536b8dc1f add support of repository restoration 2022-04-07 04:49:07 +03:00
e200ac9776 add support of officiall repositories api 2022-04-07 04:19:37 +03:00
6946745153 fix descriptions 2022-04-06 01:48:03 +03:00
6de75377c3 Release 2.0.0rc3 2022-04-04 02:40:17 +03:00
a734b86e66 allow any tag for push 2022-04-04 02:39:56 +03:00
74906d084a Release 2.0.0rc2 2022-04-04 02:27:19 +03:00
22d1d835af change regex for sed 2022-04-04 02:26:42 +03:00
b7cd83502a Release 2.0.0-rc1 2022-04-04 02:18:31 +03:00
2d2cd73010 better processing for subcommands
Old versions cached full output to memory and only after that printed it
into log. This behaviour causes issues in case if operation stucks and
you would need to find the step at which it does. New check_output
method uses Popen directly and iterates over stdout lines

Also changed behaviour from merging stderr into stdout to separate
stderr logging.

Any other behaviour of the function must be the same.

Also changed GPG.key_import method to disable local signing since it
seems it is useless (and may break process in case if there is no
private key)
2022-04-04 00:03:22 +03:00
40b84b810d docs update 2022-04-03 01:44:11 +03:00
7188cfaf78 remove implicit user from docker 2022-04-01 18:39:24 +03:00
e909e4f570
add configurable exit codes to some commands (#55) 2022-04-01 18:30:11 +03:00
06ec16ac77 create user in docker container
also fix user reading and add nocolor flag by default
2022-03-31 03:25:53 +03:00
fed2f3aab8 configure docker to work with tags 2022-03-31 02:19:48 +03:00
2bc2b63a8a add help command 2022-03-31 02:18:39 +03:00
0c5a90cd66 update license years 2022-03-31 01:49:31 +03:00
28cc38aaa5
port part of settings to database (#54) 2022-03-31 01:48:06 +03:00
fb02e676af migrate to tox
this also requires to move default configuration files to share/ahriman.
Thus the following features have been added
* default configuration is not stored in /usr/share/ahriman/settings
* package installed via PKGBUILD now copies files from /usr
* configuration class now fallbacks to default in /usr
2022-03-21 04:38:42 +03:00
13121298f5 deprecate init/repo-init command
In current workflow you need to run setup to run init (because of
repository name), but you need to run init before setup (because of
repository tree rights).

New solution just add `Repo.init()` method call to setup subcommand
after config reload to make sure that repository name has been applied.
In addition chown method as well as setuid method for check_output have
been added.
2022-03-21 01:32:11 +03:00
63e79ec57a enable privileged mode for the docker 2022-03-20 04:05:43 +03:00
b83bc5a732 fallback to AUR source in case of PermissionError exception 2022-03-20 03:46:56 +03:00
8374590b62 add fallback for utf option 2022-03-20 03:16:33 +03:00
4cc665f6ee replace pspec with spec 2022-03-20 03:08:51 +03:00
57f25c309a add console printer
also add python-requests as explicit dependency and escape symbols in
repository name for badges in default tempate
2022-03-20 02:31:50 +03:00
d33844e7b2 ALLOW_AUTO_ARCHITECTURE_RUN flag for unsafe commands 2022-03-19 03:08:45 +03:00
e9886efaa2 docker hub integration 2022-03-14 00:08:21 +03:00
61efbb71a2
add docker support (#52)
* add docker support

* make shellcheck happy
2022-03-13 23:43:25 +03:00
9f4acacada strict test checks 2022-03-04 02:04:52 +03:00
026f74121a set success status on up to date packages 2022-02-06 06:22:58 +03:00
e414616bbd Release 1.8.0 2022-02-06 05:45:50 +03:00
60a2e25b9a update for new aiohttp api 2022-02-06 04:05:33 +03:00
683abca9e5
use own aur wrapper (#49) 2022-02-06 03:44:57 +03:00
5a3770b739 Release 1.7.0 2021-12-26 02:01:09 +03:00
52cd9a0ea9 make mypy happy 2021-12-26 01:58:55 +03:00
bfca7e41ab handle dependencies recursively 2021-12-22 19:35:09 +03:00
603c5449a8
initial implementation of the local git clones (#48) 2021-12-22 15:56:24 +03:00
5aac3db2d5 do not read aur_url from settings, use repository property instead 2021-11-15 11:27:41 +03:00
3c5bcbd172 Release 1.6.4 2021-11-10 21:29:45 +03:00
042638d40e
handle packages which have been removed from the repository (#45)
* handle packages which have been removed from the repository

* manually remove packages which have been removed from the base
2021-11-10 01:37:25 +03:00
e6adb333b2 Release 1.6.3 2021-11-04 21:32:27 +03:00
fa4244d21e take python laziness into account 2021-11-04 21:30:34 +03:00
91de1c2b8a Release 1.6.2 2021-10-28 03:20:52 +03:00
32a4a82603 improve configuration extension
* Allow spaces in lists. This feature has been done in the way as shell
  interprets arguments by using quotation marks
* Clear current content on reload
2021-10-28 03:19:50 +03:00
e8a10c1bb5 add nginx configuration to the faq 2021-10-27 03:35:33 +03:00
d480eb7bc3 Release 1.6.1 2021-10-27 03:16:53 +03:00
8b0f9bfd78 update license headers 2021-10-27 03:14:39 +03:00
a2639f8dbb add update printer which will print current version if any 2021-10-27 03:11:43 +03:00
65ba590ace use PackageSource enum for Package.load method
When using add function it sill tries to load data with invalid source
2021-10-27 02:49:23 +03:00
fcb130e226 Release 1.6.0 2021-10-27 01:59:36 +03:00
ae99fe4535 drop no-quiet option and change tree_create message error to warn 2021-10-27 01:57:54 +03:00
ec23e3f912 remove help sample from readme because it changes faster than om able to maintain it 2021-10-26 04:53:45 +03:00
d3ea81d234 unify aur.search method
due to specific of the AUR API in order to reduce the code we are using
own wrapper and work with it instead of direct library calls
2021-10-26 04:49:55 +03:00
09b0f2914d Add ability to show more info in search and status subcommands
This feature also introduces the followiing changes
* aur-search command now works as expected with multiterms
* printer classes for managing of data print
* --sort-by argument for aur-search subcommand instead of using package
  name
* --quiet argument now has also --no-quite option
* if --quite is supplied, the log level will be set to warn instead of
  critical to be able to see error messages
* pretty_datetime function now also supports datetime objects
* BuildStatus is now pure dataclass
2021-10-26 04:27:36 +03:00
7351e20104 always update environnment before any action 2021-10-24 04:14:57 +03:00
dfd87c502f split application class into traits 2021-10-23 13:44:57 +03:00
0b9ab09879 add patches to clean command 2021-10-20 03:22:16 +03:00
47c54f0b40 add ability to download package from external links (e.g. HTTP) 2021-10-20 03:09:58 +03:00
a2f2fa0354 add ability to read argument list from file 2021-10-20 02:15:59 +03:00
4d68080c05 logger improvements
* remove build log since it has no usages actually (replaced by root
  logger)
* decrease boto3 log levels to INFO by default to reduce noice
2021-10-20 02:12:49 +03:00
eb16ef12f3 always return json in responses 2021-10-20 02:12:39 +03:00
e10e362dae Release 1.5.0 2021-10-18 03:48:24 +03:00
e59fdd1ccc minor architecture description update 2021-10-18 03:35:39 +03:00
22d92e3b4e add repo-status-update subcommand 2021-10-17 06:38:49 +03:00
56b77a84a6 allow to use multiple upload and report targets with the same name
In this feature target option must allways point to section name instead
of type. Type will be read from type option. In case if type option is
not presented it will try to check if section with architecture exists
(e.g. target = email, section = email:x86_64); if it does, the correct
section name and type will be used. Otherwise it will check if the
specified section exists; if it does, seection name and type will be
returned.
2021-10-17 06:06:08 +03:00
a5a99ec0b8 split github upload into generic http method and github specific
We might use some features from the http upload for another parser
2021-10-15 23:36:26 +03:00
04bbabe898 docs update 2021-10-15 04:55:46 +03:00
4521c2adde disallow to create tree in case of unsafe run 2021-10-14 04:53:09 +03:00
5c5e54228f use generic removal method 2021-10-14 04:08:21 +03:00
6514924b2d change method spelling
in order to sort method correctly we are going to use the following
namiing schema:

{subject}_{action}_{details}

This schema still have some exceptions, e.g. single word methods, bool
methods (is_) and getters in case if they are singular (i.e. there is
no any other method with this subject)
2021-10-14 04:01:54 +03:00
16aa977fa8 add test for every file 2021-10-14 03:34:12 +03:00
6e377e7261 aggressive small case 2021-10-14 03:13:15 +03:00
4502931c39 exactly one called with instead of last call check 2021-10-14 03:12:45 +03:00
fcb167b1a3
github upload support (#41) 2021-10-14 02:30:13 +03:00
72b26603bf
add ability to add manually stored packages (#40)
* add ability to add manually stored packages

* update tests

* handle manual packages in remove-unknown method

* live fixes

also rename branches to has_remotes method and change return type
2021-10-12 21:15:35 +03:00
ab8ca16981 improve scripts
move logic to separated shell scripts and also create shell script for
repository setup

Also force create directory according to systemd recommendations
2021-10-11 02:20:16 +03:00
7c4f84fbc7 more verbose help messages 2021-10-07 01:56:22 +03:00
3b6b2efcb1 patch control subcommands 2021-10-05 08:57:42 +03:00
9f99dd3ff2
patch support (#35) 2021-10-03 15:20:36 +03:00
bee97df87f do not write anything on httpexceptions in log 2021-10-03 02:05:28 +03:00
6becd01803 replace no-log with quiet
Also behavior of the flag has been changed: now it disables logs at all
2021-10-03 01:59:33 +03:00
db195391e4 Release 1.4.1 2021-10-03 01:02:41 +03:00
59f2992559 do not use set_defaults for architecture arguments
according to the source code defaults always updates the values
dictionary. This in this specific case it is impossible to override the
value it will be always empty list.

In order to handle it we are adding another property to the Handler
class which allows to run with None architecture list.

This particular set_defaults behaviour is still useful for other cases
when we have to run command without any specific architecture
2021-10-03 00:59:24 +03:00
4f06647193 Release 1.4.0 2021-10-01 09:25:35 +03:00
73a4cee257 add package request endpoint 2021-10-01 08:58:50 +03:00
13d00c6f66 docs update 2021-09-26 14:39:35 +03:00
3e032c3515 add index url 2021-09-26 14:29:42 +03:00
d73d5daad3 add debugtoolbar support 2021-09-26 12:31:12 +03:00
f55b44b391 set both value and innerText during search
current implementation just adds package name with the description which
is incorrect
2021-09-26 10:34:21 +03:00
51b28baf40 add ability to specify package source explicitly during the addition 2021-09-26 09:55:14 +03:00
24326f9753 define permissions in views directly 2021-09-25 17:03:46 +03:00
36c763069d only set file rights if requested 2021-09-23 20:36:22 +03:00
c9a155bbc4 raise httpexception instead of returning it from a function 2021-09-19 14:28:24 +03:00
182bde5e09 add manpage 2021-09-19 13:56:11 +03:00
799572fccf Release 1.3.0 2021-09-18 06:28:52 +03:00
a7a32f0080 better reload 2021-09-17 19:15:53 +03:00
af3afecce8 update aioauth-client to newest version 2021-09-17 18:45:43 +03:00
16bb1403a1 add ability to reload authentication module 2021-09-17 16:05:38 +03:00
41731ca359 add ability to remove an user
also replace old user by new one before creation
2021-09-16 02:41:56 +03:00
e99c2b0c83 remove own implementations of getlist and getpath method in order to use
converters feature
2021-09-14 03:57:20 +03:00
6294c0ba14 add ability to filter status response by package status 2021-09-13 23:27:36 +03:00
2c74be31bd raise InvalidCommand exception in case if remove option supplied without
package
2021-09-13 22:38:38 +03:00
0744ee53dc change spelling for distro name 2021-09-13 02:49:22 +03:00
284fd759bf add target for architecture and also update it 2021-09-13 02:01:48 +03:00
6f5b28c4f8 expiration on server side support (#33) 2021-09-13 01:18:04 +03:00
d211cc17c6 send data in json_responses in case of error instead of text 2021-09-12 22:41:02 +03:00
117e69c906 return description from the search 2021-09-12 22:31:34 +03:00
d19deb57e7
OAuth2 (#32)
* make auth method asyncs

* oauth2 demo support

* full coverage

* update docs
2021-09-12 21:41:38 +03:00
1b29b5773d remove deprecated access status 2021-09-11 23:06:30 +03:00
8e14e8d2cb add error description to modals 2021-09-11 23:05:51 +03:00
875bfc0823 add static files support and cookie expiration settings 2021-09-11 16:34:43 +03:00
7abdb48ac0 documentation update 2021-09-10 03:32:45 +03:00
98eb93c27a
Add ability to trigger updates from the web (#31)
* add external process spawner and update test cases

* pass no_report to handlers

* provide service api endpoints

* do not spawn process for single architecture run

* pass no report to handlers

* make _call method of handlers public and also simplify process spawn

* move update under add

* implement actions from web page

* clear logging & improve l&f
2021-09-10 00:33:35 +03:00
18de70154e add option to set user-password for service when updating its hash 2021-09-05 15:40:03 +03:00
08e0237639 move api endpoints to status-api 2021-09-05 06:46:14 +03:00
891c97b036 allow head for every get request 2021-09-05 06:41:50 +03:00
55c3386812 add repository name to base tempalte 2021-09-05 06:15:24 +03:00
b0575ee4ba allow read only pages to be requested without authorization 2021-09-05 06:09:43 +03:00
e0607ba609 update docs 2021-09-05 05:38:45 +03:00
9b8c9b2b2d
migration of jinja tempaltes to bootstrap (#30) 2021-09-05 05:27:58 +03:00
ecf45bc3bb
add remove uknown method (#29) 2021-09-03 02:28:27 +03:00
aecd679d01 add license header to __init__.py 2021-09-02 23:43:05 +03:00
e63cb509f2
Auth support (#25)
* initial auth implementation

* add create user parser

* add tests

* update dependencies list

* add login annd logout to index also improve auth

* realworld fixes

* add method set_option to Configuration and also use it everywhere
* split CreateUser handler to additional read method
* check user duplicate on auth mapping read
* generate salt by using passlib instead of random.choice
* case-insensetive usernames
* update dependencies
* update configuration reference
* improve tests

* fix codefactor errors

* hide fields if authorization is enabled, but no auth supplied

* add settings object for auth provider

* readme update
2021-09-02 23:36:00 +03:00
3922c55464 use {} instead of dict literal according to pylint recommendation 2021-08-22 13:24:42 +03:00
9d2a3bcbc1 Release 1.2.6 2021-08-21 16:19:21 +03:00
a5455b697d Release 1.2.5 2021-08-19 02:36:05 +03:00
0bfb763b2a disable manpages building for now since it requires installed distribution 2021-08-19 02:35:48 +03:00
9f3566a150 Release 1.2.4 2021-08-19 00:45:58 +03:00
16a6c4fdd7 include setup.cfg to tarball 2021-08-19 00:45:26 +03:00
91f66fdcee Release 1.2.3 2021-08-19 00:18:12 +03:00
bb45b1d868 split S3.sync to different methods 2021-08-18 23:59:18 +03:00
3d10fa472b guess mime type for local files 2021-08-18 05:04:26 +03:00
a90c93bbc4 add manpage generator 2021-08-17 04:05:18 +03:00
41a3c08d9f Release 1.2.2 2021-08-17 01:03:04 +03:00
cb328ad797 fix typo in log naming 2021-08-17 01:02:42 +03:00
810091cde9 Release 1.2.1 2021-08-17 00:52:09 +03:00
fc0474fa8f logging rethink
* well lets replace f-strings by %s as it is originally recommended
* use syslog handler by default
2021-08-17 00:23:34 +03:00
b94179e071 use asyncmock from unittest library 2021-08-11 21:09:10 +03:00
9c5a9f5837 Release 1.2.0 2021-08-11 05:02:23 +03:00
83047d8270 cleanup and speedup runs 2021-08-11 04:59:45 +03:00
990d5dda81 use nosec instead of disabling mktemp rule 2021-08-11 02:51:29 +03:00
48e79ce39c add bandit integration and fix its warnings 2021-08-11 02:45:13 +03:00
375d7c55e5 web templates improvements
* enable jinja autoescape by default for jinja raw generator
* allow to search by multiple strings (OR)
* replace test templates by symlink
2021-08-11 02:12:14 +03:00
db52b8e844 move web server to loopback by default 2021-08-11 02:02:18 +03:00
50af309c80 add docstrings for every fixture and test methods
also add tests for missing components
2021-08-11 01:55:27 +03:00
581401d60f skip update process if no update supplied 2021-08-10 23:25:12 +03:00
c2685f4746
Native s3 sync (#23)
* Native S3 sync implementation

* fix imports

* fix paths reading

* install s3 components duriing test stage
2021-08-10 23:18:56 +03:00
952b55f707 Release 1.1.0 2021-07-05 22:11:14 +03:00
b9b012be53 handle provides list 2021-07-05 22:08:04 +03:00
b8036649ab install types for mypy 2021-06-28 02:54:20 +03:00
c90e20587e remove type: ignore for newest python 2021-06-28 02:32:54 +03:00
3e020ec141
Feature/all archs (#21)
* add init subcommand

* add also init command to repository object

* add ability to generate list of architectures

* check if architecture list is not empty
2021-05-23 16:40:40 +03:00
783b7d043d
imply no-log for every unsafe parser (#20) 2021-05-19 23:30:59 +03:00
5c297d1c67 allow to specify list of package dependencies in rebuild target
also replace nargs= by action=append in non-positional args. It is
required to make arguments parsing result more predictable and
consistent
2021-04-18 13:34:27 +03:00
b0d1f3c091 Release 1.0.0 2021-04-10 01:38:55 +03:00
50e219fda5
import pgp key implementation (#17)
* import pgp key implementation

* do not ask confirmation for local sign. Also add argparser test

* superseed requests by python-aur package

* ...and drop --skippgpcheck makgepkg flag by default
2021-04-10 01:37:45 +03:00
75298d1b8a better naming for actions 2021-04-09 20:02:17 +03:00
8196dcc8a0
add search subparser (#15) 2021-04-09 11:57:06 +03:00
f634f1df58
Add web status route (#13)
* add status route

* typed status and get status at the start of application
2021-04-08 01:48:53 +03:00
32df4fc54f
Move search line inside extended report option 2021-04-06 17:03:34 +03:00
11ae930c59 Release 0.22.1 2021-04-06 05:54:04 +03:00
9c332c23d2 format long line 2021-04-06 05:53:38 +03:00
4ed0a49a44 add ability to skip email report generation for empty update list 2021-04-06 05:51:50 +03:00
50f532a48a Release 0.22.0 2021-04-06 05:46:12 +03:00
c6ccf53768
Email report (#11)
* Demo email report implementation

* improved ssl mode

* correct default option spelling and more fields to be hidden for not
extended reports
2021-04-06 05:45:17 +03:00
ce0c07cbd9 Release 0.21.4 2021-04-05 02:28:38 +03:00
912a76d5cb drop changelog
the main reason is that it uses github to generate changelog. Thus it
will be updated AFTER release is created
2021-04-05 02:27:12 +03:00
76d0b0bc6d Release 0.21.3 2021-04-05 02:22:44 +03:00
27d018e721 update changelog at correct step
also fix commit filter and do not update sha anymore
2021-04-05 02:22:11 +03:00
a0e20ffb77 Release 0.21.2 2021-04-05 02:01:28 +03:00
96e4abc3c0 add changelog generator to both gh-actions and repository 2021-04-05 02:00:05 +03:00
6df60498aa Release 0.21.1 2021-04-05 00:45:12 +03:00
eb0a4b6b4a use globing instead 2021-04-05 00:44:39 +03:00
8f469e7eac Release 0.21.0 2021-04-05 00:38:23 +03:00
535e955814 try to make auto archive upload 2021-04-05 00:37:03 +03:00
0bd3ba626a implicit type conversion from command line 2021-04-04 23:53:30 +03:00
ffe6aec190 more options in setup command 2021-04-04 15:42:06 +03:00
56c600e5ac fix check errors 2021-04-04 14:00:42 +03:00
461883217d 100% coverage 2021-04-03 21:30:57 +03:00
62d55eff19 add ability to fitler by dependency list 2021-04-02 04:20:39 +03:00
534b5600b4 add ability to remove package from status page 2021-04-02 01:26:46 +03:00
32cbafd12b Release 0.20.0 2021-04-01 02:38:59 +03:00
880c70bd58 constistent classmethod and staticmethod usage
General idea is to use classmethod for every constructor and
statismethod otherwise.
Also use self and cls whenever it's possible to call static and class
methods
2021-03-31 04:29:08 +03:00
d449eb3c2e change arch specific section naming from section_arch to section:arch
Some archs can have _ in their name. Also in future we can use sections
with similar names
2021-03-31 02:31:14 +03:00
17b5cd0751 Release 0.19.0 2021-03-31 02:19:44 +03:00
2aef906fc8 add now argument to add command 2021-03-31 02:19:13 +03:00
e034327501 filter out every foreign arch in config 2021-03-31 01:55:39 +03:00
5d79fcca22 read sign targets from correct path 2021-03-31 00:11:05 +03:00
6e9dcca254 make configuration object arch-specific 2021-03-31 00:04:13 +03:00
fbf6748d4a more verbose variables 2021-03-30 05:29:13 +03:00
2260e52d5c merge settings groups instead of using whole group 2021-03-30 04:58:15 +03:00
bd2b61494f move rsync and s3 options to configuration 2021-03-30 02:38:18 +03:00
7280d30748 verbose help message 2021-03-30 02:25:23 +03:00
710274065d
add status badge 2021-03-30 02:01:59 +03:00
e0b09cefad rename gpg test to correct naming 2021-03-30 01:53:23 +03:00
3b93510aad add more tests 2021-03-30 01:42:01 +03:00
5003cabeb5 Release 0.18.0 2021-03-29 11:48:54 +03:00
bc6af9256b more properties to be shown in status pages 2021-03-29 11:48:32 +03:00
1ac7c87317 architecture depending pacman.conf 2021-03-29 10:08:11 +03:00
803b7bee1e add status update subcommand
also satisfy pylint with too big method with too much variables
2021-03-29 04:17:10 +03:00
646190121a Release 0.17.0 2021-03-29 03:25:43 +03:00
10e4f3b629
Setup command (#9)
* block issues without templates

* add setup subcommand

* handle devtools config correctly
2021-03-29 03:24:58 +03:00
80a1f37c85 more templates 2021-03-29 00:13:20 +03:00
751676a07e Add issue templates 2021-03-28 23:50:41 +03:00
e1a7071ce5 try to integrate with github workflows 2021-03-28 23:13:42 +03:00
1605d185e2 remove unused import 2021-03-28 16:24:51 +03:00
2fdf910e78
add sign command (#7) (#8) 2021-03-28 16:24:00 +03:00
63dc43366b Release 0.16.0 2021-03-28 15:38:12 +03:00
74a244f06c
Add tests (#1) (#5)
* add models tests (#1)

also replace single quote to double one to confort PEP docstring
+ move _check_output to class properties to make it available for
mocking

* alpm tests implementation

* try to replace os with pathlib

* update tests for pathlib

* fix includes glob and trim version from dependencies

* build_tools package tests

* repository component tests

* add sign tests

* complete status tests

* handle exceptions in actual_version calls

* complete core tests

* move configuration to root conftest

* application tests

* complete application tests

* change copyright to more generic one

* base web tests

* complete web tests

* complete testkit

also add argument parsers test
2021-03-28 15:30:51 +03:00
608 changed files with 58607 additions and 3812 deletions

1
.bandit-test.yml Normal file
View File

@ -0,0 +1 @@
skips: ['B101', 'B104', 'B105', 'B106', 'B404']

1
.bandit.yml Normal file
View File

@ -0,0 +1 @@
skips: ['B404', 'B603']

14
.dockerignore Normal file
View File

@ -0,0 +1,14 @@
.eggs/
.git/
.github/
.idea/
.mypy_cache/
.pytest_cache/
.tox/
.venv/
*.egg-info/
__pycache__/
*.pyc
*.pyd
*.pyo

28
.github/ISSUE_TEMPLATE/01-bug-report.md vendored Normal file
View File

@ -0,0 +1,28 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
## Summary
A clear and concise description of what the bug is.
### Steps to reproduce
Steps to reproduce the behavior (commands, environment etc).
### Expected behavior
A clear and concise description of what you expected to happen.
### Logs
Add logs to help explain your problem. By default, the application writes logs into `/dev/log` which is usually default systemd journal and can be accessed by `journalctl` command.
You can also attach any additional information which can be helpful, e.g. configuration used by the application (be aware of passwords and other secrets if any); it can be generated by using `ahriman config` command.
It is also sometimes useful to have information about installed packages which can be accessed by `ahriman version` command.

View File

@ -0,0 +1,20 @@
---
name: Security report
about: Create a report related to security issues
title: ''
labels: security
assignees: ''
---
## Summary
A clear and concise description of what the issue is.
### Steps to reproduce
Steps to reproduce the behavior (commands, environment etc).
### Intended impact
Brief optional description of how this vulnerability can be used and which effects can be achieved.

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
## Feature summary
Brief description of the feature required
### Cause of the feature request
A clear and concise description of what the problem is. E.g. I'm always frustrated when [...]
### Proposed changes and/or features
A clear and concise description of what you want to happen.

12
.github/ISSUE_TEMPLATE/04-discussion.md vendored Normal file
View File

@ -0,0 +1,12 @@
---
name: Question
about: Create an issue to get help with project
title: ''
labels: question
assignees: ''
---
## Describe your question below
A clear and concise description of your issue for which you would like to get help.

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1 @@
blank_issues_enabled: false

13
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,13 @@
## Summary
Brief description of the pull request. Try to provide clear explanation for major changes.
Please make sure that branch called either `feature/feature-name` for feature-related pull requests or `bug/bug-name` for bug-related ones.
Put `closes #ISSUE` in case if the pull requests solves one of the opened issues.
### Checklist
- [ ] Tests to cover new code
- [ ] `make check` passed
- [ ] `make tests` passed

42
.github/workflows/docker-image.yml vendored Normal file
View File

@ -0,0 +1,42 @@
name: docker image
on:
push:
branches: [ master ]
tags:
- '*'
- '!*rc*'
jobs:
docker-image:
runs-on: ubuntu-latest
steps:
- name: extract docker metadata
id: meta
uses: docker/metadata-action@v3
with:
images: |
arcan1s/ahriman
tags: |
type=ref,event=tag
type=edge
- name: setup QEMU
uses: docker/setup-qemu-action@v1
- name: setup docker buildx
uses: docker/setup-buildx-action@v1
- name: login to docker hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: build an image and push
uses: docker/build-push-action@v2
with:
push: true
tags: ${{ steps.meta.outputs.tags }}

41
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,41 @@
name: release
on:
push:
tags:
- '*'
jobs:
make-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: extract version
id: version
run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/}
- name: create changelog
id: changelog
uses: jaywcjlove/changelog-generator@main
with:
token: ${{ secrets.GITHUB_TOKEN }}
filter: 'Release \d+\.\d+\.\d+'
- name: create archive
run: make archive
env:
VERSION: ${{ steps.version.outputs.VERSION }}
- name: release
uses: softprops/action-gh-release@v1
with:
body: |
${{ steps.changelog.outputs.compareurl }}
${{ steps.changelog.outputs.changelog }}
files: ahriman-*-src.tar.xz
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

40
.github/workflows/run-setup.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: setup
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
run-setup-minimal:
runs-on: ubuntu-latest
container:
image: archlinux:latest
volumes:
- ${{ github.workspace }}:/build
options: --privileged -w /build
steps:
- uses: actions/checkout@v2
- name: setup the minimal service in arch linux container
run: .github/workflows/setup.sh minimal
run-setup:
runs-on: ubuntu-latest
container:
image: archlinux:latest
volumes:
- ${{ github.workspace }}:/build
options: --privileged -w /build
steps:
- uses: actions/checkout@v2
- name: setup the service in arch linux container
run: .github/workflows/setup.sh

24
.github/workflows/run-tests.yml vendored Normal file
View File

@ -0,0 +1,24 @@
name: tests
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
run-tests:
runs-on: ubuntu-latest
container:
image: archlinux:latest
volumes:
- ${{ github.workspace }}:/build
options: -w /build
steps:
- uses: actions/checkout@v2
- name: run check and tests in arch linux container
run: .github/workflows/tests.sh

57
.github/workflows/setup.sh vendored Executable file
View File

@ -0,0 +1,57 @@
#!/bin/bash
# Install the package and run main install commands
set -ex
[[ $1 = "minimal" ]] && MINIMAL_INSTALL=1
# install dependencies
echo -e '[arcanisrepo]\nServer = http://repo.arcanis.me/$arch\nSigLevel = Never' | tee -a /etc/pacman.conf
# refresh the image
pacman --noconfirm -Syu
# main dependencies
pacman --noconfirm -Sy base-devel devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo python-systemd sudo
# make dependencies
pacman --noconfirm -Sy python-build python-flit python-installer python-wheel
# optional dependencies
if [[ -z $MINIMAL_INSTALL ]]; then
# VCS support
pacman --noconfirm -Sy breezy darcs mercurial subversion
# web server
pacman --noconfirm -Sy python-aioauth-client python-aiohttp python-aiohttp-apispec-git python-aiohttp-cors python-aiohttp-debugtoolbar python-aiohttp-jinja2 python-aiohttp-security python-aiohttp-session python-cryptography python-jinja
# additional features
pacman --noconfirm -Sy gnupg python-boto3 rsync
fi
# create fresh tarball
make VERSION=1.0.0 archlinux # well, it does not really matter which version we will put here
# run makepkg
mv ahriman-*-src.tar.xz package/archlinux
chmod +777 package/archlinux # because fuck you that's why
cd package/archlinux
sudo -u nobody -- makepkg -cf --skipchecksums --noconfirm
pacman --noconfirm -U ahriman-1.0.0-1-any.pkg.tar.zst
# create machine-id which is required by build tools
systemd-machine-id-setup
# initial setup command as root
[[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080")
ahriman -a x86_64 service-setup --packager "ahriman bot <ahriman@example.com>" --repository "github" "${WEB_ARGS[@]}"
# validate configuration
ahriman -a x86_64 service-config-validate --exit-code
# enable services
systemctl enable ahriman-web@x86_64
systemctl enable ahriman@x86_64.timer
if [[ -z $MINIMAL_INSTALL ]]; then
# run web service (detached)
sudo -u ahriman -- ahriman -a x86_64 web &
WEB_PID=$!
fi
# add the first package
sudo -u ahriman -- ahriman package-add --now yay
# check if package was actually installed
test -n "$(find "/var/lib/ahriman/repository/x86_64" -name "yay*pkg*")"
# run package check
sudo -u ahriman -- ahriman repo-update
# stop web service lol
[[ -z $WEB_PID ]] || kill $WEB_PID

10
.github/workflows/tests.sh vendored Executable file
View File

@ -0,0 +1,10 @@
#!/bin/bash
# Install dependencies and run test in container
set -ex
# install dependencies
pacman --noconfirm -Syu base-devel python-setuptools python-tox
# run test and check targets
make check tests

5
.gitignore vendored
View File

@ -94,3 +94,8 @@ ENV/
.venv/
*.tar.xz
status_cache.json
*.db
docs/html/

873
.pylintrc
View File

@ -1,27 +1,77 @@
[MASTER]
[MAIN]
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
# Clear in-memory caches upon conclusion of linting. Useful if running pylint
# in a server-like mode.
clear-cache-post-run=no
# Load and enable all available extensions. Use --list-extensions to see a list
# all available extensions.
#enable-all-extensions=
# In error mode, messages with a category besides ERROR or FATAL are
# suppressed, and no reports are done by default. Error mode is compatible with
# disabling specific errors.
#errors-only=
# Always return a 0 (non-error) status code, even if lint errors are found.
# This is primarily useful in continuous integration scripts.
#exit-zero=
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code.
extension-pkg-allow-list=
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code. (This is an alternative name to extension-pkg-allow-list
# for backward compatibility.)
extension-pkg-whitelist=
# Specify a score threshold to be exceeded before program exits with error.
fail-under=10.0
# Return non-zero exit code if any of these messages/categories are detected,
# even if score is above --fail-under value. Syntax same as enable. Messages
# specified are enabled, while categories only check already-enabled messages.
fail-on=
# Add files or directories to the blacklist. They should be base names, not
# paths.
# Specify a score threshold under which the program will exit with error.
fail-under=10
# Interpret the stdin as a python script, whose filename needs to be passed as
# the module_or_package argument.
#from-stdin=
# Files or directories to be skipped. They should be base names, not paths.
ignore=CVS
# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=
# Add files or directories matching the regular expressions patterns to the
# ignore-list. The regex matches against paths and can be in Posix or Windows
# format. Because '\\' represents the directory delimiter on Windows systems,
# it can't be used as an escape character.
ignore-paths=
# Files or directories matching the regular expression patterns are skipped.
# The regex matches against base names, not paths. The default value ignores
# Emacs file locks
ignore-patterns=^\.#
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis). It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
# number of processors available to use.
# number of processors available to use, and will cap the count on Windows to
# avoid hangs.
jobs=1
# Control the amount of potential inferred values when inferring a single
@ -36,6 +86,19 @@ load-plugins=
# Pickle collected data for later comparisons.
persistent=yes
# Minimum Python version to use for version dependent checks. Will default to
# the version used to run pylint.
py-version=3.11
# Discover python modules and packages in the file system subtree.
recursive=no
# Add paths to the list of the source roots. Supports globbing patterns. The
# source root is an absolute path or a path relative to the current working
# directory used to determine a package namespace for modules located under the
# source root.
source-roots=
# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode=yes
@ -44,191 +107,8 @@ suggestion-mode=yes
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
confidence=
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once). You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=print-statement,
parameter-unpacking,
unpacking-in-except,
old-raise-syntax,
backtick,
long-suffix,
old-ne-operator,
old-octal-literal,
import-star-module-level,
non-ascii-bytes-literal,
raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-symbolic-message-instead,
apply-builtin,
basestring-builtin,
buffer-builtin,
cmp-builtin,
coerce-builtin,
execfile-builtin,
file-builtin,
long-builtin,
raw_input-builtin,
reduce-builtin,
standarderror-builtin,
unicode-builtin,
xrange-builtin,
coerce-method,
delslice-method,
getslice-method,
setslice-method,
no-absolute-import,
old-division,
dict-iter-method,
dict-view-method,
next-method-called,
metaclass-assignment,
indexing-exception,
raising-string,
reload-builtin,
oct-method,
hex-method,
nonzero-method,
cmp-method,
input-builtin,
round-builtin,
intern-builtin,
unichr-builtin,
map-builtin-not-iterating,
zip-builtin-not-iterating,
range-builtin-not-iterating,
filter-builtin-not-iterating,
using-cmp-argument,
eq-without-hash,
div-method,
idiv-method,
rdiv-method,
exception-message-attribute,
invalid-str-codec,
sys-max-int,
bad-python3-import,
deprecated-string-function,
deprecated-str-translate-call,
deprecated-itertools-function,
deprecated-types-field,
next-method-defined,
dict-items-not-iterating,
dict-keys-not-iterating,
dict-values-not-iterating,
deprecated-operator-function,
deprecated-urllib-function,
xreadlines-attribute,
deprecated-sys-function,
exception-escape,
comprehension-escape,
missing-module-docstring,
line-too-long,
no-name-in-module,
import-outside-toplevel,
invalid-name,
raise-missing-from,
wrong-import-order,
too-few-public-methods,
too-many-instance-attributes,
broad-except,
logging-fstring-interpolation,
too-many-ancestors,
fixme,
too-many-arguments,
duplicate-code,
cyclic-import
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=c-extension-no-member
[REPORTS]
# Python expression which should return a score less than or equal to 10. You
# have access to the variables 'error', 'warning', 'refactor', and 'convention'
# which contain the number of messages in each category, as well as 'statement'
# which is the total number of statements analyzed. This score is used by the
# global evaluation report (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details.
#msg-template=
# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio). You can also give a reporter class, e.g.
# mypackage.mymodule.MyReporterClass.
output-format=text
# Tells whether to display a full report or only the messages.
reports=no
# Activate the evaluation score.
score=yes
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=sys.exit
[FORMAT]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=100
# Maximum number of lines in a module.
max-module-lines=1000
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
# In verbose mode, extra non-checker-related info will be displayed.
#verbose=
[BASIC]
@ -237,13 +117,15 @@ single-line-if-stmt=no
argument-naming-style=snake_case
# Regular expression matching correct argument names. Overrides argument-
# naming-style.
# naming-style. If left empty, argument names will be checked with the set
# naming style.
#argument-rgx=
# Naming style matching correct attribute names.
attr-naming-style=snake_case
# Regular expression matching correct attribute names. Overrides attr-naming-
# style. If left empty, attribute names will be checked with the set naming
# style.
#attr-rgx=
@ -263,20 +145,30 @@ bad-names-rgxs=
class-attribute-naming-style=any
# Regular expression matching correct class attribute names. Overrides class-
# attribute-naming-style.
# attribute-naming-style. If left empty, class attribute names will be checked
# with the set naming style.
#class-attribute-rgx=
# Naming style matching correct class constant names.
class-const-naming-style=UPPER_CASE
# Regular expression matching correct class constant names. Overrides class-
# const-naming-style. If left empty, class constant names will be checked with
# the set naming style.
#class-const-rgx=
# Naming style matching correct class names.
class-naming-style=PascalCase
# Regular expression matching correct class names. Overrides class-naming-
# style.
# style. If left empty, class names will be checked with the set naming style.
#class-rgx=
# Naming style matching correct constant names.
const-naming-style=UPPER_CASE
# Regular expression matching correct constant names. Overrides const-naming-
# style. If left empty, constant names will be checked with the set naming
# style.
#const-rgx=
@ -288,7 +180,8 @@ docstring-min-length=-1
function-naming-style=snake_case
# Regular expression matching correct function names. Overrides function-
# naming-style.
# naming-style. If left empty, function names will be checked with the set
# naming style.
#function-rgx=
# Good variable names which should always be accepted, separated by a comma.
@ -310,21 +203,22 @@ include-naming-hint=no
inlinevar-naming-style=any
# Regular expression matching correct inline iteration names. Overrides
# inlinevar-naming-style.
# inlinevar-naming-style. If left empty, inline iteration names will be checked
# with the set naming style.
#inlinevar-rgx=
# Naming style matching correct method names.
method-naming-style=snake_case
# Regular expression matching correct method names. Overrides method-naming-
# style.
# style. If left empty, method names will be checked with the set naming style.
#method-rgx=
# Naming style matching correct module names.
module-naming-style=snake_case
# Regular expression matching correct module names. Overrides module-naming-
# style.
# style. If left empty, module names will be checked with the set naming style.
#module-rgx=
# Colon-delimited sets of names that determine each other's naming style when
@ -340,209 +234,56 @@ no-docstring-rgx=^_
# These decorators are taken in consideration only for invalid-name.
property-classes=abc.abstractproperty
# Regular expression matching correct type alias names. If left empty, type
# alias names will be checked with the set naming style.
#typealias-rgx=
# Regular expression matching correct type variable names. If left empty, type
# variable names will be checked with the set naming style.
#typevar-rgx=
# Naming style matching correct variable names.
variable-naming-style=snake_case
# Regular expression matching correct variable names. Overrides variable-
# naming-style.
# naming-style. If left empty, variable names will be checked with the set
# naming style.
#variable-rgx=
[TYPECHECK]
[CLASSES]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# Warn about protected attribute access inside special methods
check-protected-access-in-special-methods=no
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
__new__,
setUp,
asyncSetUp,
__post_init__
# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,_fields,_replace,_source,_make,os._exit
# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
ignore-none=yes
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local
# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis). It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
# List of decorators that change the signature of a decorated function.
signature-mutators=
[SIMILARITIES]
# Ignore comments when computing similarities.
ignore-comments=yes
# Ignore docstrings when computing similarities.
ignore-docstrings=yes
# Ignore imports when computing similarities.
ignore-imports=no
# Minimum lines number of a similarity.
min-similarity-lines=4
[LOGGING]
# The type of string formatting that logging methods do. `old` means using %
# formatting, `new` is for `{}` formatting.
logging-format-style=old
# Logging modules to check that the string format arguments are in logging
# function parameter format.
logging-modules=logging
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
XXX,
TODO
# Regular expression of note tags to take in consideration.
#notes-rgx=
[SPELLING]
# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions=4
# Spelling dictionary name. Available dictionaries: none. To make it work,
# install the python-enchant package.
spelling-dict=
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains the private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to the private dictionary (see the
# --spelling-private-dict-file option) instead of raising a message.
spelling-store-unknown-words=no
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.
additional-builtins=
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,
_cb
# A regular expression matching the name of dummy variables (i.e. expected to
# not be used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
# Argument names that match this expression will be ignored. Default to name
# with leading underscore.
ignored-argument-names=_.*|^ignored_|^unused_
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
[STRING]
# This flag controls whether inconsistent-quotes generates a warning when the
# character used as a quote delimiter is used inconsistently within a module.
check-quote-consistency=no
# This flag controls whether the implicit-str-concat should generate a warning
# on implicit string concatenation in sequences defined over several lines.
check-str-concat-over-line-jumps=no
[IMPORTS]
# List of modules that can be imported at any level, not just the top level
# one.
allow-any-import-level=
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no
# Deprecated modules which should not be used, separated by a comma.
deprecated-modules=optparse,tkinter.tix
# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled).
ext-import-graph=
# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled).
import-graph=
# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled).
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
# Couples of modules and preferred modules, separated by a comma.
preferred-modules=
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=mcs
[DESIGN]
# List of regular expressions of class ancestor names to ignore when counting
# public methods (see R0903)
exclude-too-few-public-methods=
# List of qualified class names to ignore when counting class parents (see
# R0901)
ignored-parents=
# Maximum number of arguments for function / method.
max-args=5
@ -574,35 +315,331 @@ max-statements=50
min-public-methods=2
[CLASSES]
# Warn about protected attribute access inside special methods
check-protected-access-in-special-methods=no
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
__new__,
setUp,
__post_init__
# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,
_fields,
_replace,
_source,
_make
# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls
# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=cls
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to
# "BaseException, Exception".
overgeneral-exceptions=BaseException,
Exception
# Exceptions that will emit a warning when caught.
overgeneral-exceptions=builtins.BaseException,builtins.Exception
[FORMAT]
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=
# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
# Number of spaces of indent required inside a hanging or continued line.
indent-after-paren=4
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
# tab).
indent-string=' '
# Maximum number of characters on a single line.
max-line-length=100
# Maximum number of lines in a module.
max-module-lines=1000
# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no
# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no
[IMPORTS]
# List of modules that can be imported at any level, not just the top level
# one.
allow-any-import-level=
# Allow explicit reexports by alias from a package __init__.
allow-reexport-from-package=no
# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no
# Deprecated modules which should not be used, separated by a comma.
deprecated-modules=
# Output a graph (.gv or any supported image format) of external dependencies
# to the given file (report RP0402 must not be disabled).
ext-import-graph=
# Output a graph (.gv or any supported image format) of all (i.e. internal and
# external) dependencies to the given file (report RP0402 must not be
# disabled).
import-graph=
# Output a graph (.gv or any supported image format) of internal dependencies
# to the given file (report RP0402 must not be disabled).
int-import-graph=
# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=
# Force import order to recognize a module as part of a third party library.
known-third-party=enchant
# Couples of modules and preferred modules, separated by a comma.
preferred-modules=
[LOGGING]
# The type of string formatting that logging methods do. `old` means using %
# formatting, `new` is for `{}` formatting.
logging-format-style=old
# Logging modules to check that the string format arguments are in logging
# function parameter format.
logging-modules=logging
[MESSAGES CONTROL]
# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
# UNDEFINED.
confidence=HIGH,
CONTROL_FLOW,
INFERENCE,
INFERENCE_FAILURE,
UNDEFINED
# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once). You can also use "--disable=all" to
# disable everything first and then re-enable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=raw-checker-failed,
bad-inline-option,
locally-disabled,
file-ignored,
suppressed-message,
useless-suppression,
deprecated-pragma,
use-symbolic-message-instead,
missing-module-docstring,
line-too-long,
no-name-in-module,
import-outside-toplevel,
invalid-name,
raise-missing-from,
wrong-import-order,
too-few-public-methods,
too-many-instance-attributes,
broad-except,
fixme,
too-many-arguments,
duplicate-code,
cyclic-import,
# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=c-extension-no-member
[METHOD_ARGS]
# List of qualified names (i.e., library.method) which require a timeout
# parameter e.g. 'requests.api.get,requests.api.post'
timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
XXX,
TODO
# Regular expression of note tags to take in consideration.
notes-rgx=
[REFACTORING]
# Maximum number of nested blocks for function / method body
max-nested-blocks=5
# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=sys.exit,argparse.parse_error
[REPORTS]
# Python expression which should return a score less than or equal to 10. You
# have access to the variables 'fatal', 'error', 'warning', 'refactor',
# 'convention', and 'info' which contain the number of messages in each
# category, as well as 'statement' which is the total number of statements
# analyzed. This score is used by the global evaluation report (RP0004).
evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details.
msg-template=
# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio). You can also give a reporter class, e.g.
# mypackage.mymodule.MyReporterClass.
#output-format=
# Tells whether to display a full report or only the messages.
reports=no
# Activate the evaluation score.
score=yes
[SIMILARITIES]
# Comments are removed from the similarity computation
ignore-comments=yes
# Docstrings are removed from the similarity computation
ignore-docstrings=yes
# Imports are removed from the similarity computation
ignore-imports=yes
# Signatures are removed from the similarity computation
ignore-signatures=yes
# Minimum lines number of a similarity.
min-similarity-lines=4
[SPELLING]
# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions=4
# Spelling dictionary name. No available dictionaries : You need to install
# both the python package and the system dependency for enchant to work..
spelling-dict=
# List of comma separated words that should be considered directives if they
# appear at the beginning of a comment and should not be checked.
spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
# List of comma separated words that should not be checked.
spelling-ignore-words=
# A path to a file that contains the private dictionary; one word per line.
spelling-private-dict-file=
# Tells whether to store unknown words to the private dictionary (see the
# --spelling-private-dict-file option) instead of raising a message.
spelling-store-unknown-words=no
[STRING]
# This flag controls whether inconsistent-quotes generates a warning when the
# character used as a quote delimiter is used inconsistently within a module.
check-quote-consistency=no
# This flag controls whether the implicit-str-concat should generate a warning
# on implicit string concatenation in sequences defined over several lines.
check-str-concat-over-line-jumps=no
[TYPECHECK]
# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=
# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
ignore-none=yes
# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes
# List of symbolic message names to ignore for Mixin members.
ignored-checks-for-mixins=no-member,
not-async-context-manager,
not-context-manager,
attribute-defined-outside-init
# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local,argparse.Namespace
# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes
# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1
# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1
# Regex pattern to define which classes are considered mixins.
mixin-class-rgx=.*[Mm]ixin
# List of decorators that change the signature of a decorated function.
signature-mutators=
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid defining new builtins when possible.
additional-builtins=
# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes
# List of names allowed to shadow builtins
allowed-redefined-builtins=
# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,
_cb
# A regular expression matching the name of dummy variables (i.e. expected to
# not be used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
# Argument names that match this expression will be ignored.
ignored-argument-names=_.*|^ignored_|^unused_
# Tells whether we should check for unused import in __init__ files.
init-import=no
# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io

23
.readthedocs.yaml Normal file
View File

@ -0,0 +1,23 @@
version: 2
formats:
- pdf
build:
os: ubuntu-20.04
tools:
python: "3.11"
sphinx:
builder: html
configuration: docs/conf.py
fail_on_warning: true
python:
install:
- method: pip
path: .
extra_requirements:
- docs
- s3
- web

2
AUTHORS Normal file
View File

@ -0,0 +1,2 @@
Current maintainer:
Evgenii Alekseev <esalexeev (at) gmail (dot) com>

View File

@ -1,85 +0,0 @@
# ahriman configuration
Some groups can be specified for each architecture separately. E.g. if there are `build` and `build_x86_64` groups it will use the `build_x86_64` for the `x86_64` architecture and `build` for any other (architecture specific group has higher priority).
## `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.
## `alpm` group
libalpm and AUR related configuration.
* `aur_url` - base url for AUR, string, required.
* `database` - path to pacman local database cache, string, required.
* `repositories` - list of pacman repositories, space separated list of strings, required.
* `root` - root for alpm library, string, required.
## `build_*` groups
Build related configuration. Group name must refer to architecture, e.g. it should be `build_x86_64` for x86_64 architecture.
* `archbuild_flags` - additional flags passed to `archbuild` command, space separated list of strings, optional.
* `build_command` - default build command, string, required.
* `ignore_packages` - list packages to ignore during a regular update (manual update will still work), space separated list of strings, optional.
* `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_*` groups
Settings for signing packages or repository. Group name must refer to architecture, e.g. it should be `sign_x86_64` for x86_64 architecture.
* `target` - configuration flag to enable signing, space separated list of strings, required. Allowed values are `package` (sign each package separately), `repository` (sign repository database file).
* `key` - default PGP key, string, required. This key will also be used for database signing if enabled.
* `key_*` settings - PGP key which will be used for specific packages, string, optional. For example, if there is `key_yay` option the specified key will be used for yay package and default key for others.
## `report` group
Report generation settings.
* `target` - list of reports to be generated, space separated list of strings, optional. Allowed values are `html`.
### `html_*` groups
Group name must refer to architecture, e.g. it should be `html_x86_64` for x86_64 architecture.
* `path` - path to html report file, string, required.
* `homepage` - link to homepage, string, optional.
* `link_path` - prefix for HTML links, string, required.
* `template_path` - path to Jinja2 template, 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`.
### `rsync_*` groups
Group name must refer to architecture, e.g. it should be `rsync_x86_64` for x86_64 architecture. 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.
### `s3_*` groups
Group name must refer to architecture, e.g. it should be `s3_x86_64` for x86_64 architecture. 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.
## `web_*` groups
Web server settings. If any of `host`/`port` is not set, web integration will be disabled. Group name must refer to architecture, e.g. it should be `web_x86_64` for x86_64 architecture.
* `host` - host to bind, string, optional.
* `port` - port to bind, int, optional.
* `templates` - path to templates directory, string, required.

219
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,219 @@
# Contributing to ahriman
Welcome to ahriman! The goal of the project is to provide the best user experience to manage Arch linux repositories. In order to follow this we set some limitations for the issue creations and heavily restricted code contribution.
## Create an issue
Basically just follow the suggested templates:
* Bug report requires at least the way to reproduce the issue and behaviour description (expected and actual ones). In order to resolve the bug, the additional questions may be asked, please consider them as lesser evil.
* Feature requests basically just require feature description and the purpose why do you want this feature to be implemented. It is required to make sure that the feature you want is going to be implemented in the way you really want it (and to make sure that this feature is not already implemented).
* Questions and discussions have free templates, and you are free to ask your question in the way you want.
## Code contribution
There are some strict limitation for suggested pull requests:
* `autopep8`, `bandit`, `pylint`, `mypy` must pass.
* Test coverage must remain 100%.
### Code formatting
In order to resolve all difficult cases the `autopep8` is used. You can perform formatting at any time by running `make check` or running `autopep8` command directly.
### Code style
Again, the most checks can be performed by `make check` command, though some additional guidelines must be applied:
* Every class, every function (including private and protected), every attribute must be documented. The project follows [Google style documentation](https://google.github.io/styleguide/pyguide.html). The only exception is local functions.
* Correct way to document function, if section is empty, e.g. no notes or there are no args, it should be omitted:
```python
def foo(argument: str, *, flag: bool = False) -> int:
"""
do foo. With very very very long
docstring
Notes:
Very important note about this function
Args:
argument(str): an argument. This argument has
long description also
flag(bool, optional): a flag (Default value = False)
Returns:
int: result
Raises:
RuntimeError: a local function error occurs
Examples:
Very informative example how to use this function, e.g.::
>>> foo("argument", flag=False)
Note that function documentation is in rST.
"""
```
`Returns` should be replaced with `Yields` for generators.
Class attributes should be documented in the following way:
```python
class Clazz(BaseClazz):
"""
brand-new implementation of ``BaseClazz``
Attributes:
CLAZZ_ATTRIBUTE(int): (class attribute) a brand-new class attribute
instance_attribute(str): an instance attribute
Examples:
Very informative class usage example, e.g.::
>>> from module import Clazz
>>> clazz = Clazz()
"""
CLAZZ_ATTRIBUTE = 42
def __init__(self, *args: Any, **kwargs: Any) -> None:
"""
default constructor
Args:
*args(Any): positional arguments
**kwargs(Any): keyword arguments
"""
self.instance_attribute = ""
```
* Type annotations are the must, even for local functions. For the function argument `self` (for instance methods) and `cls` (for class methods) should not be annotated.
* For collection types built-in classes must be used if possible (e.g. `dict` instead of `typing.Dict`, `tuple` instead of `typing.Tuple`). In case if built-in type is not available, but `collections.abc` provides interface, it must be used (e.g. `collections.abc.Awaitable` instead of `typing.Awaitable`, `collections.abc.Iterable` instead of `typing.Iterable`). For union classes, the bar operator (`|`) must be used (e.g. `float | int` instead of `typing.Union[float, int]`), which also includes `typinng.Optional` (e.g. `str | None` instead of `Optional[str]`).
* `classmethod` should always return `Self`. In case of mypy warning (e.g. if there is a branch in which function doesn't return the instance of `cls`) consider using `staticmethod` instead.
* Recommended order of function definitions in class:
```python
class Clazz:
def __init__(self) -> None: ... # replace with `__post_init__` for dataclasses
@property
def property(self) -> Any: ...
@cached_property
def property_cached(self) -> Any: ... # cached property has to be treated as normal one
@classmethod
def class_method(cls) -> Self: ...
@staticmethod
def static_method() -> Any: ...
def __private_method(self) -> Any: ...
def _protected_method(self) -> Any: ...
def usual_method(self) -> Any: ...
def __hash__(self) -> int: ... # basically any magic (or look-alike) method
```
Methods inside one group should be ordered alphabetically, the only exception is `__init__` method (`__post__init__` for dataclasses) which should be defined first. For test methods it is recommended to follow the order in which functions are defined.
Though, we would like to highlight abstract methods (i.e. ones which raise `NotImplementedError`), we still keep in global order at the moment.
* Abstract methods must raise `NotImplementedError` instead of using `abc.abstractmethod`. The reason behind this restriction is the fact that we have class/static abstract methods for those we need to define their attribute first making the code harder to read.
* For any path interactions `pathlib.Path` must be used.
* Configuration interactions must go through `ahriman.core.configuration.Configuration` class instance.
* In case if class load requires some actions, it is recommended to create class method which can be used for class instantiating.
* The code must follow the exception safety, unless it is explicitly asked by end user. It means that most exceptions must be handled and printed to log, no other actions must be done (e.g. raising another exception).
* Exceptions without parameters should be raised without parentheses, e.g.:
```python
raise RuntimeError
```
* For the external command `ahriman.core.util.check_output` function must be used.
* Every temporary file/directory must be removed at the end of processing, no matter what. The `tempfile` module provides good ways to do it.
* Import order must be the following:
```python
# optional imports from future module
from __future__ import annotations
# Module import for those which are installed into environment (no matter standard library or not)...
import os
# ...one per line...
import pyalpm
# ...in alphabetical order
import sys
# Blank line between
# ``from module import submodule`` import
from pathlib import Path
# ...again in alphabet order. It is possible to do several imports, but make sure that they are also in alphabetical order.
from pyalpm import Handle, Package
# Blank line again and package imports
from ahriman.core.configuration import Configuration
```
* One file should define only one class, exception is class satellites in case if file length remains less than 400 lines.
* It is possible to create file which contains some functions (e.g. `ahriman.core.util`), but in this case you would need to define `__all__` attribute.
* The file size mentioned above must be applicable in general. In case of big classes consider splitting them into traits. Note, however, that `pylint` includes comments and docstrings into counter, thus you need to check file size by other tools.
* No global variable is allowed outside of `ahriman` module. `ahriman.core.context` is also special case.
* Single quotes are not allowed. The reason behind this restriction is the fact that docstrings must be written by using double quotes only, and we would like to make style consistent.
* If your class writes anything to log, the `ahriman.core.log.LazyLogging` trait must be used.
* Web API methods must be documented by using `aiohttp_apispec` library. Schema testing mostly should be implemented in related view class tests. Recommended example for documentation (excluding comments):
```python
import aiohttp_apispec
from marshmallow import Schema, fields
from ahriman.web.schemas.auth_schema import AuthSchema
from ahriman.web.schemas.error_schema import ErrorSchema
from ahriman.web.schemas.package_name_schema import PackageNameSchema
from ahriman.web.views.base import BaseView
class RequestSchema(Schema):
field = fields.String(metadata={"description": "Field description", "example": "foo"})
class ResponseSchema(Schema):
field = fields.String(required=True, metadata={"description": "Field description"})
class Foo(BaseView):
POST_PERMISSION = ...
@aiohttp_apispec.docs(
tags=["Tag"],
summary="Do foo",
description="Extended description of the method which does foo",
responses={
200: {"description": "Success response", "schema": ResponseSchema},
204: {"description": "Success response"}, # example without json schema response
400: {"description": "Bad data is supplied", "schema": ErrorSchema}, # exception raised by this method
401: {"description": "Authorization required", "schema": ErrorSchema}, # should be always presented
403: {"description": "Access is forbidden", "schema": ErrorSchema}, # should be always presented
500: {"description": "Internal server error", "schema": ErrorSchema}, # should be always presented
},
security=[{"token": [POST_PERMISSION]}],
)
@aiohttp_apispec.cookies_schema(AuthSchema) # should be always presented
@aiohttp_apispec.match_info_schema(PackageNameSchema)
@aiohttp_apispec.json_schema(RequestSchema(many=True))
async def post(self) -> None: ...
```
### Other checks
The projects also uses typing checks (provided by `mypy`) and some linter checks provided by `pylint` and `bandit`. Those checks must be passed successfully for any open pull requests.

59
Dockerfile Normal file
View File

@ -0,0 +1,59 @@
FROM archlinux:base
# image configuration
ENV AHRIMAN_ARCHITECTURE="x86_64"
ENV AHRIMAN_DEBUG=""
ENV AHRIMAN_FORCE_ROOT=""
ENV AHRIMAN_HOST="0.0.0.0"
ENV AHRIMAN_MULTILIB="yes"
ENV AHRIMAN_OUTPUT=""
ENV AHRIMAN_PACKAGER="ahriman bot <ahriman@example.com>"
ENV AHRIMAN_PACMAN_MIRROR=""
ENV AHRIMAN_PORT=""
ENV AHRIMAN_REPOSITORY="aur-clone"
ENV AHRIMAN_REPOSITORY_SERVER=""
ENV AHRIMAN_REPOSITORY_ROOT="/var/lib/ahriman/ahriman"
ENV AHRIMAN_UNIX_SOCKET=""
ENV AHRIMAN_USER="ahriman"
ENV AHRIMAN_VALIDATE_CONFIGURATION="yes"
# install environment
## update pacman.conf with multilib
RUN echo "[multilib]" >> "/etc/pacman.conf" && \
echo "Include = /etc/pacman.d/mirrorlist" >> "/etc/pacman.conf"
## install minimal required packages
RUN pacman --noconfirm -Syu binutils fakeroot git make sudo
## create build user
RUN useradd -m -d "/home/build" -s "/usr/bin/nologin" build && \
echo "build ALL=(ALL) NOPASSWD: ALL" > "/etc/sudoers.d/build"
COPY "docker/install-aur-package.sh" "/usr/local/bin/install-aur-package"
## install package dependencies
## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size
RUN pacman -Sy --noconfirm --asdeps devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo && \
pacman -Sy --noconfirm --asdeps python-build python-flit python-installer python-wheel && \
pacman -Sy --noconfirm --asdeps breezy mercurial python-aiohttp python-aiohttp-cors python-boto3 python-cryptography python-jinja python-requests-unixsocket python-systemd rsync subversion && \
runuser -u build -- install-aur-package python-aioauth-client python-aiohttp-apispec-git python-aiohttp-jinja2 \
python-aiohttp-debugtoolbar python-aiohttp-session python-aiohttp-security
# install ahriman
## copy tree
COPY --chown=build . "/home/build/ahriman"
## create package archive and install it
RUN cd "/home/build/ahriman" && \
make VERSION=$(python -c "from src.ahriman import __version__; print(__version__)") archlinux && \
cp ./*-src.tar.xz "package/archlinux" && \
cd "package/archlinux" && \
runuser -u build -- makepkg --noconfirm --install --skipchecksums && \
cd / && rm -r "/home/build/ahriman"
# cleanup unused
RUN find "/var/cache/pacman/pkg" -type f -delete
RUN pacman -Qdtq | pacman -Rscn --noconfirm -
VOLUME ["/var/lib/ahriman"]
# minimal runtime ahriman setup
COPY "docker/entrypoint.sh" "/usr/local/bin/entrypoint"
ENTRYPOINT ["entrypoint"]
# default command
CMD ["repo-update", "--refresh"]

View File

@ -1,9 +1,9 @@
.PHONY: archive archive_directory archlinux check clean directory push version
.PHONY: archive archlinux check clean directory html push specification tests version
.DEFAULT_GOAL := archlinux
PROJECT := ahriman
FILES := COPYING CONFIGURING.md README.md package src setup.py
FILES := AUTHORS CONTRIBUTING.md COPYING Makefile README.md SECURITY.md docs package pyproject.toml src tox.ini web.png
TARGET_FILES := $(addprefix $(PROJECT)/, $(FILES))
IGNORE_FILES := package/archlinux src/.mypy_cache
@ -16,35 +16,44 @@ archive: archive_directory
archive_directory: $(TARGET_FILES)
rm -fr $(addprefix $(PROJECT)/, $(IGNORE_FILES))
find $(PROJECT) -type f -name '*.pyc' -delete
find $(PROJECT) -depth -type d -name '__pycache__' -execdir rm -rf {} +
find $(PROJECT) -depth -type d -name '*.egg-info' -execdir rm -rf {} +
find "$(PROJECT)" -type f -name "*.pyc" -delete
find "$(PROJECT)" -depth -type d -name "__pycache__" -execdir rm -rf {} +
find "$(PROJECT)" -depth -type d -name "*.egg-info" -execdir rm -rf {} +
archlinux: archive
sed -i "/sha512sums=('[0-9A-Fa-f]*/s/[^'][^)]*/sha512sums=('$$(sha512sum $(PROJECT)-$(VERSION)-src.tar.xz | awk '{print $$1}')'/" package/archlinux/PKGBUILD
sed -i "s/pkgver=[0-9.]*/pkgver=$(VERSION)/" package/archlinux/PKGBUILD
sed -i "s/pkgver=.*/pkgver=$(VERSION)/" package/archlinux/PKGBUILD
check:
cd src && mypy --implicit-reexport --strict -p $(PROJECT)
cd src && find $(PROJECT) -name '*.py' -execdir autopep8 --max-line-length 120 -aa -i {} +
cd src && pylint --rcfile=../.pylintrc $(PROJECT)
check: clean
tox -e check
clean:
find . -type f -name '$(PROJECT)-*-src.tar.xz' -delete
find . -type f -name "$(PROJECT)-*-src.tar.xz" -delete
rm -rf "$(PROJECT)"
directory: clean
mkdir "$(PROJECT)"
push: archlinux
git add package/archlinux/PKGBUILD src/ahriman/version.py
html: specification
rm -rf docs/html
tox -e docs-html
push: specification archlinux
git add package/archlinux/PKGBUILD src/ahriman/__init__.py docs/ahriman-architecture.svg package/share/man/man1/ahriman.1 package/share/bash-completion/completions/_ahriman package/share/zsh/site-functions/_ahriman
git commit -m "Release $(VERSION)"
git push
git tag "$(VERSION)"
git push
git push --tags
specification:
# make sure that old files are removed
find docs -type f -name "$(PROJECT)*.rst" -delete
tox -e docs
tests: clean
tox -e tests
version:
ifndef VERSION
$(error VERSION is required, but not set)
endif
sed -i "/__version__ = '[0-9.]*/s/[^'][^)]*/__version__ = '$(VERSION)'/" src/ahriman/version.py
sed -i 's/^__version__ = .*/__version__ = "$(VERSION)"/' src/ahriman/__init__.py

View File

@ -1,68 +1,42 @@
# ArcHlinux ReposItory MANager
# ArcH linux ReposItory MANager
[![tests status](https://github.com/arcan1s/ahriman/actions/workflows/run-tests.yml/badge.svg)](https://github.com/arcan1s/ahriman/actions/workflows/run-tests.yml)
[![setup status](https://github.com/arcan1s/ahriman/actions/workflows/run-setup.yml/badge.svg)](https://github.com/arcan1s/ahriman/actions/workflows/run-setup.yml)
[![Docker Image Version (latest semver)](https://img.shields.io/docker/v/arcan1s/ahriman?label=docker%20image)](https://hub.docker.com/r/arcan1s/ahriman)
[![CodeFactor](https://www.codefactor.io/repository/github/arcan1s/ahriman/badge)](https://www.codefactor.io/repository/github/arcan1s/ahriman)
[![Documentation Status](https://readthedocs.org/projects/ahriman/badge/?version=latest)](https://ahriman.readthedocs.io/?badge=latest)
Wrapper for managing custom repository inspired by [repo-scripts](https://github.com/arcan1s/repo-scripts).
## Features
* Install-configure-forget manager for own repository
* Multi-architecture support
* VCS packages support
* Sign support with gpg (repository, package, per package settings)
* Synchronization to remote services (rsync, s3) and report generation (html)
* Dependency manager
* Repository status interface
* Install-configure-forget manager for the very own repository.
* Multi-architecture support.
* Dependency manager.
* VCS packages support.
* Official repository support.
* Ability to patch AUR packages and even create package from local PKGBUILDs.
* Various rebuild options with ability to automatically bump package version.
* Sign support with gpg (repository, package), multiple packagers support.
* Triggers for repository updates, e.g. synchronization to remote services (rsync, s3 and github) and report generation (email, html, telegram).
* Repository status interface with optional authorization and control options:
![web interface](web.png)
## Installation and run
* Install package as usual.
* Change settings if required, see [CONFIGURING](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`):
For installation details kindly refer to the [documentation](https://ahriman.readthedocs.io/en/latest/setup.html). For application commands it is possible to get information by using `--help`/`help` command or by using man page ([web version](https://ahriman.readthedocs.io/en/latest/command-line.html)).
```shell
echo 'PACKAGES="John Doe <john@doe.com>"' | sudo -u ahriman tee -a /var/lib/ahriman/.makepkg.conf
```
## Configuration
* Configure build tools (it is required for correct dependency management system):
Every available option is described in the [documentation](https://ahriman.readthedocs.io/en/latest/configuration.html).
* 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`);
* change configuration file, add your own repository, add multilib repository etc. Hint: you can use `Include` option as well;
* set `build_command` option to point to your command;
* configure `/etc/sudoers.d/ahriman` to allow running command without a password.
The application provides reasonable defaults which allow to use it out-of-box; however additional steps (like configuring build toolchain and sudoers) are recommended and can be easily achieved by following install instructions.
```shell
ln -s /usr/bin/archbuild /usr/local/bin/ahriman-x86_64-build
cp /usr/share/devtools/pacman-{extra,ahriman}.conf
## [FAQ](https://ahriman.readthedocs.io/en/latest/faq.html)
echo '[multilib]' | tee -a /usr/share/devtools/pacman-ahriman.conf
echo 'Include = /etc/pacman.d/mirrorlist' | tee -a /usr/share/devtools/pacman-ahriman.conf
## Live demos
echo '[aur-clone]' | tee -a /usr/share/devtools/pacman-ahriman.conf
echo 'SigLevel = Optional TrustAll' | tee -a /usr/share/devtools/pacman-ahriman.conf
echo 'Server = file:///var/lib/ahriman/repository/$arch' | tee -a /usr/share/devtools/pacman-ahriman.conf
echo '[build]' | tee -a /etc/ahriman.ini.d/build.ini
echo 'build_command = ahriman-x86_64-build' | tee -a /etc/ahriman.ini.d/build.ini
echo 'Cmnd_Alias CARCHBUILD_CMD = /usr/local/bin/ahriman-x86_64-build *' | tee -a /etc/sudoers.d/ahriman
echo 'ahriman ALL=(ALL) NOPASSWD: CARCHBUILD_CMD' | tee -a /etc/sudoers.d/ahriman
chmod 400 /etc/sudoers.d/ahriman
```
* Start and enable `ahriman@.timer` via `systemctl`:
```shell
systemctl enable --now ahriman@x86_64.timer
```
* Start and enable status page:
```shell
systemctl enable --now ahriman-web@x86_64
```
* Add packages by using `ahriman add {package}` command:
```shell
sudo -u ahriman ahriman -a x86_64 add yay
```
* [Build status page](https://ahriman-demo.arcanis.me). You can log in as `demo` user by using `demo` password. However, you will not be able to run tasks. [HTTP API documentation](https://ahriman-demo.arcanis.me/api-docs) is also available.
* [Repository index](http://repo.arcanis.me/x86_64/index.html).
* [Telegram feed](https://t.me/arcanisrepo).

9
SECURITY.md Normal file
View File

@ -0,0 +1,9 @@
# Security Policy
## Supported Versions
The project follows bleeding edge philosophy, thus only the latest version is supported with the exception for release candidates (i.e. tags which are marked with `rc` suffix).
## Reporting a Vulnerability
In the most cases you can report (suspected) security vulnerabilities directly on github by using ["Security report" template](https://github.com/arcan1s/ahriman/issues/new?assignees=&labels=security&template=02-security-report.md&title=). However, if your report could lead to data leak or break the system we kindly ask you to contact [current maintainer](AUTHORS) directly by email.

69
docker/entrypoint.sh Executable file
View File

@ -0,0 +1,69 @@
#!/bin/bash
set -e
[ -n "$AHRIMAN_DEBUG" ] && set -x
# configuration tune
cat <<EOF > "/etc/ahriman.ini.d/00-docker.ini"
[repository]
root = $AHRIMAN_REPOSITORY_ROOT
[settings]
database = $AHRIMAN_REPOSITORY_ROOT/ahriman.db
[web]
host = $AHRIMAN_HOST
EOF
AHRIMAN_DEFAULT_ARGS=("--architecture" "$AHRIMAN_ARCHITECTURE")
if [ -n "$AHRIMAN_OUTPUT" ]; then
AHRIMAN_DEFAULT_ARGS+=("--log-handler" "$AHRIMAN_OUTPUT")
fi
# create repository root inside the [[mounted]] directory and set correct ownership
[ -d "$AHRIMAN_REPOSITORY_ROOT" ] || mkdir "$AHRIMAN_REPOSITORY_ROOT"
chown "$AHRIMAN_USER":"$AHRIMAN_USER" "$AHRIMAN_REPOSITORY_ROOT"
# create .gnupg directory which is required for keys
AHRIMAN_GNUPG_HOME="$(getent passwd "$AHRIMAN_USER" | cut -d : -f 6)/.gnupg"
[ -d "$AHRIMAN_GNUPG_HOME" ] || mkdir -m700 "$AHRIMAN_GNUPG_HOME"
chown "$AHRIMAN_USER":"$AHRIMAN_USER" "$AHRIMAN_GNUPG_HOME"
# run built-in setup command
AHRIMAN_SETUP_ARGS=("--build-as-user" "$AHRIMAN_USER")
AHRIMAN_SETUP_ARGS+=("--packager" "$AHRIMAN_PACKAGER")
AHRIMAN_SETUP_ARGS+=("--repository" "$AHRIMAN_REPOSITORY")
if [ -z "$AHRIMAN_MULTILIB" ]; then
AHRIMAN_SETUP_ARGS+=("--no-multilib")
fi
if [ -n "$AHRIMAN_PACMAN_MIRROR" ]; then
AHRIMAN_SETUP_ARGS+=("--mirror" "$AHRIMAN_PACMAN_MIRROR")
fi
if [ -n "$AHRIMAN_PORT" ]; then
AHRIMAN_SETUP_ARGS+=("--web-port" "$AHRIMAN_PORT")
fi
if [ -n "$AHRIMAN_REPOSITORY_SERVER" ]; then
AHRIMAN_SETUP_ARGS+=("--server" "$AHRIMAN_REPOSITORY_SERVER")
fi
if [ -n "$AHRIMAN_UNIX_SOCKET" ]; then
AHRIMAN_SETUP_ARGS+=("--web-unix-socket" "$AHRIMAN_UNIX_SOCKET")
fi
ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" service-setup "${AHRIMAN_SETUP_ARGS[@]}"
# validate configuration if set
[ -n "$AHRIMAN_VALIDATE_CONFIGURATION" ] && ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" service-config-validate --exit-code
# create machine-id which is required by build tools
systemd-machine-id-setup &> /dev/null
# if AHRIMAN_FORCE_ROOT is set or command is unsafe we can run without sudo
# otherwise we prepend executable by sudo command
if [ -n "$AHRIMAN_FORCE_ROOT" ]; then
AHRIMAN_EXECUTABLE=("ahriman")
elif ahriman help-commands-unsafe -- "$@" &> /dev/null; then
AHRIMAN_EXECUTABLE=("sudo" "-E" "-u" "$AHRIMAN_USER" "--" "ahriman")
else
AHRIMAN_EXECUTABLE=("ahriman")
fi
exec "${AHRIMAN_EXECUTABLE[@]}" "${AHRIMAN_DEFAULT_ARGS[@]}" "$@"

12
docker/install-aur-package.sh Executable file
View File

@ -0,0 +1,12 @@
#!/bin/bash
set -e
for PACKAGE in "$@"; do
BUILD_DIR="$(mktemp -d)"
git clone https://aur.archlinux.org/"$PACKAGE".git "$BUILD_DIR"
cd "$BUILD_DIR"
makepkg --noconfirm --install --rmdeps --syncdeps
cd /
rm -r "$BUILD_DIR"
done

42
docs/advanced-usage.rst Normal file
View File

@ -0,0 +1,42 @@
Advanced usage
==============
Depending on the goal the package can be used in different ways. Nevertheless, in the most cases you will need some basic classes
.. code-block:: python
from pathlib import Path
from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
architecture = "x86_64"
configuration = Configuration.from_path(Path("/etc/ahriman.ini"), architecture)
database = SQLite.load(configuration)
At this point there are ``configuration`` and ``database`` instances which can be used later at any time anywhere, e.g.
.. code-block:: python
# instance of ``RepositoryPaths`` class
paths = configuration.repository_paths
Almost all actions are wrapped by ``ahriman.core.repository.Repository`` class
.. code-block:: python
from ahriman.core.repository import Repository
repository = Repository(architecture, configuration, database, report=True, unsafe=False)
And the ``repository`` instance can be used to perform repository maintenance
.. code-block:: python
build_result = repository.process_build(known_packages)
built_packages = repository.packages_built()
update_result = repository.process_update(built_packages)
repository.triggers.on_result(update_result, repository.packages())
For the more info please refer to the classes documentation.

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 839 KiB

View File

@ -0,0 +1,45 @@
ahriman.application.application package
=======================================
Submodules
----------
ahriman.application.application.application module
--------------------------------------------------
.. automodule:: ahriman.application.application.application
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.application.application\_packages module
------------------------------------------------------------
.. automodule:: ahriman.application.application.application_packages
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.application.application\_properties module
--------------------------------------------------------------
.. automodule:: ahriman.application.application.application_properties
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.application.application\_repository module
--------------------------------------------------------------
.. automodule:: ahriman.application.application.application_repository
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.application.application
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,237 @@
ahriman.application.handlers package
====================================
Submodules
----------
ahriman.application.handlers.add module
---------------------------------------
.. automodule:: ahriman.application.handlers.add
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.backup module
------------------------------------------
.. automodule:: ahriman.application.handlers.backup
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.clean module
-----------------------------------------
.. automodule:: ahriman.application.handlers.clean
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.daemon module
------------------------------------------
.. automodule:: ahriman.application.handlers.daemon
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.dump module
----------------------------------------
.. automodule:: ahriman.application.handlers.dump
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.handler module
-------------------------------------------
.. automodule:: ahriman.application.handlers.handler
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.help module
----------------------------------------
.. automodule:: ahriman.application.handlers.help
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.key\_import module
-----------------------------------------------
.. automodule:: ahriman.application.handlers.key_import
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.patch module
-----------------------------------------
.. automodule:: ahriman.application.handlers.patch
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.rebuild module
-------------------------------------------
.. automodule:: ahriman.application.handlers.rebuild
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.remove module
------------------------------------------
.. automodule:: ahriman.application.handlers.remove
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.remove\_unknown module
---------------------------------------------------
.. automodule:: ahriman.application.handlers.remove_unknown
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.restore module
-------------------------------------------
.. automodule:: ahriman.application.handlers.restore
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.search module
------------------------------------------
.. automodule:: ahriman.application.handlers.search
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.service\_updates module
----------------------------------------------------
.. automodule:: ahriman.application.handlers.service_updates
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.setup module
-----------------------------------------
.. automodule:: ahriman.application.handlers.setup
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.shell module
-----------------------------------------
.. automodule:: ahriman.application.handlers.shell
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.sign module
----------------------------------------
.. automodule:: ahriman.application.handlers.sign
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.status module
------------------------------------------
.. automodule:: ahriman.application.handlers.status
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.status\_update module
--------------------------------------------------
.. automodule:: ahriman.application.handlers.status_update
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.structure module
---------------------------------------------
.. automodule:: ahriman.application.handlers.structure
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.triggers module
--------------------------------------------
.. automodule:: ahriman.application.handlers.triggers
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.unsafe\_commands module
----------------------------------------------------
.. automodule:: ahriman.application.handlers.unsafe_commands
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.update module
------------------------------------------
.. automodule:: ahriman.application.handlers.update
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.users module
-----------------------------------------
.. automodule:: ahriman.application.handlers.users
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.validate module
--------------------------------------------
.. automodule:: ahriman.application.handlers.validate
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.versions module
--------------------------------------------
.. automodule:: ahriman.application.handlers.versions
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.web module
---------------------------------------
.. automodule:: ahriman.application.handlers.web
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.application.handlers
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,38 @@
ahriman.application package
===========================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.application.application
ahriman.application.handlers
Submodules
----------
ahriman.application.ahriman module
----------------------------------
.. automodule:: ahriman.application.ahriman
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.lock module
-------------------------------
.. automodule:: ahriman.application.lock
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.application
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,45 @@
ahriman.core.alpm.remote package
================================
Submodules
----------
ahriman.core.alpm.remote.aur module
-----------------------------------
.. automodule:: ahriman.core.alpm.remote.aur
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.alpm.remote.official module
----------------------------------------
.. automodule:: ahriman.core.alpm.remote.official
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.alpm.remote.official\_syncdb module
------------------------------------------------
.. automodule:: ahriman.core.alpm.remote.official_syncdb
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.alpm.remote.remote module
--------------------------------------
.. automodule:: ahriman.core.alpm.remote.remote
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.alpm.remote
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,37 @@
ahriman.core.alpm package
=========================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.core.alpm.remote
Submodules
----------
ahriman.core.alpm.pacman module
-------------------------------
.. automodule:: ahriman.core.alpm.pacman
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.alpm.repo module
-----------------------------
.. automodule:: ahriman.core.alpm.repo
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.alpm
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,45 @@
ahriman.core.auth package
=========================
Submodules
----------
ahriman.core.auth.auth module
-----------------------------
.. automodule:: ahriman.core.auth.auth
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.auth.helpers module
--------------------------------
.. automodule:: ahriman.core.auth.helpers
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.auth.mapping module
--------------------------------
.. automodule:: ahriman.core.auth.mapping
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.auth.oauth module
------------------------------
.. automodule:: ahriman.core.auth.oauth
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.auth
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,29 @@
ahriman.core.build\_tools package
=================================
Submodules
----------
ahriman.core.build\_tools.sources module
----------------------------------------
.. automodule:: ahriman.core.build_tools.sources
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.build\_tools.task module
-------------------------------------
.. automodule:: ahriman.core.build_tools.task
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.build_tools
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,45 @@
ahriman.core.configuration package
==================================
Submodules
----------
ahriman.core.configuration.configuration module
-----------------------------------------------
.. automodule:: ahriman.core.configuration.configuration
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.configuration.schema module
----------------------------------------
.. automodule:: ahriman.core.configuration.schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.configuration.shell\_interpolator module
-----------------------------------------------------
.. automodule:: ahriman.core.configuration.shell_interpolator
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.configuration.validator module
-------------------------------------------
.. automodule:: ahriman.core.configuration.validator
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.configuration
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,101 @@
ahriman.core.database.migrations package
========================================
Submodules
----------
ahriman.core.database.migrations.m000\_initial module
-----------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m000_initial
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.migrations.m001\_package\_source module
-------------------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m001_package_source
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.migrations.m002\_user\_access module
----------------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m002_user_access
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.migrations.m003\_patch\_variables module
--------------------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m003_patch_variables
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.migrations.m004\_logs module
--------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m004_logs
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.migrations.m005\_make\_opt\_depends module
----------------------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m005_make_opt_depends
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.migrations.m006\_packages\_architecture\_required module
------------------------------------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m006_packages_architecture_required
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.migrations.m007\_check\_depends module
------------------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m007_check_depends
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.migrations.m008\_packagers module
-------------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m008_packagers
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.migrations.m009\_local\_source module
-----------------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m009_local_source
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.migrations.m010\_version\_based\_logs\_removal module
---------------------------------------------------------------------------
.. automodule:: ahriman.core.database.migrations.m010_version_based_logs_removal
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.database.migrations
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,61 @@
ahriman.core.database.operations package
========================================
Submodules
----------
ahriman.core.database.operations.auth\_operations module
--------------------------------------------------------
.. automodule:: ahriman.core.database.operations.auth_operations
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.operations.build\_operations module
---------------------------------------------------------
.. automodule:: ahriman.core.database.operations.build_operations
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.operations.logs\_operations module
--------------------------------------------------------
.. automodule:: ahriman.core.database.operations.logs_operations
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.operations.operations module
--------------------------------------------------
.. automodule:: ahriman.core.database.operations.operations
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.operations.package\_operations module
-----------------------------------------------------------
.. automodule:: ahriman.core.database.operations.package_operations
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.database.operations.patch\_operations module
---------------------------------------------------------
.. automodule:: ahriman.core.database.operations.patch_operations
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.database.operations
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,30 @@
ahriman.core.database package
=============================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.core.database.migrations
ahriman.core.database.operations
Submodules
----------
ahriman.core.database.sqlite module
-----------------------------------
.. automodule:: ahriman.core.database.sqlite
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.database
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,125 @@
ahriman.core.formatters package
===============================
Submodules
----------
ahriman.core.formatters.aur\_printer module
-------------------------------------------
.. automodule:: ahriman.core.formatters.aur_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.build\_printer module
---------------------------------------------
.. automodule:: ahriman.core.formatters.build_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.configuration\_paths\_printer module
------------------------------------------------------------
.. automodule:: ahriman.core.formatters.configuration_paths_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.configuration\_printer module
-----------------------------------------------------
.. automodule:: ahriman.core.formatters.configuration_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.package\_printer module
-----------------------------------------------
.. automodule:: ahriman.core.formatters.package_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.patch\_printer module
---------------------------------------------
.. automodule:: ahriman.core.formatters.patch_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.printer module
--------------------------------------
.. automodule:: ahriman.core.formatters.printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.status\_printer module
----------------------------------------------
.. automodule:: ahriman.core.formatters.status_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.string\_printer module
----------------------------------------------
.. automodule:: ahriman.core.formatters.string_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.tree\_printer module
--------------------------------------------
.. automodule:: ahriman.core.formatters.tree_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.update\_printer module
----------------------------------------------
.. automodule:: ahriman.core.formatters.update_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.user\_printer module
--------------------------------------------
.. automodule:: ahriman.core.formatters.user_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.validation\_printer module
--------------------------------------------------
.. automodule:: ahriman.core.formatters.validation_printer
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.formatters.version\_printer module
-----------------------------------------------
.. automodule:: ahriman.core.formatters.version_printer
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.formatters
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,45 @@
ahriman.core.gitremote package
==============================
Submodules
----------
ahriman.core.gitremote.remote\_pull module
------------------------------------------
.. automodule:: ahriman.core.gitremote.remote_pull
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.gitremote.remote\_pull\_trigger module
---------------------------------------------------
.. automodule:: ahriman.core.gitremote.remote_pull_trigger
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.gitremote.remote\_push module
------------------------------------------
.. automodule:: ahriman.core.gitremote.remote_push
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.gitremote.remote\_push\_trigger module
---------------------------------------------------
.. automodule:: ahriman.core.gitremote.remote_push_trigger
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.gitremote
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,21 @@
ahriman.core.http package
=========================
Submodules
----------
ahriman.core.http.sync\_http\_client module
-------------------------------------------
.. automodule:: ahriman.core.http.sync_http_client
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.http
:members:
:no-undoc-members:
:show-inheritance:

53
docs/ahriman.core.log.rst Normal file
View File

@ -0,0 +1,53 @@
ahriman.core.log package
========================
Submodules
----------
ahriman.core.log.filtered\_access\_logger module
------------------------------------------------
.. automodule:: ahriman.core.log.filtered_access_logger
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.log.http\_log\_handler module
------------------------------------------
.. automodule:: ahriman.core.log.http_log_handler
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.log.journal\_handler module
----------------------------------------
.. automodule:: ahriman.core.log.journal_handler
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.log.lazy\_logging module
-------------------------------------
.. automodule:: ahriman.core.log.lazy_logging
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.log.log module
---------------------------
.. automodule:: ahriman.core.log.log
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.log
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,77 @@
ahriman.core.report package
===========================
Submodules
----------
ahriman.core.report.console module
----------------------------------
.. automodule:: ahriman.core.report.console
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.report.email module
--------------------------------
.. automodule:: ahriman.core.report.email
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.report.html module
-------------------------------
.. automodule:: ahriman.core.report.html
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.report.jinja\_template module
------------------------------------------
.. automodule:: ahriman.core.report.jinja_template
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.report.remote\_call module
---------------------------------------
.. automodule:: ahriman.core.report.remote_call
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.report.report module
---------------------------------
.. automodule:: ahriman.core.report.report
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.report.report\_trigger module
------------------------------------------
.. automodule:: ahriman.core.report.report_trigger
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.report.telegram module
-----------------------------------
.. automodule:: ahriman.core.report.telegram
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.report
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,53 @@
ahriman.core.repository package
===============================
Submodules
----------
ahriman.core.repository.cleaner module
--------------------------------------
.. automodule:: ahriman.core.repository.cleaner
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.repository.executor module
---------------------------------------
.. automodule:: ahriman.core.repository.executor
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.repository.repository module
-----------------------------------------
.. automodule:: ahriman.core.repository.repository
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.repository.repository\_properties module
-----------------------------------------------------
.. automodule:: ahriman.core.repository.repository_properties
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.repository.update\_handler module
----------------------------------------------
.. automodule:: ahriman.core.repository.update_handler
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.repository
:members:
:no-undoc-members:
:show-inheritance:

68
docs/ahriman.core.rst Normal file
View File

@ -0,0 +1,68 @@
ahriman.core package
====================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.core.alpm
ahriman.core.auth
ahriman.core.build_tools
ahriman.core.configuration
ahriman.core.database
ahriman.core.formatters
ahriman.core.gitremote
ahriman.core.http
ahriman.core.log
ahriman.core.report
ahriman.core.repository
ahriman.core.sign
ahriman.core.status
ahriman.core.support
ahriman.core.triggers
ahriman.core.upload
Submodules
----------
ahriman.core.exceptions module
------------------------------
.. automodule:: ahriman.core.exceptions
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.spawn module
-------------------------
.. automodule:: ahriman.core.spawn
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.tree module
------------------------
.. automodule:: ahriman.core.tree
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.util module
------------------------
.. automodule:: ahriman.core.util
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,21 @@
ahriman.core.sign package
=========================
Submodules
----------
ahriman.core.sign.gpg module
----------------------------
.. automodule:: ahriman.core.sign.gpg
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.sign
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,37 @@
ahriman.core.status package
===========================
Submodules
----------
ahriman.core.status.client module
---------------------------------
.. automodule:: ahriman.core.status.client
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.status.watcher module
----------------------------------
.. automodule:: ahriman.core.status.watcher
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.status.web\_client module
--------------------------------------
.. automodule:: ahriman.core.status.web_client
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.status
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,37 @@
ahriman.core.support.pkgbuild package
=====================================
Submodules
----------
ahriman.core.support.pkgbuild.keyring\_generator module
-------------------------------------------------------
.. automodule:: ahriman.core.support.pkgbuild.keyring_generator
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.support.pkgbuild.mirrorlist\_generator module
----------------------------------------------------------
.. automodule:: ahriman.core.support.pkgbuild.mirrorlist_generator
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.support.pkgbuild.pkgbuild\_generator module
--------------------------------------------------------
.. automodule:: ahriman.core.support.pkgbuild.pkgbuild_generator
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.support.pkgbuild
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,45 @@
ahriman.core.support package
============================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.core.support.pkgbuild
Submodules
----------
ahriman.core.support.keyring\_trigger module
--------------------------------------------
.. automodule:: ahriman.core.support.keyring_trigger
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.support.mirrorlist\_trigger module
-----------------------------------------------
.. automodule:: ahriman.core.support.mirrorlist_trigger
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.support.package\_creator module
--------------------------------------------
.. automodule:: ahriman.core.support.package_creator
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.support
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,29 @@
ahriman.core.triggers package
=============================
Submodules
----------
ahriman.core.triggers.trigger module
------------------------------------
.. automodule:: ahriman.core.triggers.trigger
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.triggers.trigger\_loader module
--------------------------------------------
.. automodule:: ahriman.core.triggers.trigger_loader
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.triggers
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,69 @@
ahriman.core.upload package
===========================
Submodules
----------
ahriman.core.upload.github module
---------------------------------
.. automodule:: ahriman.core.upload.github
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.upload.http\_upload module
---------------------------------------
.. automodule:: ahriman.core.upload.http_upload
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.upload.remote\_service module
------------------------------------------
.. automodule:: ahriman.core.upload.remote_service
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.upload.rsync module
--------------------------------
.. automodule:: ahriman.core.upload.rsync
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.upload.s3 module
-----------------------------
.. automodule:: ahriman.core.upload.s3
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.upload.upload module
---------------------------------
.. automodule:: ahriman.core.upload.upload
:members:
:no-undoc-members:
:show-inheritance:
ahriman.core.upload.upload\_trigger module
------------------------------------------
.. automodule:: ahriman.core.upload.upload_trigger
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.core.upload
:members:
:no-undoc-members:
:show-inheritance:

237
docs/ahriman.models.rst Normal file
View File

@ -0,0 +1,237 @@
ahriman.models package
======================
Submodules
----------
ahriman.models.action module
----------------------------
.. automodule:: ahriman.models.action
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.aur\_package module
----------------------------------
.. automodule:: ahriman.models.aur_package
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.auth\_settings module
------------------------------------
.. automodule:: ahriman.models.auth_settings
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.build\_status module
-----------------------------------
.. automodule:: ahriman.models.build_status
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.context\_key module
----------------------------------
.. automodule:: ahriman.models.context_key
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.counters module
------------------------------
.. automodule:: ahriman.models.counters
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.internal\_status module
--------------------------------------
.. automodule:: ahriman.models.internal_status
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.log\_handler module
----------------------------------
.. automodule:: ahriman.models.log_handler
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.log\_record\_id module
-------------------------------------
.. automodule:: ahriman.models.log_record_id
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.migration module
-------------------------------
.. automodule:: ahriman.models.migration
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.migration\_result module
---------------------------------------
.. automodule:: ahriman.models.migration_result
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.package module
-----------------------------
.. automodule:: ahriman.models.package
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.package\_description module
------------------------------------------
.. automodule:: ahriman.models.package_description
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.package\_source module
-------------------------------------
.. automodule:: ahriman.models.package_source
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.packagers module
-------------------------------
.. automodule:: ahriman.models.packagers
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.pacman\_synchronization module
---------------------------------------------
.. automodule:: ahriman.models.pacman_synchronization
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.pkgbuild\_patch module
-------------------------------------
.. automodule:: ahriman.models.pkgbuild_patch
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.property module
------------------------------
.. automodule:: ahriman.models.property
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.remote\_source module
------------------------------------
.. automodule:: ahriman.models.remote_source
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.report\_settings module
--------------------------------------
.. automodule:: ahriman.models.report_settings
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.repository\_paths module
---------------------------------------
.. automodule:: ahriman.models.repository_paths
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.result module
----------------------------
.. automodule:: ahriman.models.result
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.sign\_settings module
------------------------------------
.. automodule:: ahriman.models.sign_settings
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.smtp\_ssl\_settings module
-----------------------------------------
.. automodule:: ahriman.models.smtp_ssl_settings
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.upload\_settings module
--------------------------------------
.. automodule:: ahriman.models.upload_settings
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.user module
--------------------------
.. automodule:: ahriman.models.user
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.user\_access module
----------------------------------
.. automodule:: ahriman.models.user_access
:members:
:no-undoc-members:
:show-inheritance:
ahriman.models.waiter module
----------------------------
.. automodule:: ahriman.models.waiter
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.models
:members:
:no-undoc-members:
:show-inheritance:

21
docs/ahriman.rst Normal file
View File

@ -0,0 +1,21 @@
ahriman package
===============
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.application
ahriman.core
ahriman.models
ahriman.web
Module contents
---------------
.. automodule:: ahriman
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,29 @@
ahriman.web.middlewares package
===============================
Submodules
----------
ahriman.web.middlewares.auth\_handler module
--------------------------------------------
.. automodule:: ahriman.web.middlewares.auth_handler
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.middlewares.exception\_handler module
-------------------------------------------------
.. automodule:: ahriman.web.middlewares.exception_handler
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web.middlewares
:members:
:no-undoc-members:
:show-inheritance:

55
docs/ahriman.web.rst Normal file
View File

@ -0,0 +1,55 @@
ahriman.web package
===================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.web.middlewares
ahriman.web.schemas
ahriman.web.views
Submodules
----------
ahriman.web.apispec module
--------------------------
.. automodule:: ahriman.web.apispec
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.cors module
-----------------------
.. automodule:: ahriman.web.cors
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.routes module
-------------------------
.. automodule:: ahriman.web.routes
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.web module
----------------------
.. automodule:: ahriman.web.web
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,197 @@
ahriman.web.schemas package
===========================
Submodules
----------
ahriman.web.schemas.aur\_package\_schema module
-----------------------------------------------
.. automodule:: ahriman.web.schemas.aur_package_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.auth\_schema module
---------------------------------------
.. automodule:: ahriman.web.schemas.auth_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.counters\_schema module
-------------------------------------------
.. automodule:: ahriman.web.schemas.counters_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.error\_schema module
----------------------------------------
.. automodule:: ahriman.web.schemas.error_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.file\_schema module
---------------------------------------
.. automodule:: ahriman.web.schemas.file_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.internal\_status\_schema module
---------------------------------------------------
.. automodule:: ahriman.web.schemas.internal_status_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.log\_schema module
--------------------------------------
.. automodule:: ahriman.web.schemas.log_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.login\_schema module
----------------------------------------
.. automodule:: ahriman.web.schemas.login_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.logs\_schema module
---------------------------------------
.. automodule:: ahriman.web.schemas.logs_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.oauth2\_schema module
-----------------------------------------
.. automodule:: ahriman.web.schemas.oauth2_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.package\_name\_schema module
------------------------------------------------
.. automodule:: ahriman.web.schemas.package_name_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.package\_names\_schema module
-------------------------------------------------
.. automodule:: ahriman.web.schemas.package_names_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.package\_properties\_schema module
------------------------------------------------------
.. automodule:: ahriman.web.schemas.package_properties_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.package\_schema module
------------------------------------------
.. automodule:: ahriman.web.schemas.package_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.package\_status\_schema module
--------------------------------------------------
.. automodule:: ahriman.web.schemas.package_status_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.pgp\_key\_id\_schema module
-----------------------------------------------
.. automodule:: ahriman.web.schemas.pgp_key_id_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.pgp\_key\_schema module
-------------------------------------------
.. automodule:: ahriman.web.schemas.pgp_key_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.process\_id\_schema module
----------------------------------------------
.. automodule:: ahriman.web.schemas.process_id_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.process\_schema module
------------------------------------------
.. automodule:: ahriman.web.schemas.process_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.remote\_schema module
-----------------------------------------
.. automodule:: ahriman.web.schemas.remote_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.search\_schema module
-----------------------------------------
.. automodule:: ahriman.web.schemas.search_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.status\_schema module
-----------------------------------------
.. automodule:: ahriman.web.schemas.status_schema
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.schemas.update\_flags\_schema module
------------------------------------------------
.. automodule:: ahriman.web.schemas.update_flags_schema
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web.schemas
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,29 @@
ahriman.web.views.api package
=============================
Submodules
----------
ahriman.web.views.api.docs module
---------------------------------
.. automodule:: ahriman.web.views.api.docs
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.api.swagger module
------------------------------------
.. automodule:: ahriman.web.views.api.swagger
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web.views.api
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,40 @@
ahriman.web.views package
=========================
Subpackages
-----------
.. toctree::
:maxdepth: 4
ahriman.web.views.api
ahriman.web.views.service
ahriman.web.views.status
ahriman.web.views.user
Submodules
----------
ahriman.web.views.base module
-----------------------------
.. automodule:: ahriman.web.views.base
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.index module
------------------------------
.. automodule:: ahriman.web.views.index
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web.views
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,85 @@
ahriman.web.views.service package
=================================
Submodules
----------
ahriman.web.views.service.add module
------------------------------------
.. automodule:: ahriman.web.views.service.add
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.service.pgp module
------------------------------------
.. automodule:: ahriman.web.views.service.pgp
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.service.process module
----------------------------------------
.. automodule:: ahriman.web.views.service.process
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.service.rebuild module
----------------------------------------
.. automodule:: ahriman.web.views.service.rebuild
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.service.remove module
---------------------------------------
.. automodule:: ahriman.web.views.service.remove
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.service.request module
----------------------------------------
.. automodule:: ahriman.web.views.service.request
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.service.search module
---------------------------------------
.. automodule:: ahriman.web.views.service.search
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.service.update module
---------------------------------------
.. automodule:: ahriman.web.views.service.update
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.service.upload module
---------------------------------------
.. automodule:: ahriman.web.views.service.upload
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web.views.service
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,45 @@
ahriman.web.views.status package
================================
Submodules
----------
ahriman.web.views.status.logs module
------------------------------------
.. automodule:: ahriman.web.views.status.logs
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.status.package module
---------------------------------------
.. automodule:: ahriman.web.views.status.package
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.status.packages module
----------------------------------------
.. automodule:: ahriman.web.views.status.packages
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.status.status module
--------------------------------------
.. automodule:: ahriman.web.views.status.status
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web.views.status
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -0,0 +1,29 @@
ahriman.web.views.user package
==============================
Submodules
----------
ahriman.web.views.user.login module
-----------------------------------
.. automodule:: ahriman.web.views.user.login
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.user.logout module
------------------------------------
.. automodule:: ahriman.web.views.user.logout
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web.views.user
:members:
:no-undoc-members:
:show-inheritance:

349
docs/architecture.rst Normal file
View File

@ -0,0 +1,349 @@
Architecture
============
Package structure
-----------------
Packages have strict rules of importing:
* ``ahriman.application`` package must not be used anywhere except for itself.
* ``ahriman.core`` and ``ahriman.models`` packages don't have any import restriction. Actually we would like to totally restrict importing of ``core`` package from ``models``, but it is impossible at the moment.
* ``ahriman.web`` package is allowed to be imported from ``ahriman.application`` (web handler only, only ``ahriman.web.web`` methods). It also must not be imported globally, only local import is allowed.
Full dependency diagram:
.. image:: ahriman-architecture.svg
:target: _images/ahriman-architecture.svg
:alt: architecture
``ahriman.application`` package
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This package contains application (aka executable) related classes and everything for that. It also contains package called ``ahriman.application.handlers`` in which all available subcommands are described as separated classes derived from base ``ahriman.application.handlers.Handler`` class.
``ahriman.application.application.Application`` (god class) is used for any interaction from parsers with repository. It is divided into multiple traits by functions (package related and repository related) in the same package.
``ahriman.application.ahriman`` contains only command line parses and executes specified ``Handler`` on success, ``ahriman.application.lock.Lock`` is additional class which provides file-based lock and also performs some common checks.
``ahriman.core`` package
^^^^^^^^^^^^^^^^^^^^^^^^
This package contains everything required for the most of application actions and it is separated into several packages:
* ``ahriman.core.alpm`` package controls pacman related functions. It provides wrappers for ``pyalpm`` library and safe calls for repository tools (``repo-add`` and ``repo-remove``). Also this package contains ``ahriman.core.alpm.remote`` package which provides wrapper for remote sources (e.g. AUR RPC and official repositories RPC).
* ``ahriman.core.auth`` package provides classes for authorization methods used by web mostly. Base class is ``ahriman.core.auth.Auth`` which must be called by ``load`` method.
* ``ahriman.core.build_tools`` is a package which provides wrapper for ``devtools`` commands.
* ``ahriman.core.configuration`` contains extension for standard ``configparser`` library and some validation related classes.
* ``ahriman.core.database`` is everything including data and schema migrations for database.
* ``ahriman.core.formatters`` package provides ``Printer`` sub-classes for printing data (e.g. package properties) to stdout which are used by some handlers.
* ``ahriman.core.gitremote`` is a package with remote PKGBUILD triggers. Should not be called directly.
* ``ahriman.core.http`` package provides HTTP clients which can be later used by other classes.
* ``ahriman.core.log`` is a log utils package. It includes logger loader class, custom HTTP based logger and access logger for HTTP services with additional filters.
* ``ahriman.core.report`` is a package with reporting triggers. Should not be called directly.
* ``ahriman.core.repository`` contains several traits and base repository (``ahriman.core.repository.Repository`` class) implementation.
* ``ahriman.core.sign`` package provides sign feature (only gpg calls are available).
* ``ahriman.core.status`` contains helpers and watcher class which are required for web application. Reporter must be initialized by using ``ahriman.core.status.client.Client.load`` method.
* ``ahriman.core.support`` provides plugins for support packages (mirrorlist and keyring) generation.
* ``ahriman.core.triggers`` package contains base trigger classes. Classes from this package must be imported in order to implement user extensions. In fact, ``ahriman.core.report`` and ``ahriman.core.upload`` use this package.
* ``ahriman.core.upload`` package provides sync feature, should not be called directly.
This package also provides some generic functions and classes which may be used by other packages:
* ``ahriman.core.exceptions`` provides custom exceptions.
* ``ahriman.core.spawn.Spawn`` is a tool which can spawn another ``ahriman`` process. This feature is used by web application.
* ``ahriman.core.tree`` is a dependency tree implementation.
``ahriman.models`` package
^^^^^^^^^^^^^^^^^^^^^^^^^^
It provides models for any other part of application. Unlike ``ahriman.core`` package classes from here provide only conversion methods (e.g. create class from another or convert to). Mostly case classes and enumerations.
``ahriman.web`` package
^^^^^^^^^^^^^^^^^^^^^^^
Web application. It is important that this package is isolated from any other to allow it to be optional feature (i.e. dependencies which are required by the package are optional).
* ``ahriman.web.middlewares`` provides middlewares for request handlers.
* ``ahriman.web.schemas`` provides schemas (actually copy paste from dataclasses) used by swagger documentation.
* ``ahriman.web.views`` contains web views derived from aiohttp view class.
* ``ahriman.web.apispec`` provides generators for swagger documentation.
* ``ahriman.web.cors`` contains helpers for cross origin resource sharing middlewares.
* ``ahriman.web.routes`` creates routes for web application.
* ``ahriman.web.web`` provides main web application functions (e.g. start, initialization).
Application run
---------------
#. Parse command line arguments, find command and related handler which is set by parser.
#. Call ``Handler.execute`` method.
#. Define list of architectures to run. In case if there is more than one architecture specified run several subprocesses or process in current process otherwise. Class attribute ``ALLOW_MULTI_ARCHITECTURE_RUN`` controls whether application can be run in multiple processes or not - this feature is required for some handlers (e.g. ``Web``) which should be able to spawn child process in daemon mode (it is impossible to do from daemonic processes).
#. In each child process call lock functions.
#. After success checks pass control to ``Handler.run`` method defined by specific handler class.
#. Return result (success or failure) of each subprocess and exit from application.
#. Some handlers may override their status and throw ``ExitCode`` exception. This exception is just silently suppressed and changes application exit code to ``1``.
In the most cases handlers spawn god class ``ahriman.application.application.Application`` class and call required methods.
Application is designed to run from ``systemd`` services and provides parametrized by architecture timer and service file for that.
Subcommand design
^^^^^^^^^^^^^^^^^
All subcommands are divided into several groups depending on the role they are doing:
* ``aur`` (``aur-search``) group is for AUR operations.
* ``help`` (e.g. ``help``) are system commands.
* ``package`` subcommands (e.g. ``package-add``) allow to perform single package actions.
* ``patch`` subcommands (e.g. ``pacth-list``) are the special case of ``package`` subcommands introduced in order to control patches for packages.
* ``repo`` subcommands (e.g. ``repo-check``) usually perform actions on whole repository.
* ``service`` subcommands (e.g. ``service-setup``) perform actions which are related to whole service managing: create repository, show configuration.
* ``user`` subcommands (``user-add``) are intended for user management.
* ``web`` subcommands are related to web service management.
For historical reasons and in order to keep backward compatibility some subcommands have aliases to their shorter forms or even other groups, but the service doesn't guarantee that they will remain unchanged.
Database
--------
The service uses SQLite database in order to store some internal info.
Database instance
^^^^^^^^^^^^^^^^^
All methods related to specific part of database (basically operations per table) are split into different traits located inside ``ahriman.core.database.operations`` package. The base trait ``ahriman.core.database.operations.Operations`` also provides generic methods for database access (e.g. row converters and transactional support).
The ``ahriman.core.database.SQLite`` class itself derives from all of these traits and implements methods for initialization, including migrations.
Schema and data migrations
^^^^^^^^^^^^^^^^^^^^^^^^^^
The schema migration are applied according to current ``pragma user_info`` values, located at ``ahriman.core.database.migrations`` package and named as ``m000_migration_name.py`` (the preceding ``m`` is required in order to import migration content for tests). Additional class ``ahriman.core.database.migrations.Migrations`` reads all migrations automatically and applies them in alphabetical order.
These migrations can also contain data migrations. Though the recommended way is to migrate data directly from SQL requests, sometimes it is required to have external data (like packages list) in order to set correct data. To do so, special method `migrate_data` is used.
Type conversions
^^^^^^^^^^^^^^^^
By default, it parses rows into python dictionary. In addition, the following pseudo-types are supported:
* ``dict[str, Any]``, ``list[Any]`` - for storing JSON data structures in database (technically there is no restriction on types for dictionary keys and values, but it is recommended to use only string keys). The type is stored as ``json`` data type and ``json.loads`` and ``json.dumps`` methods are used in order to read and write from/to database respectively.
Basic flows
-----------
By default package build operations are performed with ``PACKAGER`` which is specified in ``makepkg.conf``, however, it is possible to override this variable from command line; in this case service performs lookup in the following way:
* If packager is not set, it reads environment variables (e.g. ``SUDO_USER`` and ``USER``), otherwise it uses value from command line.
* It checks users for the specified username and tries to extract packager variable from it.
* If packager value has been found, it will be passed as ``PACKAGER`` system variable (sudo configuration required).
Add new packages or rebuild existing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Idea is to copy package to the directory from which it will be handled at the next update run. Different variants are supported:
* If supplied argument is file then application moves the file to the directory with built packages. Same rule applies for directory, but in this case it copies every package-like file from the specified directory.
* If supplied argument is directory and there is ``PKGBUILD`` file there it will be treated as local package. In this case it will queue this package to build and copy source files (``PKGBUILD`` and ``.SRCINFO``) to caches.
* If supplied argument is not file then application tries to lookup for the specified name in AUR and clones it into the directory with manual updates. This scenario can also handle package dependencies which are missing in repositories.
This logic can be overwritten by specifying the ``source`` parameter, which is partially useful if you would like to add package from AUR, but there is local directory cloned from AUR.
Rebuild packages
^^^^^^^^^^^^^^^^
Same as add function for every package in repository. Optional filters by reverse dependency or build status can be supplied.
Remove packages
^^^^^^^^^^^^^^^
This flow removes package from filesystem, updates repository database and also runs synchronization and reporting methods.
Update packages
^^^^^^^^^^^^^^^
This feature is divided into to stages: check AUR for updates and run rebuild for required packages. Whereas check does not do anything except for check itself, update flow is the following:
#. Process every built package first. Those packages are usually added manually.
#. Run sync and report methods.
#. Generate dependency tree for packages to be built.
#. For each level of tree it does:
#. Download package data from AUR.
#. Bump ``pkgrel`` if there is duplicate version in the local repository (see explanation below).
#. Build every package in clean chroot.
#. Sign packages if required.
#. Add packages to database and sign database if required.
#. Process triggers.
After any step any package data is being removed.
pkgrel bump rules
^^^^^^^^^^^^^^^^^
The application is able to automatically bump package release (``pkgrel``) during build process if there is duplicate version in repository. The version will be incremented as following:
#. Get version of the remote package.
#. Get version of the local package if any.
#. If local version is not set, proceed with remote one.
#. If local version is set and epoch or package version (``pkgver``) are different, proceed with remote version.
#. If local version is set and remote version is newer than local one, proceed with remote.
#. Extract ``pkgrel`` value.
#. If it has ``major.minor`` notation (e.g. ``1.1``), then increment last part by 1, e.g. ``1.1 -> 1.2``, ``1.0.1 -> 1.0.2``.
#. If ``pkgrel`` is a number (e.g. ``1``), then append 1 to the end of the string, e.g. ``1 -> 1.1``.
Core functions reference
------------------------
Configuration
^^^^^^^^^^^^^
``ahriman.core.configuration.Configuration`` class provides some additional methods (e.g. ``getpath`` and ``getlist``) and also combines multiple files into single configuration dictionary using architecture overrides. It is the recommended way to deal with settings.
Enumerations
^^^^^^^^^^^^
All enumerations are derived from ``str`` and ``enum.Enum``. Integer enumerations are not allowed, because most of operations require conversions from string variable. Derivation from string class is required to make json conversions implicitly (e.g. during calling ``json.dumps`` methods).
In addition, some enumerations provide ``from_option`` class methods in order to allow some flexibility while reading configuration options.
Utils
^^^^^
For every external command run (which is actually not recommended if possible) custom wrapper for ``subprocess`` is used. Additional functions ``ahriman.core.auth.helpers`` provide safe calls for ``aiohttp_security`` methods and are required to make this dependency optional.
Context variables
^^^^^^^^^^^^^^^^^
Package provides implicit global variables which can be accessed from ``ahriman.core`` package as ``context`` variable, wrapped by ``contextvars.ContextVar`` class. The value of the variable is defaulting to private ``_Context`` class which is defined in the same module. The default values - such as ``database`` and ``sign`` - are being set on the service initialization.
The ``_Context`` class itself mimics default collection interface (as is Mapping) and can be modified by ``_Context.set`` method. The stored variables can be achieved by ``_Context.get`` method, which is unlike default ``Mapping`` interface also performs type and presence checks.
In order to provide statically typed interface, the ``ahriman.models.context_key.ContextKey`` class is used for both ``_Content.get`` and ``_Content.set`` methods; the context instance itself, however, does not store information about types.
Submodules
^^^^^^^^^^
Some packages provide different behaviour depending on configuration settings. In these cases inheritance is used and recommended way to deal with them is to call class method ``load`` from base classes.
Authorization
^^^^^^^^^^^^^
The package provides several authorization methods: disabled, based on configuration and OAuth2.
Disabled (default) authorization provider just allows everything for everyone and does not have any specific configuration (it uses some default configuration parameters though). It also provides generic interface for derived classes.
Mapping (aka configuration) provider uses hashed passwords with optional salt from the database in order to authenticate users. This provider also enables user permission checking (read/write) (authorization). Thus, it defines the following methods:
* ``check_credentials`` - user password validation (authentication).
* ``verify_access`` - user permission validation (authorization).
Passwords must be stored in database as ``hash(password + salt)``, where ``password`` is user defined password (taken from user input), ``salt`` is random string (any length) defined globally in configuration and ``hash`` is secure hash function. Thus, the following configuration
.. code-block::
"username","password","access"
"username","$6$rounds=656000$mWBiecMPrHAL1VgX$oU4Y5HH8HzlvMaxwkNEJjK13ozElyU1wAHBoO/WW5dAaE4YEfnB0X3FxbynKMl4FBdC3Ovap0jINz4LPkNADg0","read"
means that there is user ``username`` with ``read`` access and password ``password`` hashed by ``sha512`` with salt ``salt``.
OAuth provider uses library definitions (``aioauth-client``) in order *authenticate* users. It still requires user permission to be set in database, thus it inherits mapping provider without any changes. Whereas we could override ``check_credentials`` (authentication method) by something custom, OAuth flow is a bit more complex than just forward request, thus we have to implement the flow in login form.
OAuth's implementation also allows authenticating users via username + password (in the same way as mapping does) though it is not recommended for end-users and password must be left blank. In particular this feature can be used by service reporting (aka robots).
In addition, web service checks the source socket used. In case if it belongs to ``socket.AF_UNIX`` family, it will skip any further checks considering the request to be performed in safe environment (e.g. on the same physical machine). This feature, in particular is being used by the reporter instances in case if socket address is set in configuration.
In order to configure users there are special commands.
Triggers
^^^^^^^^
Triggers are extensions which can be used in order to perform any actions on application start, after the update process and, finally, before the application exit.
The main idea is to load classes by their full path (e.g. ``ahriman.core.upload.UploadTrigger``) by using ``importlib``: get the last part of the import and treat it as class name, join remain part by ``.`` and interpret as module path, import module and extract attribute from it.
The loaded triggers will be called with ``ahriman.models.result.Result`` and ``list[Packages]`` arguments, which describes the process result and current repository packages respectively. Any exception raised will be suppressed and will generate an exception message in logs.
In addition triggers can implement ``on_start`` and ``on_stop`` actions which will be called on the application start and right before the application exit. The ``on_start`` action is usually being called from handlers directly in order to make sure that no trigger will be run when it is not required (e.g. on user management). As soon as ``on_start`` action is called, the additional flag will be set; ``ahriman.core.triggers.TriggerLoader`` class implements ``__del__`` method in which, if the flag is set, the ``on_stop`` actions will be called.
For more details how to deal with the triggers, refer to :doc:`documentation <triggers>` and modules descriptions.
Remote synchronization
^^^^^^^^^^^^^^^^^^^^^^
There are several supported synchronization providers, currently they are ``rsync``, ``s3``, ``github``.
``rsync`` provider does not have any specific logic except for running external rsync application with configured arguments. The service does not handle SSH configuration, thus it has to be configured before running application manually.
``s3`` provider uses ``boto3`` package and implements sync feature. The files are stored in architecture directory (e.g. if bucket is ``repository``, packages will be stored in ``repository/x86_64`` for the ``x86_64`` architecture), bucket must be created before any action and API key must have permissions to write to the bucket. No external configuration required. In order to upload only changed files the service compares calculated hashes with the Amazon ETags, used realization is described `here <https://teppen.io/2018/10/23/aws_s3_verify_etags/>`_.
``github`` provider authenticates through basic auth, API key with repository write permissions is required. There will be created a release with the name of the architecture in case if it does not exist; files will be uploaded to the release assets. It also stores array of files and their MD5 checksums in release body in order to upload only changed ones. According to the Github API in case if there is already uploaded asset with the same name (e.g. database files), asset will be removed first.
Additional features
^^^^^^^^^^^^^^^^^^^
Some features require optional dependencies to be installed:
* Version control executables (e.g. ``git``, ``svn``) for VCS packages.
* ``gnupg`` application for package and repository sign feature.
* ``rsync`` application for rsync based repository sync.
* ``boto3`` python package for ``S3`` sync.
* ``Jinja2`` python package for HTML report generation (it is also used by web application).
Web application
---------------
Web application requires the following python packages to be installed:
* Core part requires ``aiohttp`` (application itself), ``aiohttp_jinja2`` and ``Jinja2`` (HTML generation from templates).
* Additional web features also require ``aiohttp-apispec`` (autogenerated documentation), ``aiohttp_cors`` (CORS support, required by documentation)
* In addition, ``aiohttp_debugtoolbar`` is required for debug panel. Please note that this option does not work together with authorization and basically must not be used in production.
* In addition, authorization feature requires ``aiohttp_security``, ``aiohttp_session`` and ``cryptography``.
* In addition to base authorization dependencies, OAuth2 also requires ``aioauth-client`` library.
* In addition if you would like to disable authorization for local access (recommended way in order to run the application itself with reporting support), the ``requests-unixsocket`` library is required.
Middlewares
^^^^^^^^^^^
Service provides some custom middlewares, e.g. logging every exception (except for user ones) and user authorization.
HEAD and OPTIONS requests
^^^^^^^^^^^^^^^^^^^^^^^^^
``HEAD`` request is automatically generated by ``ahriman.web.views.base.BaseView`` class. It just calls ``GET`` method, removes any data from body and returns the result. In case if no ``GET`` method available for this view, the ``aiohttp.web.HTTPMethodNotAllowed`` exception will be raised.
On the other side, ``OPTIONS`` method is implemented in the ``ahriman.web.middlewares.exception_handler.exception_handler`` middleware. In case if ``aiohttp.web.HTTPMethodNotAllowed`` exception is raised and original method was ``OPTIONS``, the middleware handles it, converts to valid request and returns response to user.
Web views
^^^^^^^^^
All web views are defined in separated package and derived from ``ahriman.web.views.base.Base`` class which provides typed interfaces for web application.
REST API supports both form and JSON data, but the last one is recommended.
Different APIs are separated into different packages:
* ``ahriman.web.views.api`` not a real API, but some views which provide OpenAPI support.
* ``ahriman.web.views.service`` provides views for application controls.
* ``ahriman.web.views.status`` package provides REST API for application reporting.
* ``ahriman.web.views.user`` package provides login and logout methods which can be called without authorization.
Templating
^^^^^^^^^^
Package provides base jinja templates which can be overridden by settings. Vanilla templates are actively using bootstrap library.
Requests and scopes
^^^^^^^^^^^^^^^^^^^
Service provides optional authorization which can be turned on in settings. In order to control user access there are two levels of authorization - read-only (only GET-like requests) and write (anything) which are provided by each web view directly.
If this feature is configured any request will be prohibited without authentication. In addition, configuration flag ``auth.allow_read_only`` can be used in order to allow read-only operations - reading index page and packages - without authorization.
For authenticated users it uses encrypted session cookies to store tokens; encryption key is generated each time at the start of the application. It also stores expiration time of the session inside.
External calls
^^^^^^^^^^^^^^
Web application provides external calls to control main service. It spawns child process with specific arguments and waits for its termination. This feature must be used either with authorization or in safe (i.e. when status page is not available world-wide) environment.
For most actions it also extracts user from authentication (if provided) and passes it to underlying process.

10
docs/command-line.rst Normal file
View File

@ -0,0 +1,10 @@
Commands reference
==================
ahriman
-------
.. argparse::
:module: ahriman.application.ahriman
:func: _parser
:prog: ahriman

92
docs/conf.py Normal file
View File

@ -0,0 +1,92 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
import sys
from pathlib import Path
from ahriman import __version__
basedir = Path(__file__).resolve().parent.parent / "src"
sys.path.insert(0, str(basedir))
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
# -- Project information -----------------------------------------------------
project = "ahriman"
copyright = "2021-2023, ahriman team"
author = "ahriman team"
# The full version, including alpha/beta/rc tags
release = __version__
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named "sphinx.ext.*") or your custom
# ones.
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.napoleon",
"sphinx_rtd_theme",
"sphinxarg.ext",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = "en"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = "sphinx_rtd_theme"
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = []
add_module_names = False
modindex_common_prefix = ["ahriman.application.", "ahriman.core.", "ahriman.models.", "ahriman.web."]
# -- Extension configuration -------------------------------------------------
autoclass_content = "both"
autodoc_member_order = "groupwise"
autodoc_mock_imports = ["pyalpm"]
autodoc_default_options = {
"no-undoc-members": True,
}

336
docs/configuration.rst Normal file
View File

@ -0,0 +1,336 @@
Configuration
=============
Some groups can be specified for each architecture separately. E.g. if there are ``build`` and ``build:x86_64`` groups it will use an option from ``build:x86_64`` for the ``x86_64`` architecture and ``build`` for any other (architecture specific group has higher priority). In case if both groups are presented, architecture specific options will be merged into global ones overriding them.
There are two variable types which have been added to default ones, they are paths and lists. List values will be read in the same way as shell does:
* By default, it splits value by spaces excluding empty elements.
* In case if quotation mark (``"`` or ``'``) will be found, any spaces inside will be ignored.
* In order to use quotation mark inside value it is required to put it to another quotation mark, e.g. ``wor"'"d "with quote"`` will be parsed as ``["wor'd", "with quote"]`` and vice versa.
* Unclosed quotation mark is not allowed and will rise an exception.
Path values, except for casting to ``pathlib.Path`` type, will be also expanded to absolute paths relative to the configuration path. E.g. if path is set to ``ahriman.ini.d/logging.ini`` and root configuration path is ``/etc/ahriman.ini``, the value will be expanded to ``/etc/ahriman.ini.d/logging.ini``. In order to disable path expand, use the full path, e.g. ``/etc/ahriman.ini.d/logging.ini``.
Configuration allows string interpolation from environment variables, e.g.:
.. code-block:: ini
[section]
key = $SECRET
will try to read value from ``SECRET`` environment variable. In case if the required environment variable wasn't found, it will keep original value (i.e. ``$SECRET`` in the example). Dollar sign can be set as ``$$``.
There is also additional subcommand which will allow to validate configuration and print found errors. In order to do so, run ``service-config-validate`` subcommand, e.g.:
.. code-block:: shell
ahriman -a x86_64 service-config-validate
It will check current settings on common errors and compare configuration with known schema.
``settings`` group
------------------
Base configuration settings.
* ``include`` - path to directory with configuration files overrides, string, required.
* ``database`` - path to SQLite database, string, required.
* ``logging`` - path to logging configuration, string, required. Check ``logging.ini`` for reference.
* ``suppress_http_log_errors`` - suppress http log errors, boolean, optional, default ``no``. If set to ``yes``, any http log errors (e.g. if web server is not available, but http logging is enabled) will be suppressed.
``alpm:*`` groups
-----------------
libalpm and AUR related configuration. Group name can refer to architecture, e.g. ``alpm:x86_64`` can be used for x86_64 architecture specific settings.
* ``database`` - path to pacman system database cache, string, required.
* ``mirror`` - package database mirror used by pacman for syncronization, string, required. This option supports standard pacman substitutions with ``$arch`` and ``$repo``. Note that the mentioned mirror should contain all repositories which are set by ``alpm.repositories`` option.
* ``repositories`` - list of pacman repositories, space separated list of strings, required.
* ``root`` - root for alpm library, string, required.
* ``use_ahriman_cache`` - use local pacman package cache instead of system one, boolean, required. With this option enabled you might want to refresh database periodically (available as additional flag for some subcommands).
``auth`` group
--------------
Base authorization settings. ``OAuth`` provider requires ``aioauth-client`` library to be installed.
* ``target`` - specifies authorization provider, string, optional, default ``disabled``. Allowed values are ``disabled``, ``configuration``, ``oauth``.
* ``allow_read_only`` - allow requesting status APIs without authorization, boolean, required.
* ``client_id`` - OAuth2 application client ID, string, required in case if ``oauth`` is used.
* ``client_secret`` - OAuth2 application client secret key, string, required in case if ``oauth`` is used.
* ``cookie_secret_key`` - secret key which will be used for cookies encryption, string, optional. It must be 32 url-safe base64-encoded bytes and can be generated as following ``base64.urlsafe_b64encode(os.urandom(32)).decode("utf8")``. If not set, it will be generated automatically; note, however, that in this case, all sessions will be automatically expired during restart.
* ``max_age`` - parameter which controls both cookie expiration and token expiration inside the service, integer, optional, default is 7 days.
* ``oauth_provider`` - OAuth2 provider class name as is in ``aioauth-client`` (e.g. ``GoogleClient``, ``GithubClient`` etc), string, required in case if ``oauth`` is used.
* ``oauth_scopes`` - scopes list for OAuth2 provider, which will allow retrieving user email (which is used for checking user permissions), e.g. ``https://www.googleapis.com/auth/userinfo.email`` for ``GoogleClient`` or ``user:email`` for ``GithubClient``, space separated list of strings, required in case if ``oauth`` is used.
* ``salt`` - additional password hash salt, string, optional.
Authorized users are stored inside internal database, if any of external provides are used the password field for non-service users must be empty.
``build:*`` groups
------------------
Build related configuration. Group name can refer to architecture, e.g. ``build:x86_64`` can be used for x86_64 architecture specific settings.
* ``archbuild_flags`` - additional flags passed to ``archbuild`` command, space separated list of strings, optional.
* ``build_command`` - default build command, string, required.
* ``ignore_packages`` - list packages to ignore during a regular update (manual update will still work), space separated list of strings, optional.
* ``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.
* ``triggers`` - list of ``ahriman.core.triggers.Trigger`` class implementation (e.g. ``ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger``) which will be loaded and run at the end of processing, space separated list of strings, optional. You can also specify triggers by their paths, e.g. ``/usr/lib/python3.10/site-packages/ahriman/core/report/report.py.ReportTrigger``. Triggers are run in the order of mention.
* ``triggers_known`` - optional list of ``ahriman.core.triggers.Trigger`` class implementations which are not run automatically and used only for trigger discovery and configuration validation.
* ``vcs_allowed_age`` - maximal age in seconds of the VCS packages before their version will be updated with its remote source, int, optional, default ``604800``.
``repository`` group
--------------------
Base repository settings.
* ``name`` - repository name, string, required.
* ``root`` - root path for application, string, required.
``sign:*`` groups
-----------------
Settings for signing packages or repository. Group name can refer to architecture, e.g. ``sign:x86_64`` can be used for x86_64 architecture specific settings.
* ``target`` - configuration flag to enable signing, space separated list of strings, required. Allowed values are ``package`` (sign each package separately), ``repository`` (sign repository database file).
* ``key`` - default PGP key, string, required. This key will also be used for database signing if enabled.
``web:*`` groups
----------------
Web server settings. If any of ``host``/``port`` is not set, web integration will be disabled. Group name can refer to architecture, e.g. ``web:x86_64`` can be used for x86_64 architecture specific settings. This feature requires ``aiohttp`` libraries to be installed.
* ``address`` - optional address in form ``proto://host:port`` (``port`` can be omitted in case of default ``proto`` ports), will be used instead of ``http://{host}:{port}`` in case if set, string, optional. This option is required in case if ``OAuth`` provider is used.
* ``debug`` - enable debug toolbar, boolean, optional, default ``no``.
* ``debug_check_host`` - check hosts to access debug toolbar, boolean, optional, default ``no``.
* ``debug_allowed_hosts`` - allowed hosts to get access to debug toolbar, space separated list of string, optional.
* ``enable_archive_upload`` - allow to upload packages via HTTP (i.e. call of ``/api/v1/service/upload`` uri), boolean, optional, default ``no``.
* ``host`` - host to bind, string, optional.
* ``index_url`` - full url of the repository index page, string, optional.
* ``max_body_size`` - max body size in bytes to be validated for archive upload, integer, optional. If not set, validation will be disabled.
* ``password`` - password to authorize in web service in order to update service status, string, required in case if authorization enabled.
* ``port`` - port to bind, int, optional.
* ``static_path`` - path to directory with static files, string, required.
* ``templates`` - path to templates directory, string, required.
* ``timeout`` - HTTP request timeout in seconds, int, optional, default is ``30``.
* ``unix_socket`` - path to the listening unix socket, string, optional. If set, server will create the socket on the specified address which can (and will) be used by application. Note, that unlike usual host/port configuration, unix socket allows to perform requests without authorization.
* ``unix_socket_unsafe`` - set unsafe (o+w) permissions to unix socket, boolean, optional, default ``yes``. This option is enabled by default, because it is supposed that unix socket is created in safe environment (only web service is supposed to be used in unsafe), but it can be disabled by configuration.
* ``username`` - username to authorize in web service in order to update service status, string, required in case if authorization enabled.
* ``wait_timeout`` - wait timeout in seconds, maximum amount of time to be waited before lock will be free, int, optional.
``keyring`` group
--------------------
Keyring package generator plugin.
* ``target`` - list of generator settings sections, space separated list of strings, required. It must point to valid section name.
Keyring generator plugin
^^^^^^^^^^^^^^^^^^^^^^^^
* ``type`` - type of the generator, string, optional, must be set to ``keyring-generator`` if exists.
* ``description`` - keyring package description, string, optional, default is ``repo PGP keyring``, where ``repo`` is the repository name.
* ``homepage`` - url to homepage location if any, string, optional.
* ``license`` - list of licenses which are applied to this package, space separated list of strings, optional, default is ``Unlicense``.
* ``package`` - keyring package name, string, optional, default is ``repo-keyring``, where ``repo`` is the repository name.
* ``packagers`` - list of packagers keys, space separated list of strings, optional, if not set, the ``key_*`` options from ``sign`` group will be used.
* ``revoked`` - list of revoked packagers keys, space separated list of strings, optional.
* ``trusted`` - list of master keys, space separated list of strings, optional, if not set, the ``key`` option from ``sign`` group will be used.
``mirrorlist`` group
--------------------
Mirrorlist package generator plugin.
* ``target`` - list of generator settings sections, space separated list of strings, required. It must point to valid section name.
Mirrorlist generator plugin
^^^^^^^^^^^^^^^^^^^^^^^^^^^
* ``type`` - type of the generator, string, optional, must be set to ``mirrorlist-generator`` if exists.
* ``description`` - mirrorlist package description, string, optional, default is ``repo mirror list for use by pacman``, where ``repo`` is the repository name.
* ``homepage`` - url to homepage location if any, string, optional.
* ``license`` - list of licenses which are applied to this package, space separated list of strings, optional, default is ``Unlicense``.
* ``package`` - mirrorlist package name, string, optional, default is ``repo-mirrorlist``, where ``repo`` is the repository name.
* ``path`` - absolute path to generated mirrorlist file, string, optional, default is ``/etc/pacman.d/repo-mirrorlist``, where ``repo`` is the repository name.
* ``servers`` - list of repository mirrors, space separated list of strings, required.
``remote-pull`` group
---------------------
Remote git source synchronization settings. Unlike ``Upload`` triggers those triggers are used for PKGBUILD synchronization - fetch from remote repository PKGBUILDs before updating process.
It supports authorization; to do so you'd need to prefix the url with authorization part, e.g. ``https://key:token@github.com/arcan1s/ahriman.git``. It is highly recommended to use application tokens instead of your user authorization details. Alternatively, you can use any other option supported by git, e.g.:
* by SSH key: generate SSH key as ``ahriman`` user and put public part of it to the repository keys.
* by git credentials helper: consult with the `related man page <https://git-scm.com/docs/gitcredentials>`_.
Available options are:
* ``target`` - list of remote pull triggers to be used, space separated list of strings, optional, defaults to ``gitremote``. It must point to valid section (or to section with architecture), e.g. ``gitremote`` must point to either ``gitremote`` or ``gitremote:x86_64`` (the one with architecture has higher priority).
Remote pull trigger
^^^^^^^^^^^^^^^^^^^
* ``pull_url`` - url of the remote repository from which PKGBUILDs can be pulled before build process, string, required.
* ``pull_branch`` - branch of the remote repository from which PKGBUILDs can be pulled before build process, string, optional, default is ``master``.
``remote-push`` group
---------------------
Remote git source synchronization settings. Same as remote pull triggers those triggers are used for PKGBUILD synchronization - push updated PKGBUILDs to the remote repository after build process.
It supports authorization; to do so you'd need to prefix the url with authorization part, e.g. ``https://key:token@github.com/arcan1s/ahriman.git``. It is highly recommended to use application tokens instead of your user authorization details. Alternatively, you can use any other option supported by git, e.g.:
* by SSH key: generate SSH key as ``ahriman`` user and put public part of it to the repository keys.
* by git credentials helper: consult with the `related man page <https://git-scm.com/docs/gitcredentials>`_.
Available options are:
* ``target`` - list of remote push triggers to be used, space separated list of strings, optional, defaults to ``gitremote``. It must point to valid section (or to section with architecture), e.g. ``gitremote`` must point to either ``gitremote`` or ``gitremote:x86_64`` (the one with architecture has higher priority).
Remote push trigger
^^^^^^^^^^^^^^^^^^^
* ``commit_email`` - git commit email, string, optional, default is ``ahriman@localhost``.
* ``commit_user`` - git commit user, string, optional, default is ``ahriman``.
* ``push_url`` - url of the remote repository to which PKGBUILDs should be pushed after build process, string, required.
* ``push_branch`` - branch of the remote repository to which PKGBUILDs should be pushed after build process, string, optional, default is ``master``.
``report`` group
----------------
Report generation settings.
* ``target`` - list of reports to be generated, space separated list of strings, required. It must point to valid section (or to section with architecture), e.g. ``somerandomname`` must point to existing section, ``email`` must point to either ``email`` or ``email:x86_64`` (the one with architecture has higher priority).
Type will be read from several sources:
* In case if ``type`` option set inside the section, it will be used.
* Otherwise, it will look for type from section name removing architecture name.
* And finally, it will use section name as type.
``console`` type
^^^^^^^^^^^^^^^^
Section name must be either ``console`` (plus optional architecture name, e.g. ``console:x86_64``) or random name with ``type`` set.
* ``type`` - type of the report, string, optional, must be set to ``console`` if exists.
* ``use_utf`` - use utf8 symbols in output if set and ascii otherwise, boolean, optional, default ``yes``.
``email`` type
^^^^^^^^^^^^^^
Section name must be either ``email`` (plus optional architecture name, e.g. ``email:x86_64``) or random name with ``type`` set.
* ``type`` - type of the report, string, optional, must be set to ``email`` if exists.
* ``full_template_path`` - path to Jinja2 template for full package description index, string, optional.
* ``homepage`` - link to homepage, string, optional.
* ``host`` - SMTP host for sending emails, string, required.
* ``link_path`` - prefix for HTML links, string, required.
* ``no_empty_report`` - skip report generation for empty packages list, boolean, optional, default ``yes``.
* ``password`` - SMTP password to authenticate, string, optional.
* ``port`` - SMTP port for sending emails, int, required.
* ``receivers`` - SMTP receiver addresses, space separated list of strings, required.
* ``sender`` - SMTP sender address, string, required.
* ``ssl`` - SSL mode for SMTP connection, one of ``ssl``, ``starttls``, ``disabled``, optional, default ``disabled``.
* ``template_path`` - path to Jinja2 template, string, required.
* ``user`` - SMTP user to authenticate, string, optional.
``html`` type
^^^^^^^^^^^^^
Section name must be either ``html`` (plus optional architecture name, e.g. ``html:x86_64``) or random name with ``type`` set.
* ``type`` - type of the report, string, optional, must be set to ``html`` if exists.
* ``homepage`` - link to homepage, string, optional.
* ``link_path`` - prefix for HTML links, string, required.
* ``path`` - path to html report file, string, required.
* ``template_path`` - path to Jinja2 template, string, required.
``remote-call`` type
^^^^^^^^^^^^^^^^^^^^
Section name must be either ``remote-call`` (plus optional architecture name, e.g. ``remote-call:x86_64``) or random name with ``type`` set.
* ``type`` - type of the report, string, optional, must be set to ``remote-call`` if exists.
* ``aur`` - check for AUR packages updates, boolean, optional, default ``no``.
* ``local`` - check for local packages updates, boolean, optional, default ``no``.
* ``manual`` - update manually built packages, boolean, optional, default ``no``.
* ``wait_timeout`` - maximum amount of time in seconds to be waited before remote process will be terminated, int, optional, default ``-1``.
``telegram`` type
^^^^^^^^^^^^^^^^^
Section name must be either ``telegram`` (plus optional architecture name, e.g. ``telegram:x86_64``) or random name with ``type`` set.
* ``type`` - type of the report, string, optional, must be set to ``telegram`` if exists.
* ``api_key`` - telegram bot API key, string, required. Please refer FAQ about how to create chat and bot
* ``chat_id`` - telegram chat id, either string with ``@`` or integer value, required.
* ``homepage`` - link to homepage, string, optional.
* ``link_path`` - prefix for HTML links, string, required.
* ``template_path`` - path to Jinja2 template, string, required.
* ``template_type`` - ``parse_mode`` to be passed to telegram API, one of ``MarkdownV2``, ``HTML``, ``Markdown``, string, optional, default ``HTML``.
* ``timeout`` - HTTP request timeout in seconds, int, optional, default is ``30``.
``upload`` group
----------------
Remote synchronization settings.
* ``target`` - list of synchronizations to be used, space separated list of strings, required. It must point to valid section (or to section with architecture), e.g. ``somerandomname`` must point to existing section, ``github`` must point to one of ``github`` of ``github:x86_64`` (with architecture it has higher priority).
Type will be read from several sources:
* In case if ``type`` option set inside the section, it will be used.
* Otherwise, it will look for type from section name removing architecture name.
* And finally, it will use section name as type.
``github`` type
^^^^^^^^^^^^^^^
This feature requires Github key creation (see below). Section name must be either ``github`` (plus optional architecture name, e.g. ``github:x86_64``) or random name with ``type`` set.
* ``type`` - type of the upload, string, optional, must be set to ``github`` if exists.
* ``owner`` - Github repository owner, string, required.
* ``password`` - created Github API key. In order to create it do the following:
#. Go to `settings page <https://github.com/settings/profile>`_.
#. Switch to `developers settings <https://github.com/settings/apps>`_.
#. Switch to `personal access tokens <https://github.com/settings/tokens>`_.
#. Generate new token. Required scope is ``public_repo`` (or ``repo`` for private repository support).
* ``repository`` - Github repository name, string, required. Repository must be created before any action and must have active branch (e.g. with readme).
* ``timeout`` - HTTP request timeout in seconds, int, optional, default is ``30``.
* ``username`` - Github authorization user, string, required. Basically the same as ``owner``.
``remote-service`` type
^^^^^^^^^^^^^^^^^^^^^^^
Section name must be either ``remote-service`` (plus optional architecture name, e.g. ``remote-service:x86_64``) or random name with ``type`` set.
* ``type`` - type of the report, string, optional, must be set to ``remote-service`` if exists.
* ``timeout`` - HTTP request timeout in seconds, int, optional, default is ``30``.
``rsync`` type
^^^^^^^^^^^^^^
Requires ``rsync`` package to be installed. Do not forget to configure ssh for user ``ahriman``. Section name must be either ``rsync`` (plus optional architecture name, e.g. ``rsync:x86_64``) or random name with ``type`` set.
* ``type`` - type of the upload, string, optional, must be set to ``rsync`` if exists.
* ``command`` - rsync command to run, space separated list of string, required.
* ``remote`` - remote server to rsync (e.g. ``1.2.3.4:path/to/sync``), string, required.
``s3`` type
^^^^^^^^^^^
Requires ``boto3`` library to be installed. Section name must be either ``s3`` (plus optional architecture name, e.g. ``s3:x86_64``) or random name with ``type`` set.
* ``type`` - type of the upload, string, optional, must be set to ``github`` if exists.
* ``access_key`` - AWS access key ID, string, required.
* ``bucket`` - bucket name (e.g. ``bucket``), string, required.
* ``chunk_size`` - chunk size for calculating entity tags, int, optional, default 8 * 1024 * 1024.
* ``region`` - bucket region (e.g. ``eu-central-1``), string, required.
* ``secret_key`` - AWS secret access key, string, required.

1278
docs/faq.rst Normal file

File diff suppressed because it is too large Load Diff

40
docs/index.rst Normal file
View File

@ -0,0 +1,40 @@
Welcome to ahriman's documentation!
===================================
Wrapper for managing custom repository inspired by `repo-scripts <https://github.com/arcan1s/repo-scripts>`_.
Features
--------
* Install-configure-forget manager for the very own repository.
* Multi-architecture support.
* Dependency manager.
* VCS packages support.
* Official repository support.
* Ability to patch AUR packages and even create package from local PKGBUILDs.
* Various rebuild options with ability to automatically bump package version.
* Sign support with gpg (repository, package), multiple packagers support.
* Triggers for repository updates, e.g. synchronization to remote services (rsync, s3 and github) and report generation (email, html, telegram).
* Repository status interface with optional authorization and control options.
Live demos
----------
* `Build status page <https://ahriman-demo.arcanis.me>`_. You can login as ``demo`` user by using ``demo`` password. Note, however, you will not be able to run tasks. `HTTP API documentation <https://ahriman-demo.arcanis.me/api-docs>`_ is also available.
* `Repository index <http://repo.arcanis.me/x86_64/index.html>`_.
* `Telegram feed <https://t.me/arcanisrepo>`_.
Contents
--------
.. toctree::
:maxdepth: 2
setup
configuration
command-line
faq
architecture
advanced-usage
triggers
modules

7
docs/modules.rst Normal file
View File

@ -0,0 +1,7 @@
Modules
=======
.. toctree::
:maxdepth: 4
ahriman

93
docs/setup.rst Normal file
View File

@ -0,0 +1,93 @@
Initial setup
=============
#.
Install package as usual.
#.
Change settings if required, see :doc:`configuration reference <configuration>` for more details.
#.
Perform initial setup:
.. code-block:: shell
sudo ahriman -a x86_64 service-setup ...
``service-setup`` literally does the following steps:
#.
Create ``/var/lib/ahriman/.makepkg.conf`` with ``makepkg.conf`` overrides if required (at least you might want to set ``PACKAGER``):
.. code-block:: shell
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):
#.
Create build command (you can choose any name for command, basically it should be ``{name}-{arch}-build``):
.. code-block:: shell
ln -s /usr/bin/archbuild /usr/local/bin/ahriman-x86_64-build
#.
Create configuration file (same as previous ``{name}.conf``):
.. code-block:: shell
cp /usr/share/devtools/pacman.conf.d/{extra,ahriman}.conf
#.
Change configuration file, add your own repository, add multilib repository etc:
.. code-block:: shell
echo '[multilib]' | tee -a /usr/share/devtools/pacman-ahriman.conf
echo 'Include = /etc/pacman.d/mirrorlist' | tee -a /usr/share/devtools/pacman.conf.d/ahriman.conf
echo '[aur-clone]' | tee -a /usr/share/devtools/pacman-ahriman.conf
echo 'SigLevel = Optional TrustAll' | tee -a /usr/share/devtools/pacman.conf.d/ahriman.conf
echo 'Server = file:///var/lib/ahriman/repository/$arch' | tee -a /usr/share/devtools/pacman.conf.d/ahriman.conf
#.
Set ``build_command`` option to point to your command:
.. code-block:: shell
echo '[build]' | tee -a /etc/ahriman.ini.d/build.ini
echo 'build_command = ahriman-x86_64-build' | tee -a /etc/ahriman.ini.d/build.ini
#.
Configure ``/etc/sudoers.d/ahriman`` to allow running command without a password:
.. code-block:: shell
echo 'Cmnd_Alias CARCHBUILD_CMD = /usr/local/bin/ahriman-x86_64-build *' | tee -a /etc/sudoers.d/ahriman
echo 'ahriman ALL=(ALL) NOPASSWD:SETENV: CARCHBUILD_CMD' | tee -a /etc/sudoers.d/ahriman
chmod 400 /etc/sudoers.d/ahriman
This command supports several arguments, kindly refer to its help message.
#.
Start and enable ``ahriman@.timer`` via ``systemctl``:
.. code-block:: shell
systemctl enable --now ahriman@x86_64.timer
#.
Start and enable status page:
.. code-block:: shell
systemctl enable --now ahriman-web@x86_64
#.
Add packages by using ``ahriman package-add {package}`` command:
.. code-block:: shell
sudo -u ahriman ahriman -a x86_64 package-add ahriman --now --refresh
The ``--refresh`` flag is required in order to handle local database update.

142
docs/triggers.rst Normal file
View File

@ -0,0 +1,142 @@
Triggers
========
The package provides ability to write custom extensions which will be run on (the most) actions, e.g. after updates. By default ahriman provides three types of extensions - reporting, files uploading and PKGBUILD syncronization. Each extension must derive from the ``ahriman.core.triggers.Trigger`` class and should implement at least one of the abstract methods:
* ``on_result`` - trigger action which will be called after build process, the build result and the list of repository packages will be supplied as arguments.
* ``on_start`` - trigger action which will be called right before the start of the application process.
* ``on_stop`` - action which will be called right before the exit.
Note, it isn't required to implement all of those methods (or even one of them), however, it is highly recommended to avoid trigger actions in ``__init__`` method as it will be run on any application start (e.g. even if you are just searching in AUR).
Built-in triggers
-----------------
For the configuration details and settings explanation kindly refer to the :doc:`documentation <configuration>`.
``ahriman.core.gitremote.RemotePullTrigger``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This trigger will be called before any action (``on_start``) and pulls remote PKGBUILD repository locally; after that it copies found PKGBUILDs from the cloned repository to the local cache. It is useful in case if you have patched PGKBUILDs (or even missing in AUR) which you would like to use for package building and, technically, just simplifies the local package building.
In order to update those packages you would need to clone your repository separately, make changes in PKGBUILD (e.g. bump version and update checksums), commit them and push back. On the next ahriman's repository update, it will pull changes you committed and will perform package update.
``ahriman.core.gitremote.RemotePushTrigger``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This trigger will be called right after build process (``on_result``). It will pick PKGBUILDs for the updated packages, pull them (together with any other files) and commit and push changes to remote repository. No real use cases, but the most of user repositories do it.
``ahriman.core.report.ReportTrigger``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Trigger which can be used for reporting. It implements ``on_result`` method and thus being called on each build update and generates report (e.g. html, telegram etc) according to the current settings.
``ahriman.core.support.KeyringTrigger``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Generator for keyring package. This trigger will extract keys from local keychain and pack them into keyring specific format. This trigger will generate sources including PKGBUILD, which can be used later for package building.
``ahriman.core.support.MirrorlistTrigger``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Simple generator for mirrorlist package, based on the urls which were set by configuration. This trigger will generate sources including PKGBUILD, which can be used later for package building.
``ahriman.core.upload.UploadTrigger``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This trigger takes build result (``on_result``) and performs syncing of the local packages to the remote mirror (e.g. S3 or just by rsync).
Context variables
-----------------
By default, only configuration and architecture are passed to triggers. However, some triggers might want to have access to other high-level wrappers. In order to provide such ability and avoid (double) initialization, the service provides a global context variables, which can be accessed from ``ahriman.core`` package:
.. code-block:: python
from ahriman.core import context
ctx = context.get()
Just because context is wrapped inside ``contexvars.ContextVar``, you need to explicitly extract variable by ``get()`` method. Later you can extract any variable if it is set, e.g.:
.. code-block:: python
from ahriman.core.database import SQLite
from ahriman.models.context_key import ContextKey
database = ctx.get(ContextKey("database", SQLite))
In order to provide typed API, all variables are stored together with their type. The ``get(ContextKey)`` method will throw ``KeyError`` in case if key is missing. Alternatively you can set your own variable inside context:
.. code-block:: python
ctx.set(ContextKey("answer", int), 42)
context.set(ctx)
Note, however, that there are several limitations:
* Context variables are immutable, thus you cannot override value if the key already presented.
* The ``return_type`` of ``ContextKey`` should match the value type, otherwise exception will be thrown.
The ``context`` also implements collection methods such as ``__iter__`` and ``__len__``.
Trigger example
---------------
Lets consider example of reporting trigger (e.g. `slack <https://slack.com/>`_, which provides easy HTTP API for integration triggers).
In order to post message to slack we will need a specific trigger url (something like ``https://hooks.slack.com/services/company_id/trigger_id``), channel (e.g. ``#archrepo``) and username (``repo-bot``).
As it has been mentioned, our trigger must derive from specific class:
.. code-block:: python
from ahriman.core.triggers import Trigger
class SlackReporter(Trigger):
def __init__(self, architecture, configuration):
Trigger.__init__(self, architecture, configuration)
self.slack_url = configuration.get("slack", "url")
self.channel = configuration.get("slack", "channel")
self.username = configuration.get("slack", "username")
By now we have class with all required variables. Lets implement run method. Slack API requires positing data with specific payload by HTTP, thus:
.. code-block:: python
import json
import requests
def notify(result, slack_url, channel, username):
text = f"""Build has been completed with packages: {", ".join([package.name for package in result.success])}"""
payload = {"channel": channel, "username": username, "text": text}
response = requests.post(slack_url, data={"payload": json.dumps(payload)})
response.raise_for_status()
Obviously you can implement the specified method in class, but for guide purpose it has been done as separated method. Now we can merge this method into the class:
.. code-block:: python
class SlackReporter(Trigger):
def __init__(self, architecture, configuration):
Trigger.__init__(self, architecture, configuration)
self.slack_url = configuration.get("slack", "url")
self.channel = configuration.get("slack", "channel")
self.username = configuration.get("slack", "username")
def on_result(self, result, packages):
notify(result, self.slack_url, self.channel, self.username)
Setup the trigger
^^^^^^^^^^^^^^^^^
First, put the trigger in any path it can be exported, e.g. by packing the resource into python package (which will lead to import path as ``package.slack_reporter.SlackReporter``) or just put file somewhere it can be accessed by application (e.g. ``/usr/local/lib/slack_reporter.py.SlackReporter``).
After that run application as usual and receive notification in your slack channel.
Trigger configuration schema
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Triggers can expose their configuration schema. It can be achieved by implementing ``CONFIGURATION_SCHEMA`` class variable according to `cerberus <https://docs.python-cerberus.org/>`_ documentation. For more details and examples, please refer to built-in triggers implementations.

BIN
github-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View File

@ -1,45 +1,61 @@
# Maintainer: Evgeniy Alekseev
pkgname='ahriman'
pkgver=0.15.0
pkgver=2.11.0
pkgrel=1
pkgdesc="ArcHlinux ReposItory MANager"
pkgdesc="ArcH linux ReposItory MANager"
arch=('any')
url="https://github.com/arcan1s/ahriman"
license=('GPL3')
depends=('devtools' 'git' 'pyalpm' 'python-aur' 'python-srcinfo')
makedepends=('python-pip')
optdepends=('aws-cli: sync to s3'
'breezy: -bzr packages support'
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-cerberus' 'python-inflection' 'python-passlib' 'python-requests' 'python-srcinfo')
makedepends=('python-build' 'python-flit' 'python-installer' 'python-wheel')
optdepends=('breezy: -bzr packages support'
'darcs: -darcs packages support'
'gnupg: package and repository sign'
'mercurial: -hg packages support'
'python-aioauth-client: web server with OAuth2 authorization'
'python-aiohttp: web server'
'python-aiohttp-apispec>=3.0.0: web server'
'python-aiohttp-cors: web server'
'python-aiohttp-debugtoolbar: web server with enabled debug panel'
'python-aiohttp-jinja2: web server'
'python-aiohttp-security: web server with authorization'
'python-aiohttp-session: web server with authorization'
'python-boto3: sync to s3'
'python-cryptography: web server with authorization'
'python-requests-unixsocket: client report to web server by unix socket'
'python-jinja: html report generation'
'python-requests: web server'
'python-systemd: journal support'
'rsync: sync by using rsync'
'subversion: -svn packages support')
source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgname-$pkgver-src.tar.xz"
'ahriman.sysusers'
'ahriman.tmpfiles')
sha512sums=('a1db44390ce1785da3d535e3cfd2242d8d56070228eb9b3c1d5629163b65941d60753c481c0fdc69e475e534a828ceea39568dc6711abeee092616dac08e31a9'
'13718afec2c6786a18f0b223ef8e58dccf0688bca4cdbe203f14071f5031ed20120eb0ce38b52c76cfd6e8b6581a9c9eaa2743eb11abbaca637451a84c33f075'
'55b20f6da3d66e7bbf2add5d95a3b60632df121717d25a993e56e737d14f51fe063eb6f1b38bd81cc32e05db01c0c1d80aaa720c45cde87f238d8b46cdb8cbc4')
install="$pkgname.install"
backup=('etc/ahriman.ini'
'etc/ahriman.ini.d/logging.ini')
build() {
cd "$pkgname"
python setup.py build
python -m build --wheel --no-isolation
}
package() {
cd "$pkgname"
python setup.py install --root="$pkgdir"
python -m installer --destdir="$pkgdir" "dist/$pkgname-$pkgver-py3-none-any.whl"
# thanks too PEP517, which we all wanted, you need to install data files manually nowadays
pushd package && find . -type f -exec install -Dm644 "{}" "$pkgdir/usr/{}" \; && popd
# keep usr/share configs as reference and copy them to /etc
install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini" "$pkgdir/etc/ahriman.ini"
install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini.d/logging.ini" "$pkgdir/etc/ahriman.ini.d/logging.ini"
install -Dm644 "$srcdir/$pkgname.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgname.conf"
install -Dm644 "$srcdir/$pkgname.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgname.conf"
}
sha512sums=('19841842641520b573cdde6cb80a7cfcd69756d323fdfeebc2eee2d264a1325ead4ab2f8383bb369f7896bfc1de59d7358f133f4afeb90a9b9f0695f482a58d0'
'53d37efec812afebf86281716259f9ea78a307b83897166c72777251c3eebcb587ecee375d907514781fb2a5c808cbb24ef9f3f244f12740155d0603bf213131'
'62b2eccc352d33853ef243c9cddd63663014aa97b87242f1b5bc5099a7dbd69ff3821f24ffc58e1b7f2387bd4e9e9712cc4c67f661b1724ad99cdf09b3717794')

View File

@ -0,0 +1,25 @@
post_upgrade() {
local breakpoints=(
2.9.0-1
)
for v in "${breakpoints[@]}"; do
if [[ $(vercmp "$v" "$2") -eq 1 ]]; then
"_${v//[.-]/_}_changes"
fi
done
}
_2_9_0_1_changes() {
cat << EOF
It was found that you were upgrading from old-devtools package to the new one, which requires manual intervention:
* make sure that devtools are upgraded to the latest release;
* merge service configuration if required;
* run setup command (i.e. sudo ahriman service-setup) with the same arguments as you did before;
* remove build chroot: sudo rm -r /var/lib/ahriman/chroot/ahriman-x86_64/;
* update local databases: sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy;
For more information kindly refer to changelog https://github.com/arcan1s/ahriman/releases/tag/2.9.0
EOF
}

View File

@ -1 +1 @@
u ahriman 643 "ArcHlinux ReposItory MANager" /var/lib/ahriman
u ahriman 643 "ArcH linux ReposItory MANager" /var/lib/ahriman

View File

@ -1,2 +1 @@
d /var/lib/ahriman 0775 ahriman log
d /var/log/ahriman 0755 ahriman ahriman
d /var/lib/ahriman 0755 ahriman ahriman

View File

@ -1,3 +0,0 @@
#!/bin/sh
exec python -B -m ahriman.application.ahriman "$@"

View File

@ -1,47 +0,0 @@
[settings]
include = /etc/ahriman.ini.d
logging = /etc/ahriman.ini.d/logging.ini
[alpm]
aur_url = https://aur.archlinux.org
database = /var/lib/pacman
repositories = core extra community multilib
root = /
[build]
archbuild_flags =
build_command = extra-x86_64-build
ignore_packages =
makechrootpkg_flags =
makepkg_flags = --skippgpcheck
[repository]
name = aur-clone
root = /var/lib/ahriman
[sign]
target =
key =
[report]
target =
[html]
path =
homepage =
link_path =
template_path = /usr/share/ahriman/repo-index.jinja2
[upload]
target =
[rsync]
remote =
[s3]
bucket =
[web]
host =
port =
templates = /usr/share/ahriman

View File

@ -1,59 +0,0 @@
[loggers]
keys = root,builder,build_details,http
[handlers]
keys = console_handler,build_file_handler,file_handler,http_handler
[formatters]
keys = generic_format
[handler_console_handler]
class = StreamHandler
level = DEBUG
formatter = generic_format
args = (sys.stderr,)
[handler_file_handler]
class = logging.handlers.RotatingFileHandler
level = DEBUG
formatter = generic_format
args = ('/var/log/ahriman/ahriman.log', 'a', 20971520, 20)
[handler_build_file_handler]
class = logging.handlers.RotatingFileHandler
level = DEBUG
formatter = generic_format
args = ('/var/log/ahriman/build.log', 'a', 20971520, 20)
[handler_http_handler]
class = logging.handlers.RotatingFileHandler
level = DEBUG
formatter = generic_format
args = ('/var/log/ahriman/http.log', 'a', 20971520, 20)
[formatter_generic_format]
format = [%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d] [%(funcName)s]: %(message)s
datefmt =
[logger_root]
level = DEBUG
handlers = file_handler
qualname = root
[logger_builder]
level = DEBUG
handlers = file_handler
qualname = builder
propagate = 0
[logger_build_details]
level = DEBUG
handlers = build_file_handler
qualname = build_details
propagate = 0
[logger_http]
level = DEBUG
handlers = http_handler
qualname = http
propagate = 0

View File

@ -1,5 +1,5 @@
[Unit]
Description=ArcHlinux ReposItory MANager web server (%I architecture)
Description=ArcH linux ReposItory MANager web server (%I architecture)
After=network.target
[Service]
@ -8,8 +8,5 @@ ExecStart=/usr/bin/ahriman --architecture %i web
User=ahriman
Group=ahriman
KillSignal=SIGQUIT
SuccessExitStatus=SIGQUIT
[Install]
WantedBy=multi-user.target

View File

@ -1,7 +1,7 @@
[Unit]
Description=ArcHlinux ReposItory MANager (%I architecture)
Description=ArcH linux ReposItory MANager (%I architecture)
[Service]
ExecStart=/usr/bin/ahriman --architecture %i update
ExecStart=/usr/bin/ahriman --architecture %i repo-update --refresh
User=ahriman
Group=ahriman

View File

@ -1,5 +1,5 @@
[Unit]
Description=ArcHlinux ReposItory MANager timer (%I architecture)
Description=ArcH linux ReposItory MANager timer (%I architecture)
[Timer]
OnCalendar=daily

View File

@ -1,54 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>{{ repository|e }}</title>
{% include "style.jinja2" %}
{% include "sorttable.jinja2" %}
{% include "search.jinja2" %}
</head>
<body>
<div class="root">
<h1>ahriman
<img src="https://img.shields.io/badge/version-{{ version|e }}-informational" alt="{{ version|e }}">
<img src="https://img.shields.io/badge/architecture-{{ architecture|e }}-informational" alt="{{ architecture|e }}">
<img src="https://img.shields.io/badge/service%20status-{{ service.status|e }}-{{ service.status_color|e }}" alt="{{ service.status|e }}" title="{{ service.timestamp|e }}">
</h1>
{% include "search-line.jinja2" %}
<section class="element">
<table class="sortable search-table">
<tr class="header">
<th>package base</th>
<th>packages</th>
<th>version</th>
<th>last update</th>
<th>status</th>
</tr>
{% for package in packages %}
<tr class="package">
<td class="include-search"><a href="{{ package.web_url|e }}" title="{{ package.base|e }}">{{ package.base|e }}</a></td>
<td class="include-search">{{ package.packages|join("<br>"|safe) }}</td>
<td>{{ package.version|e }}</td>
<td>{{ package.timestamp|e }}</td>
<td class="status package-{{ package.status|e }}">{{ package.status|e }}</td>
</tr>
{% endfor %}
</table>
</section>
<footer>
<ul class="navigation">
<li><a href="https://github.com/arcan1s/ahriman" title="sources">ahriman</a></li>
<li><a href="https://github.com/arcan1s/ahriman/releases" title="releases list">releases</a></li>
<li><a href="https://github.com/arcan1s/ahriman/issues" title="issues tracker">report a bug</a></li>
</ul>
</footer>
</div>
</body>
</html>

View File

@ -1,62 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<title>{{ repository|e }}</title>
{% include "style.jinja2" %}
{% include "sorttable.jinja2" %}
{% include "search.jinja2" %}
</head>
<body>
<div class="root">
<h1>Archlinux user repository</h1>
<section class="element">
{% if pgp_key is not none %}
<p>This repository is signed with <a href="http://keys.gnupg.net/pks/lookup?search=0x{{ pgp_key|e }}&fingerprint=on&op=index" title="key search">{{ pgp_key|e }}</a> by default.</p>
{% endif %}
<code>
$ cat /etc/pacman.conf<br>
[{{ repository|e }}]<br>
Server = {{ link_path|e }}<br>
SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Package{% if has_package_signed %}Required{% else %}Never{% endif %} TrustedOnly
</code>
</section>
{% include "search-line.jinja2" %}
<section class="element">
<table class="sortable search-table">
<tr class="header">
<th>package</th>
<th>version</th>
<th>archive size</th>
<th>installed size</th>
<th>build date</th>
</tr>
{% for package in packages %}
<tr class="package">
<td class="include-search"><a href="{{ link_path|e }}/{{ package.filename|e }}" title="{{ package.name|e }}">{{ package.name|e }}</a></td>
<td>{{ package.version|e }}</td>
<td>{{ package.archive_size|e }}</td>
<td>{{ package.installed_size|e }}</td>
<td>{{ package.build_date|e }}</td>
</tr>
{% endfor %}
</table>
</section>
<footer>
<ul class="navigation">
{% if homepage is not none %}
<li><a href="{{ homepage|e }}" title="homepage">Homepage</a></li>
{% endif %}
</ul>
</footer>
</div>
</body>
</html>

View File

@ -1,3 +0,0 @@
<section class="element">
<input type="search" id="search" onkeyup="searchInTable()" placeholder="search for package" title="search for package"/>
</section>

View File

@ -1,25 +0,0 @@
<script type="text/javascript">
function searchInTable() {
const input = document.getElementById("search");
const filter = input.value.toLowerCase();
const tables = document.getElementsByClassName("search-table");
for (let i = 0; i < tables.length; i++) {
const tr = tables[i].getElementsByTagName("tr");
// from 1 coz of header
for (let i = 1; i < tr.length; i++) {
let td = tr[i].getElementsByClassName("include-search");
let display = "none";
for (let j = 0; j < td.length; j++) {
if (td[j].tagName.toLowerCase() === "td") {
if (td[j].innerHTML.toLowerCase().indexOf(filter) > -1) {
display = "";
break;
}
}
}
tr[i].style.display = display;
}
}
}
</script>

View File

@ -0,0 +1,83 @@
[settings]
include = ahriman.ini.d
logging = ahriman.ini.d/logging.ini
database = /var/lib/ahriman/ahriman.db
suppress_http_log_errors = yes
[alpm]
database = /var/lib/pacman
mirror = https://geo.mirror.pkgbuild.com/$repo/os/$arch
repositories = core extra multilib
root = /
use_ahriman_cache = yes
[auth]
target = disabled
max_age = 604800
oauth_provider = GoogleClient
oauth_scopes = https://www.googleapis.com/auth/userinfo.email
allow_read_only = yes
[build]
archbuild_flags =
build_command = extra-x86_64-build
ignore_packages =
makechrootpkg_flags =
makepkg_flags = --nocolor --ignorearch
triggers = ahriman.core.gitremote.RemotePullTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.gitremote.RemotePushTrigger
triggers_known = ahriman.core.gitremote.RemotePullTrigger ahriman.core.gitremote.RemotePushTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.support.KeyringTrigger ahriman.core.support.MirrorlistTrigger
vcs_allowed_age = 604800
[repository]
name = aur-clone
root = /var/lib/ahriman
[sign]
target =
[keyring]
target =
[mirrorlist]
target =
[remote-pull]
target =
[remote-push]
target =
[report]
target = console
[console]
use_utf = yes
[email]
no_empty_report = yes
template_path = /usr/share/ahriman/templates/email-index.jinja2
ssl = disabled
[html]
template_path = /usr/share/ahriman/templates/repo-index.jinja2
[telegram]
template_path = /usr/share/ahriman/templates/telegram-index.jinja2
[upload]
target =
[rsync]
command = rsync --archive --compress --partial --delete
[s3]
chunk_size = 8388608
[web]
debug = no
debug_check_host = no
debug_allowed_hosts =
host = 127.0.0.1
static_path = /usr/share/ahriman/templates/static
templates = /usr/share/ahriman/templates
unix_socket_unsafe = yes

View File

@ -0,0 +1,66 @@
[loggers]
keys = root,http,stderr,boto3,botocore,nose,s3transfer
[handlers]
keys = console_handler,journald_handler,syslog_handler
[formatters]
keys = generic_format,syslog_format
[handler_console_handler]
class = logging.StreamHandler
level = DEBUG
formatter = generic_format
args = (sys.stderr,)
[handler_journald_handler]
class = ahriman.core.log.journal_handler.JournalHandler
level = DEBUG
formatter = syslog_format
kwargs = {"SYSLOG_IDENTIFIER": "ahriman"}
[handler_syslog_handler]
class = logging.handlers.SysLogHandler
level = DEBUG
formatter = syslog_format
args = ("/dev/log",)
[formatter_generic_format]
format = [%(levelname)s %(asctime)s] [%(name)s]: %(message)s
[formatter_syslog_format]
format = [%(levelname)s] [%(name)s]: %(message)s
[logger_root]
level = DEBUG
qualname = root
[logger_http]
level = DEBUG
qualname = http
propagate = 0
[logger_stderr]
level = DEBUG
handlers = console_handler
qualname = stderr
[logger_boto3]
level = INFO
qualname = boto3
propagate = 0
[logger_botocore]
level = INFO
qualname = botocore
propagate = 0
[logger_nose]
level = INFO
qualname = nose
propagate = 0
[logger_s3transfer]
level = INFO
qualname = s3transfer
propagate = 0

View File

@ -1 +0,0 @@
<script src="https://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>

View File

@ -1,136 +0,0 @@
<style>
:root {
--color-building: 255, 255, 146;
--color-failed: 255, 94, 94;
--color-pending: 255, 255, 146;
--color-success: 94, 255, 94;
--color-unknown: 225, 225, 225;
--color-header: 200, 200, 255;
--color-hover: 255, 255, 225;
--color-line-blue: 235, 235, 255;
--color-line-white: 255, 255, 255;
}
@keyframes blink-building {
0% { background-color: rgba(var(--color-building), 1.0); }
10% { background-color: rgba(var(--color-building), 0.9); }
20% { background-color: rgba(var(--color-building), 0.8); }
30% { background-color: rgba(var(--color-building), 0.7); }
40% { background-color: rgba(var(--color-building), 0.6); }
50% { background-color: rgba(var(--color-building), 0.5); }
60% { background-color: rgba(var(--color-building), 0.4); }
70% { background-color: rgba(var(--color-building), 0.3); }
80% { background-color: rgba(var(--color-building), 0.2); }
90% { background-color: rgba(var(--color-building), 0.1); }
100% { background-color: rgba(var(--color-building), 0.0); }
}
div.root {
width: 70%;
padding: 15px 15% 0;
}
section.element, footer {
width: 100%;
padding: 10px 0;
}
code, input, table {
width: inherit;
}
th, td {
padding: 5px;
}
tr.package:nth-child(odd) {
background-color: rgba(var(--color-line-white), 1.0);
}
tr.package:nth-child(even) {
background-color: rgba(var(--color-line-blue), 1.0);
}
tr.package:hover {
background-color: rgba(var(--color-hover), 1.0);
}
tr.header{
background-color: rgba(var(--color-header), 1.0);
}
td.status {
text-align: center;
}
td.package-unknown {
background-color: rgba(var(--color-unknown), 1.0);
}
td.package-pending {
background-color: rgba(var(--color-pending), 1.0);
}
td.package-building {
background-color: rgba(var(--color-building), 1.0);
animation-name: blink-building;
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
td.package-failed {
background-color: rgba(var(--color-failed), 1.0);
}
td.package-success {
background-color: rgba(var(--color-success), 1.0);
}
li.service-unknown {
background-color: rgba(var(--color-unknown), 1.0);
}
li.service-building {
background-color: rgba(var(--color-building), 1.0);
animation-name: blink-building;
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: infinite;
animation-direction: alternate;
}
li.service-failed {
background-color: rgba(var(--color-failed), 1.0);
}
li.service-success {
background-color: rgba(var(--color-success), 1.0);
}
ul.navigation {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: rgba(var(--color-header), 1.0);
}
ul.navigation li {
float: left;
}
ul.navigation li.status {
display: block;
text-align: center;
text-decoration: none;
padding: 14px 16px;
}
ul.navigation li a {
display: block;
color: black;
text-align: center;
text-decoration: none;
padding: 14px 16px;
}
ul.navigation li a:hover {
background-color: rgba(var(--color-hover), 1.0);
}
</style>

View File

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ahriman API</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Embed elements Elements via Web Component -->
<script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css" type="text/css">
<link rel="shortcut icon" href="/static/favicon.ico">
</head>
<body>
<elements-api
apiDescriptionUrl="/api-docs/swagger.json"
router="hash"
layout="sidebar"
/>
</body>
</html>

View File

@ -0,0 +1,148 @@
<!doctype html>
<html lang="en">
<head>
<title>{{ repository }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="shortcut icon" href="/static/favicon.ico">
{% include "utils/style.jinja2" %}
</head>
<body>
{% include "utils/bootstrap-scripts.jinja2" %}
<div class="container">
<h1 id="badge-repository">ahriman</h1>
</div>
<div id="alert-placeholder" class="toast-container p3 top-0 start-50 translate-middle-x"></div>
<div class="container">
<div id="toolbar" class="dropdown">
<a id="badge-status" tabindex="0" role="button" class="btn btn-outline-secondary" data-bs-toggle="popover" data-bs-trigger="focus" data-bs-content="no run data"><i class="bi bi-info-circle"></i></a>
{% if not auth.enabled or auth.username is not none %}
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-box"></i> packages
</button>
<ul class="dropdown-menu">
<li>
<button id="package-add-btn" class="btn dropdown-item" data-bs-toggle="modal" data-bs-target="#package-add-modal" hidden>
<i class="bi bi-plus"></i> add
</button>
</li>
<li>
<button id="package-update-btn" class="btn dropdown-item" onclick="updatePackages()" hidden>
<i class="bi bi-play"></i> update
</button>
</li>
<li>
<button id="package-rebuild-btn" class="btn dropdown-item" data-bs-toggle="modal" data-bs-target="#package-rebuild-modal" hidden>
<i class="bi bi-arrow-clockwise"></i> rebuild
</button>
</li>
<li>
<button id="package-remove-btn" class="btn dropdown-item" onclick="removePackages()" disabled hidden>
<i class="bi bi-trash"></i> remove
</button>
</li>
</ul>
<button id="key-import-btn" type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#key-import-modal" hidden>
<i class="bi bi-key"></i> import key
</button>
{% endif %}
<button type="button" class="btn btn-secondary" onclick="reload()">
<i class="bi bi-arrow-clockwise"></i> reload
</button>
</div>
<table id="packages" class="table table-striped table-hover"
data-export-options='{"fileName": "packages"}'
data-filter-control="true"
data-filter-control-visible="false"
data-page-list="[10, 25, 50, 100, all]"
data-page-size="10"
data-pagination="true"
data-resizable="true"
data-search="true"
data-show-columns="true"
data-show-columns-search="true"
data-show-columns-toggle-all="true"
data-show-export="true"
data-show-filter-control-switch="true"
data-show-fullscreen="true"
data-show-search-clear-button="true"
data-sortable="true"
data-sort-name="base"
data-sort-order="asc"
data-toggle="table"
data-toolbar="#toolbar">
<thead class="table-primary">
<tr>
<th data-checkbox="true"></th>
<th data-sortable="true" data-switchable="false" data-field="base" data-filter-control="input" data-filter-control-placeholder="(any base)">package base</th>
<th data-sortable="true" data-field="version" data-filter-control="input" data-filter-control-placeholder="(any version)">version</th>
<th data-sortable="true" data-field="packages" data-filter-control="input" data-filter-control-placeholder="(any package)">packages</th>
<th data-sortable="true" data-visible="false" data-field="groups" data-filter-control="select" data-filter-data="func:filterListGroups" data-filter-custom-search="filterList" data-filter-control-placeholder="(any group)">groups</th>
<th data-sortable="true" data-visible="false" data-field="licenses" data-filter-control="select" data-filter-data="func:filterListLicenses" data-filter-custom-search="filterList" data-filter-control-placeholder="(any license)">licenses</th>
<th data-sortable="true" data-visible="false" data-field="packager" data-filter-control="select" data-filter-custom-search="filterContains" data-filter-control-placeholder="(any packager)">packager</th>
<th data-sortable="true" data-field="timestamp" data-filter-control="input" data-filter-custom-search="filterDateRange" data-filter-control-placeholder="(any date)">last update</th>
<th data-sortable="true" data-cell-style="statusFormat" data-field="status" data-filter-control="select" data-filter-control-placeholder="(any status)">status</th>
</tr>
</thead>
</table>
</div>
<div class="container">
<footer class="d-flex flex-wrap justify-content-between align-items-center border-top">
<ul class="nav">
<li><a id="badge-version" class="nav-link" href="https://github.com/arcan1s/ahriman" title="sources"><i class="bi bi-github"></i> ahriman</a></li>
<li><a class="nav-link" href="https://github.com/arcan1s/ahriman/releases" title="releases list">releases</a></li>
<li><a class="nav-link" href="https://github.com/arcan1s/ahriman/issues" title="issues tracker">report a bug</a></li>
<li><a class="nav-link" href="/api-docs" title="API documentation">api</a></li>
</ul>
{% if index_url is not none %}
<ul class="nav">
<li><a class="nav-link" href="{{ index_url }}" title="repo index"><i class="bi bi-house"></i> repo index</a></li>
</ul>
{% endif %}
{% if auth.enabled %}
<ul class="nav">
{% if auth.username is none %}
<li>{{ auth.control|safe }}</li>
{% else %}
<li>
<form action="/api/v1/logout" method="post">
<button class="btn btn-link" style="text-decoration: none"><i class="bi bi-box-arrow-right"></i> logout ({{ auth.username }})</button>
</form>
</li>
{% endif %}
</ul>
{% endif %}
</footer>
</div>
{% if auth.enabled %}
{% include "build-status/login-modal.jinja2" %}
{% endif %}
{% include "build-status/alerts.jinja2" %}
{% include "build-status/package-add-modal.jinja2" %}
{% include "build-status/package-rebuild-modal.jinja2" %}
{% include "build-status/key-import-modal.jinja2" %}
{% include "build-status/package-info-modal.jinja2" %}
{% include "build-status/table.jinja2" %}
</body>
</html>

View File

@ -0,0 +1,45 @@
<script>
const alertPlaceholder = $("#alert-placeholder");
function createAlert(title, message, clz) {
const wrapper = document.createElement("div");
wrapper.classList.add("toast", clz);
wrapper.role = "alert";
wrapper.ariaLive = "assertive";
wrapper.ariaAtomic = "true";
wrapper.style.width = "500px"; // 500px is default modal size
const header = document.createElement("div");
header.classList.add("toast-header");
header.innerHTML = `<strong class="me-auto">${safe(title)}</strong> <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="close"></button>`;
wrapper.appendChild(header);
const body = document.createElement("div");
body.classList.add("toast-body", "text-bg-light");
body.innerText = message;
wrapper.appendChild(body);
alertPlaceholder.append(wrapper);
const toast = new bootstrap.Toast(wrapper);
wrapper.addEventListener("hidden.bs.toast", () => {
wrapper.remove(); // bootstrap doesn't remove elements
reload();
});
toast.show();
}
function showFailure(title, description, jqXHR, errorThrown) {
let details;
try {
details = $.parseJSON(jqXHR.responseText).error; // execution handler json error response
} catch (_) {
details = errorThrown;
}
createAlert(title, description(details), "text-bg-danger");
}
function showSuccess(title, description) {
createAlert(title, description, "text-bg-success");
}
</script>

View File

@ -0,0 +1,93 @@
<div id="key-import-modal" tabindex="-1" role="dialog" class="modal fade">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">
<form id="key-import-form" onsubmit="return false">
<div class="modal-header">
<h4 class="modal-title">Import key from PGP server</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
</div>
<div class="modal-body">
<div class="form-group row">
<label for="key-fingerprint-input" class="col-sm-2 col-form-label">fingerprint</label>
<div class="col-sm-10">
<input id="key-fingerprint-input" type="text" class="form-control" placeholder="PGP key fingerprint" name="key" required>
</div>
</div>
<div class="form-group row">
<label for="key-server-input" class="col-sm-2 col-form-label">key server</label>
<div class="col-sm-10">
<input id="key-server-input" type="text" class="form-control" placeholder="PGP key server" name="server" value="keyserver.ubuntu.com" required>
</div>
</div>
<div class="form-group row">
<div class="col-sm-2"></div>
<div class="col-sm-10">
<pre class="language-less"><samp id="key-body-input" class="pre-scrollable language-less"></samp><button id="key-copy-btn" type="button" class="btn language-less" onclick="copyPgpKey()"><i class="bi bi-clipboard"></i> copy</button></pre>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" onclick="importPgpKey()"><i class="bi bi-play"></i> import</button>
<button type="submit" class="btn btn-success" onclick="fetchPgpKey()"><i class="bi bi-arrow-clockwise"></i> fetch</button>
</div>
</form>
</div>
</div>
</div>
<script>
const keyImportModal = $("#key-import-modal");
const keyImportForm = $("#key-import-form");
keyImportModal.on("hidden.bs.modal", () => {
keyBodyInput.text("");
keyImportForm.trigger("reset");
});
const keyBodyInput = $("#key-body-input");
const keyCopyButton = $("#key-copy-btn");
const keyFingerprintInput = $("#key-fingerprint-input");
const keyServerInput = $("#key-server-input");
async function copyPgpKey() {
const logs = keyBodyInput.text();
await copyToClipboard(logs, keyCopyButton);
}
function fetchPgpKey() {
const key = keyFingerprintInput.val();
const server = keyServerInput.val();
if (key && server) {
$.ajax({
url: "/api/v1/service/pgp",
data: {"key": key, "server": server},
type: "GET",
dataType: "json",
success: response => { keyBodyInput.text(response.key); },
});
}
}
function importPgpKey() {
const key = keyFingerprintInput.val();
const server = keyServerInput.val();
if (key && server) {
$.ajax({
url: "/api/v1/service/pgp",
data: JSON.stringify({key: key, server: server}),
type: "POST",
contentType: "application/json",
success: _ => {
keyImportModal.modal("hide");
showSuccess("Success", `Key ${key} has been imported`);
},
error: (jqXHR, _, errorThrown) => {
const message = _ => `Could not import key ${key} from ${server}`;
showFailure("Action failed", message, jqXHR, errorThrown);
},
});
}
}
</script>

View File

@ -0,0 +1,51 @@
<div id="login-modal" tabindex="-1" role="dialog" class="modal fade">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form action="/api/v1/login" method="post">
<div class="modal-header">
<h4 class="modal-title">Login</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
</div>
<div class="modal-body">
<div class="form-group row">
<label for="username" class="col-sm-2 col-form-label">username</label>
<div class="col-sm-10">
<input id="username" type="text" class="form-control" placeholder="enter username" name="username" required>
</div>
</div>
<div class="form-group row">
<label for="password" class="col-sm-2 col-form-label">password</label>
<div class="col-sm-10">
<div class="input-group">
<input id="password" type="password" class="form-control" placeholder="enter password" name="password" required>
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" onclick="showPassword()"><i id="show-hide-password-btn" class="bi bi-eye"></i></button>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary"><i class="bi bi-person"></i> login</button>
</div>
</form>
</div>
</div>
</div>
<script>
const passwordInput = $("#password");
const showHidePasswordButton = $("#show-hide-password-btn");
function showPassword() {
if (passwordInput.attr("type") === "password") {
passwordInput.attr("type", "text");
showHidePasswordButton.removeClass("bi-eye");
showHidePasswordButton.addClass("bi-eye-slash");
} else {
passwordInput.attr("type", "password");
showHidePasswordButton.removeClass("bi-eye-slash");
showHidePasswordButton.addClass("bi-eye");
}
}
</script>

View File

@ -0,0 +1,78 @@
<div id="package-add-modal" tabindex="-1" role="dialog" class="modal fade">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form id="package-add-form" onsubmit="return false">
<div class="modal-header">
<h4 class="modal-title">Add new packages</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
</div>
<div class="modal-body">
<div class="form-group row">
<label for="package-input" class="col-sm-2 col-form-label">package</label>
<div class="col-sm-10">
<input id="package-input" type="text" list="known-packages-dlist" autocomplete="off" class="form-control" placeholder="AUR package" name="package" required>
<datalist id="known-packages-dlist"></datalist>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" onclick="packagesAdd()"><i class="bi bi-play"></i> add</button>
<button type="submit" class="btn btn-success" onclick="packagesRequest()"><i class="bi bi-plus"></i> request</button>
</div>
</form>
</div>
</div>
</div>
<script>
const packageAddModal = $("#package-add-modal");
const packageAddForm = $("#package-add-form");
packageAddModal.on("hidden.bs.modal", () => { packageAddForm.trigger("reset"); });
const packageInput = $("#package-input");
const knownPackagesList = $("#known-packages-dlist");
packageInput.keyup(() => {
clearTimeout(packageInput.data("timeout"));
packageInput.data("timeout", setTimeout($.proxy(() => {
const value = packageInput.val();
if (value.length >= 3) {
$.ajax({
url: "/api/v1/service/search",
data: {"for": value},
type: "GET",
dataType: "json",
success: response => {
const options = response.map(pkg => {
const option = document.createElement("option");
option.value = pkg.package;
option.innerText = `${pkg.package} (${pkg.description})`;
return option;
});
knownPackagesList.empty().append(options);
},
});
}
}, this), 500));
});
function packagesAdd() {
const packages = packageInput.val();
if (packages) {
packageAddModal.modal("hide");
const onSuccess = update => `Packages ${update} have been added`;
const onFailure = error => `Package addition failed: ${error}`;
doPackageAction("/api/v1/service/add", [packages], onSuccess, onFailure);
}
}
function packagesRequest() {
const packages = packageInput.val();
if (packages) {
packageAddModal.modal("hide");
const onSuccess = update => `Packages ${update} have been requested`;
const onFailure = error => `Package request failed: ${error}`;
doPackageAction("/api/v1/service/request", [packages], onSuccess, onFailure);
}
}
</script>

View File

@ -0,0 +1,70 @@
<div id="package-info-modal" tabindex="-1" role="dialog" class="modal fade">
<div class="modal-dialog modal-xl" role="document">
<div class="modal-content">
<div id="package-info-modal-header" class="modal-header">
<h4 id="package-info" class="modal-title"></h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
</div>
<div class="modal-body">
<pre class="language-logs"><samp id="package-info-logs-input" class="pre-scrollable language-logs"></samp><button id="logs-copy-btn" type="button" class="btn language-logs" onclick="copyLogs()"><i class="bi bi-clipboard"></i> copy</button></pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="showLogs()"><i class="bi bi-arrow-clockwise"></i> reload</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"><i class="bi bi-x"></i> close</button>
</div>
</div>
</div>
</div>
<script>
const packageInfoModal = $("#package-info-modal");
const packageInfoModalHeader = $("#package-info-modal-header");
const packageInfo = $("#package-info");
const packageInfoLogsInput = $("#package-info-logs-input");
const packageInfoLogsCopyButton = $("#logs-copy-btn");
async function copyLogs() {
const logs = packageInfoLogsInput.text();
await copyToClipboard(logs, packageInfoLogsCopyButton);
}
function showLogs(packageBase) {
const isPackageBaseSet = packageBase !== undefined;
if (isPackageBaseSet)
packageInfoModal.data("package", packageBase); // set package base as currently used
else
packageBase = packageInfoModal.data("package"); // read package base from the current window attribute
const headerClass = status => {
if (status === "pending") return ["bg-warning"];
if (status === "building") return ["bg-warning"];
if (status === "failed") return ["bg-danger", "text-white"];
if (status === "success") return ["bg-success", "text-white"];
return ["bg-secondary", "text-white"];
};
$.ajax({
url: `/api/v1/packages/${packageBase}/logs`,
type: "GET",
dataType: "json",
success: response => {
packageInfo.text(`${response.package_base} ${response.status.status} at ${new Date(1000 * response.status.timestamp).toISOString()}`);
packageInfoLogsInput.text(response.logs);
packageInfoModalHeader.removeClass();
packageInfoModalHeader.addClass("modal-header");
headerClass(response.status.status).forEach((clz) => packageInfoModalHeader.addClass(clz));
if (isPackageBaseSet) packageInfoModal.modal("show"); // we don't need to show window again
},
error: (jqXHR, _, errorThrown) => {
// show failed modal in case if first time loading
if (isPackageBaseSet) {
const message = error => `Could not load package ${packageBase} logs: ${error}`;
showFailure("Load failure", message, jqXHR, errorThrown);
}
},
});
}
</script>

View File

@ -0,0 +1,41 @@
<div id="package-rebuild-modal" tabindex="-1" role="dialog" class="modal fade">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form id="package-rebuild-form" onsubmit="return false">
<div class="modal-header">
<h4 class="modal-title">Rebuild depending packages</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
</div>
<div class="modal-body">
<div class="form-group row">
<label for="dependency-input" class="col-sm-4 col-form-label">dependency</label>
<div class="col-sm-8">
<input id="dependency-input" type="text" class="form-control" placeholder="packages dependency" name="package" required>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" onclick="packagesRebuild()"><i class="bi bi-play"></i> rebuild</button>
</div>
</form>
</div>
</div>
</div>
<script>
const packageRebuildModal = $("#package-rebuild-modal");
const packageRebuildForm = $("#package-rebuild-form");
packageRebuildModal.on("hidden.bs.modal", () => { packageRebuildForm.trigger("reset"); });
const dependencyInput = $("#dependency-input");
function packagesRebuild() {
const packages = dependencyInput.val();
if (packages) {
packageRebuildModal.modal("hide");
const onSuccess = update => `Repository rebuild has been run for packages which depend on ${update}`;
const onFailure = error => `Repository rebuild failed: ${error}`;
doPackageAction("/api/v1/service/rebuild", [packages], onSuccess, onFailure);
}
}
</script>

View File

@ -0,0 +1,197 @@
<script>
const keyImportButton = $("#key-import-btn");
const packageAddButton = $("#package-add-btn");
const packageRebuildButton = $("#package-rebuild-btn");
const packageRemoveButton = $("#package-remove-btn");
const packageUpdateButton = $("#package-update-btn");
const table = $("#packages");
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", () => {
packageRemoveButton.prop("disabled", !table.bootstrapTable("getSelections").length);
});
table.on("click-row.bs.table", (self, data, row, cell) => {
if (0 === cell || "base" === cell) {
const method = data[0] === true ? "uncheckBy" : "checkBy"; // fck javascript
table.bootstrapTable(method, {field: "id", values: [data.id]});
} else showLogs(data.id);
});
table.on("created-controls.bs.table", () => {
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
pickerInput.daterangepicker({
autoUpdateInput: false,
locale: {
cancelLabel: "Clear",
},
});
pickerInput.on("apply.daterangepicker", (event, picker) => {
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
table.bootstrapTable("triggerSearch");
});
pickerInput.on("cancel.daterangepicker", () => {
pickerInput.val("");
table.bootstrapTable("triggerSearch");
});
});
const repositoryBadge = $("#badge-repository");
const statusBadge = $("#badge-status");
const versionBadge = $("#badge-version");
function doPackageAction(uri, packages, successText, failureText) {
$.ajax({
url: uri,
data: JSON.stringify({packages: packages}),
type: "POST",
contentType: "application/json",
success: _ => {
const message = successText(packages.join(", "));
showSuccess("Success", message);
},
error: (jqXHR, _, errorThrown) => {
showFailure("Action failed", failureText, jqXHR, errorThrown);
},
});
}
function getSelection() {
return table.bootstrapTable("getSelections").map(row => row.id);
}
function removePackages() {
const onSuccess = update => `Packages ${update} have been removed`;
const onFailure = error => `Could not remove packages: ${error}`;
doPackageAction("/api/v1/service/remove", getSelection(), onSuccess, onFailure);
}
function updatePackages() {
const currentSelection = getSelection();
const [url, onSuccess] = currentSelection.length === 0
? ["/api/v1/service/update", _ => "Repository update has been run"]
: ["/api/v1/service/add", update => `Run update for packages ${update}`];
const onFailure = error => `Packages update failed: ${error}`;
doPackageAction(url, currentSelection, onSuccess, onFailure);
}
function hideControls(hidden) {
keyImportButton.attr("hidden", hidden);
packageAddButton.attr("hidden", hidden);
packageRebuildButton.attr("hidden", hidden);
packageRemoveButton.attr("hidden", hidden);
packageUpdateButton.attr("hidden", hidden);
}
function reload() {
table.bootstrapTable("showLoading");
const badgeClass = status => {
if (status === "pending") return "btn-outline-warning";
if (status === "building") return "btn-outline-warning";
if (status === "failed") return "btn-outline-danger";
if (status === "success") return "btn-outline-success";
return "btn-outline-secondary";
};
$.ajax({
url: "/api/v1/packages",
type: "GET",
dataType: "json",
success: response => {
const extractListProperties = (description, property) => {
return Object.values(description.packages)
.map(pkg => pkg[property])
.reduce((left, right) => left.concat(right), []);
};
const listToTable = data => {
return Array.from(new Set(data))
.sort()
.map(entry => safe(entry))
.join("<br>");
};
const payload = response.map(description => {
const package_base = description.package.base;
const web_url = description.package.remote.web_url;
return {
id: package_base,
base: web_url ? `<a href="${safe(web_url)}" title="${safe(package_base)}">${safe(package_base)}</a>` : safe(package_base),
version: safe(description.package.version),
packager: description.package.packager ? safe(description.package.packager) : "",
packages: listToTable(Object.keys(description.package.packages)),
groups: listToTable(extractListProperties(description.package, "groups")),
licenses: listToTable(extractListProperties(description.package, "licenses")),
timestamp: new Date(1000 * description.status.timestamp).toISOString(),
status: description.status.status,
};
});
table.bootstrapTable("load", payload);
table.bootstrapTable("uncheckAll");
table.bootstrapTable("hideLoading");
hideControls(false);
},
error: (jqXHR, _, errorThrown) => {
if ((jqXHR.status === 401) || (jqXHR.status === 403)) {
// authorization error
const text = "In order to see statuses you must login first.";
table.find("tr.unauthorized").remove();
table.find("tbody").append(`<tr class="unauthorized"><td colspan="100%">${safe(text)}</td></tr>`);
table.bootstrapTable("hideLoading");
} else {
// other errors
const message = error => `Could not load list of packages: ${error}`;
showFailure("Load failure", message, jqXHR, errorThrown);
}
hideControls(true);
},
});
$.ajax({
url: "/api/v1/status",
type: "GET",
dataType: "json",
success: response => {
repositoryBadge.text(`${response.repository} ${response.architecture}`);
versionBadge.html(`<i class="bi bi-github"></i> ahriman ${safe(response.version)}`);
statusBadge
.popover("dispose")
.attr("data-bs-content", `${response.status.status} at ${new Date(1000 * response.status.timestamp).toISOString()}`)
.popover();
statusBadge.removeClass();
statusBadge.addClass("btn");
statusBadge.addClass(badgeClass(response.status.status));
},
});
}
function statusFormat(value) {
const cellClass = status => {
if (status === "pending") return "table-warning";
if (status === "building") return "table-warning";
if (status === "failed") return "table-danger";
if (status === "success") return "table-success";
return "table-secondary";
};
return {classes: cellClass(value)};
}
function filterListGroups() {
return extractDataList(table.bootstrapTable("getData"), "groups");
}
function filterListLicenses() {
return extractDataList(table.bootstrapTable("getData"), "licenses");
}
function filterListPackagers() {
return extractDataList(table.bootstrapTable("getData"), "packager");
}
$(() => {
table.bootstrapTable({});
statusBadge.popover();
reload();
});
</script>

Some files were not shown because too many files have changed in this diff Show More