mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 23:37:18 +00:00
Compare commits
297 Commits
Author | SHA1 | Date | |
---|---|---|---|
5d4bd9e459 | |||
4f21eb6fe6 | |||
9a008ddafa | |||
0cd07afa0f | |||
f590136197 | |||
1855e513a8 | |||
233dda8420 | |||
9556779ee2 | |||
8b32bd43db | |||
0eadef597a | |||
e58ccdc8ad | |||
2a07356d24 | |||
43c553a3db | |||
0d1a890bd0 | |||
3aeaa8ce2c | |||
7cee859f19 | |||
fb6b22cdd7 | |||
4f35ec6542 | |||
d98211e5e5 | |||
b97c8928e1 | |||
649df81aa5 | |||
ad7cdb7d95 | |||
4bb598d2eb | |||
f47be6cab0 | |||
342b3cb652 | |||
fc0d8387df | |||
e0b0c3caeb | |||
61969dd682 | |||
e441d93a56 | |||
664b6369bb | |||
4f6bd29ff4 | |||
f6d9ea480a | |||
08f62842ba | |||
1912790ccc | |||
cf3c48ffeb | |||
6633766cc3 | |||
f73d1eb424 | |||
87ab3683ad | |||
9c2f73af8c | |||
31f551bdf2 | |||
cbbe2b01e4 | |||
cd361a483d | |||
cee4fd4cce | |||
18daecaac7 | |||
03c298c762 | |||
79d4a488a0 | |||
22847aac68 | |||
75b9a96798 | |||
a0cfb7561d | |||
f4131b8cd7 | |||
9f134e37b6 | |||
07b7689701 | |||
47de715d7d | |||
5674b7b388 | |||
f6e57a411c | |||
38e48b1571 | |||
d492c968ea | |||
a11fd188a2 | |||
2431d5de0e | |||
88f71b240d | |||
99874845b5 | |||
d98cfa3732 | |||
b6db2a8035 | |||
47c578ea08 | |||
98910240dd | |||
33e9fea47c | |||
304690e0d0 | |||
3d9fae5415 | |||
b7dca2d797 | |||
b7debddaea | |||
1cfc751d21 | |||
6ebbb04504 | |||
c9ee470ee2 | |||
a2610504e5 | |||
36b8b0f46a | |||
d90f417cae | |||
0db619136d | |||
208a9b920d | |||
cb63bc08ff | |||
6551c8d983 | |||
a6c8d64053 | |||
fd78f2b5e2 | |||
900907cdaa | |||
5ff2f43506 | |||
dd521b49b5 | |||
5b1f5a8473 | |||
86af13f09e | |||
733c014229 | |||
783c16b2ed | |||
2536b8dc1f | |||
e200ac9776 | |||
6946745153 | |||
6de75377c3 | |||
a734b86e66 | |||
74906d084a | |||
22d1d835af | |||
b7cd83502a | |||
2d2cd73010 | |||
40b84b810d | |||
7188cfaf78 | |||
e909e4f570 | |||
06ec16ac77 | |||
fed2f3aab8 | |||
2bc2b63a8a | |||
0c5a90cd66 | |||
28cc38aaa5 | |||
fb02e676af | |||
13121298f5 | |||
63e79ec57a | |||
b83bc5a732 | |||
8374590b62 | |||
4cc665f6ee | |||
57f25c309a | |||
d33844e7b2 | |||
e9886efaa2 | |||
61efbb71a2 | |||
9f4acacada | |||
026f74121a | |||
e414616bbd | |||
60a2e25b9a | |||
683abca9e5 | |||
5a3770b739 | |||
52cd9a0ea9 | |||
bfca7e41ab | |||
603c5449a8 | |||
5aac3db2d5 | |||
3c5bcbd172 | |||
042638d40e | |||
e6adb333b2 | |||
fa4244d21e | |||
91de1c2b8a | |||
32a4a82603 | |||
e8a10c1bb5 | |||
d480eb7bc3 | |||
8b0f9bfd78 | |||
a2639f8dbb | |||
65ba590ace | |||
fcb130e226 | |||
ae99fe4535 | |||
ec23e3f912 | |||
d3ea81d234 | |||
09b0f2914d | |||
7351e20104 | |||
dfd87c502f | |||
0b9ab09879 | |||
47c54f0b40 | |||
a2f2fa0354 | |||
4d68080c05 | |||
eb16ef12f3 | |||
e10e362dae | |||
e59fdd1ccc | |||
22d92e3b4e | |||
56b77a84a6 | |||
a5a99ec0b8 | |||
04bbabe898 | |||
4521c2adde | |||
5c5e54228f | |||
6514924b2d | |||
16aa977fa8 | |||
6e377e7261 | |||
4502931c39 | |||
fcb167b1a3 | |||
72b26603bf | |||
ab8ca16981 | |||
7c4f84fbc7 | |||
3b6b2efcb1 | |||
9f99dd3ff2 | |||
bee97df87f | |||
6becd01803 | |||
db195391e4 | |||
59f2992559 | |||
4f06647193 | |||
73a4cee257 | |||
13d00c6f66 | |||
3e032c3515 | |||
d73d5daad3 | |||
f55b44b391 | |||
51b28baf40 | |||
24326f9753 | |||
36c763069d | |||
c9a155bbc4 | |||
182bde5e09 | |||
799572fccf | |||
a7a32f0080 | |||
af3afecce8 | |||
16bb1403a1 | |||
41731ca359 | |||
e99c2b0c83 | |||
6294c0ba14 | |||
2c74be31bd | |||
0744ee53dc | |||
284fd759bf | |||
6f5b28c4f8 | |||
d211cc17c6 | |||
117e69c906 | |||
d19deb57e7 | |||
1b29b5773d | |||
8e14e8d2cb | |||
875bfc0823 | |||
7abdb48ac0 | |||
98eb93c27a | |||
18de70154e | |||
08e0237639 | |||
891c97b036 | |||
55c3386812 | |||
b0575ee4ba | |||
e0607ba609 | |||
9b8c9b2b2d | |||
ecf45bc3bb | |||
aecd679d01 | |||
e63cb509f2 | |||
3922c55464 | |||
9d2a3bcbc1 | |||
a5455b697d | |||
0bfb763b2a | |||
9f3566a150 | |||
16a6c4fdd7 | |||
91f66fdcee | |||
bb45b1d868 | |||
3d10fa472b | |||
a90c93bbc4 | |||
41a3c08d9f | |||
cb328ad797 | |||
810091cde9 | |||
fc0474fa8f | |||
b94179e071 | |||
9c5a9f5837 | |||
83047d8270 | |||
990d5dda81 | |||
48e79ce39c | |||
375d7c55e5 | |||
db52b8e844 | |||
50af309c80 | |||
581401d60f | |||
c2685f4746 | |||
952b55f707 | |||
b9b012be53 | |||
b8036649ab | |||
c90e20587e | |||
3e020ec141 | |||
783b7d043d | |||
5c297d1c67 | |||
b0d1f3c091 | |||
50e219fda5 | |||
75298d1b8a | |||
8196dcc8a0 | |||
f634f1df58 | |||
32df4fc54f | |||
11ae930c59 | |||
9c332c23d2 | |||
4ed0a49a44 | |||
50f532a48a | |||
c6ccf53768 | |||
ce0c07cbd9 | |||
912a76d5cb | |||
76d0b0bc6d | |||
27d018e721 | |||
a0e20ffb77 | |||
96e4abc3c0 | |||
6df60498aa | |||
eb0a4b6b4a | |||
8f469e7eac | |||
535e955814 | |||
0bd3ba626a | |||
ffe6aec190 | |||
56c600e5ac | |||
461883217d | |||
62d55eff19 | |||
534b5600b4 | |||
32cbafd12b | |||
880c70bd58 | |||
d449eb3c2e | |||
17b5cd0751 | |||
2aef906fc8 | |||
e034327501 | |||
5d79fcca22 | |||
6e9dcca254 | |||
fbf6748d4a | |||
2260e52d5c | |||
bd2b61494f | |||
7280d30748 | |||
710274065d | |||
e0b09cefad | |||
3b93510aad | |||
5003cabeb5 | |||
bc6af9256b | |||
1ac7c87317 | |||
803b7bee1e | |||
646190121a | |||
10e4f3b629 | |||
80a1f37c85 | |||
751676a07e | |||
e1a7071ce5 | |||
1605d185e2 | |||
2fdf910e78 | |||
63dc43366b | |||
74a244f06c |
1
.bandit-test.yml
Normal file
1
.bandit-test.yml
Normal file
@ -0,0 +1 @@
|
||||
skips: ['B101', 'B105', 'B106', 'B404']
|
1
.bandit.yml
Normal file
1
.bandit.yml
Normal file
@ -0,0 +1 @@
|
||||
skips: ['B404', 'B603']
|
14
.dockerignore
Normal file
14
.dockerignore
Normal 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/bug-report.md
vendored
Normal file
28
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal 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.
|
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
1
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1 @@
|
||||
blank_issues_enabled: false
|
12
.github/ISSUE_TEMPLATE/discussion.md
vendored
Normal file
12
.github/ISSUE_TEMPLATE/discussion.md
vendored
Normal 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.
|
20
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal 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.
|
13
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
13
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal 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
42
.github/workflows/docker-image.yml
vendored
Normal 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
41
.github/workflows/release.yml
vendored
Normal 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
40
.github/workflows/run-setup.yml
vendored
Normal 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
24
.github/workflows/run-tests.yml
vendored
Normal 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
|
59
.github/workflows/setup.sh
vendored
Executable file
59
.github/workflows/setup.sh
vendored
Executable file
@ -0,0 +1,59 @@
|
||||
#!/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-aur python-passlib python-setuptools python-srcinfo sudo
|
||||
# make dependencies
|
||||
pacman --noconfirm -Sy python-build 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-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
|
||||
|
||||
# special thing for the container, because /dev/log interface is not available there
|
||||
sed -i "s/handlers = syslog_handler/handlers = console_handler/g" /etc/ahriman.ini.d/logging.ini
|
||||
# initial setup command as root
|
||||
[[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080")
|
||||
ahriman -a x86_64 repo-setup --packager "ahriman bot <ahriman@example.com>" --repository "github" "${WEB_ARGS[@]}"
|
||||
# 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=$!
|
||||
sleep 15s # wait for the web service activation
|
||||
fi
|
||||
# add the first package
|
||||
# the build itself does not really work in the container
|
||||
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
10
.github/workflows/tests.sh
vendored
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
# Install dependencies and run test in container
|
||||
|
||||
set -ex
|
||||
|
||||
# install dependencies
|
||||
pacman --noconfirm -Syu base-devel python-pip python-setuptools python-tox
|
||||
|
||||
# run test and check targets
|
||||
make check tests
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -94,3 +94,8 @@ ENV/
|
||||
.venv/
|
||||
|
||||
*.tar.xz
|
||||
status_cache.json
|
||||
|
||||
*.db
|
||||
|
||||
docs/html/
|
||||
|
81
.pylintrc
81
.pylintrc
@ -22,7 +22,7 @@ ignore-patterns=
|
||||
|
||||
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
|
||||
# number of processors available to use.
|
||||
jobs=1
|
||||
jobs=0
|
||||
|
||||
# Control the amount of potential inferred values when inferring a single
|
||||
# object. This can help the performance when dealing with large functions or
|
||||
@ -60,17 +60,7 @@ confidence=
|
||||
# --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,
|
||||
disable=raw-checker-failed,
|
||||
bad-inline-option,
|
||||
locally-disabled,
|
||||
file-ignored,
|
||||
@ -78,67 +68,6 @@ disable=print-statement,
|
||||
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,
|
||||
@ -149,12 +78,12 @@ disable=print-statement,
|
||||
too-few-public-methods,
|
||||
too-many-instance-attributes,
|
||||
broad-except,
|
||||
logging-fstring-interpolation,
|
||||
too-many-ancestors,
|
||||
fixme,
|
||||
too-many-arguments,
|
||||
duplicate-code,
|
||||
cyclic-import
|
||||
cyclic-import,
|
||||
confusing-with-statement,
|
||||
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
@ -220,7 +149,7 @@ indent-string=' '
|
||||
max-line-length=100
|
||||
|
||||
# Maximum number of lines in a module.
|
||||
max-module-lines=1000
|
||||
max-module-lines=400
|
||||
|
||||
# Allow the body of a class to be on the same line as the declaration if body
|
||||
# contains single statement.
|
||||
|
20
.readthedocs.yaml
Normal file
20
.readthedocs.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
version: 2
|
||||
|
||||
formats: all
|
||||
|
||||
build:
|
||||
os: ubuntu-20.04
|
||||
tools:
|
||||
python: "3.10"
|
||||
|
||||
sphinx:
|
||||
builder: html
|
||||
configuration: docs/conf.py
|
||||
|
||||
python:
|
||||
install:
|
||||
- method: pip
|
||||
path: .
|
||||
extra_requirements:
|
||||
- docs
|
||||
system_packages: true
|
2
AUTHORS
Normal file
2
AUTHORS
Normal file
@ -0,0 +1,2 @@
|
||||
Current developers:
|
||||
Evgenii Alekseev aka arcanis <esalexeev (at) gmail (dot) com>
|
@ -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.
|
68
CONTRIBUTING.md
Normal file
68
CONTRIBUTING.md
Normal file
@ -0,0 +1,68 @@
|
||||
# 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.
|
||||
* Type annotations are the must, even for local functions.
|
||||
* 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).
|
||||
* 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.version` module.
|
||||
* 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.lazy_logging.LazyLogging` trait must be used.
|
||||
|
||||
### 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.
|
53
Dockerfile
Normal file
53
Dockerfile
Normal file
@ -0,0 +1,53 @@
|
||||
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_OUTPUT="syslog"
|
||||
ENV AHRIMAN_PACKAGER="ahriman bot <ahriman@example.com>"
|
||||
ENV AHRIMAN_PORT=""
|
||||
ENV AHRIMAN_REPOSITORY="aur-clone"
|
||||
ENV AHRIMAN_REPOSITORY_ROOT="/var/lib/ahriman/ahriman"
|
||||
ENV AHRIMAN_USER="ahriman"
|
||||
|
||||
# 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 --noconfirm -Sy devtools git pyalpm python-inflection python-passlib python-requests python-setuptools python-srcinfo && \
|
||||
pacman --noconfirm -Sy python-build python-installer python-wheel && \
|
||||
pacman --noconfirm -Sy breezy mercurial python-aiohttp python-boto3 python-cryptography python-jinja rsync subversion && \
|
||||
runuser -u build -- install-aur-package python-aioauth-client python-aiohttp-jinja2 python-aiohttp-debugtoolbar \
|
||||
python-aiohttp-session python-aiohttp-security
|
||||
|
||||
# cleanup unused
|
||||
RUN find "/var/cache/pacman/pkg" -type f -delete
|
||||
|
||||
# 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.version 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"
|
||||
|
||||
VOLUME ["/var/lib/ahriman"]
|
||||
|
||||
# minimal runtime ahriman setup
|
||||
COPY "docker/entrypoint.sh" "/usr/local/bin/entrypoint"
|
||||
ENTRYPOINT ["entrypoint"]
|
||||
# default command
|
||||
CMD ["repo-update"]
|
41
Makefile
41
Makefile
@ -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 README.md docs package src setup.py 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/version.py docs/ahriman-architecture.svg docs/ahriman.1
|
||||
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/version.py
|
||||
|
79
README.md
79
README.md
@ -1,68 +1,35 @@
|
||||
# ArcHlinux ReposItory MANager
|
||||
# ArcH linux ReposItory MANager
|
||||
|
||||
[](https://github.com/arcan1s/ahriman/actions/workflows/run-tests.yml)
|
||||
[](https://github.com/arcan1s/ahriman/actions/workflows/run-setup.yml)
|
||||
[](https://hub.docker.com/r/arcan1s/ahriman)
|
||||
[](https://www.codefactor.io/repository/github/arcan1s/ahriman)
|
||||
[](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.
|
||||
* Sign support with gpg (repository, package, per package settings).
|
||||
* 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:
|
||||
|
||||

|
||||
|
||||
## 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
|
||||
|
||||
echo '[multilib]' | tee -a /usr/share/devtools/pacman-ahriman.conf
|
||||
echo 'Include = /etc/pacman.d/mirrorlist' | tee -a /usr/share/devtools/pacman-ahriman.conf
|
||||
|
||||
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
|
||||
```
|
||||
## [FAQ](https://ahriman.readthedocs.io/en/latest/faq.html)
|
||||
|
49
docker/entrypoint.sh
Executable file
49
docker/entrypoint.sh
Executable file
@ -0,0 +1,49 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
[ -n "$AHRIMAN_DEBUG" ] && set -x
|
||||
|
||||
# configuration tune
|
||||
sed -i "s|root = /var/lib/ahriman|root = $AHRIMAN_REPOSITORY_ROOT|g" "/etc/ahriman.ini"
|
||||
sed -i "s|database = /var/lib/ahriman/ahriman.db|database = $AHRIMAN_REPOSITORY_ROOT/ahriman.db|g" "/etc/ahriman.ini"
|
||||
sed -i "s|host = 127.0.0.1|host = $AHRIMAN_HOST|g" "/etc/ahriman.ini"
|
||||
sed -i "s|handlers = syslog_handler|handlers = ${AHRIMAN_OUTPUT}_handler|g" "/etc/ahriman.ini.d/logging.ini"
|
||||
|
||||
AHRIMAN_DEFAULT_ARGS=("--architecture" "$AHRIMAN_ARCHITECTURE")
|
||||
if [[ "$AHRIMAN_OUTPUT" == "syslog" ]]; then
|
||||
if [ ! -e "/dev/log" ]; then
|
||||
# by default ahriman uses syslog which is not available inside container
|
||||
# to make noise less we force quiet mode in case if /dev/log was not mounted
|
||||
AHRIMAN_DEFAULT_ARGS+=("--quiet")
|
||||
fi
|
||||
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"
|
||||
|
||||
# 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 [ -n "$AHRIMAN_PORT" ]; then
|
||||
# in addition it must be handled in docker run command
|
||||
AHRIMAN_SETUP_ARGS+=("--web-port" "$AHRIMAN_PORT")
|
||||
fi
|
||||
ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" repo-setup "${AHRIMAN_SETUP_ARGS[@]}"
|
||||
|
||||
# refresh database
|
||||
pacman -Syy &> /dev/null
|
||||
# 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 --command="$*" &> /dev/null; then
|
||||
AHRIMAN_EXECUTABLE=("sudo" "-u" "$AHRIMAN_USER" "--" "ahriman")
|
||||
else
|
||||
AHRIMAN_EXECUTABLE=("ahriman")
|
||||
fi
|
||||
exec "${AHRIMAN_EXECUTABLE[@]}" "${AHRIMAN_DEFAULT_ARGS[@]}" "$@"
|
12
docker/install-aur-package.sh
Executable file
12
docker/install-aur-package.sh
Executable 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
42
docs/advanced-usage.rst
Normal 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, quiet=False)
|
||||
sqlite = 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, no_report=False, 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.process_triggers(update_result)
|
||||
|
||||
For the more info please refer to the classes documentation.
|
6088
docs/ahriman-architecture.svg
Normal file
6088
docs/ahriman-architecture.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 613 KiB |
718
docs/ahriman.1
Normal file
718
docs/ahriman.1
Normal file
@ -0,0 +1,718 @@
|
||||
.TH AHRIMAN "1" "2022\-11\-11" "ahriman" "Generated Python Manual"
|
||||
.SH NAME
|
||||
ahriman
|
||||
.SH SYNOPSIS
|
||||
.B ahriman
|
||||
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--report | --no-report] [-q] [--unsafe] [-V] {aur-search,search,daemon,help,help-commands-unsafe,key-import,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-clean,clean,repo-config,config,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-setup,init,repo-init,setup,repo-sign,sign,repo-status-update,repo-sync,sync,repo-triggers,repo-update,update,shell,user-add,user-list,user-remove,version,web} ...
|
||||
.SH DESCRIPTION
|
||||
ArcH linux ReposItory MANager
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-a\fR \fI\,ARCHITECTURE\/\fR, \fB\-\-architecture\fR \fI\,ARCHITECTURE\/\fR
|
||||
target architectures (can be used multiple times)
|
||||
|
||||
.TP
|
||||
\fB\-c\fR \fI\,CONFIGURATION\/\fR, \fB\-\-configuration\fR \fI\,CONFIGURATION\/\fR
|
||||
configuration path
|
||||
|
||||
.TP
|
||||
\fB\-\-force\fR
|
||||
force run, remove file lock
|
||||
|
||||
.TP
|
||||
\fB\-l\fR \fI\,LOCK\/\fR, \fB\-\-lock\fR \fI\,LOCK\/\fR
|
||||
lock file
|
||||
|
||||
.TP
|
||||
\fB\-\-report\fR, \fB\-\-no\-report\fR
|
||||
force enable or disable reporting to web service (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-q\fR, \fB\-\-quiet\fR
|
||||
force disable any logging
|
||||
|
||||
.TP
|
||||
\fB\-\-unsafe\fR
|
||||
allow to run ahriman as non\-ahriman user. Some actions might be unavailable
|
||||
|
||||
.TP
|
||||
\fB\-V\fR, \fB\-\-version\fR
|
||||
show program's version number and exit
|
||||
|
||||
.SH
|
||||
COMMAND
|
||||
.TP
|
||||
\fBahriman\fR \fI\,aur\-search\/\fR
|
||||
search for package
|
||||
.TP
|
||||
\fBahriman\fR \fI\,daemon\/\fR
|
||||
run application as daemon
|
||||
.TP
|
||||
\fBahriman\fR \fI\,help\/\fR
|
||||
show help message
|
||||
.TP
|
||||
\fBahriman\fR \fI\,help\-commands\-unsafe\/\fR
|
||||
list unsafe commands
|
||||
.TP
|
||||
\fBahriman\fR \fI\,key\-import\/\fR
|
||||
import PGP key
|
||||
.TP
|
||||
\fBahriman\fR \fI\,package\-add\/\fR
|
||||
add package
|
||||
.TP
|
||||
\fBahriman\fR \fI\,package\-remove\/\fR
|
||||
remove package
|
||||
.TP
|
||||
\fBahriman\fR \fI\,package\-status\/\fR
|
||||
get package status
|
||||
.TP
|
||||
\fBahriman\fR \fI\,package\-status\-remove\/\fR
|
||||
remove package status
|
||||
.TP
|
||||
\fBahriman\fR \fI\,package\-status\-update\/\fR
|
||||
update package status
|
||||
.TP
|
||||
\fBahriman\fR \fI\,patch\-add\/\fR
|
||||
add patch for PKGBUILD function
|
||||
.TP
|
||||
\fBahriman\fR \fI\,patch\-list\/\fR
|
||||
list patch sets
|
||||
.TP
|
||||
\fBahriman\fR \fI\,patch\-remove\/\fR
|
||||
remove patch set
|
||||
.TP
|
||||
\fBahriman\fR \fI\,patch\-set\-add\/\fR
|
||||
add patch set
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-backup\/\fR
|
||||
backup repository data
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-check\/\fR
|
||||
check for updates
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-clean\/\fR
|
||||
clean local caches
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-config\/\fR
|
||||
dump configuration
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-rebuild\/\fR
|
||||
rebuild repository
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-remove\-unknown\/\fR
|
||||
remove unknown packages
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-report\/\fR
|
||||
generate report
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-restore\/\fR
|
||||
restore repository data
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-setup\/\fR
|
||||
initial service configuration
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-sign\/\fR
|
||||
sign packages
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-status\-update\/\fR
|
||||
update repository status
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-sync\/\fR
|
||||
sync repository
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-triggers\/\fR
|
||||
run triggers
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-update\/\fR
|
||||
update packages
|
||||
.TP
|
||||
\fBahriman\fR \fI\,shell\/\fR
|
||||
envoke python shell
|
||||
.TP
|
||||
\fBahriman\fR \fI\,user\-add\/\fR
|
||||
create or update user
|
||||
.TP
|
||||
\fBahriman\fR \fI\,user\-list\/\fR
|
||||
user known users and their access
|
||||
.TP
|
||||
\fBahriman\fR \fI\,user\-remove\/\fR
|
||||
remove user
|
||||
.TP
|
||||
\fBahriman\fR \fI\,version\/\fR
|
||||
application version
|
||||
.TP
|
||||
\fBahriman\fR \fI\,web\/\fR
|
||||
web server
|
||||
|
||||
.SH COMMAND \fI\,'ahriman aur\-search'\/\fR
|
||||
usage: ahriman aur\-search [\-h] [\-e] [\-\-info | \-\-no\-info]
|
||||
[\-\-sort\-by {description,first_submitted,id,last_modified,maintainer,name,num_votes,out_of_date,package_base,package_base_id,popularity,repository,url,url_path,version}]
|
||||
search [search ...]
|
||||
|
||||
search for package in AUR using API
|
||||
|
||||
.TP
|
||||
\fBsearch\fR
|
||||
search terms, can be specified multiple times, the result will match all terms
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman aur\-search'\/\fR
|
||||
.TP
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit status if result is empty
|
||||
|
||||
.TP
|
||||
\fB\-\-info\fR, \fB\-\-no\-info\fR
|
||||
show additional package information (default: False)
|
||||
|
||||
.TP
|
||||
\fB\-\-sort\-by\fR \fI\,{description,first_submitted,id,last_modified,maintainer,name,num_votes,out_of_date,package_base,package_base_id,popularity,repository,url,url_path,version}\/\fR
|
||||
sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted
|
||||
by name
|
||||
|
||||
.SH COMMAND \fI\,'ahriman daemon'\/\fR
|
||||
usage: ahriman daemon [\-h] [\-i INTERVAL] [\-\-aur | \-\-no\-aur] [\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual]
|
||||
[\-\-vcs | \-\-no\-vcs] [\-y]
|
||||
|
||||
start process which periodically will run update process
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman daemon'\/\fR
|
||||
.TP
|
||||
\fB\-i\fR \fI\,INTERVAL\/\fR, \fB\-\-interval\fR \fI\,INTERVAL\/\fR
|
||||
interval between runs in seconds
|
||||
|
||||
.TP
|
||||
\fB\-\-aur\fR, \fB\-\-no\-aur\fR
|
||||
enable or disable checking for AUR updates. Implies \-\-no\-vcs (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-local\fR, \fB\-\-no\-local\fR
|
||||
enable or disable checking of local packages for updates (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-manual\fR, \fB\-\-no\-manual\fR
|
||||
include or exclude manual updates (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
|
||||
enable or disable checking of VCS packages (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-y\fR, \fB\-\-refresh\fR
|
||||
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
||||
|
||||
.SH COMMAND \fI\,'ahriman help'\/\fR
|
||||
usage: ahriman help [\-h] [command]
|
||||
|
||||
show help message for application or command and exit
|
||||
|
||||
.TP
|
||||
\fBcommand\fR
|
||||
show help message for specific command
|
||||
|
||||
.SH COMMAND \fI\,'ahriman help\-commands\-unsafe'\/\fR
|
||||
usage: ahriman help\-commands\-unsafe [\-h] [\-\-command COMMAND]
|
||||
|
||||
list unsafe commands as defined in default args
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman help\-commands\-unsafe'\/\fR
|
||||
.TP
|
||||
\fB\-\-command\fR \fI\,COMMAND\/\fR
|
||||
instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1
|
||||
otherwise
|
||||
|
||||
.SH COMMAND \fI\,'ahriman key\-import'\/\fR
|
||||
usage: ahriman key\-import [\-h] [\-\-key\-server KEY_SERVER] key
|
||||
|
||||
import PGP key from public sources to the repository user
|
||||
|
||||
.TP
|
||||
\fBkey\fR
|
||||
PGP key to import from public server
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman key\-import'\/\fR
|
||||
.TP
|
||||
\fB\-\-key\-server\fR \fI\,KEY_SERVER\/\fR
|
||||
key server for key import
|
||||
|
||||
.SH COMMAND \fI\,'ahriman package\-add'\/\fR
|
||||
usage: ahriman package\-add [\-h] [\-e] [\-n] [\-y] [\-s {auto,archive,aur,directory,local,remote,repository}]
|
||||
[\-\-without\-dependencies]
|
||||
package [package ...]
|
||||
|
||||
add existing or new package to the build queue
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
package source (base name, path to local files, remote URL)
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman package\-add'\/\fR
|
||||
.TP
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit status if result is empty
|
||||
|
||||
.TP
|
||||
\fB\-n\fR, \fB\-\-now\fR
|
||||
run update function after
|
||||
|
||||
.TP
|
||||
\fB\-y\fR, \fB\-\-refresh\fR
|
||||
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
||||
|
||||
.TP
|
||||
\fB\-s\fR \fI\,{auto,archive,aur,directory,local,remote,repository}\/\fR, \fB\-\-source\fR \fI\,{auto,archive,aur,directory,local,remote,repository}\/\fR
|
||||
explicitly specify the package source for this command
|
||||
|
||||
.TP
|
||||
\fB\-\-without\-dependencies\fR
|
||||
do not add dependencies
|
||||
|
||||
.SH COMMAND \fI\,'ahriman package\-remove'\/\fR
|
||||
usage: ahriman package\-remove [\-h] package [package ...]
|
||||
|
||||
remove package from the repository
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
package name or base
|
||||
|
||||
.SH COMMAND \fI\,'ahriman package\-status'\/\fR
|
||||
usage: ahriman package\-status [\-h] [\-\-ahriman] [\-e] [\-i] [\-s {unknown,pending,building,failed,success}] [package ...]
|
||||
|
||||
request status of the package
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
filter status by package base
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman package\-status'\/\fR
|
||||
.TP
|
||||
\fB\-\-ahriman\fR
|
||||
get service status itself
|
||||
|
||||
.TP
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit status if result is empty
|
||||
|
||||
.TP
|
||||
\fB\-i\fR, \fB\-\-info\fR
|
||||
show additional package information
|
||||
|
||||
.TP
|
||||
\fB\-s\fR \fI\,{unknown,pending,building,failed,success}\/\fR, \fB\-\-status\fR \fI\,{unknown,pending,building,failed,success}\/\fR
|
||||
filter packages by status
|
||||
|
||||
.SH COMMAND \fI\,'ahriman package\-status\-remove'\/\fR
|
||||
usage: ahriman package\-status\-remove [\-h] package [package ...]
|
||||
|
||||
remove the package from the status page
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
remove specified packages from status page
|
||||
|
||||
.SH COMMAND \fI\,'ahriman package\-status\-update'\/\fR
|
||||
usage: ahriman package\-status\-update [\-h] [\-s {unknown,pending,building,failed,success}] [package ...]
|
||||
|
||||
update package status on the status page
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
set status for specified packages. If no packages supplied, service status will be updated
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman package\-status\-update'\/\fR
|
||||
.TP
|
||||
\fB\-s\fR \fI\,{unknown,pending,building,failed,success}\/\fR, \fB\-\-status\fR \fI\,{unknown,pending,building,failed,success}\/\fR
|
||||
new package build status
|
||||
|
||||
.SH COMMAND \fI\,'ahriman patch\-add'\/\fR
|
||||
usage: ahriman patch\-add [\-h] package variable [patch]
|
||||
|
||||
create or update patched PKGBUILD function or variable
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
package base
|
||||
|
||||
.TP
|
||||
\fBvariable\fR
|
||||
PKGBUILD variable or function name. If variable is a function, it must end with ()
|
||||
|
||||
.TP
|
||||
\fBpatch\fR
|
||||
path to file which contains function or variable value. If not set, the value will be read from stdin
|
||||
|
||||
.SH COMMAND \fI\,'ahriman patch\-list'\/\fR
|
||||
usage: ahriman patch\-list [\-h] [\-e] [\-v VARIABLE] [package]
|
||||
|
||||
list available patches for the package
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
package base
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman patch\-list'\/\fR
|
||||
.TP
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit status if result is empty
|
||||
|
||||
.TP
|
||||
\fB\-v\fR \fI\,VARIABLE\/\fR, \fB\-\-variable\fR \fI\,VARIABLE\/\fR
|
||||
if set, show only patches for specified PKGBUILD variables
|
||||
|
||||
.SH COMMAND \fI\,'ahriman patch\-remove'\/\fR
|
||||
usage: ahriman patch\-remove [\-h] [\-v VARIABLE] package
|
||||
|
||||
remove patches for the package
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
package base
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman patch\-remove'\/\fR
|
||||
.TP
|
||||
\fB\-v\fR \fI\,VARIABLE\/\fR, \fB\-\-variable\fR \fI\,VARIABLE\/\fR
|
||||
should be used for single\-function patches in case if you wold like to remove only specified PKGBUILD variables. In case
|
||||
if not set, it will remove all patches related to the package
|
||||
|
||||
.SH COMMAND \fI\,'ahriman patch\-set\-add'\/\fR
|
||||
usage: ahriman patch\-set\-add [\-h] [\-t TRACK] package
|
||||
|
||||
create or update source patches
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
path to directory with changed files for patch addition/update
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman patch\-set\-add'\/\fR
|
||||
.TP
|
||||
\fB\-t\fR \fI\,TRACK\/\fR, \fB\-\-track\fR \fI\,TRACK\/\fR
|
||||
files which has to be tracked
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-backup'\/\fR
|
||||
usage: ahriman repo\-backup [\-h] path
|
||||
|
||||
backup repository settings and database
|
||||
|
||||
.TP
|
||||
\fBpath\fR
|
||||
path of the output archive
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-check'\/\fR
|
||||
usage: ahriman repo\-check [\-h] [\-e] [\-\-vcs | \-\-no\-vcs] [\-y] [package ...]
|
||||
|
||||
check for packages updates. Same as repo\-update \-\-dry\-run \-\-no\-manual
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
filter check by package base
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman repo\-check'\/\fR
|
||||
.TP
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit status if result is empty
|
||||
|
||||
.TP
|
||||
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
|
||||
enable or disable checking of VCS packages (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-y\fR, \fB\-\-refresh\fR
|
||||
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-clean'\/\fR
|
||||
usage: ahriman repo\-clean [\-h] [\-\-cache | \-\-no\-cache] [\-\-chroot | \-\-no\-chroot] [\-\-manual | \-\-no\-manual]
|
||||
[\-\-packages | \-\-no\-packages] [\-\-pacman | \-\-no\-pacman]
|
||||
|
||||
remove local caches
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman repo\-clean'\/\fR
|
||||
.TP
|
||||
\fB\-\-cache\fR, \fB\-\-no\-cache\fR
|
||||
clear directory with package caches (default: False)
|
||||
|
||||
.TP
|
||||
\fB\-\-chroot\fR, \fB\-\-no\-chroot\fR
|
||||
clear build chroot (default: False)
|
||||
|
||||
.TP
|
||||
\fB\-\-manual\fR, \fB\-\-no\-manual\fR
|
||||
clear manually added packages queue (default: False)
|
||||
|
||||
.TP
|
||||
\fB\-\-packages\fR, \fB\-\-no\-packages\fR
|
||||
clear directory with built packages (default: False)
|
||||
|
||||
.TP
|
||||
\fB\-\-pacman\fR, \fB\-\-no\-pacman\fR
|
||||
clear directory with pacman local database cache (default: False)
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-config'\/\fR
|
||||
usage: ahriman repo\-config [\-h]
|
||||
|
||||
dump configuration for the specified architecture
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-rebuild'\/\fR
|
||||
usage: ahriman repo\-rebuild [\-h] [\-\-depends\-on DEPENDS_ON] [\-\-dry\-run] [\-\-from\-database] [\-e]
|
||||
|
||||
force rebuild whole repository
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman repo\-rebuild'\/\fR
|
||||
.TP
|
||||
\fB\-\-depends\-on\fR \fI\,DEPENDS_ON\/\fR
|
||||
only rebuild packages that depend on specified packages
|
||||
|
||||
.TP
|
||||
\fB\-\-dry\-run\fR
|
||||
just perform check for packages without rebuild process itself
|
||||
|
||||
.TP
|
||||
\fB\-\-from\-database\fR
|
||||
read packages from database instead of filesystem. This feature in particular is required in case if you would like to
|
||||
restore repository from another repository instance. Note, however, that in order to restore packages you need to have
|
||||
original ahriman instance run with web service and have run repo\-update at least once.
|
||||
|
||||
.TP
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit status if result is empty
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-remove\-unknown'\/\fR
|
||||
usage: ahriman repo\-remove\-unknown [\-h] [\-\-dry\-run]
|
||||
|
||||
remove packages which are missing in AUR and do not have local PKGBUILDs
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman repo\-remove\-unknown'\/\fR
|
||||
.TP
|
||||
\fB\-\-dry\-run\fR
|
||||
just perform check for packages without removal
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-report'\/\fR
|
||||
usage: ahriman repo\-report [\-h]
|
||||
|
||||
generate repository report according to current settings
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-restore'\/\fR
|
||||
usage: ahriman repo\-restore [\-h] [\-o OUTPUT] path
|
||||
|
||||
restore settings and database
|
||||
|
||||
.TP
|
||||
\fBpath\fR
|
||||
path of the input archive
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman repo\-restore'\/\fR
|
||||
.TP
|
||||
\fB\-o\fR \fI\,OUTPUT\/\fR, \fB\-\-output\fR \fI\,OUTPUT\/\fR
|
||||
root path of the extracted files
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-setup'\/\fR
|
||||
usage: ahriman repo\-setup [\-h] [\-\-build\-as\-user BUILD_AS_USER] [\-\-build\-command BUILD_COMMAND]
|
||||
[\-\-from\-configuration FROM_CONFIGURATION] [\-\-multilib | \-\-no\-multilib] \-\-packager PACKAGER
|
||||
\-\-repository REPOSITORY [\-\-sign\-key SIGN_KEY] [\-\-sign\-target {disabled,pacakges,repository}]
|
||||
[\-\-web\-port WEB_PORT]
|
||||
|
||||
create initial service configuration, requires root
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman repo\-setup'\/\fR
|
||||
.TP
|
||||
\fB\-\-build\-as\-user\fR \fI\,BUILD_AS_USER\/\fR
|
||||
force makepkg user to the specific one
|
||||
|
||||
.TP
|
||||
\fB\-\-build\-command\fR \fI\,BUILD_COMMAND\/\fR
|
||||
build command prefix
|
||||
|
||||
.TP
|
||||
\fB\-\-from\-configuration\fR \fI\,FROM_CONFIGURATION\/\fR
|
||||
path to default devtools pacman configuration
|
||||
|
||||
.TP
|
||||
\fB\-\-multilib\fR, \fB\-\-no\-multilib\fR
|
||||
add or do not multilib repository (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-packager\fR \fI\,PACKAGER\/\fR
|
||||
packager name and email
|
||||
|
||||
.TP
|
||||
\fB\-\-repository\fR \fI\,REPOSITORY\/\fR
|
||||
repository name
|
||||
|
||||
.TP
|
||||
\fB\-\-sign\-key\fR \fI\,SIGN_KEY\/\fR
|
||||
sign key id
|
||||
|
||||
.TP
|
||||
\fB\-\-sign\-target\fR \fI\,{disabled,pacakges,repository}\/\fR
|
||||
sign options
|
||||
|
||||
.TP
|
||||
\fB\-\-web\-port\fR \fI\,WEB_PORT\/\fR
|
||||
port of the web service
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-sign'\/\fR
|
||||
usage: ahriman repo\-sign [\-h] [package ...]
|
||||
|
||||
(re\-)sign packages and repository database according to current settings
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
sign only specified packages
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-status\-update'\/\fR
|
||||
usage: ahriman repo\-status\-update [\-h] [\-s {unknown,pending,building,failed,success}]
|
||||
|
||||
update repository status on the status page
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman repo\-status\-update'\/\fR
|
||||
.TP
|
||||
\fB\-s\fR \fI\,{unknown,pending,building,failed,success}\/\fR, \fB\-\-status\fR \fI\,{unknown,pending,building,failed,success}\/\fR
|
||||
new status
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-sync'\/\fR
|
||||
usage: ahriman repo\-sync [\-h]
|
||||
|
||||
sync repository files to remote server according to current settings
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-triggers'\/\fR
|
||||
usage: ahriman repo\-triggers [\-h] [trigger ...]
|
||||
|
||||
run triggers on empty build result as configured by settings
|
||||
|
||||
.TP
|
||||
\fBtrigger\fR
|
||||
instead of running all triggers as set by configuration, just process specified ones oin order of metion
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-update'\/\fR
|
||||
usage: ahriman repo\-update [\-h] [\-\-dry\-run] [\-e] [\-\-aur | \-\-no\-aur] [\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual]
|
||||
[\-\-vcs | \-\-no\-vcs] [\-y]
|
||||
[package ...]
|
||||
|
||||
check for packages updates and run build process if requested
|
||||
|
||||
.TP
|
||||
\fBpackage\fR
|
||||
filter check by package base
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman repo\-update'\/\fR
|
||||
.TP
|
||||
\fB\-\-dry\-run\fR
|
||||
just perform check for updates, same as check command
|
||||
|
||||
.TP
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit status if result is empty
|
||||
|
||||
.TP
|
||||
\fB\-\-aur\fR, \fB\-\-no\-aur\fR
|
||||
enable or disable checking for AUR updates. Implies \-\-no\-vcs (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-local\fR, \fB\-\-no\-local\fR
|
||||
enable or disable checking of local packages for updates (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-manual\fR, \fB\-\-no\-manual\fR
|
||||
include or exclude manual updates (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
|
||||
enable or disable checking of VCS packages (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-y\fR, \fB\-\-refresh\fR
|
||||
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
||||
|
||||
.SH COMMAND \fI\,'ahriman shell'\/\fR
|
||||
usage: ahriman shell [\-h] [code]
|
||||
|
||||
drop into python shell while having created application
|
||||
|
||||
.TP
|
||||
\fBcode\fR
|
||||
instead of dropping into shell, just execute the specified code
|
||||
|
||||
.SH COMMAND \fI\,'ahriman user\-add'\/\fR
|
||||
usage: ahriman user\-add [\-h] [\-\-as\-service] [\-p PASSWORD] [\-r {unauthorized,read,reporter,full}] [\-s] username
|
||||
|
||||
update user for web services with the given password and role. In case if password was not entered it will be asked interactively
|
||||
|
||||
.TP
|
||||
\fBusername\fR
|
||||
username for web service
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman user\-add'\/\fR
|
||||
.TP
|
||||
\fB\-\-as\-service\fR
|
||||
add user as service user
|
||||
|
||||
.TP
|
||||
\fB\-p\fR \fI\,PASSWORD\/\fR, \fB\-\-password\fR \fI\,PASSWORD\/\fR
|
||||
user password. Blank password will be treated as empty password, which is in particular must be used for OAuth2
|
||||
authorization type.
|
||||
|
||||
.TP
|
||||
\fB\-r\fR \fI\,{unauthorized,read,reporter,full}\/\fR, \fB\-\-role\fR \fI\,{unauthorized,read,reporter,full}\/\fR
|
||||
user access level
|
||||
|
||||
.TP
|
||||
\fB\-s\fR, \fB\-\-secure\fR
|
||||
set file permissions to user\-only
|
||||
|
||||
.SH COMMAND \fI\,'ahriman user\-list'\/\fR
|
||||
usage: ahriman user\-list [\-h] [\-e] [\-r {unauthorized,read,reporter,full}] [username]
|
||||
|
||||
list users from the user mapping and their roles
|
||||
|
||||
.TP
|
||||
\fBusername\fR
|
||||
filter users by username
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman user\-list'\/\fR
|
||||
.TP
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit status if result is empty
|
||||
|
||||
.TP
|
||||
\fB\-r\fR \fI\,{unauthorized,read,reporter,full}\/\fR, \fB\-\-role\fR \fI\,{unauthorized,read,reporter,full}\/\fR
|
||||
filter users by role
|
||||
|
||||
.SH COMMAND \fI\,'ahriman user\-remove'\/\fR
|
||||
usage: ahriman user\-remove [\-h] [\-s] username
|
||||
|
||||
remove user from the user mapping and update the configuration
|
||||
|
||||
.TP
|
||||
\fBusername\fR
|
||||
username for web service
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman user\-remove'\/\fR
|
||||
.TP
|
||||
\fB\-s\fR, \fB\-\-secure\fR
|
||||
set file permissions to user\-only
|
||||
|
||||
.SH COMMAND \fI\,'ahriman version'\/\fR
|
||||
usage: ahriman version [\-h]
|
||||
|
||||
print application and its dependencies versions
|
||||
|
||||
.SH COMMAND \fI\,'ahriman web'\/\fR
|
||||
usage: ahriman web [\-h]
|
||||
|
||||
start web server
|
||||
|
||||
.SH COMMENTS
|
||||
Argument list can also be read from file by using @ prefix.
|
||||
|
||||
.SH AUTHORS
|
||||
.nf
|
||||
ahriman team
|
||||
.fi
|
||||
.nf
|
||||
|
||||
.fi
|
||||
|
||||
.SH DISTRIBUTION
|
||||
The latest version of ahriman may be downloaded from
|
||||
.UR https://github.com/arcan1s/ahriman
|
||||
.UE
|
45
docs/ahriman.application.application.rst
Normal file
45
docs/ahriman.application.application.rst
Normal 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:
|
213
docs/ahriman.application.handlers.rst
Normal file
213
docs/ahriman.application.handlers.rst
Normal file
@ -0,0 +1,213 @@
|
||||
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.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.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.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:
|
38
docs/ahriman.application.rst
Normal file
38
docs/ahriman.application.rst
Normal 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:
|
45
docs/ahriman.core.alpm.remote.rst
Normal file
45
docs/ahriman.core.alpm.remote.rst
Normal 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:
|
37
docs/ahriman.core.alpm.rst
Normal file
37
docs/ahriman.core.alpm.rst
Normal 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:
|
45
docs/ahriman.core.auth.rst
Normal file
45
docs/ahriman.core.auth.rst
Normal 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:
|
29
docs/ahriman.core.build_tools.rst
Normal file
29
docs/ahriman.core.build_tools.rst
Normal 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:
|
45
docs/ahriman.core.database.data.rst
Normal file
45
docs/ahriman.core.database.data.rst
Normal file
@ -0,0 +1,45 @@
|
||||
ahriman.core.database.data package
|
||||
==================================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.core.database.data.package\_remotes module
|
||||
--------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.database.data.package_remotes
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.database.data.package\_statuses module
|
||||
---------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.database.data.package_statuses
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.database.data.patches module
|
||||
-----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.database.data.patches
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.database.data.users module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.database.data.users
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.core.database.data
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
45
docs/ahriman.core.database.migrations.rst
Normal file
45
docs/ahriman.core.database.migrations.rst
Normal file
@ -0,0 +1,45 @@
|
||||
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:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.core.database.migrations
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
53
docs/ahriman.core.database.operations.rst
Normal file
53
docs/ahriman.core.database.operations.rst
Normal file
@ -0,0 +1,53 @@
|
||||
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.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:
|
31
docs/ahriman.core.database.rst
Normal file
31
docs/ahriman.core.database.rst
Normal file
@ -0,0 +1,31 @@
|
||||
ahriman.core.database package
|
||||
=============================
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
ahriman.core.database.data
|
||||
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:
|
101
docs/ahriman.core.formatters.rst
Normal file
101
docs/ahriman.core.formatters.rst
Normal file
@ -0,0 +1,101 @@
|
||||
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\_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.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.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:
|
45
docs/ahriman.core.gitremote.rst
Normal file
45
docs/ahriman.core.gitremote.rst
Normal 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:
|
69
docs/ahriman.core.report.rst
Normal file
69
docs/ahriman.core.report.rst
Normal file
@ -0,0 +1,69 @@
|
||||
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.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:
|
53
docs/ahriman.core.repository.rst
Normal file
53
docs/ahriman.core.repository.rst
Normal 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:
|
80
docs/ahriman.core.rst
Normal file
80
docs/ahriman.core.rst
Normal file
@ -0,0 +1,80 @@
|
||||
ahriman.core package
|
||||
====================
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
ahriman.core.alpm
|
||||
ahriman.core.auth
|
||||
ahriman.core.build_tools
|
||||
ahriman.core.database
|
||||
ahriman.core.formatters
|
||||
ahriman.core.gitremote
|
||||
ahriman.core.report
|
||||
ahriman.core.repository
|
||||
ahriman.core.sign
|
||||
ahriman.core.status
|
||||
ahriman.core.triggers
|
||||
ahriman.core.upload
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.core.configuration module
|
||||
---------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.configuration
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.exceptions module
|
||||
------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.exceptions
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.lazy\_logging module
|
||||
---------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.lazy_logging
|
||||
: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:
|
21
docs/ahriman.core.sign.rst
Normal file
21
docs/ahriman.core.sign.rst
Normal 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:
|
37
docs/ahriman.core.status.rst
Normal file
37
docs/ahriman.core.status.rst
Normal 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:
|
29
docs/ahriman.core.triggers.rst
Normal file
29
docs/ahriman.core.triggers.rst
Normal 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:
|
61
docs/ahriman.core.upload.rst
Normal file
61
docs/ahriman.core.upload.rst
Normal file
@ -0,0 +1,61 @@
|
||||
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.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:
|
197
docs/ahriman.models.rst
Normal file
197
docs/ahriman.models.rst
Normal file
@ -0,0 +1,197 @@
|
||||
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.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.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.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.user\_identity module
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: ahriman.models.user_identity
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.models
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
32
docs/ahriman.rst
Normal file
32
docs/ahriman.rst
Normal file
@ -0,0 +1,32 @@
|
||||
ahriman package
|
||||
===============
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
ahriman.application
|
||||
ahriman.core
|
||||
ahriman.models
|
||||
ahriman.web
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.version module
|
||||
----------------------
|
||||
|
||||
.. automodule:: ahriman.version
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
29
docs/ahriman.web.middlewares.rst
Normal file
29
docs/ahriman.web.middlewares.rst
Normal 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:
|
38
docs/ahriman.web.rst
Normal file
38
docs/ahriman.web.rst
Normal file
@ -0,0 +1,38 @@
|
||||
ahriman.web package
|
||||
===================
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
ahriman.web.middlewares
|
||||
ahriman.web.views
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
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:
|
39
docs/ahriman.web.views.rst
Normal file
39
docs/ahriman.web.views.rst
Normal file
@ -0,0 +1,39 @@
|
||||
ahriman.web.views package
|
||||
=========================
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
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:
|
45
docs/ahriman.web.views.service.rst
Normal file
45
docs/ahriman.web.views.service.rst
Normal file
@ -0,0 +1,45 @@
|
||||
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.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:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.views.service
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
37
docs/ahriman.web.views.status.rst
Normal file
37
docs/ahriman.web.views.status.rst
Normal file
@ -0,0 +1,37 @@
|
||||
ahriman.web.views.status package
|
||||
================================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
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:
|
29
docs/ahriman.web.views.user.rst
Normal file
29
docs/ahriman.web.views.user.rst
Normal 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:
|
283
docs/architecture.rst
Normal file
283
docs/architecture.rst
Normal file
@ -0,0 +1,283 @@
|
||||
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 which is required for any time of application run and 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.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.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.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.configuration.Configuration`` is an extension for standard ``configparser`` library.
|
||||
* ``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 provides 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.views`` contains web views derived from aiohttp view class.
|
||||
* ``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 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.
|
||||
|
||||
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.
|
||||
|
||||
There are also data migrations which are located at ``ahriman.core.database.data`` package and move data from old-style (e.g. json files in filesystem, directory trees, etc) to the database. They are also part of migration and (unlike schema migrations) are applied only at specific version breakpoints (e.g. if ``user_version`` is more than 0 no initial migration will be applied).
|
||||
|
||||
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
|
||||
-----------
|
||||
|
||||
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 filter by reverse dependency 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.
|
||||
#. 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.
|
||||
|
||||
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.
|
||||
|
||||
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 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 is used by service reporting (aka robots).
|
||||
|
||||
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 package provides two default extensions - one is report generation and another one is remote upload feature.
|
||||
|
||||
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).
|
||||
* 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.
|
||||
|
||||
Middlewares
|
||||
^^^^^^^^^^^
|
||||
|
||||
Service provides some custom middlewares, e.g. logging every exception (except for user ones) and user authorization.
|
||||
|
||||
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.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.
|
10
docs/command-line.rst
Normal file
10
docs/command-line.rst
Normal file
@ -0,0 +1,10 @@
|
||||
Commands reference
|
||||
==================
|
||||
|
||||
ahriman
|
||||
-------
|
||||
|
||||
.. argparse::
|
||||
:module: ahriman.application.ahriman
|
||||
:func: _parser
|
||||
:prog: ahriman
|
107
docs/conf.py
Normal file
107
docs/conf.py
Normal file
@ -0,0 +1,107 @@
|
||||
# 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 unittest import mock
|
||||
|
||||
from ahriman.version import __version__
|
||||
|
||||
|
||||
basedir = Path(__file__).resolve().parent.parent / "src"
|
||||
sys.path.insert(0, str(basedir))
|
||||
|
||||
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
|
||||
|
||||
for module in (
|
||||
"aioauth_client",
|
||||
"aiohttp",
|
||||
"aiohttp.web",
|
||||
"aiohttp.web_exceptions",
|
||||
"aiohttp.web_response",
|
||||
"aiohttp.web_urldispatcher",
|
||||
"aiohttp_jinja2",
|
||||
"aiohttp_security",
|
||||
"aiohttp_session",
|
||||
"aiohttp_session.cookie_storage",
|
||||
"boto3",
|
||||
"cryptography",
|
||||
"pyalpm",
|
||||
):
|
||||
sys.modules[module] = mock.Mock()
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = "ahriman"
|
||||
copyright = "2021-2022, 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",
|
||||
"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 = "default" if on_rtd else "alabaster"
|
||||
|
||||
# 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 = ["_static"]
|
||||
|
||||
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_default_options = {
|
||||
"no-undoc-members": True,
|
||||
}
|
242
docs/configuration.rst
Normal file
242
docs/configuration.rst
Normal file
@ -0,0 +1,242 @@
|
||||
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``.
|
||||
|
||||
``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.
|
||||
|
||||
``alpm`` group
|
||||
--------------
|
||||
|
||||
libalpm and AUR related configuration.
|
||||
|
||||
* ``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.
|
||||
* ``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`` - password hash salt, string, required in case if authorization enabled (automatically generated by ``create-user`` subcommand).
|
||||
|
||||
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.
|
||||
|
||||
``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.
|
||||
* ``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.
|
||||
|
||||
``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.
|
||||
|
||||
* ``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.
|
||||
|
||||
* ``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
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
* ``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 ways:
|
||||
|
||||
* 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.
|
||||
|
||||
``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 ways:
|
||||
|
||||
* 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``.
|
||||
|
||||
``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.
|
||||
|
||||
``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.
|
||||
* ``host`` - host to bind, string, optional.
|
||||
* ``index_url`` - full url of the repository index page, string, optional.
|
||||
* ``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.
|
||||
* ``username`` - username to authorize in web service in order to update service status, string, required in case if authorization enabled.
|
776
docs/faq.rst
Normal file
776
docs/faq.rst
Normal file
@ -0,0 +1,776 @@
|
||||
|
||||
FAQ
|
||||
===
|
||||
|
||||
General topics
|
||||
--------------
|
||||
|
||||
What is the purpose of the project
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This project has been created in order to maintain self-hosted Arch Linux user repository without manual intervention - checking for updates and building packages.
|
||||
|
||||
How to install ahriman
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
TL;DR
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S ahriman
|
||||
sudo ahriman -a x86_64 repo-setup --packager "ahriman bot <ahriman@example.com>" --repository "repository"
|
||||
systemctl enable --now ahriman@x86_64.timer
|
||||
|
||||
Long answer
|
||||
"""""""""""
|
||||
|
||||
The idea is to install the package as usual, create working directory tree, create configuration for ``sudo`` and ``devtools``. Detailed description of the setup instruction can be found :doc:`here <setup>`.
|
||||
|
||||
What does "architecture specific" mean / How to configure for different architectures
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Some sections can be configured per architecture. The service will merge architecture specific values into common settings. In order to specify settings for specific architecture you must point it in section name.
|
||||
|
||||
For example, the section
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[build]
|
||||
build_command = extra-x86_64-build
|
||||
|
||||
states that default build command is ``extra-x86_64-build``. But if there is section
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[build:i686]
|
||||
build_command = extra-i686-build
|
||||
|
||||
the ``extra-i686-build`` command will be used for ``i686`` architecture.
|
||||
|
||||
How to generate build reports
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Normally you probably like to generate only one report for the specific type, e.g. only one email report. In order to do it you will need to have the following configuration:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[report]
|
||||
target = email
|
||||
|
||||
[email]
|
||||
...
|
||||
|
||||
or in case of multiple architectures and *different* reporting settings:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[report]
|
||||
target = email
|
||||
|
||||
[email:i686]
|
||||
...
|
||||
|
||||
[email:x86_64]
|
||||
...
|
||||
|
||||
But for some cases you would like to have multiple different reports with the same type (e.g. sending different templates to different addresses). For these cases you will need to specify section name in target and type in section, e.g. the following configuration can be used:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[report]
|
||||
target = email_1 email_2
|
||||
|
||||
[email_1]
|
||||
type = email
|
||||
...
|
||||
|
||||
[email_2]
|
||||
type = email
|
||||
...
|
||||
|
||||
How do I add new package
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman package-add ahriman --now
|
||||
|
||||
``--now`` flag is totally optional and just run ``repo-update`` subcommand after the registering the new package, Thus the extended flow is the following:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman package-add ahriman
|
||||
sudo -u ahriman ahriman repo-update
|
||||
|
||||
How to build package from local PKGBUILD
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
TL;DR
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman package-add /path/to/local/directory/with/PKGBUILD --now
|
||||
|
||||
Before using this command you will need to create local directory, put ``PKGBUILD`` there and generate ``.SRCINFO`` by using ``makepkg --printsrcinfo > .SRCINFO`` command. These packages will be stored locally and *will be ignored* during automatic update; in order to update the package you will need to run ``package-add`` command again.
|
||||
|
||||
|
||||
How to fetch PKGBUILDs from remote repository
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For that purpose you could use ``RemotePullTrigger`` trigger. To do so you will need:
|
||||
|
||||
#.
|
||||
Append ``triggers`` option in ``build`` section with the following line:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[build]
|
||||
triggers = ahriman.core.gitremote.RemotePullTrigger
|
||||
|
||||
#.
|
||||
Configure trigger as following:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[remote-pull]
|
||||
target = gitremote
|
||||
|
||||
[gitremote]
|
||||
pull_url = https://github.com/username/repository
|
||||
|
||||
During the next application run it will fetch repository from the specified url and will try to find packages there which can be used as local sources.
|
||||
|
||||
How to push updated PKGBUILDs to remote repository
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For that purpose you'd need to use another trigger called ``RemotePushTrigger``. Configure it as following:
|
||||
|
||||
#.
|
||||
Append ``triggers`` option in ``build`` section with the trigger name:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[build]
|
||||
triggers = ahriman.core.gitremote.RemotePushTrigger
|
||||
|
||||
#.
|
||||
Configure trigger as following:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[remote-push]
|
||||
target = gitremote
|
||||
|
||||
[gitremote]
|
||||
push_url = https://github.com/username/repository
|
||||
|
||||
Unlike ``RemotePullTrigger`` trigger, the ``RemotePushTrigger`` more likely will require authorization. It is highly recommended to use application tokens for that instead of using your password (e.g. for Github you can generate tokens `here <https://github.com/settings/tokens>`_ with scope ``public_repo``). Authorization can be supplied by using authorization part of the url, e.g. ``https://key:token@github.com/username/repository``.
|
||||
|
||||
How to change PKGBUILDs before build
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Well it is supported also. The recommended way is to patch specific function, e.g. by running ``sudo -u ahriman ahriman patch-add ahriman version``. This command will prompt for new value of the PKGBUILD variable ``version``. You can also write it to file and read from it ``sudo -u ahriman ahriman patch-add ahriman version version.patch``.
|
||||
|
||||
Alternatively you can create full-diff patches, which are calculated by using ``git diff`` from current PKGBUILD master branch:
|
||||
|
||||
#. Clone sources from AUR.
|
||||
#. Make changes you would like to (e.g. edit ``PKGBUILD``, add external patches).
|
||||
#. Run ``sudo -u ahriman ahriman patch-set-add /path/to/local/directory/with/PKGBUILD``.
|
||||
|
||||
The last command will calculate diff from current tree to the ``HEAD`` and will store it locally. Patches will be applied on any package actions (e.g. it can be used for dependency management).
|
||||
|
||||
How to build package from official repository
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
So it is the same as adding any other package, but due to restrictions you must specify source explicitly, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman package-add pacman -s repository
|
||||
|
||||
This feature is heavily depends on local pacman cache. In order to use this feature it is recommended to either run ``pacman -Sy`` before the interaction or configure timer for this.
|
||||
|
||||
Package build fails because it cannot validate PGP signature of source files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
TL;DR
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman key-import ...
|
||||
|
||||
How to update VCS packages
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Normally the service handles VCS packages correctly, however it requires additional dependencies:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
pacman -S breezy darcs mercurial subversion
|
||||
|
||||
How to remove package
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman package-remove ahriman
|
||||
|
||||
Also, there is command ``repo-remove-unknown`` which checks packages in AUR and local storage and removes ones which have been removed.
|
||||
|
||||
Remove commands also remove any package files (patches, caches etc).
|
||||
|
||||
How to rebuild packages after library update
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
TL;DR
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman repo-rebuild --depends-on python
|
||||
|
||||
You can even rebuild the whole repository (which is particular useful in case if you would like to change packager) if you do not supply ``--depends-on`` option.
|
||||
|
||||
However, note that you do not need to rebuild repository in case if you just changed signing option, just use ``repo-sign`` command instead.
|
||||
|
||||
How to install built packages
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Add the following lines to your ``pacman.conf``:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[repository]
|
||||
Server = file:///var/lib/ahriman/repository/x86_64
|
||||
|
||||
(You might need to add ``SigLevel`` option according to the pacman documentation.)
|
||||
|
||||
How to serve repository
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Easy. For example, nginx configuration (without SSL) will look like:
|
||||
|
||||
.. code-block::
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name repo.example.com;
|
||||
|
||||
location / {
|
||||
autoindex on;
|
||||
root /var/lib/ahriman/repository;
|
||||
}
|
||||
}
|
||||
|
||||
Example of the status page configuration is the following (status service is using 8080 port):
|
||||
|
||||
.. code-block::
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name builds.example.com;
|
||||
|
||||
location / {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarder-Proto $scheme;
|
||||
|
||||
proxy_pass http://127.0.0.1:8080;
|
||||
}
|
||||
}
|
||||
|
||||
Docker image
|
||||
------------
|
||||
|
||||
We provide official images which can be found under ``arcan1s/ahriman`` repository. Docker image is being updated on each commit to master as well as on each version. If you would like to use last (probably unstable) build you can use ``edge`` tag or ``latest`` for any tagged versions; otherwise you can use any version tag available.
|
||||
|
||||
The default action (in case if no arguments provided) is ``repo-update``. Basically the idea is to run container, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker run --privileged -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest
|
||||
|
||||
``--privileged`` flag is required to make mount possible inside container. In addition, you can pass own configuration overrides by using the same ``-v`` flag, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker run -v /path/to/local/repo:/var/lib/ahriman -v /etc/ahriman.ini:/etc/ahriman.ini.d/10-overrides.ini arcan1s/ahriman:latest
|
||||
|
||||
The action can be specified during run, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker run arcan1s/ahriman:latest package-add ahriman --now
|
||||
|
||||
For more details please refer to docker FAQ.
|
||||
|
||||
Environment variables
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The following environment variables are supported:
|
||||
|
||||
* ``AHRIMAN_ARCHITECTURE`` - architecture of the repository, default is ``x86_64``.
|
||||
* ``AHRIMAN_DEBUG`` - if set all commands will be logged to console.
|
||||
* ``AHRIMAN_FORCE_ROOT`` - force run ahriman as root instead of guessing by subcommand.
|
||||
* ``AHRIMAN_HOST`` - host for the web interface, default is ``0.0.0.0``.
|
||||
* ``AHRIMAN_OUTPUT`` - controls logging handler, e.g. ``syslog``, ``console``. The name must be found in logging configuration. Note that if ``syslog`` (the default) handler is used you will need to mount ``/dev/log`` inside container because it is not available there.
|
||||
* ``AHRIMAN_PACKAGER`` - packager name from which packages will be built, default is ``ahriman bot <ahriman@example.com>``.
|
||||
* ``AHRIMAN_PORT`` - HTTP server port if any, default is empty.
|
||||
* ``AHRIMAN_REPOSITORY`` - repository name, default is ``aur-clone``.
|
||||
* ``AHRIMAN_REPOSITORY_ROOT`` - repository root. Because of filesystem rights it is required to override default repository root. By default, it uses ``ahriman`` directory inside ahriman's home, which can be passed as mount volume.
|
||||
* ``AHRIMAN_USER`` - ahriman user, usually must not be overwritten, default is ``ahriman``.
|
||||
|
||||
You can pass any of these variables by using ``-e`` argument, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker run -e AHRIMAN_PORT=8080 arcan1s/ahriman:latest
|
||||
|
||||
Web service setup
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Well for that you would need to have web container instance running forever; it can be achieved by the following command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker run -p 8080:8080 -e AHRIMAN_PORT=8080 -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest
|
||||
|
||||
Note about ``AHRIMAN_PORT`` environment variable which is required in order to enable web service. An additional port bind by ``-p 8080:8080`` is required to pass docker port outside of container.
|
||||
|
||||
For every next container run use arguments ``-e AHRIMAN_PORT=8080 --net=host``, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker run --privileged -e AHRIMAN_PORT=8080 --net=host -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest
|
||||
|
||||
Daemon service
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
There is special subcommand which emulates systemd timer and will perform repository update periodically:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker run arcan1s/ahriman:latest daemon
|
||||
|
||||
This command uses same rules as ``repo-update``, thus, e.g. requires ``--privileged`` flag.
|
||||
|
||||
Remote synchronization
|
||||
----------------------
|
||||
|
||||
How to sync repository to another server
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
There are several choices:
|
||||
|
||||
#.
|
||||
Easy and cheap, just share your local files through the internet, e.g. for ``nginx``:
|
||||
|
||||
.. code-block::
|
||||
|
||||
server {
|
||||
location /x86_64 {
|
||||
root /var/lib/ahriman/repository/x86_64;
|
||||
autoindex on;
|
||||
}
|
||||
}
|
||||
|
||||
#.
|
||||
You can also upload your packages using ``rsync`` to any available server. In order to use it you would need to configure ahriman first:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[upload]
|
||||
target = rsync
|
||||
|
||||
[rsync]
|
||||
remote = 192.168.0.1:/srv/repo
|
||||
|
||||
After that just add ``/srv/repo`` to the ``pacman.conf`` as usual. You can also upload to S3 (e.g. ``Server = https://s3.eu-central-1.amazonaws.com/repository/x86_64``) or to Github (e.g. ``Server = https://github.com/ahriman/repository/releases/download/x86_64``).
|
||||
|
||||
How to sync to S3
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
#.
|
||||
Install dependencies:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
pacman -S python-boto3
|
||||
|
||||
#.
|
||||
Create a bucket.
|
||||
|
||||
#.
|
||||
Create user with write access to the bucket:
|
||||
|
||||
.. code-block::
|
||||
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "ListObjectsInBucket",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"s3:ListBucket"
|
||||
],
|
||||
"Resource": [
|
||||
"arn:aws:s3:::repository"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Sid": "AllObjectActions",
|
||||
"Effect": "Allow",
|
||||
"Action": "s3:*Object",
|
||||
"Resource": [
|
||||
"arn:aws:s3:::repository/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
#.
|
||||
Create an API key for the user and store it.
|
||||
|
||||
#.
|
||||
Configure the service as following:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[upload]
|
||||
target = s3
|
||||
|
||||
[s3]
|
||||
access_key = ...
|
||||
bucket = repository
|
||||
region = eu-central-1
|
||||
secret_key = ...
|
||||
|
||||
How to sync to Github releases
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
#.
|
||||
Create a repository.
|
||||
#.
|
||||
`Create API key <https://github.com/settings/tokens>`_ with scope ``public_repo``.
|
||||
#.
|
||||
Configure the service as following:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[upload]
|
||||
target = github
|
||||
|
||||
[github]
|
||||
owner = ahriman
|
||||
password = ...
|
||||
repository = repository
|
||||
username = ahriman
|
||||
|
||||
Reporting
|
||||
---------
|
||||
|
||||
How to report by email
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
#.
|
||||
Install dependencies:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S python-jinja
|
||||
|
||||
#.
|
||||
Configure the service:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[report]
|
||||
target = email
|
||||
|
||||
[email]
|
||||
host = smtp.example.com
|
||||
link_path = http://example.com/x86_64
|
||||
password = ...
|
||||
port = 465
|
||||
receivers = me@example.com
|
||||
sender = me@example.com
|
||||
user = me@example.com
|
||||
|
||||
How to generate index page for S3
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
#.
|
||||
Install dependencies:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S python-jinja
|
||||
|
||||
#.
|
||||
Configure the service:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[report]
|
||||
target = html
|
||||
|
||||
[html]
|
||||
path = /var/lib/ahriman/repository/x86_64/index.html
|
||||
link_path = http://example.com/x86_64
|
||||
|
||||
After these steps ``index.html`` file will be automatically synced to S3
|
||||
|
||||
How to post build report to telegram
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
#.
|
||||
It still requires additional dependencies:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S python-jinja
|
||||
|
||||
#.
|
||||
Register bot in telegram. You can do it by talking with `@BotFather <https://t.me/botfather>`_. For more details please refer to `official documentation <https://core.telegram.org/bots>`_.
|
||||
|
||||
#.
|
||||
Optionally (if you want to post message in chat):
|
||||
|
||||
|
||||
#. Create telegram channel.
|
||||
#. Invite your bot into the channel.
|
||||
#. Make your channel public
|
||||
|
||||
#.
|
||||
Get chat id if you want to use by numerical id or just use id prefixed with ``@`` (e.g. ``@ahriman``). If you are not using chat the chat id is your user id. If you don't want to make channel public you can use `this guide <https://stackoverflow.com/a/33862907>`_.
|
||||
|
||||
#.
|
||||
Configure the service:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[report]
|
||||
target = telegram
|
||||
|
||||
[telegram]
|
||||
api_key = aaAAbbBBccCC
|
||||
chat_id = @ahriman
|
||||
link_path = http://example.com/x86_64
|
||||
|
||||
``api_key`` is the one sent by `@BotFather <https://t.me/botfather>`_, ``chat_id`` is the value retrieved from previous step.
|
||||
|
||||
If you did everything fine you should receive the message with the next update. Quick credentials check can be done by using the following command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
curl 'https://api.telegram.org/bot${CHAT_ID}/sendMessage?chat_id=${API_KEY}&text=hello'
|
||||
|
||||
(replace ``${CHAT_ID}`` and ``${API_KEY}`` with the values from configuration).
|
||||
|
||||
Web service
|
||||
-----------
|
||||
|
||||
How to setup web service
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
#.
|
||||
Install dependencies:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S python-aiohttp python-aiohttp-jinja2
|
||||
|
||||
#.
|
||||
Configure service:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[web]
|
||||
port = 8080
|
||||
|
||||
#.
|
||||
Start the web service ``systemctl enable --now ahriman-web@x86_64``.
|
||||
|
||||
How to enable basic authorization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
#.
|
||||
Install dependencies 😊:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S python-aiohttp-security python-aiohttp-session python-cryptography
|
||||
|
||||
#.
|
||||
Configure the service to enable authorization:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[auth]
|
||||
target = configuration
|
||||
|
||||
#.
|
||||
Create user for the service:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman user-add --as-service -r write api
|
||||
|
||||
This command will ask for the password, just type it in stdin; *do not* leave the field blank, user will not be able to authorize.
|
||||
|
||||
#.
|
||||
Create end-user ``sudo -u ahriman ahriman user-add -r write my-first-user`` with password.
|
||||
|
||||
#. Restart web service ``systemctl restart ahriman-web@x86_64``.
|
||||
|
||||
How to enable OAuth authorization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
#.
|
||||
Create OAuth web application, download its ``client_id`` and ``client_secret``.
|
||||
#.
|
||||
Guess what? Install dependencies:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S python-aiohttp-security python-aiohttp-session python-cryptography python-aioauth-client
|
||||
|
||||
#.
|
||||
Configure the service:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[auth]
|
||||
target = oauth
|
||||
client_id = ...
|
||||
client_secret = ...
|
||||
|
||||
[web]
|
||||
address = https://example.com
|
||||
|
||||
Configure ``oauth_provider`` and ``oauth_scopes`` in case if you would like to use different from Google provider. Scope must grant access to user email. ``web.address`` is required to make callback URL available from internet.
|
||||
|
||||
#.
|
||||
Create service user:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman user-add --as-service -r write api
|
||||
|
||||
#.
|
||||
Create end-user ``sudo -u ahriman ahriman user-add -r write my-first-user``. When it will ask for the password leave it blank.
|
||||
|
||||
#. Restart web service ``systemctl restart ahriman-web@x86_64``.
|
||||
|
||||
Backup and restore
|
||||
------------------
|
||||
|
||||
The service provides several commands aim to do easy repository backup and restore. If you would like to move repository from the server ``server1.example.com`` to another ``server2.example.com`` you have to perform the following steps:
|
||||
|
||||
#.
|
||||
On the source server ``server1.example.com`` run ``repo-backup`` command, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo ahriman repo-backup /tmp/repo.tar.gz
|
||||
|
||||
This command will pack all configuration files together with database file into the archive specified as command line argument (i.e. ``/tmp/repo.tar.gz``). In addition it will also archive ``cache`` directory (the one which contains local clones used by e.g. local packages) and ``.gnupg`` of the ``ahriman`` user.
|
||||
|
||||
#.
|
||||
Copy created archive from source server ``server1.example.com`` to target ``server2.example.com``.
|
||||
|
||||
#.
|
||||
Install ahriman as usual on the target server ``server2.example.com`` if you didn't yet.
|
||||
|
||||
#.
|
||||
Extract archive e.g. by using subcommand:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo ahriman repo-restore /tmp/repo.tar.gz
|
||||
|
||||
An additional argument ``-o``/``--output`` can be used to specify extraction root (``/`` by default).
|
||||
|
||||
#.
|
||||
Rebuild repository:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman repo-rebuild --from-database
|
||||
|
||||
Other topics
|
||||
------------
|
||||
|
||||
How does it differ from %another-manager%?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Short answer - I do not know. Also for some references credits to `Alad <https://github.com/AladW>`_, he `did <https://wiki.archlinux.org/title/User:Alad/Local_repo_tools>`_ really good investigation of existing alternatives.
|
||||
|
||||
`arch-repo-manager <https://github.com/Martchus/arch-repo-manager>`_
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Looks actually pretty good, in case if I would find it, I would probably didn't start this project, most of features (like web interface or additional helpers) are already implemented or planned to be. However, this project seems to be at early alpha stage (as for Nov 2022), written in C++ (not pro or con) and misses code documentation.
|
||||
|
||||
`archrepo2 <https://github.com/lilydjwg/archrepo2>`_
|
||||
""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Don't know, haven't tried it. But it lacks of documentation at least.
|
||||
|
||||
* ``ahriman`` has web interface.
|
||||
* ``archrepo2`` doesn't have synchronization and reporting.
|
||||
* ``archrepo2`` actively uses direct shell calls and ``yaourt`` components.
|
||||
* ``archrepo2`` has constantly running process instead of timer process (it is not pro or con).
|
||||
|
||||
`repoctl <https://github.com/cassava/repoctl>`_
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
* ``ahriman`` has web interface.
|
||||
* ``repoctl`` does not have reporting feature.
|
||||
* ``repoctl`` does not support local packages and patches.
|
||||
* Some actions are not fully automated in ``repoctl`` (e.g. package update still requires manual intervention for the build itself).
|
||||
* ``repoctl`` has better AUR interaction features. With colors!
|
||||
* ``repoctl`` has much easier configuration and even completion.
|
||||
* ``repoctl`` is able to store old packages.
|
||||
* Ability to host repository from same command in ``repoctl`` vs external services (e.g. nginx) in ``ahriman``.
|
||||
|
||||
`repo-scripts <https://github.com/arcan1s/repo-scripts>`_
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
Though originally I've created ahriman by trying to improve the project, it still lacks a lot of features:
|
||||
|
||||
* ``ahriman`` has web interface.
|
||||
* ``ahriman`` has better reporting with template support.
|
||||
* ``ahriman`` has more synchronization features (there was only ``rsync`` based).
|
||||
* ``ahriman`` supports local packages and patches.
|
||||
* ``repo-scripts`` doesn't have dependency management.
|
||||
|
||||
...and so on. ``repo-scripts`` also has bad architecture and bad quality code and uses out-of-dated ``yaourt`` and ``package-query``.
|
||||
|
||||
`toolbox <https://github.com/chaotic-aur/toolbox>`_
|
||||
"""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
It is automation tools for ``repoctl`` mentioned above. Except for using shell it looks pretty cool and also offers some additional features like patches, remote synchronization (isn't it?) and reporting.
|
||||
|
||||
How to check service logs
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
By default, the service writes logs to ``/dev/log`` which can be accessed by using ``journalctl`` command (logs are written to the journal of the user under which command is run).
|
||||
|
||||
You can also edit configuration and forward logs to ``stderr``, just change ``handlers`` value, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sed -i 's/handlers = syslog_handler/handlers = console_handler/g' /etc/ahriman.ini.d/logging.ini
|
||||
|
||||
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_. The application uses java concept to log messages, e.g. class ``Application`` imported from ``ahriman.application.application`` package will have logger called ``ahriman.application.application.Application``. In order to e.g. change logger name for whole application package it is possible to change values for ``ahriman.application`` package; thus editing ``ahriman`` logger configuration will change logging for whole application (unless there are overrides for another logger).
|
||||
|
||||
Html customization
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is possible to customize html templates. In order to do so, create files somewhere (refer to Jinja2 documentation and the service source code for available parameters) and put ``template_path`` to configuration pointing to this directory.
|
||||
|
||||
I did not find my question
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
`Create an issue <https://github.com/arcan1s/ahriman/issues>`_ with type **Question**.
|
32
docs/index.rst
Normal file
32
docs/index.rst
Normal file
@ -0,0 +1,32 @@
|
||||
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.
|
||||
* Sign support with gpg (repository, package, per package settings).
|
||||
* 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.
|
||||
|
||||
Contents
|
||||
--------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
setup
|
||||
configuration
|
||||
command-line
|
||||
faq
|
||||
architecture
|
||||
advanced-usage
|
||||
triggers
|
||||
modules
|
7
docs/modules.rst
Normal file
7
docs/modules.rst
Normal file
@ -0,0 +1,7 @@
|
||||
Modules
|
||||
=======
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
ahriman
|
91
docs/setup.rst
Normal file
91
docs/setup.rst
Normal file
@ -0,0 +1,91 @@
|
||||
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 repo-setup ...
|
||||
|
||||
``repo-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 ``pacman-{name}.conf``):
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
cp /usr/share/devtools/pacman-{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-ahriman.conf
|
||||
|
||||
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
|
||||
|
||||
#.
|
||||
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: 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
|
93
docs/triggers.rst
Normal file
93
docs/triggers.rst
Normal file
@ -0,0 +1,93 @@
|
||||
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 commited 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.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).
|
||||
|
||||
Trigger example
|
||||
---------------
|
||||
|
||||
Lets consider example of reporting trigger (e.g. `slack <https://slack.com/>`_, which provides easy HTTP API for integration triggers).gre
|
||||
|
||||
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.
|
@ -1,45 +1,54 @@
|
||||
# Maintainer: Evgeniy Alekseev
|
||||
|
||||
pkgname='ahriman'
|
||||
pkgver=0.15.0
|
||||
pkgver=2.3.0rc2
|
||||
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' 'git' 'pyalpm' 'python-inflection' 'python-passlib' 'python-requests' 'python-setuptools' 'python-srcinfo')
|
||||
makedepends=('python-build' '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-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-jinja: html report generation'
|
||||
'python-requests: web server'
|
||||
'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')
|
||||
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"
|
||||
|
||||
# python-installer actually thinks that you cannot just copy files to root
|
||||
# thus we need to copy them manually
|
||||
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=('112b0d8aac68e5330bbdd2b86a59c8a9af8ab7a7c636489623c8460bb90f1318585851edd2a97a8ce20e2d2ad93b847b522685df707c190aa39d23ab908fa8ef'
|
||||
'53d37efec812afebf86281716259f9ea78a307b83897166c72777251c3eebcb587ecee375d907514781fb2a5c808cbb24ef9f3f244f12740155d0603bf213131'
|
||||
'62b2eccc352d33853ef243c9cddd63663014aa97b87242f1b5bc5099a7dbd69ff3821f24ffc58e1b7f2387bd4e9e9712cc4c67f661b1724ad99cdf09b3717794')
|
||||
|
@ -1 +1 @@
|
||||
u ahriman 643 "ArcHlinux ReposItory MANager" /var/lib/ahriman
|
||||
u ahriman 643 "ArcH linux ReposItory MANager" /var/lib/ahriman
|
@ -1,2 +1,2 @@
|
||||
d /var/lib/ahriman 0775 ahriman log
|
||||
d /var/lib/ahriman 0755 ahriman ahriman
|
||||
d /var/log/ahriman 0755 ahriman ahriman
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=ArcHlinux ReposItory MANager timer (%I architecture)
|
||||
Description=ArcH linux ReposItory MANager timer (%I architecture)
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
|
@ -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>
|
@ -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>
|
@ -1,3 +0,0 @@
|
||||
<section class="element">
|
||||
<input type="search" id="search" onkeyup="searchInTable()" placeholder="search for package" title="search for package"/>
|
||||
</section>
|
@ -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>
|
67
package/share/ahriman/settings/ahriman.ini
Normal file
67
package/share/ahriman/settings/ahriman.ini
Normal file
@ -0,0 +1,67 @@
|
||||
[settings]
|
||||
include = ahriman.ini.d
|
||||
logging = ahriman.ini.d/logging.ini
|
||||
database = /var/lib/ahriman/ahriman.db
|
||||
|
||||
[alpm]
|
||||
database = /var/lib/pacman
|
||||
mirror = https://geo.mirror.pkgbuild.com/$repo/os/$arch
|
||||
repositories = core extra community 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.report.ReportTrigger ahriman.core.upload.UploadTrigger
|
||||
|
||||
[repository]
|
||||
name = aur-clone
|
||||
root = /var/lib/ahriman
|
||||
|
||||
[sign]
|
||||
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
|
68
package/share/ahriman/settings/ahriman.ini.d/logging.ini
Normal file
68
package/share/ahriman/settings/ahriman.ini.d/logging.ini
Normal file
@ -0,0 +1,68 @@
|
||||
[loggers]
|
||||
keys = root,http,stderr,boto3,botocore,nose,s3transfer
|
||||
|
||||
[handlers]
|
||||
keys = console_handler,syslog_handler
|
||||
|
||||
[formatters]
|
||||
keys = generic_format,syslog_format
|
||||
|
||||
[handler_console_handler]
|
||||
class = StreamHandler
|
||||
level = DEBUG
|
||||
formatter = generic_format
|
||||
args = (sys.stderr,)
|
||||
|
||||
[handler_syslog_handler]
|
||||
class = logging.handlers.SysLogHandler
|
||||
level = DEBUG
|
||||
formatter = syslog_format
|
||||
args = ("/dev/log",)
|
||||
|
||||
[formatter_generic_format]
|
||||
format = [%(levelname)s %(asctime)s] [%(threadName)s] [%(name)s]: %(message)s
|
||||
datefmt =
|
||||
|
||||
[formatter_syslog_format]
|
||||
format = [%(levelname)s] [%(threadName)s] [%(name)s]: %(message)s
|
||||
datefmt =
|
||||
|
||||
[logger_root]
|
||||
level = DEBUG
|
||||
handlers = syslog_handler
|
||||
qualname = root
|
||||
|
||||
[logger_http]
|
||||
level = DEBUG
|
||||
handlers = syslog_handler
|
||||
qualname = http
|
||||
propagate = 0
|
||||
|
||||
[logger_stderr]
|
||||
level = DEBUG
|
||||
handlers = console_handler
|
||||
qualname = stderr
|
||||
|
||||
[logger_boto3]
|
||||
level = INFO
|
||||
handlers = syslog_handler
|
||||
qualname = boto3
|
||||
propagate = 0
|
||||
|
||||
[logger_botocore]
|
||||
level = INFO
|
||||
handlers = syslog_handler
|
||||
qualname = botocore
|
||||
propagate = 0
|
||||
|
||||
[logger_nose]
|
||||
level = INFO
|
||||
handlers = syslog_handler
|
||||
qualname = nose
|
||||
propagate = 0
|
||||
|
||||
[logger_s3transfer]
|
||||
level = INFO
|
||||
handlers = syslog_handler
|
||||
qualname = s3transfer
|
||||
propagate = 0
|
@ -1 +0,0 @@
|
||||
<script src="https://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
|
@ -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>
|
117
package/share/ahriman/templates/build-status.jinja2
Normal file
117
package/share/ahriman/templates/build-status.jinja2
Normal file
@ -0,0 +1,117 @@
|
||||
<!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>
|
||||
|
||||
<div class="container">
|
||||
<h1>ahriman
|
||||
<img id="badge-version" src="https://img.shields.io/badge/version-unknown-informational" alt="unknown">
|
||||
<img id="badge-repository" src="https://img.shields.io/badge/repository-unknown-informational" alt="unknown">
|
||||
<img id="badge-architecture" src="https://img.shields.io/badge/architecture-unknown-informational" alt="unknown">
|
||||
<img id="badge-status" src="https://img.shields.io/badge/service%20status-unknown-inactive" alt="unknown">
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div id="toolbar">
|
||||
{% if not auth.enabled or auth.username is not none %}
|
||||
<button id="add-btn" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#add-form" hidden>
|
||||
<i class="bi bi-plus"></i> add
|
||||
</button>
|
||||
<button id="update-btn" class="btn btn-secondary" onclick="updatePackages()" hidden>
|
||||
<i class="bi bi-play"></i> update
|
||||
</button>
|
||||
<button id="remove-btn" class="btn btn-danger" onclick="removePackages()" disabled hidden>
|
||||
<i class="bi bi-trash"></i> remove
|
||||
</button>
|
||||
{% endif %}
|
||||
<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-click-to-select="true"
|
||||
data-export-options='{"fileName": "packages"}'
|
||||
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-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">package base</th>
|
||||
<th data-sortable="true" data-field="version">version</th>
|
||||
<th data-sortable="true" data-field="packages">packages</th>
|
||||
<th data-sortable="true" data-visible="false" data-field="groups">groups</th>
|
||||
<th data-sortable="true" data-visible="false" data-field="licenses">licenses</th>
|
||||
<th data-sortable="true" data-field="timestamp">last update</th>
|
||||
<th data-sortable="true" data-cell-style="statusFormat" data-field="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 class="nav-link" href="https://github.com/arcan1s/ahriman" title="sources">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>
|
||||
</ul>
|
||||
|
||||
{% if index_url is not none %}
|
||||
<ul class="nav">
|
||||
<li><a class="nav-link" href="{{ index_url }}" title="repo index">repo index</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
{% if auth.enabled %}
|
||||
{% if auth.username is none %}
|
||||
{{ auth.control|safe }}
|
||||
{% else %}
|
||||
<form action="/api/v1/logout" method="post">
|
||||
<button class="btn btn-link" style="text-decoration: none">logout ({{ auth.username }})</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
{% if auth.enabled %}
|
||||
{% include "build-status/login-modal.jinja2" %}
|
||||
{% endif %}
|
||||
|
||||
{% include "utils/bootstrap-scripts.jinja2" %}
|
||||
|
||||
{% include "build-status/failed-modal.jinja2" %}
|
||||
{% include "build-status/success-modal.jinja2" %}
|
||||
|
||||
{% include "build-status/package-add-modal.jinja2" %}
|
||||
|
||||
{% include "build-status/table.jinja2" %}
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -0,0 +1,28 @@
|
||||
<div id="failed-form" tabindex="-1" role="dialog" class="modal fade">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-danger">
|
||||
<h4 class="modal-title">failed</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Packages update has failed.</p>
|
||||
<p id="error-details"></p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const failedForm = $("#failed-form");
|
||||
const errorDetails = $("#error-details");
|
||||
failedForm.on("hidden.bs.modal", () => { reload(); });
|
||||
|
||||
function showFailure(details) {
|
||||
errorDetails.text(details);
|
||||
failedForm.modal("show");
|
||||
}
|
||||
</script>
|
@ -0,0 +1,29 @@
|
||||
<div id="loginForm" 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">
|
||||
<input id="password" type="password" class="form-control" placeholder="enter password" name="password" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary">login</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,61 @@
|
||||
<div id="add-form" tabindex="-1" role="dialog" class="modal fade">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<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" class="col-sm-2 col-form-label">package</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="package-form" 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="button" class="btn btn-secondary" data-bs-dismiss="modal">close</button>
|
||||
<button type="button" class="btn btn-success" data-bs-dismiss="modal" onclick="requestPackages()">request</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" onclick="addPackages()">add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const packageInput = $("#package-form");
|
||||
const knownPackages = $("#known-packages-dlist");
|
||||
packageInput.keyup(() => {
|
||||
clearTimeout(packageInput.data("timeout"));
|
||||
packageInput.data("timeout", setTimeout($.proxy(() => {
|
||||
const value = packageInput.val();
|
||||
|
||||
$.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;
|
||||
});
|
||||
knownPackages.empty().append(options);
|
||||
},
|
||||
})
|
||||
}, this), 500));
|
||||
});
|
||||
|
||||
function addPackages() {
|
||||
const packages = [packageInput.val()];
|
||||
doPackageAction("/api/v1/service/add", packages);
|
||||
}
|
||||
|
||||
function requestPackages() {
|
||||
const packages = [packageInput.val()];
|
||||
doPackageAction("/api/v1/service/request", packages);
|
||||
}
|
||||
</script>
|
@ -0,0 +1,28 @@
|
||||
<div id="success-form" tabindex="-1" role="dialog" class="modal fade">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-success">
|
||||
<h4 class="modal-title">success</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Packages update has been run.</p>
|
||||
<ul id="success-details"></ul>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const successForm = $("#success-form");
|
||||
const successDetails = $("#success-details");
|
||||
successForm.on("hidden.bs.modal", () => { reload(); });
|
||||
|
||||
function showSuccess(details) {
|
||||
successDetails.empty().append(details);
|
||||
successForm.modal("show");
|
||||
}
|
||||
</script>
|
157
package/share/ahriman/templates/build-status/table.jinja2
Normal file
157
package/share/ahriman/templates/build-status/table.jinja2
Normal file
@ -0,0 +1,157 @@
|
||||
<script>
|
||||
const addButton = $("#add-btn");
|
||||
const removeButton = $("#remove-btn");
|
||||
const updateButton = $("#update-btn");
|
||||
|
||||
const table = $("#packages");
|
||||
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table",
|
||||
() => {
|
||||
removeButton.prop("disabled", !table.bootstrapTable("getSelections").length);
|
||||
});
|
||||
|
||||
const architectureBadge = $("#badge-architecture");
|
||||
const repositoryBadge = $("#badge-repository");
|
||||
const statusBadge = $("#badge-status");
|
||||
const versionBadge = $("#badge-version");
|
||||
|
||||
function doPackageAction(uri, packages) {
|
||||
$.ajax({
|
||||
url: uri,
|
||||
data: JSON.stringify({packages: packages}),
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
success: _ => {
|
||||
const details = packages.map(pkg => {
|
||||
const li = document.createElement("li");
|
||||
li.innerText = pkg;
|
||||
return li;
|
||||
});
|
||||
showSuccess(details);
|
||||
},
|
||||
error: (jqXHR, _, errorThrown) => { showFailure(errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
function getSelection() {
|
||||
return table.bootstrapTable("getSelections").map(row => { return row.id; });
|
||||
}
|
||||
|
||||
function removePackages() { doPackageAction("/api/v1/service/remove", getSelection()); }
|
||||
|
||||
function updatePackages() { doPackageAction("/api/v1/service/add", getSelection()); }
|
||||
|
||||
function hideControls(hidden) {
|
||||
addButton.attr("hidden", hidden);
|
||||
removeButton.attr("hidden", hidden);
|
||||
updateButton.attr("hidden", hidden);
|
||||
}
|
||||
|
||||
function reload() {
|
||||
table.bootstrapTable("showLoading");
|
||||
|
||||
$.ajax({
|
||||
url: "/api/v1/packages",
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: response => {
|
||||
const extractListProperties = (description, property) => {
|
||||
return Object.values(description.packages)
|
||||
.map(pkg => { return pkg[property]; })
|
||||
.reduce((left, right) => { return left.concat(right); }, []);
|
||||
};
|
||||
const listToTable = data => {
|
||||
return Array.from(new Set(data))
|
||||
.sort()
|
||||
.map(entry => { return 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),
|
||||
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
|
||||
showFailure(errorThrown);
|
||||
}
|
||||
hideControls(true);
|
||||
},
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: "/api/v1/status",
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: response => {
|
||||
const badgeColor = status => {
|
||||
if (status === "pending") return "yellow";
|
||||
if (status === "building") return "yellow";
|
||||
if (status === "failed") return "critical";
|
||||
if (status === "success") return "success";
|
||||
return "inactive";
|
||||
};
|
||||
|
||||
architectureBadge
|
||||
.attr("src", `https://img.shields.io/badge/architecture-${response.architecture}-informational`)
|
||||
.attr("alt", response.architecture);
|
||||
repositoryBadge
|
||||
.attr("src", `https://img.shields.io/badge/repository-${response.repository.replace(/-/g, "--")}-informational`)
|
||||
.attr("alt", response.repository);
|
||||
statusBadge
|
||||
.attr("src", `https://img.shields.io/badge/service%20status-${response.status.status}-${badgeColor(response.status.status)}`)
|
||||
.attr("alt", response.status.status)
|
||||
.attr("title", `at ${new Date(1000 * response.status.timestamp).toISOString()}`);
|
||||
versionBadge
|
||||
.attr("src", `https://img.shields.io/badge/version-${response.version}-informational`)
|
||||
.attr("alt", response.version);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function safe(string) {
|
||||
return String(string)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """);
|
||||
}
|
||||
|
||||
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)};
|
||||
}
|
||||
|
||||
$(() => {
|
||||
table.bootstrapTable({});
|
||||
reload();
|
||||
});
|
||||
</script>
|
42
package/share/ahriman/templates/email-index.jinja2
Normal file
42
package/share/ahriman/templates/email-index.jinja2
Normal file
@ -0,0 +1,42 @@
|
||||
{#simplified version of full report#}
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{{ repository }}</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{% include "utils/style.jinja2" %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<table id="packages" class="table table-striped">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th>package</th>
|
||||
<th>version</th>
|
||||
<th>archive size</th>
|
||||
<th>installed size</th>
|
||||
<th>build date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for package in packages %}
|
||||
<tr>
|
||||
<td><a href="{{ link_path }}/{{ package.filename }}" title="{{ package.name }}">{{ package.name }}</a></td>
|
||||
<td>{{ package.version }}</td>
|
||||
<td>{{ package.archive_size }}</td>
|
||||
<td>{{ package.installed_size }}</td>
|
||||
<td>{{ package.build_date }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
99
package/share/ahriman/templates/repo-index.jinja2
Normal file
99
package/share/ahriman/templates/repo-index.jinja2
Normal file
@ -0,0 +1,99 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{{ repository }}</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{% include "utils/style.jinja2" %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<h1>Arch linux user repository</h1>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
{% if pgp_key is not none %}
|
||||
<p>This repository is signed with <a href="https://pgp.mit.edu/pks/lookup?search=0x{{ pgp_key }}&fingerprint=on&op=index" title="key search">{{ pgp_key }}</a> by default.</p>
|
||||
{% endif %}
|
||||
|
||||
<pre>$ cat /etc/pacman.conf
|
||||
[{{ repository }}]
|
||||
Server = {{ link_path }}
|
||||
SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Package{% if has_package_signed %}Required{% else %}Never{% endif %} TrustedOnly</pre>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<table id="packages" class="table table-striped table-hover"
|
||||
data-export-options='{"fileName": "packages"}'
|
||||
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-fullscreen="true"
|
||||
data-show-search-clear-button="true"
|
||||
data-sortable="true"
|
||||
data-sort-name="base"
|
||||
data-sort-order="asc"
|
||||
data-toggle="table">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th data-sortable="true" data-switchable="false">package</th>
|
||||
<th data-sortable="true">version</th>
|
||||
<th data-sortable="true" data-visible="false">architecture</th>
|
||||
<th data-sortable="true" data-visible="false">description</th>
|
||||
<th data-sortable="true" data-visible="false">upstream url</th>
|
||||
<th data-sortable="true" data-visible="false">licenses</th>
|
||||
<th data-sortable="true" data-visible="false">groups</th>
|
||||
<th data-sortable="true" data-visible="false">depends</th>
|
||||
<th data-sortable="true">archive size</th>
|
||||
<th data-sortable="true">installed size</th>
|
||||
<th data-sortable="true">build date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for package in packages %}
|
||||
<tr>
|
||||
<td><a href="{{ link_path }}/{{ package.filename }}" title="{{ package.name }}">{{ package.name }}</a></td>
|
||||
<td>{{ package.version }}</td>
|
||||
<td>{{ package.architecture }}</td>
|
||||
<td>{{ package.description }}</td>
|
||||
<td><a href="{{ package.url }}" title="{{ package.name }} upstream url">{{ package.url }}</a></td>
|
||||
<td>{{ package.licenses|join("<br>"|safe) }}</td>
|
||||
<td>{{ package.groups|join("<br>"|safe) }}</td>
|
||||
<td>{{ package.depends|join("<br>"|safe) }}</td>
|
||||
<td>{{ package.archive_size }}</td>
|
||||
<td>{{ package.installed_size }}</td>
|
||||
<td>{{ package.build_date }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<footer class="d-flex flex-wrap justify-content-between align-items-center border-top">
|
||||
<ul class="nav">
|
||||
{% if homepage is not none %}
|
||||
<li><a class="nav-link" href="{{ homepage }}" title="homepage">homepage</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<ul class="nav">
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ahriman" title="sources">ahriman</a></li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
{% include "utils/bootstrap-scripts.jinja2" %}
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
18
package/share/ahriman/templates/shell
Normal file
18
package/share/ahriman/templates/shell
Normal file
@ -0,0 +1,18 @@
|
||||
[00m
|
||||
[38;5;60m▄[48;5;60;38;5;67m▄[49;38;5;60m▄[39m [38;5;60m▄▄▄▄▄▄[48;5;60m█[49m▀[39m [00m
|
||||
[38;5;60m▄[48;5;60;38;5;67m▄[48;5;67;38;5;60m▄[48;5;60;38;5;103m▄[48;5;103;38;5;110m▄[48;5;60;38;5;103m▄[38;5;67m▄▄▄[48;5;67m██[38;5;60m▄▄▄[38;5;67m█[48;5;60m▄[49;38;5;60m▄[39m [00m
|
||||
[48;5;60;38;5;60m█[48;5;67;38;5;67m█[48;5;60;38;5;103m▄[48;5;103;38;5;110m▄[48;5;110m██[48;5;103;38;5;103m█[48;5;60;38;5;67m▄▄▄▄[48;5;67;38;5;60m▄[38;5;67m██[48;5;60m▄[48;5;67;38;5;60m▄[38;5;67m█[48;5;60m▄[49;38;5;60m▄[39m [00m
|
||||
[48;5;60;38;5;60m█[48;5;67m▄[48;5;103;38;5;103m█[48;5;110;38;5;110m█[48;5;103;38;5;103m█[48;5;110;38;5;110m██[48;5;103;38;5;103m█[48;5;60;38;5;110m▄▄[38;5;103m▄[48;5;110;38;5;110m█[48;5;60;38;5;60m█[48;5;67;38;5;67m██[48;5;60m▄[48;5;67;38;5;60m▄[38;5;67m█[48;5;60m▄[49;38;5;60m▄[39m [38;5;60m▄[39m[00m
|
||||
[48;5;60;38;5;60m█[38;5;67m▄[48;5;103;38;5;60m▄[48;5;110;38;5;103m▄[38;5;110m█████████[48;5;60m▄▄[48;5;67;38;5;60m▄▄[49m▀[48;5;67m▄[38;5;67m█[48;5;60m▄[38;5;60m█[49m▀[39m[00m
|
||||
[48;5;60;38;5;60m█[49m▄▀[48;5;67m▄[48;5;103;38;5;103m█[48;5;110;38;5;110m███[38;5;232m▄[38;5;110m█[38;5;232m▄▄▄▄[38;5;110m███[48;5;103m▄[49;38;5;103m▄[39m [38;5;60m▀▀[39m [00m
|
||||
[48;5;60;38;5;60m█[48;5;67m▄[48;5;60;38;5;67m▄▄[48;5;103;38;5;103m█[48;5;110;38;5;110m███[38;5;232m▄[48;5;232m█[48;5;188;38;5;188m█[48;5;231;38;5;231m██[48;5;232;38;5;232m██[48;5;110;38;5;110m███[48;5;103;38;5;103m█[49;39m [00m
|
||||
[38;5;60m▄▄[48;5;60;38;5;67m▄▄▄▄[49;38;5;60m▄▄▄[39m [38;5;60m▀[48;5;60m█[38;5;67m▄[48;5;103;38;5;103m█[48;5;110;38;5;110m████[48;5;232m▄[48;5;145;38;5;231m▄[48;5;232;38;5;145m▄[38;5;231m▄[38;5;232m█[38;5;231m▄[48;5;110;38;5;110m██[48;5;103;38;5;103m█[49m▄[39m [00m
|
||||
[38;5;60m▄[48;5;60;38;5;67m▄[48;5;67m███[38;5;60m▄▄▄▄▄▄[48;5;60;38;5;67m▄▄[49;38;5;60m▄[39m [38;5;60m▀[39m [38;5;103m▀[48;5;110m▄[38;5;110m█████[48;5;188m▄▄[48;5;110m█[38;5;103m▄[38;5;110m██[48;5;103;38;5;103m█[49;39m [00m
|
||||
[48;5;60;38;5;60m█[48;5;67;38;5;67m██[38;5;60m▄[48;5;60;38;5;67m▄[48;5;67m████[38;5;60m▄▄[48;5;60m█[48;5;67m▄[38;5;67m█[48;5;60;38;5;60m█[49;38;5;103m▄▄▄[39m [48;5;103;38;5;103m█[48;5;110;38;5;110m██[48;5;103m▄[48;5;110;38;5;103m▄▄▄▄▄[48;5;103m█[49m▀▀[39m [00m
|
||||
[48;5;60;38;5;60m█[48;5;67;38;5;67m█[48;5;60;38;5;60m█[48;5;67;38;5;67m████[38;5;60m▄[49m▀[39m [48;5;60;38;5;103m▄[48;5;103;38;5;110m▄[48;5;110;38;5;179m▄[38;5;110m██[48;5;103m▄▄▄[48;5;110m████[48;5;103;38;5;103m█[49;39m [00m
|
||||
[48;5;60;38;5;60m█[48;5;67;38;5;67m█[48;5;60m▄[48;5;67;38;5;60m▄[38;5;67m███[48;5;60;38;5;60m█[49;39m [48;5;103;38;5;103m█[48;5;185;38;5;110m▄[48;5;110m█[38;5;179m▄[48;5;179;38;5;110m▄[48;5;110m████████[48;5;103;38;5;103m█[49;39m [00m
|
||||
[38;5;60m▄[48;5;60;38;5;67m▄[48;5;67m█[38;5;60m▄[48;5;60;38;5;67m▄[48;5;67m██[38;5;60m▄[49m▀[39m [38;5;103m▀[48;5;110m▄[38;5;110m████[38;5;103m▄[38;5;110m██[38;5;103m▄[38;5;110m██[38;5;103m▄[48;5;103;38;5;67m▄[49;39m [00m
|
||||
[48;5;60;38;5;60m█[48;5;67;38;5;67m██[48;5;60;38;5;60m█[48;5;67;38;5;67m███[48;5;60;38;5;60m█[49;39m [38;5;103m▄[48;5;103m█[48;5;110;38;5;110m██[38;5;103m▄[48;5;103;38;5;110m▄[38;5;67m▄[38;5;103m█[38;5;110m▄[48;5;110m█[48;5;103;38;5;103m█[48;5;110;38;5;110m█[48;5;67;38;5;67m█[49;39m [00m
|
||||
[38;5;60m▄[48;5;60;38;5;67m▄[48;5;67;38;5;60m▄[48;5;60;38;5;67m▄[48;5;67m███[38;5;60m▄[49m▀[39m [38;5;103m▄[48;5;103;38;5;110m▄[48;5;110m██[48;5;103;38;5;103m█[48;5;110;38;5;110m█[48;5;67;38;5;67m█[49;39m [48;5;103;38;5;103m█[48;5;110;38;5;110m██[48;5;103m▄[48;5;110;38;5;103m▄[48;5;67;38;5;110m▄[49;38;5;67m▄[39m [00m
|
||||
[38;5;60m▄▄▄[48;5;60m█[48;5;67;38;5;67m█[38;5;60m▄[48;5;60;38;5;67m▄[48;5;67m█[38;5;60m▄▄▄[49m▀[39m [48;5;103;38;5;103m█[48;5;110;38;5;110m███[48;5;103;38;5;103m█[48;5;110;38;5;67m▄[48;5;67m█[49;39m [48;5;103;38;5;103m█[48;5;110;38;5;110m███[48;5;103;38;5;103m█[48;5;110;38;5;67m▄[48;5;67m█[49;39m [00m
|
||||
[38;5;60m▀▀▀▀▀▀▀[39m [38;5;103m▀▀▀▀[39m [38;5;103m▀▀▀▀[39m [00m
|
BIN
package/share/ahriman/templates/static/favicon.ico
Normal file
BIN
package/share/ahriman/templates/static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
4
package/share/ahriman/templates/telegram-index.jinja2
Normal file
4
package/share/ahriman/templates/telegram-index.jinja2
Normal file
@ -0,0 +1,4 @@
|
||||
{#simplified version of full report#}
|
||||
<b>{{ repository }} update</b>
|
||||
{% for package in packages %}
|
||||
<a href="{{ link_path }}/{{ package.filename }}">{{ package.name }}</a> {{ package.version }}{% endfor %}
|
@ -0,0 +1,12 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/tableexport.jquery.plugin/tableExport.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.min.js"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
|
||||
<script src="https://unpkg.com/bootstrap-table@1.20.2/dist/bootstrap-table.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/bootstrap-table@1.20.2/dist/extensions/export/bootstrap-table-export.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/bootstrap-table@1.20.2/dist/extensions/resizable/bootstrap-table-resizable.js"></script>
|
9
package/share/ahriman/templates/utils/style.jinja2
Normal file
9
package/share/ahriman/templates/utils/style.jinja2
Normal file
@ -0,0 +1,9 @@
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous" type="text/css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.3/font/bootstrap-icons.css" type="text/css">
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.20.2/dist/bootstrap-table.min.css" type="text/css">
|
||||
|
||||
<link href="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.css" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
</style>
|
143
setup.py
143
setup.py
@ -1,72 +1,135 @@
|
||||
from distutils.util import convert_path
|
||||
from setuptools import setup, find_packages
|
||||
from os import path
|
||||
from pathlib import Path
|
||||
from setuptools import find_packages, setup
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
metadata_path = Path(__file__).resolve().parent / "src/ahriman/version.py"
|
||||
metadata: Dict[str, Any] = {}
|
||||
with metadata_path.open() as metadata_file:
|
||||
exec(metadata_file.read(), metadata) # pylint: disable=exec-used
|
||||
|
||||
here = path.abspath(path.dirname(__file__))
|
||||
metadata = dict()
|
||||
with open(convert_path('src/ahriman/version.py')) as metadata_file:
|
||||
exec(metadata_file.read(), metadata)
|
||||
|
||||
setup(
|
||||
name='ahriman',
|
||||
name="ahriman",
|
||||
|
||||
version=metadata['__version__'],
|
||||
version=metadata["__version__"],
|
||||
zip_safe=False,
|
||||
|
||||
description='ArcHlinux ReposItory MANager',
|
||||
description="ArcH linux ReposItory MANager",
|
||||
|
||||
author='arcanis',
|
||||
author_email='',
|
||||
url='https://github.com/arcan1s/ahriman',
|
||||
author="ahriman team",
|
||||
author_email="",
|
||||
url="https://github.com/arcan1s/ahriman",
|
||||
|
||||
license='GPL3',
|
||||
license="GPL3",
|
||||
|
||||
packages=find_packages('src'),
|
||||
package_dir={'': 'src'},
|
||||
packages=find_packages("src"),
|
||||
package_dir={"": "src"},
|
||||
|
||||
dependency_links=[
|
||||
],
|
||||
install_requires=[
|
||||
'aur',
|
||||
'pyalpm',
|
||||
'srcinfo',
|
||||
"inflection",
|
||||
"passlib",
|
||||
"requests",
|
||||
"setuptools",
|
||||
"srcinfo",
|
||||
],
|
||||
setup_requires=[
|
||||
'pytest-runner',
|
||||
],
|
||||
tests_require=[
|
||||
'pytest',
|
||||
"pytest",
|
||||
"pytest-aiohttp",
|
||||
"pytest-cov",
|
||||
"pytest-helpers-namespace",
|
||||
"pytest-mock",
|
||||
"pytest-spec",
|
||||
"pytest-resource-path",
|
||||
],
|
||||
|
||||
include_package_data=True,
|
||||
scripts=[
|
||||
'package/bin/ahriman',
|
||||
"package/bin/ahriman",
|
||||
],
|
||||
data_files=[
|
||||
('/etc', [
|
||||
'package/etc/ahriman.ini',
|
||||
("share/ahriman/settings", [
|
||||
"package/share/ahriman/settings/ahriman.ini",
|
||||
]),
|
||||
('/etc/ahriman.ini.d', [
|
||||
'package/etc/ahriman.ini.d/logging.ini',
|
||||
("share/ahriman/settings/ahriman.ini.d", [
|
||||
"package/share/ahriman/settings/ahriman.ini.d/logging.ini",
|
||||
]),
|
||||
('lib/systemd/system', [
|
||||
'package/lib/systemd/system/ahriman@.service',
|
||||
'package/lib/systemd/system/ahriman@.timer',
|
||||
'package/lib/systemd/system/ahriman-web@.service',
|
||||
("lib/systemd/system", [
|
||||
"package/lib/systemd/system/ahriman@.service",
|
||||
"package/lib/systemd/system/ahriman@.timer",
|
||||
"package/lib/systemd/system/ahriman-web@.service",
|
||||
]),
|
||||
('share/ahriman', [
|
||||
'package/share/ahriman/build-status.jinja2',
|
||||
'package/share/ahriman/repo-index.jinja2',
|
||||
'package/share/ahriman/search.jinja2',
|
||||
'package/share/ahriman/search-line.jinja2',
|
||||
'package/share/ahriman/sorttable.jinja2',
|
||||
'package/share/ahriman/style.jinja2',
|
||||
("share/ahriman/templates", [
|
||||
"package/share/ahriman/templates/build-status.jinja2",
|
||||
"package/share/ahriman/templates/email-index.jinja2",
|
||||
"package/share/ahriman/templates/repo-index.jinja2",
|
||||
"package/share/ahriman/templates/shell",
|
||||
"package/share/ahriman/templates/telegram-index.jinja2",
|
||||
]),
|
||||
("share/ahriman/templates/build-status", [
|
||||
"package/share/ahriman/templates/build-status/failed-modal.jinja2",
|
||||
"package/share/ahriman/templates/build-status/login-modal.jinja2",
|
||||
"package/share/ahriman/templates/build-status/package-add-modal.jinja2",
|
||||
"package/share/ahriman/templates/build-status/success-modal.jinja2",
|
||||
"package/share/ahriman/templates/build-status/table.jinja2",
|
||||
]),
|
||||
("share/ahriman/templates/static", [
|
||||
"package/share/ahriman/templates/static/favicon.ico",
|
||||
]),
|
||||
("share/ahriman/templates/utils", [
|
||||
"package/share/ahriman/templates/utils/bootstrap-scripts.jinja2",
|
||||
"package/share/ahriman/templates/utils/style.jinja2",
|
||||
]),
|
||||
("share/man/man1", [
|
||||
"docs/ahriman.1",
|
||||
])
|
||||
],
|
||||
|
||||
extras_require={
|
||||
'html-templates': ['Jinja2'],
|
||||
'test': ['coverage', 'pytest'],
|
||||
'web': ['Jinja2', 'aiohttp', 'aiohttp_jinja2', 'requests'],
|
||||
"check": [
|
||||
"autopep8",
|
||||
"bandit",
|
||||
"mypy",
|
||||
"pylint",
|
||||
],
|
||||
"docs": [
|
||||
"Sphinx",
|
||||
"argparse-manpage",
|
||||
"pydeps",
|
||||
"sphinx-argparse",
|
||||
"sphinxcontrib-napoleon",
|
||||
],
|
||||
# FIXME technically this dependency is required, but in some cases we do not have access to
|
||||
# the libalpm which is required in order to install the package. Thus in case if we do not
|
||||
# really need to run the application we can move it to "optional" dependencies
|
||||
"pacman": [
|
||||
"pyalpm",
|
||||
],
|
||||
"s3": [
|
||||
"boto3",
|
||||
],
|
||||
"tests": [
|
||||
"pytest",
|
||||
"pytest-aiohttp",
|
||||
"pytest-cov",
|
||||
"pytest-helpers-namespace",
|
||||
"pytest-mock",
|
||||
"pytest-resource-path",
|
||||
"pytest-spec",
|
||||
],
|
||||
"web": [
|
||||
"Jinja2",
|
||||
"aiohttp",
|
||||
"aiohttp_jinja2",
|
||||
"aioauth-client",
|
||||
"aiohttp_debugtoolbar",
|
||||
"aiohttp_session",
|
||||
"aiohttp_security",
|
||||
"cryptography",
|
||||
],
|
||||
},
|
||||
)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021 Evgenii Alekseev.
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021 Evgenii Alekseev.
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021 Evgenii Alekseev.
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -17,91 +17,869 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# pylint: disable=too-many-lines
|
||||
import argparse
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
import ahriman.application.handlers as handlers
|
||||
import ahriman.version as version
|
||||
from pathlib import Path
|
||||
from typing import List, TypeVar
|
||||
|
||||
from ahriman import version
|
||||
from ahriman.application import handlers
|
||||
from ahriman.core.util import enum_values
|
||||
from ahriman.models.action import Action
|
||||
from ahriman.models.build_status import BuildStatusEnum
|
||||
from ahriman.models.package_source import PackageSource
|
||||
from ahriman.models.sign_settings import SignSettings
|
||||
from ahriman.models.user_access import UserAccess
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(prog='ahriman', description='ArcHlinux ReposItory MANager')
|
||||
parser.add_argument(
|
||||
'-a',
|
||||
'--architecture',
|
||||
help='target architectures (can be used multiple times)',
|
||||
action='append')
|
||||
parser.add_argument('-c', '--config', help='configuration path', default='/etc/ahriman.ini')
|
||||
parser.add_argument('--force', help='force run, remove file lock', action='store_true')
|
||||
parser.add_argument('--lock', help='lock file', default='/tmp/ahriman.lock')
|
||||
parser.add_argument('--no-log', help='redirect all log messages to stderr', action='store_true')
|
||||
parser.add_argument('--no-report', help='force disable reporting to web service', action='store_true')
|
||||
parser.add_argument('--unsafe', help='allow to run ahriman as non-ahriman user', action='store_true')
|
||||
parser.add_argument('-v', '--version', action='version', version=version.__version__)
|
||||
subparsers = parser.add_subparsers(title='command')
|
||||
__all__: List[str] = []
|
||||
|
||||
add_parser = subparsers.add_parser('add', description='add package')
|
||||
add_parser.add_argument('package', help='package base/name or archive path', nargs='+')
|
||||
add_parser.add_argument('--without-dependencies', help='do not add dependencies', action='store_true')
|
||||
add_parser.set_defaults(handler=handlers.Add)
|
||||
|
||||
check_parser = subparsers.add_parser('check', description='check for updates. Same as update --dry-run --no-manual')
|
||||
check_parser.add_argument('package', help='filter check by package base', nargs='*')
|
||||
check_parser.add_argument('--no-vcs', help='do not check VCS packages', action='store_true')
|
||||
check_parser.set_defaults(handler=handlers.Update, no_aur=False, no_manual=True, dry_run=True)
|
||||
# this workaround is for several things
|
||||
# firstly python devs don't think that is it error and asking you for workarounds https://bugs.python.org/issue41592
|
||||
# secondly linters don't like when you are importing private members
|
||||
# thirdly new mypy doesn't like _SubParsersAction and thinks it is a template
|
||||
SubParserAction = TypeVar("SubParserAction", bound="argparse._SubParsersAction[argparse.ArgumentParser]")
|
||||
|
||||
clean_parser = subparsers.add_parser('clean', description='clear all local caches')
|
||||
clean_parser.add_argument('--no-build', help='do not clear directory with package sources', action='store_true')
|
||||
clean_parser.add_argument('--no-cache', help='do not clear directory with package caches', action='store_true')
|
||||
clean_parser.add_argument('--no-chroot', help='do not clear build chroot', action='store_true')
|
||||
clean_parser.add_argument(
|
||||
'--no-manual',
|
||||
help='do not clear directory with manually added packages',
|
||||
action='store_true')
|
||||
clean_parser.add_argument('--no-packages', help='do not clear directory with built packages', action='store_true')
|
||||
clean_parser.set_defaults(handler=handlers.Clean)
|
||||
|
||||
config_parser = subparsers.add_parser('config', description='dump configuration for specified architecture')
|
||||
config_parser.set_defaults(handler=handlers.Dump, lock=None, no_report=True, unsafe=True)
|
||||
def _formatter(prog: str) -> argparse.HelpFormatter:
|
||||
"""
|
||||
formatter for the help message
|
||||
|
||||
rebuild_parser = subparsers.add_parser('rebuild', description='rebuild whole repository')
|
||||
rebuild_parser.set_defaults(handler=handlers.Rebuild)
|
||||
Args:
|
||||
prog(str): application name
|
||||
|
||||
remove_parser = subparsers.add_parser('remove', description='remove package')
|
||||
remove_parser.add_argument('package', help='package name or base', nargs='+')
|
||||
remove_parser.set_defaults(handler=handlers.Remove)
|
||||
Returns:
|
||||
argparse.HelpFormatter: formatter used by default
|
||||
"""
|
||||
return argparse.ArgumentDefaultsHelpFormatter(prog, width=120)
|
||||
|
||||
report_parser = subparsers.add_parser('report', description='generate report')
|
||||
report_parser.add_argument('target', help='target to generate report', nargs='*')
|
||||
report_parser.set_defaults(handler=handlers.Report)
|
||||
|
||||
status_parser = subparsers.add_parser('status', description='request status of the package')
|
||||
status_parser.add_argument('--ahriman', help='get service status itself', action='store_true')
|
||||
status_parser.add_argument('package', help='filter status by package base', nargs='*')
|
||||
status_parser.set_defaults(handler=handlers.Status, lock=None, no_report=True, unsafe=True)
|
||||
def _parser() -> argparse.ArgumentParser:
|
||||
"""
|
||||
command line parser generator
|
||||
|
||||
sync_parser = subparsers.add_parser('sync', description='sync packages to remote server')
|
||||
sync_parser.add_argument('target', help='target to sync', nargs='*')
|
||||
sync_parser.set_defaults(handler=handlers.Sync)
|
||||
Returns:
|
||||
argparse.ArgumentParser: command line parser for the application
|
||||
"""
|
||||
parser = argparse.ArgumentParser(prog="ahriman", description="ArcH linux ReposItory MANager",
|
||||
epilog="Argument list can also be read from file by using @ prefix.",
|
||||
fromfile_prefix_chars="@", formatter_class=_formatter)
|
||||
parser.add_argument("-a", "--architecture", help="target architectures (can be used multiple times)",
|
||||
action="append")
|
||||
parser.add_argument("-c", "--configuration", help="configuration path", type=Path, default=Path("/etc/ahriman.ini"))
|
||||
parser.add_argument("--force", help="force run, remove file lock", action="store_true")
|
||||
parser.add_argument("-l", "--lock", help="lock file", type=Path,
|
||||
default=Path(tempfile.gettempdir()) / "ahriman.lock")
|
||||
parser.add_argument("--report", help="force enable or disable reporting to web service",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
|
||||
parser.add_argument("--unsafe", help="allow to run ahriman as non-ahriman user. Some actions might be unavailable",
|
||||
action="store_true")
|
||||
parser.add_argument("-V", "--version", action="version", version=version.__version__)
|
||||
|
||||
update_parser = subparsers.add_parser('update', description='run updates')
|
||||
update_parser.add_argument('package', help='filter check by package base', nargs='*')
|
||||
update_parser.add_argument(
|
||||
'--dry-run', help='just perform check for updates, same as check command', action='store_true')
|
||||
update_parser.add_argument('--no-aur', help='do not check for AUR updates. Implies --no-vcs', action='store_true')
|
||||
update_parser.add_argument('--no-manual', help='do not include manual updates', action='store_true')
|
||||
update_parser.add_argument('--no-vcs', help='do not check VCS packages', action='store_true')
|
||||
update_parser.set_defaults(handler=handlers.Update)
|
||||
subparsers = parser.add_subparsers(title="command", help="command to run", dest="command", required=True)
|
||||
|
||||
web_parser = subparsers.add_parser('web', description='start web server')
|
||||
web_parser.set_defaults(handler=handlers.Web, lock=None, no_report=True)
|
||||
_set_aur_search_parser(subparsers)
|
||||
_set_daemon_parser(subparsers)
|
||||
_set_help_parser(subparsers)
|
||||
_set_help_commands_unsafe_parser(subparsers)
|
||||
_set_key_import_parser(subparsers)
|
||||
_set_package_add_parser(subparsers)
|
||||
_set_package_remove_parser(subparsers)
|
||||
_set_package_status_parser(subparsers)
|
||||
_set_package_status_remove_parser(subparsers)
|
||||
_set_package_status_update_parser(subparsers)
|
||||
_set_patch_add_parser(subparsers)
|
||||
_set_patch_list_parser(subparsers)
|
||||
_set_patch_remove_parser(subparsers)
|
||||
_set_patch_set_add_parser(subparsers)
|
||||
_set_repo_backup_parser(subparsers)
|
||||
_set_repo_check_parser(subparsers)
|
||||
_set_repo_clean_parser(subparsers)
|
||||
_set_repo_config_parser(subparsers)
|
||||
_set_repo_rebuild_parser(subparsers)
|
||||
_set_repo_remove_unknown_parser(subparsers)
|
||||
_set_repo_report_parser(subparsers)
|
||||
_set_repo_restore_parser(subparsers)
|
||||
_set_repo_setup_parser(subparsers)
|
||||
_set_repo_sign_parser(subparsers)
|
||||
_set_repo_status_update_parser(subparsers)
|
||||
_set_repo_sync_parser(subparsers)
|
||||
_set_repo_triggers_parser(subparsers)
|
||||
_set_repo_update_parser(subparsers)
|
||||
_set_shell_parser(subparsers)
|
||||
_set_user_add_parser(subparsers)
|
||||
_set_user_list_parser(subparsers)
|
||||
_set_user_remove_parser(subparsers)
|
||||
_set_version_parser(subparsers)
|
||||
_set_web_parser(subparsers)
|
||||
|
||||
args = parser.parse_args()
|
||||
if 'handler' not in args:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
return parser
|
||||
|
||||
handler: handlers.Handler = args.handler
|
||||
status = handler.execute(args)
|
||||
|
||||
sys.exit(status)
|
||||
def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for AUR search subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("aur-search", aliases=["search"], help="search for package",
|
||||
description="search for package in AUR using API", formatter_class=_formatter)
|
||||
parser.add_argument("search", help="search terms, can be specified multiple times, the result will match all terms",
|
||||
nargs="+")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("--info", help="show additional package information",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--sort-by", help="sort field by this field. In case if two packages have the same value of "
|
||||
"the specified field, they will be always sorted by name",
|
||||
default="name", choices=sorted(handlers.Search.SORT_FIELDS))
|
||||
parser.set_defaults(handler=handlers.Search, architecture=[""], lock=None, report=False, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_daemon_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for daemon subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("daemon", help="run application as daemon",
|
||||
description="start process which periodically will run update process",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("-i", "--interval", help="interval between runs in seconds", type=int, default=60 * 60 * 12)
|
||||
parser.add_argument("--aur", help="enable or disable checking for AUR updates. Implies --no-vcs",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--local", help="enable or disable checking of local packages for updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--manual", help="include or exclude manual updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--vcs", help="enable or disable checking of VCS packages",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
action="count", default=0)
|
||||
parser.set_defaults(handler=handlers.Daemon, dry_run=False, exit_code=False, package=[])
|
||||
return parser
|
||||
|
||||
|
||||
def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for listing help subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("help", help="show help message",
|
||||
description="show help message for application or command and exit",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("command", help="show help message for specific command", nargs="?")
|
||||
parser.set_defaults(handler=handlers.Help, architecture=[""], lock=None, report=False, quiet=True,
|
||||
unsafe=True, parser=_parser)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for listing unsafe commands
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("help-commands-unsafe", help="list unsafe commands",
|
||||
description="list unsafe commands as defined in default args", formatter_class=_formatter)
|
||||
parser.add_argument("--command", help="instead of showing commands, just test command line for unsafe subcommand "
|
||||
"and return 0 in case if command is safe and 1 otherwise")
|
||||
parser.set_defaults(handler=handlers.UnsafeCommands, architecture=[""], lock=None, report=False, quiet=True,
|
||||
unsafe=True, parser=_parser)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_key_import_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for key import subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("key-import", help="import PGP key",
|
||||
description="import PGP key from public sources to the repository user",
|
||||
epilog="By default ahriman runs build process with package sources validation "
|
||||
"(in case if signature and keys are available in PKGBUILD). This process will "
|
||||
"fail in case if key is not known for build user. This subcommand can be used "
|
||||
"in order to import the PGP key to user keychain.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--key-server", help="key server for key import", default="pgp.mit.edu")
|
||||
parser.add_argument("key", help="PGP key to import from public server")
|
||||
parser.set_defaults(handler=handlers.KeyImport, architecture=[""], lock=None, report=False)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_package_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package addition subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-add", aliases=["add", "package-update"], help="add package",
|
||||
description="add existing or new package to the build queue",
|
||||
epilog="This subcommand should be used for new package addition. It also supports flag "
|
||||
"--now in case if you would like to build the package immediately. "
|
||||
"You can add new package from one of supported sources: "
|
||||
"1) if it is already built package you can specify the path to the archive; "
|
||||
"2) you can also add built packages from the directory (e.g. during the migration "
|
||||
"from another repository source); "
|
||||
"3) it is also possible to add package from local PKGBUILD, but in this case it "
|
||||
"will be ignored during the next automatic updates; "
|
||||
"4) ahriman supports downloading archives from remote (e.g. HTTP) sources; "
|
||||
"5) and finally you can add package from AUR.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="package source (base name, path to local files, remote URL)", nargs="+")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("-n", "--now", help="run update function after", action="store_true")
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
action="count", default=0)
|
||||
parser.add_argument("-s", "--source", help="explicitly specify the package source for this command",
|
||||
type=PackageSource, choices=enum_values(PackageSource), default=PackageSource.Auto)
|
||||
parser.add_argument("--without-dependencies", help="do not add dependencies", action="store_true")
|
||||
parser.set_defaults(handler=handlers.Add)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_package_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package removal subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-remove", aliases=["remove"], help="remove package",
|
||||
description="remove package from the repository", formatter_class=_formatter)
|
||||
parser.add_argument("package", help="package name or base", nargs="+")
|
||||
parser.set_defaults(handler=handlers.Remove)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_package_status_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package status subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-status", aliases=["status"], help="get package status",
|
||||
description="request status of the package",
|
||||
epilog="This feature requests package status from the web interface if it is available.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="filter status by package base", nargs="*")
|
||||
parser.add_argument("--ahriman", help="get service status itself", action="store_true")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("-i", "--info", help="show additional package information", action="store_true")
|
||||
parser.add_argument("-s", "--status", help="filter packages by status",
|
||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum))
|
||||
parser.set_defaults(handler=handlers.Status, lock=None, report=False, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_package_status_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package status remove subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-status-remove", help="remove package status",
|
||||
description="remove the package from the status page",
|
||||
epilog="Please note that this subcommand does not remove the package itself, it just "
|
||||
"clears the status page.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="remove specified packages from status page", nargs="+")
|
||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Remove, lock=None, report=False, quiet=True,
|
||||
unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_package_status_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for package status update subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("package-status-update", aliases=["status-update"], help="update package status",
|
||||
description="update package status on the status page", formatter_class=_formatter)
|
||||
parser.add_argument("package", help="set status for specified packages. "
|
||||
"If no packages supplied, service status will be updated",
|
||||
nargs="*")
|
||||
parser.add_argument("-s", "--status", help="new package build status",
|
||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, report=False, quiet=True,
|
||||
unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_patch_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for new single-function patch subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("patch-add", help="add patch for PKGBUILD function",
|
||||
description="create or update patched PKGBUILD function or variable",
|
||||
epilog="Unlike ``patch-set-add``, this function allows to patch only one PKGBUILD "
|
||||
"function, e.g. typing ``ahriman patch-add ahriman pkgver`` it will change the "
|
||||
"``pkgver`` inside PKGBUILD, typing ``ahriman patch-add ahriman build()`` "
|
||||
"it will change ``build()`` function inside PKGBUILD",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="package base")
|
||||
parser.add_argument("variable", help="PKGBUILD variable or function name. If variable is a function, "
|
||||
"it must end with ()")
|
||||
parser.add_argument("patch", help="path to file which contains function or variable value. If not set, "
|
||||
"the value will be read from stdin", type=Path, nargs="?")
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture=[""], lock=None, report=False)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_patch_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for list patches subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("patch-list", help="list patch sets",
|
||||
description="list available patches for the package", formatter_class=_formatter)
|
||||
parser.add_argument("package", help="package base", nargs="?")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("-v", "--variable", help="if set, show only patches for specified PKGBUILD variables",
|
||||
action="append")
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.List, architecture=[""], lock=None, report=False)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_patch_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for remove patches subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("patch-remove", help="remove patch set", description="remove patches for the package",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="package base")
|
||||
parser.add_argument("-v", "--variable", help="should be used for single-function patches in case if you wold like "
|
||||
"to remove only specified PKGBUILD variables. In case if not set, "
|
||||
"it will remove all patches related to the package",
|
||||
action="append")
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.Remove, architecture=[""], lock=None, report=False)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_patch_set_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for new full-diff patch subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("patch-set-add", help="add patch set", description="create or update source patches",
|
||||
epilog="In order to add a patch set for the package you will need to clone "
|
||||
"the AUR package manually, add required changes (e.g. external patches, "
|
||||
"edit PKGBUILD) and run command, e.g. ``ahriman patch-set-add path/to/directory``. "
|
||||
"By default it tracks *.patch and *.diff files, but this behavior can be changed "
|
||||
"by using --track option",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="path to directory with changed files for patch addition/update", type=Path)
|
||||
parser.add_argument("-t", "--track", help="files which has to be tracked", action="append",
|
||||
default=["*.diff", "*.patch"])
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture=[""], lock=None, report=False,
|
||||
variable=None)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_backup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository backup subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-backup", help="backup repository data",
|
||||
description="backup repository settings and database", formatter_class=_formatter)
|
||||
parser.add_argument("path", help="path of the output archive", type=Path)
|
||||
parser.set_defaults(handler=handlers.Backup, architecture=[""], lock=None, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_check_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository check subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-check", aliases=["check"], help="check for updates",
|
||||
description="check for packages updates. Same as repo-update --dry-run --no-manual",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="filter check by package base", nargs="*")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("--vcs", help="enable or disable checking of VCS packages",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
action="count", default=0)
|
||||
parser.set_defaults(handler=handlers.Update, dry_run=True, aur=True, local=True, manual=False)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_clean_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository clean subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-clean", aliases=["clean"], help="clean local caches",
|
||||
description="remove local caches",
|
||||
epilog="The subcommand clears every temporary directories (builds, caches etc). Normally "
|
||||
"you should not run this command manually. Also in case if you are going to clear "
|
||||
"the chroot directories you will need root privileges.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--cache", help="clear directory with package caches",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--chroot", help="clear build chroot", action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--manual", help="clear manually added packages queue",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--packages", help="clear directory with built packages",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--pacman", help="clear directory with pacman local database cache",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.set_defaults(handler=handlers.Clean, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_config_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for config subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-config", aliases=["config"], help="dump configuration",
|
||||
description="dump configuration for the specified architecture",
|
||||
formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.Dump, lock=None, report=False, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_rebuild_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository rebuild subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-rebuild", aliases=["rebuild"], help="rebuild repository",
|
||||
description="force rebuild whole repository", formatter_class=_formatter)
|
||||
parser.add_argument("--depends-on", help="only rebuild packages that depend on specified packages", action="append")
|
||||
parser.add_argument("--dry-run", help="just perform check for packages without rebuild process itself",
|
||||
action="store_true")
|
||||
parser.add_argument("--from-database",
|
||||
help="read packages from database instead of filesystem. This feature in particular is "
|
||||
"required in case if you would like to restore repository from another repository "
|
||||
"instance. Note, however, that in order to restore packages you need to have original "
|
||||
"ahriman instance run with web service and have run repo-update at least once.",
|
||||
action="store_true")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.set_defaults(handler=handlers.Rebuild)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_remove_unknown_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for remove unknown packages subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-remove-unknown", aliases=["remove-unknown"], help="remove unknown packages",
|
||||
description="remove packages which are missing in AUR and do not have local PKGBUILDs",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--dry-run", help="just perform check for packages without removal", action="store_true")
|
||||
parser.set_defaults(handler=handlers.RemoveUnknown)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_report_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for report subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-report", aliases=["report"], help="generate report",
|
||||
description="generate repository report according to current settings",
|
||||
epilog="Create and/or update repository report as configured.",
|
||||
formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.Triggers, trigger=["ahriman.core.report.ReportTrigger"])
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository restore subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-restore", help="restore repository data",
|
||||
description="restore settings and database", formatter_class=_formatter)
|
||||
parser.add_argument("path", help="path of the input archive", type=Path)
|
||||
parser.add_argument("-o", "--output", help="root path of the extracted files", type=Path, default=Path("/"))
|
||||
parser.set_defaults(handler=handlers.Restore, architecture=[""], lock=None, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for setup subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-setup", aliases=["init", "repo-init", "setup"], help="initial service configuration",
|
||||
description="create initial service configuration, requires root",
|
||||
epilog="Create _minimal_ configuration for the service according to provided options.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--build-as-user", help="force makepkg user to the specific one")
|
||||
parser.add_argument("--build-command", help="build command prefix", default="ahriman")
|
||||
parser.add_argument("--from-configuration", help="path to default devtools pacman configuration",
|
||||
type=Path, default=Path("/usr/share/devtools/pacman-extra.conf"))
|
||||
parser.add_argument("--multilib", help="add or do not multilib repository",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--packager", help="packager name and email", required=True)
|
||||
parser.add_argument("--repository", help="repository name", required=True)
|
||||
parser.add_argument("--sign-key", help="sign key id")
|
||||
parser.add_argument("--sign-target", help="sign options", action="append",
|
||||
type=SignSettings.from_option, choices=enum_values(SignSettings))
|
||||
parser.add_argument("--web-port", help="port of the web service", type=int)
|
||||
parser.set_defaults(handler=handlers.Setup, lock=None, report=False, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_sign_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for sign subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-sign", aliases=["sign"], help="sign packages",
|
||||
description="(re-)sign packages and repository database according to current settings",
|
||||
epilog="Sign repository and/or packages as configured.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="sign only specified packages", nargs="*")
|
||||
parser.set_defaults(handler=handlers.Sign)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_status_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository status update subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-status-update", help="update repository status",
|
||||
description="update repository status on the status page", formatter_class=_formatter)
|
||||
parser.add_argument("-s", "--status", help="new status",
|
||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, report=False, package=[],
|
||||
quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_sync_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository sync subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-sync", aliases=["sync"], help="sync repository",
|
||||
description="sync repository files to remote server according to current settings",
|
||||
epilog="Synchronize the repository to remote services as configured.",
|
||||
formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.Triggers, trigger=["ahriman.core.upload.UploadTrigger"])
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_triggers_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository triggers subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-triggers", help="run triggers",
|
||||
description="run triggers on empty build result as configured by settings",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("trigger", help="instead of running all triggers as set by configuration, just process "
|
||||
"specified ones oin order of metion", nargs="*")
|
||||
parser.set_defaults(handler=handlers.Triggers)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository update subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-update", aliases=["update"], help="update packages",
|
||||
description="check for packages updates and run build process if requested",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="filter check by package base", nargs="*")
|
||||
parser.add_argument("--dry-run", help="just perform check for updates, same as check command", action="store_true")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("--aur", help="enable or disable checking for AUR updates. Implies --no-vcs",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--local", help="enable or disable checking of local packages for updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--manual", help="include or exclude manual updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--vcs", help="enable or disable checking of VCS packages",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
action="count", default=0)
|
||||
parser.set_defaults(handler=handlers.Update)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for shell subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("shell", help="envoke python shell",
|
||||
description="drop into python shell while having created application",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("code", help="instead of dropping into shell, just execute the specified code", nargs="?")
|
||||
parser.add_argument("-v", "--verbose", help=argparse.SUPPRESS, action="store_true")
|
||||
parser.set_defaults(handler=handlers.Shell, lock=None, report=False)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for create user subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("user-add", help="create or update user",
|
||||
description="update user for web services with the given password and role. "
|
||||
"In case if password was not entered it will be asked interactively",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("username", help="username for web service")
|
||||
parser.add_argument("--as-service", help="add user as service user", action="store_true")
|
||||
parser.add_argument("-p", "--password", help="user password. Blank password will be treated as empty password, "
|
||||
"which is in particular must be used for OAuth2 authorization type.")
|
||||
parser.add_argument("-r", "--role", help="user access level",
|
||||
type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read)
|
||||
parser.add_argument("-s", "--secure", help="set file permissions to user-only", action="store_true")
|
||||
parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture=[""], lock=None, report=False,
|
||||
quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_user_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for user list subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("user-list", help="user known users and their access",
|
||||
description="list users from the user mapping and their roles",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("username", help="filter users by username", nargs="?")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("-r", "--role", help="filter users by role", type=UserAccess, choices=enum_values(UserAccess))
|
||||
parser.set_defaults(handler=handlers.Users, action=Action.List, architecture=[""], lock=None, report=False, # nosec
|
||||
password="", quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for user removal subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("user-remove", help="remove user",
|
||||
description="remove user from the user mapping and update the configuration",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("username", help="username for web service")
|
||||
parser.add_argument("-s", "--secure", help="set file permissions to user-only", action="store_true")
|
||||
parser.set_defaults(handler=handlers.Users, action=Action.Remove, architecture=[""], lock=None, report=False, # nosec
|
||||
password="", quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_version_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for version subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("version", help="application version",
|
||||
description="print application and its dependencies versions", formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.Versions, architecture=[""], lock=None, report=False, quiet=True,
|
||||
unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_web_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for web subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("web", help="web server", description="start web server", formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.Web, lock=None, report=False, parser=_parser)
|
||||
return parser
|
||||
|
||||
|
||||
def run() -> None:
|
||||
"""
|
||||
run application instance
|
||||
"""
|
||||
if __name__ == "__main__":
|
||||
args_parser = _parser()
|
||||
args = args_parser.parse_args()
|
||||
|
||||
handler: handlers.Handler = args.handler
|
||||
status = handler.execute(args)
|
||||
|
||||
sys.exit(status)
|
||||
|
||||
|
||||
run()
|
||||
|
@ -1,200 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2021 Evgenii Alekseev.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from typing import Callable, Iterable, List, Optional, Set
|
||||
|
||||
from ahriman.core.build_tools.task import Task
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.repository.repository import Repository
|
||||
from ahriman.core.tree import Tree
|
||||
from ahriman.core.util import package_like
|
||||
from ahriman.models.package import Package
|
||||
|
||||
|
||||
class Application:
|
||||
'''
|
||||
base application class
|
||||
:ivar architecture: repository architecture
|
||||
:ivar config: configuration instance
|
||||
:ivar logger: application logger
|
||||
:ivar repository: repository instance
|
||||
'''
|
||||
|
||||
def __init__(self, architecture: str, config: Configuration) -> None:
|
||||
'''
|
||||
default constructor
|
||||
:param architecture: repository architecture
|
||||
:param config: configuration instance
|
||||
'''
|
||||
self.logger = logging.getLogger('root')
|
||||
self.config = config
|
||||
self.architecture = architecture
|
||||
self.repository = Repository(architecture, config)
|
||||
|
||||
def _known_packages(self) -> Set[str]:
|
||||
'''
|
||||
load packages from repository and pacman repositories
|
||||
:return: list of known packages
|
||||
'''
|
||||
known_packages: Set[str] = set()
|
||||
# local set
|
||||
for package in self.repository.packages():
|
||||
known_packages.update(package.packages.keys())
|
||||
known_packages.update(self.repository.pacman.all_packages())
|
||||
return known_packages
|
||||
|
||||
def _finalize(self) -> None:
|
||||
'''
|
||||
generate report and sync to remote server
|
||||
'''
|
||||
self.report()
|
||||
self.sync()
|
||||
|
||||
def get_updates(self, filter_packages: List[str], no_aur: bool, no_manual: bool, no_vcs: bool,
|
||||
log_fn: Callable[[str], None]) -> List[Package]:
|
||||
'''
|
||||
get list of packages to run update process
|
||||
:param filter_packages: do not check every package just specified in the list
|
||||
:param no_aur: do not check for aur updates
|
||||
:param no_manual: do not check for manual updates
|
||||
:param no_vcs: do not check VCS packages
|
||||
:param log_fn: logger function to log updates
|
||||
:return: list of out-of-dated packages
|
||||
'''
|
||||
updates = []
|
||||
|
||||
if not no_aur:
|
||||
updates.extend(self.repository.updates_aur(filter_packages, no_vcs))
|
||||
if not no_manual:
|
||||
updates.extend(self.repository.updates_manual())
|
||||
|
||||
for package in updates:
|
||||
log_fn(f'{package.base} = {package.version}')
|
||||
|
||||
return updates
|
||||
|
||||
def add(self, names: Iterable[str], without_dependencies: bool) -> None:
|
||||
'''
|
||||
add packages for the next build
|
||||
:param names: list of package bases to add
|
||||
:param without_dependencies: if set, dependency check will be disabled
|
||||
'''
|
||||
known_packages = self._known_packages()
|
||||
|
||||
def add_directory(path: str) -> None:
|
||||
for package in filter(package_like, os.listdir(path)):
|
||||
full_path = os.path.join(path, package)
|
||||
add_manual(full_path)
|
||||
|
||||
def add_manual(name: str) -> str:
|
||||
package = Package.load(name, self.repository.pacman, self.config.get('alpm', 'aur_url'))
|
||||
path = os.path.join(self.repository.paths.manual, package.base)
|
||||
Task.fetch(path, package.git_url)
|
||||
return path
|
||||
|
||||
def add_archive(src: str) -> None:
|
||||
dst = os.path.join(self.repository.paths.packages, os.path.basename(src))
|
||||
shutil.move(src, dst)
|
||||
|
||||
def process_dependencies(path: str) -> None:
|
||||
if without_dependencies:
|
||||
return
|
||||
dependencies = Package.dependencies(path)
|
||||
self.add(dependencies.difference(known_packages), without_dependencies)
|
||||
|
||||
def process_single(name: str) -> None:
|
||||
if os.path.isdir(name):
|
||||
add_directory(name)
|
||||
elif os.path.isfile(name):
|
||||
add_archive(name)
|
||||
else:
|
||||
path = add_manual(name)
|
||||
process_dependencies(path)
|
||||
|
||||
for name in names:
|
||||
process_single(name)
|
||||
|
||||
def clean(self, no_build: bool, no_cache: bool, no_chroot: bool, no_manual: bool, no_packages: bool) -> None:
|
||||
'''
|
||||
run all clean methods. Warning: some functions might not be available under non-root
|
||||
:param no_build: do not clear directory with package sources
|
||||
:param no_cache: do not clear directory with package caches
|
||||
:param no_chroot: do not clear build chroot
|
||||
:param no_manual: do not clear directory with manually added packages
|
||||
:param no_packages: do not clear directory with built packages
|
||||
'''
|
||||
if not no_build:
|
||||
self.repository.clear_build()
|
||||
if not no_cache:
|
||||
self.repository.clear_cache()
|
||||
if not no_chroot:
|
||||
self.repository.clear_chroot()
|
||||
if not no_manual:
|
||||
self.repository.clear_manual()
|
||||
if not no_packages:
|
||||
self.repository.clear_packages()
|
||||
|
||||
def remove(self, names: Iterable[str]) -> None:
|
||||
'''
|
||||
remove packages from repository
|
||||
:param names: list of packages (either base or name) to remove
|
||||
'''
|
||||
self.repository.process_remove(names)
|
||||
self._finalize()
|
||||
|
||||
def report(self, target: Optional[Iterable[str]] = None) -> None:
|
||||
'''
|
||||
generate report
|
||||
:param target: list of targets to run (e.g. html)
|
||||
'''
|
||||
targets = target or None
|
||||
self.repository.process_report(targets)
|
||||
|
||||
def sync(self, target: Optional[Iterable[str]] = None) -> None:
|
||||
'''
|
||||
sync to remote server
|
||||
:param target: list of targets to run (e.g. s3)
|
||||
'''
|
||||
targets = target or None
|
||||
self.repository.process_sync(targets)
|
||||
|
||||
def update(self, updates: Iterable[Package]) -> None:
|
||||
'''
|
||||
run package updates
|
||||
:param updates: list of packages to update
|
||||
'''
|
||||
def process_update(paths: Iterable[str]) -> None:
|
||||
self.repository.process_update(paths)
|
||||
self._finalize()
|
||||
|
||||
# process built packages
|
||||
packages = self.repository.packages_built()
|
||||
process_update(packages)
|
||||
|
||||
# process manual packages
|
||||
tree = Tree()
|
||||
tree.load(updates)
|
||||
for num, level in enumerate(tree.levels()):
|
||||
self.logger.info(f'processing level #{num} {[package.base for package in level]}')
|
||||
packages = self.repository.process_build(level)
|
||||
process_update(packages)
|
20
src/ahriman/application/application/__init__.py
Normal file
20
src/ahriman/application/application/__init__.py
Normal file
@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from ahriman.application.application.application import Application
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user