Compare commits

..

16 Commits

Author SHA1 Message Date
f01f35238d Release 2.13.5 2024-04-04 13:33:03 +03:00
d30d512eb6 fix: update Repo.init to the latest pacman release 2024-04-04 13:16:05 +03:00
0437f90e5a build: install base-devel package 2024-04-04 13:16:03 +03:00
3cab65855a fix: lazy web component initialization
In some cases (probably slow internet) in place initialization can cause
exception, because elements are not available yet. This commit moves
events initialization to $()
2024-04-04 13:14:17 +03:00
ecfb615f97 feat: add ability to disable debug packages distribution
The feature is implemented as supplying !debug option to makepkg when
generating package list. In this case debug packages still will be
built, however, they will not be added to the repository
2024-04-04 13:14:17 +03:00
243983ee64 docs: update docs 2024-02-10 03:12:09 +02:00
812c03d1eb Release 2.13.4 2024-02-09 17:47:01 +02:00
01597c531b fix: return only built packages from task
Since the last updates makepkg --packagelist also adds debug packages
which causes errors
2024-02-09 17:37:50 +02:00
4fec42eac8 refactor: rename packages http methods to own package
docs: update docs import
2024-01-22 02:20:11 +02:00
7574b8e5ce Release 2.13.3 2024-01-13 01:24:30 +02:00
0f2e7f45da fix: replace logo and name in title to just icon 2024-01-12 01:25:46 +02:00
5956a8720b Release 2.13.2 2024-01-08 22:48:55 +02:00
8dd4ced5e9 fix: report only unique result entries
since builder intro the triggers are called with merged result, thus it
would lead to duplicated callouts
2024-01-08 22:46:42 +02:00
6361c41f76 Release 2.13.1 2024-01-08 21:17:35 +02:00
270084bb39 fix: do not raise 404 in case of unknown package on patches endpoints
Previous improvements raise 404 error in case if no packages were found
for patches endpoints. However, in case of multirepo setup this feature
doesn't work properly because package can be located in any other
repository different from default
2024-01-08 14:32:40 +02:00
f89a5252de build: pass ssh agent to tox release env 2024-01-08 14:22:53 +02:00
50 changed files with 6113 additions and 6197 deletions

View File

@ -12,7 +12,7 @@ pacman -Syu --noconfirm
# main dependencies # main dependencies
pacman -Sy --noconfirm devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo python-systemd sudo pacman -Sy --noconfirm devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo python-systemd sudo
# make dependencies # make dependencies
pacman -Sy --noconfirm python-build python-flit python-installer python-tox python-wheel pacman -Sy --noconfirm --asdeps base-devel python-build python-flit python-installer python-tox python-wheel
# optional dependencies # optional dependencies
if [[ -z $MINIMAL_INSTALL ]]; then if [[ -z $MINIMAL_INSTALL ]]; then
# VCS support # VCS support
@ -32,10 +32,13 @@ mv dist/ahriman-*.tar.gz package/archlinux
chmod +777 package/archlinux # because fuck you that's why chmod +777 package/archlinux # because fuck you that's why
cd package/archlinux cd package/archlinux
sudo -u nobody -- makepkg -cf --skipchecksums --noconfirm sudo -u nobody -- makepkg -cf --skipchecksums --noconfirm
sudo -u nobody -- makepkg --packagelist | pacman -U --noconfirm - sudo -u nobody -- makepkg --packagelist | grep -v -- -debug- | pacman -U --noconfirm -
# create machine-id which is required by build tools # create machine-id which is required by build tools
systemd-machine-id-setup systemd-machine-id-setup
# remove unused dependencies
pacman -Qdtq | pacman -Rscn --noconfirm -
# initial setup command as root # initial setup command as root
[[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080") [[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080")
ahriman -a x86_64 -r "github" service-setup --packager "ahriman bot <ahriman@example.com>" "${WEB_ARGS[@]}" ahriman -a x86_64 -r "github" service-setup --packager "ahriman bot <ahriman@example.com>" "${WEB_ARGS[@]}"
@ -50,7 +53,7 @@ if [[ -z $MINIMAL_INSTALL ]]; then
WEB_PID=$! WEB_PID=$!
fi fi
# add the first package # add the first package
sudo -u ahriman -- ahriman package-add --now ahriman sudo -u ahriman -- ahriman --log-handler console package-add --now ahriman
# check if package was actually installed # check if package was actually installed
test -n "$(find "/var/lib/ahriman/repository/github/x86_64" -name "ahriman*pkg*")" test -n "$(find "/var/lib/ahriman/repository/github/x86_64" -name "ahriman*pkg*")"
# run package check # run package check

View File

@ -33,9 +33,9 @@ COPY "docker/install-aur-package.sh" "/usr/local/bin/install-aur-package"
## install package dependencies ## install package dependencies
## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size ## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size
RUN pacman -Sy --noconfirm --asdeps devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo && \ RUN pacman -Sy --noconfirm --asdeps devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo && \
pacman -Sy --noconfirm --asdeps python-build python-flit python-installer python-wheel && \ pacman -Sy --noconfirm --asdeps base-devel python-build python-flit python-installer python-wheel && \
pacman -Sy --noconfirm --asdeps breezy git mercurial python-aiohttp python-boto3 python-cryptography python-jinja python-requests-unixsocket python-systemd rsync subversion && \ pacman -Sy --noconfirm --asdeps breezy git mercurial python-aiohttp python-boto3 python-cryptography python-jinja python-requests-unixsocket python-systemd rsync subversion && \
runuser -u build -- install-aur-package python-aioauth-client python-aiohttp-apispec-git python-aiohttp-cors \ runuser -u build -- install-aur-package python-aioauth-client python-webargs python-aiohttp-apispec-git python-aiohttp-cors \
python-aiohttp-jinja2 python-aiohttp-session python-aiohttp-security python-aiohttp-jinja2 python-aiohttp-session python-aiohttp-security
## FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container ## FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container

View File

@ -6,7 +6,7 @@ for PACKAGE in "$@"; do
BUILD_DIR="$(mktemp -d)" BUILD_DIR="$(mktemp -d)"
git clone https://aur.archlinux.org/"$PACKAGE".git "$BUILD_DIR" git clone https://aur.archlinux.org/"$PACKAGE".git "$BUILD_DIR"
cd "$BUILD_DIR" cd "$BUILD_DIR"
makepkg --noconfirm --install --rmdeps --syncdeps makepkg --nocheck --noconfirm --install --rmdeps --syncdeps
cd / cd /
rm -r "$BUILD_DIR" rm -r "$BUILD_DIR"
done done

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -0,0 +1,61 @@
ahriman.web.views.v1.packages package
=====================================
Submodules
----------
ahriman.web.views.v1.packages.changes module
--------------------------------------------
.. automodule:: ahriman.web.views.v1.packages.changes
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.packages.logs module
-----------------------------------------
.. automodule:: ahriman.web.views.v1.packages.logs
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.packages.package module
--------------------------------------------
.. automodule:: ahriman.web.views.v1.packages.package
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.packages.packages module
---------------------------------------------
.. automodule:: ahriman.web.views.v1.packages.packages
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.packages.patch module
------------------------------------------
.. automodule:: ahriman.web.views.v1.packages.patch
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.packages.patches module
--------------------------------------------
.. automodule:: ahriman.web.views.v1.packages.patches
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web.views.v1.packages
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -8,6 +8,7 @@ Subpackages
:maxdepth: 4 :maxdepth: 4
ahriman.web.views.v1.distributed ahriman.web.views.v1.distributed
ahriman.web.views.v1.packages
ahriman.web.views.v1.service ahriman.web.views.v1.service
ahriman.web.views.v1.status ahriman.web.views.v1.status
ahriman.web.views.v1.user ahriman.web.views.v1.user

View File

@ -4,14 +4,6 @@ ahriman.web.views.v1.status package
Submodules Submodules
---------- ----------
ahriman.web.views.v1.status.changes module
------------------------------------------
.. automodule:: ahriman.web.views.v1.status.changes
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.info module ahriman.web.views.v1.status.info module
--------------------------------------- ---------------------------------------
@ -20,46 +12,6 @@ ahriman.web.views.v1.status.info module
:no-undoc-members: :no-undoc-members:
:show-inheritance: :show-inheritance:
ahriman.web.views.v1.status.logs module
---------------------------------------
.. automodule:: ahriman.web.views.v1.status.logs
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.package module
------------------------------------------
.. automodule:: ahriman.web.views.v1.status.package
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.packages module
-------------------------------------------
.. automodule:: ahriman.web.views.v1.status.packages
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.patch module
----------------------------------------
.. automodule:: ahriman.web.views.v1.status.patch
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.patches module
------------------------------------------
.. automodule:: ahriman.web.views.v1.status.patches
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.repositories module ahriman.web.views.v1.status.repositories module
----------------------------------------------- -----------------------------------------------

View File

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

View File

@ -7,7 +7,7 @@ Subpackages
.. toctree:: .. toctree::
:maxdepth: 4 :maxdepth: 4
ahriman.web.views.v2.status ahriman.web.views.v2.packages
Module contents Module contents
--------------- ---------------

View File

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

View File

@ -81,6 +81,7 @@ Build related configuration. Group name can refer to architecture, e.g. ``build:
* ``archbuild_flags`` - additional flags passed to ``archbuild`` command, space separated list of strings, optional. * ``archbuild_flags`` - additional flags passed to ``archbuild`` command, space separated list of strings, optional.
* ``build_command`` - default build command, string, required. * ``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. * ``ignore_packages`` - list packages to ignore during a regular update (manual update will still work), space separated list of strings, optional.
* ``include_debug_packages`` - distribute debug packages, boolean, optional, default ``yes``.
* ``makepkg_flags`` - additional flags passed to ``makepkg`` command, 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. * ``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 definition. * ``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 definition.

View File

@ -1,7 +1,7 @@
# Maintainer: Evgeniy Alekseev # Maintainer: Evgeniy Alekseev
pkgname='ahriman' pkgname='ahriman'
pkgver=2.13.0 pkgver=2.13.5
pkgrel=1 pkgrel=1
pkgdesc="ArcH linux ReposItory MANager" pkgdesc="ArcH linux ReposItory MANager"
arch=('any') arch=('any')

View File

@ -46,8 +46,12 @@ allow_read_only = yes
[build] [build]
; List of additional flags passed to archbuild command. ; List of additional flags passed to archbuild command.
;archbuild_flags = ;archbuild_flags =
; Path to build command
;build_command =
; List of packages to be ignored during automatic updates. ; List of packages to be ignored during automatic updates.
;ignore_packages = ;ignore_packages =
; Include debug packages
;include_debug_packages = yes
; List of additional flags passed to makechrootpkg command. ; List of additional flags passed to makechrootpkg command.
;makechrootpkg_flags = ;makechrootpkg_flags =
; List of additional flags passed to makepkg command. ; List of additional flags passed to makepkg command.

View File

@ -15,7 +15,7 @@
<div class="container"> <div class="container">
<nav class="navbar navbar-expand-lg"> <nav class="navbar navbar-expand-lg">
<div class="navbar-brand"><img src="/static/logo.svg" width="30" height="30" alt=""> ahriman</div> <div class="navbar-brand"><img src="/static/logo.svg" width="30" height="30" alt=""></div>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#repositories-navbar-supported-content" aria-controls="repositories-navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#repositories-navbar-supported-content" aria-controls="repositories-navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>

View File

@ -38,10 +38,6 @@
<script> <script>
const keyImportModal = $("#key-import-modal"); const keyImportModal = $("#key-import-modal");
const keyImportForm = $("#key-import-form"); const keyImportForm = $("#key-import-form");
keyImportModal.on("hidden.bs.modal", () => {
keyImportBodyInput.text("");
keyImportForm.trigger("reset");
});
const keyImportBodyInput = $("#key-import-body-input"); const keyImportBodyInput = $("#key-import-body-input");
const keyImportCopyButton = $("#key-import-copy-button"); const keyImportCopyButton = $("#key-import-copy-button");
@ -90,4 +86,11 @@
}); });
} }
} }
$(() => {
keyImportModal.on("hidden.bs.modal", () => {
keyImportBodyInput.text("");
keyImportForm.trigger("reset");
});
});
</script> </script>

View File

@ -36,9 +36,6 @@
<script> <script>
const loginModal = $("#login-modal"); const loginModal = $("#login-modal");
const loginForm = $("#login-form"); const loginForm = $("#login-form");
loginModal.on("hidden.bs.modal", () => {
loginForm.trigger("reset");
});
const loginPasswordInput = $("#login-password"); const loginPasswordInput = $("#login-password");
const loginUsernameInput = $("#login-username"); const loginUsernameInput = $("#login-username");
@ -77,4 +74,10 @@
showHidePasswordButton.addClass("bi-eye"); showHidePasswordButton.addClass("bi-eye");
} }
} }
$(() => {
loginModal.on("hidden.bs.modal", () => {
loginForm.trigger("reset");
});
});
</script> </script>

View File

@ -43,41 +43,10 @@
<script> <script>
const packageAddModal = $("#package-add-modal"); const packageAddModal = $("#package-add-modal");
const packageAddForm = $("#package-add-form"); const packageAddForm = $("#package-add-form");
packageAddModal.on("shown.bs.modal", () => {
$(`#package-add-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
});
packageAddModal.on("hidden.bs.modal", () => {
packageAddVariablesDiv.empty();
packageAddForm.trigger("reset");
});
const packageAddInput = $("#package-add-input"); const packageAddInput = $("#package-add-input");
const packageAddRepositoryInput = $("#package-add-repository-input"); const packageAddRepositoryInput = $("#package-add-repository-input");
const packageAddKnownPackagesList = $("#package-add-known-packages-dlist"); const packageAddKnownPackagesList = $("#package-add-known-packages-dlist");
packageAddInput.keyup(() => {
clearTimeout(packageAddInput.data("timeout"));
packageAddInput.data("timeout", setTimeout($.proxy(() => {
const value = packageAddInput.val();
if (value.length >= 3) {
$.ajax({
url: "/api/v1/service/search",
data: {"for": value},
type: "GET",
dataType: "json",
success: response => {
const options = response.map(pkg => {
const option = document.createElement("option");
option.value = pkg.package;
option.innerText = `${pkg.package} (${pkg.description})`;
return option;
});
packageAddKnownPackagesList.empty().append(options);
},
});
}
}, this), 500));
});
const packageAddVariablesDiv = $("#package-add-variables-div"); const packageAddVariablesDiv = $("#package-add-variables-div");
@ -156,4 +125,39 @@
doPackageAction("/api/v1/service/request", [packages], repository, onSuccess, onFailure, patches); doPackageAction("/api/v1/service/request", [packages], repository, onSuccess, onFailure, patches);
} }
} }
$(() => {
packageAddModal.on("shown.bs.modal", () => {
$(`#package-add-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
});
packageAddModal.on("hidden.bs.modal", () => {
packageAddVariablesDiv.empty();
packageAddForm.trigger("reset");
});
packageAddInput.keyup(() => {
clearTimeout(packageAddInput.data("timeout"));
packageAddInput.data("timeout", setTimeout($.proxy(() => {
const value = packageAddInput.val();
if (value.length >= 3) {
$.ajax({
url: "/api/v1/service/search",
data: {"for": value},
type: "GET",
dataType: "json",
success: response => {
const options = response.map(pkg => {
const option = document.createElement("option");
option.value = pkg.package;
option.innerText = `${pkg.package} (${pkg.description})`;
return option;
});
packageAddKnownPackagesList.empty().append(options);
},
});
}
}, this), 500));
});
});
</script> </script>

View File

@ -72,26 +72,6 @@
const packageInfoModal = $("#package-info-modal"); const packageInfoModal = $("#package-info-modal");
const packageInfoModalHeader = $("#package-info-modal-header"); const packageInfoModalHeader = $("#package-info-modal-header");
const packageInfo = $("#package-info"); const packageInfo = $("#package-info");
packageInfoModal.on("hidden.bs.modal", () => {
packageInfoAurUrl.empty();
packageInfoDepends.empty();
packageInfoGroups.empty();
packageInfoLicenses.empty();
packageInfoPackager.empty();
packageInfoPackages.empty();
packageInfoUpstreamUrl.empty();
packageInfoVersion.empty();
packageInfoVariablesBlock.attr("hidden", true);
packageInfoVariablesDiv.empty();
packageInfoLogsInput.empty();
packageInfoChangesInput.empty();
packageInfoModal.trigger("reset");
hideInfoControls(true);
});
const packageInfoLogsInput = $("#package-info-logs-input"); const packageInfoLogsInput = $("#package-info-logs-input");
const packageInfoLogsCopyButton = $("#package-info-logs-copy-button"); const packageInfoLogsCopyButton = $("#package-info-logs-copy-button");
@ -309,4 +289,27 @@
if (isPackageBaseSet) packageInfoModal.modal("show"); if (isPackageBaseSet) packageInfoModal.modal("show");
} }
$(() => {
packageInfoModal.on("hidden.bs.modal", () => {
packageInfoAurUrl.empty();
packageInfoDepends.empty();
packageInfoGroups.empty();
packageInfoLicenses.empty();
packageInfoPackager.empty();
packageInfoPackages.empty();
packageInfoUpstreamUrl.empty();
packageInfoVersion.empty();
packageInfoVariablesBlock.attr("hidden", true);
packageInfoVariablesDiv.empty();
packageInfoLogsInput.empty();
packageInfoChangesInput.empty();
packageInfoModal.trigger("reset");
hideInfoControls(true);
});
});
</script> </script>

View File

@ -35,11 +35,6 @@
<script> <script>
const packageRebuildModal = $("#package-rebuild-modal"); const packageRebuildModal = $("#package-rebuild-modal");
const packageRebuildForm = $("#package-rebuild-form"); const packageRebuildForm = $("#package-rebuild-form");
packageRebuildModal.on("shown.bs.modal", () => {
$(`#package-rebuild-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
});
packageRebuildModal.on("hidden.bs.modal", () => { packageRebuildForm.trigger("reset"); });
const packageRebuildDependencyInput = $("#package-rebuild-dependency-input"); const packageRebuildDependencyInput = $("#package-rebuild-dependency-input");
const packageRebuildRepositoryInput = $("#package-rebuild-repository-input"); const packageRebuildRepositoryInput = $("#package-rebuild-repository-input");
@ -54,4 +49,12 @@
doPackageAction("/api/v1/service/rebuild", [packages], repository, onSuccess, onFailure); doPackageAction("/api/v1/service/rebuild", [packages], repository, onSuccess, onFailure);
} }
} }
$(() => {
packageRebuildModal.on("shown.bs.modal", () => {
$(`#package-rebuild-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
});
packageRebuildModal.on("hidden.bs.modal", () => { packageRebuildForm.trigger("reset"); });
});
</script> </script>

View File

@ -9,46 +9,8 @@
const packageInfoUpdateButton = $("#package-info-update-button"); const packageInfoUpdateButton = $("#package-info-update-button");
let repository = null; let repository = null;
$("#repositories a").on("click", (event) => {
const element = event.target;
repository = {
architecture: element.dataset.architecture,
repository: element.dataset.repository,
};
packageUpdateButton.html(`<i class="bi bi-play"></i> update<span class="d-none d-sm-inline"> ${safe(repository.repository)} (${safe(repository.architecture)})</span>`);
$(`#${element.id}`).tab("show");
reload();
});
const table = $("#packages"); const table = $("#packages");
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", () => {
packageRemoveButton.prop("disabled", !table.bootstrapTable("getSelections").length);
});
table.on("click-row.bs.table", (self, data, row, cell) => {
if (0 === cell || "base" === cell) {
const method = data[0] === true ? "uncheckBy" : "checkBy"; // fck javascript
table.bootstrapTable(method, {field: "id", values: [data.id]});
} else showPackageInfo(data.id);
});
table.on("created-controls.bs.table", () => {
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
pickerInput.daterangepicker({
autoUpdateInput: false,
locale: {
cancelLabel: "Clear",
},
});
pickerInput.on("apply.daterangepicker", (event, picker) => {
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
table.bootstrapTable("triggerSearch");
});
pickerInput.on("cancel.daterangepicker", () => {
pickerInput.val("");
table.bootstrapTable("triggerSearch");
});
});
const statusBadge = $("#badge-status"); const statusBadge = $("#badge-status");
const versionBadge = $("#badge-version"); const versionBadge = $("#badge-version");
@ -221,6 +183,46 @@
} }
$(() => { $(() => {
$("#repositories a").on("click", event => {
const element = event.target;
repository = {
architecture: element.dataset.architecture,
repository: element.dataset.repository,
};
packageUpdateButton.html(`<i class="bi bi-play"></i> update<span class="d-none d-sm-inline"> ${safe(repository.repository)} (${safe(repository.architecture)})</span>`);
$(`#${element.id}`).tab("show");
reload();
});
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", () => {
packageRemoveButton.prop("disabled", !table.bootstrapTable("getSelections").length);
});
table.on("click-row.bs.table", (self, data, row, cell) => {
if (0 === cell || "base" === cell) {
const method = data[0] === true ? "uncheckBy" : "checkBy"; // fck javascript
table.bootstrapTable(method, {field: "id", values: [data.id]});
} else showPackageInfo(data.id);
});
table.on("created-controls.bs.table", () => {
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
pickerInput.daterangepicker({
autoUpdateInput: false,
locale: {
cancelLabel: "Clear",
},
});
pickerInput.on("apply.daterangepicker", (event, picker) => {
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
table.bootstrapTable("triggerSearch");
});
pickerInput.on("cancel.daterangepicker", () => {
pickerInput.val("");
table.bootstrapTable("triggerSearch");
});
});
table.bootstrapTable({}); table.bootstrapTable({});
statusBadge.popover(); statusBadge.popover();
selectRepository(); selectRepository();

View File

@ -102,25 +102,6 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
<script> <script>
const table = $("#packages"); const table = $("#packages");
table.on("created-controls.bs.table", () => {
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
pickerInput.daterangepicker({
autoUpdateInput: false,
locale: {
cancelLabel: "Clear",
},
});
pickerInput.on("apply.daterangepicker", (event, picker) => {
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
table.bootstrapTable("triggerSearch");
});
pickerInput.on("cancel.daterangepicker", () => {
pickerInput.val("");
table.bootstrapTable("triggerSearch");
});
});
const pacmanConf = $("#pacman-conf"); const pacmanConf = $("#pacman-conf");
const pacmanConfCopyButton = $("#copy-btn"); const pacmanConfCopyButton = $("#copy-btn");
@ -141,6 +122,28 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
function filterListLicenses() { function filterListLicenses() {
return extractDataList(table.bootstrapTable("getData"), "licenses"); return extractDataList(table.bootstrapTable("getData"), "licenses");
} }
$(() => {
table.on("created-controls.bs.table", () => {
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
pickerInput.daterangepicker({
autoUpdateInput: false,
locale: {
cancelLabel: "Clear",
},
});
pickerInput.on("apply.daterangepicker", (event, picker) => {
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
table.bootstrapTable("triggerSearch");
});
pickerInput.on("cancel.daterangepicker", () => {
pickerInput.val("");
table.bootstrapTable("triggerSearch");
});
});
});
</script> </script>
</body> </body>

View File

@ -584,7 +584,7 @@ _set_new_action() {
current_action_nargs=1 current_action_nargs=1
fi fi
current_action_args_start_index=$(( $word_index + 1 )) current_action_args_start_index=$(( $word_index + 1 - $pos_only ))
current_action_is_positional=$2 current_action_is_positional=$2
} }
@ -611,6 +611,7 @@ _shtab_ahriman() {
local prefix=_shtab_ahriman local prefix=_shtab_ahriman
local word_index=0 local word_index=0
local pos_only=0 # "--" delimeter not encountered yet
_set_parser_defaults _set_parser_defaults
word_index=1 word_index=1
@ -619,26 +620,30 @@ _shtab_ahriman() {
while [ $word_index -ne $COMP_CWORD ]; do while [ $word_index -ne $COMP_CWORD ]; do
local this_word="${COMP_WORDS[$word_index]}" local this_word="${COMP_WORDS[$word_index]}"
if [[ -n $sub_parsers && " ${sub_parsers[@]} " == *" ${this_word} "* ]]; then if [[ $pos_only = 1 || " $this_word " != " -- " ]]; then
# valid subcommand: add it to the prefix & reset the current action if [[ -n $sub_parsers && " ${sub_parsers[@]} " == *" ${this_word} "* ]]; then
prefix="${prefix}_$(_shtab_replace_nonword $this_word)" # valid subcommand: add it to the prefix & reset the current action
_set_parser_defaults prefix="${prefix}_$(_shtab_replace_nonword $this_word)"
fi _set_parser_defaults
fi
if [[ " ${current_option_strings[@]} " == *" ${this_word} "* ]]; then if [[ " ${current_option_strings[@]} " == *" ${this_word} "* ]]; then
# a new action should be acquired (due to recognised option string or # a new action should be acquired (due to recognised option string or
# no more input expected from current action); # no more input expected from current action);
# the next positional action can fill in here # the next positional action can fill in here
_set_new_action $this_word false _set_new_action $this_word false
fi fi
if [[ "$current_action_nargs" != "*" ]] && \ if [[ "$current_action_nargs" != "*" ]] && \
[[ "$current_action_nargs" != "+" ]] && \ [[ "$current_action_nargs" != "+" ]] && \
[[ "$current_action_nargs" != *"..." ]] && \ [[ "$current_action_nargs" != *"..." ]] && \
(( $word_index + 1 - $current_action_args_start_index >= \ (( $word_index + 1 - $current_action_args_start_index - $pos_only >= \
$current_action_nargs )); then $current_action_nargs )); then
$current_action_is_positional && let "completed_positional_actions += 1" $current_action_is_positional && let "completed_positional_actions += 1"
_set_new_action "pos_${completed_positional_actions}" true _set_new_action "pos_${completed_positional_actions}" true
fi
else
pos_only=1 # "--" delimeter encountered
fi fi
let "word_index+=1" let "word_index+=1"
@ -646,7 +651,7 @@ _shtab_ahriman() {
# Generate the completions # Generate the completions
if [[ "${completing_word}" == -* ]]; then if [[ $pos_only = 0 && "${completing_word}" == -* ]]; then
# optional argument started: use option strings # optional argument started: use option strings
COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") ) COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") )
else else

View File

@ -1,4 +1,4 @@
.TH AHRIMAN "1" "2024\-01\-05" "ahriman" "Generated Python Manual" .TH AHRIMAN "1" "2024\-04\-04" "ahriman" "Generated Python Manual"
.SH NAME .SH NAME
ahriman ahriman
.SH SYNOPSIS .SH SYNOPSIS

View File

@ -736,4 +736,12 @@ _shtab_ahriman() {
typeset -A opt_args typeset -A opt_args
_shtab_ahriman "$@"
if [[ $zsh_eval_context[-1] == eval ]]; then
# eval/source/. command, register function for later
compdef _shtab_ahriman -N ahriman
else
# autoload from fpath, call function directly
_shtab_ahriman "$@"
fi

View File

@ -17,4 +17,4 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
__version__ = "2.13.0" __version__ = "2.13.5"

View File

@ -163,8 +163,8 @@ class ApplicationRepository(ApplicationProperties):
built_packages = self.repository.packages_built() built_packages = self.repository.packages_built()
if built_packages: # speedup a bit if built_packages: # speedup a bit
build_result = self.repository.process_update(built_packages, packagers) build_result = self.repository.process_update(built_packages, packagers)
self.on_result(build_result)
result.merge(build_result) result.merge(build_result)
self.on_result(result.merge(build_result))
builder = Updater.load(self.repository_id, self.configuration, self.repository) builder = Updater.load(self.repository_id, self.configuration, self.repository)
@ -173,7 +173,8 @@ class ApplicationRepository(ApplicationProperties):
for num, partition in enumerate(partitions): for num, partition in enumerate(partitions):
self.logger.info("processing chunk #%i %s", num, [package.base for package in partition]) self.logger.info("processing chunk #%i %s", num, [package.base for package in partition])
build_result = builder.update(partition, packagers, bump_pkgrel=bump_pkgrel) build_result = builder.update(partition, packagers, bump_pkgrel=bump_pkgrel)
self.on_result(result.merge(build_result)) self.on_result(build_result)
result.merge(build_result)
return result return result

View File

@ -68,7 +68,7 @@ class Repo(LazyLogging):
path(Path): path to archive to add path(Path): path to archive to add
""" """
check_output( check_output(
"repo-add", *self.sign_args, "-R", str(self.repo_path), str(path), "repo-add", *self.sign_args, "--remove", str(self.repo_path), str(path),
exception=BuildError.from_process(path.name), exception=BuildError.from_process(path.name),
cwd=self.paths.repository, cwd=self.paths.repository,
logger=self.logger, logger=self.logger,
@ -78,8 +78,13 @@ class Repo(LazyLogging):
""" """
create empty repository database. It just calls add with empty arguments create empty repository database. It just calls add with empty arguments
""" """
check_output("repo-add", *self.sign_args, str(self.repo_path), # since pacman-6.1.0 repo-add doesn't create empty database in case if no packages supplied
cwd=self.paths.repository, logger=self.logger, user=self.uid) # this code creates empty files instead
if self.repo_path.exists():
return # database is already created, skip this part
self.repo_path.touch(exist_ok=True)
(self.paths.repository / f"{self.name}.db").symlink_to(self.repo_path)
def remove(self, package: str, filename: Path) -> None: def remove(self, package: str, filename: Path) -> None:
""" """

View File

@ -38,6 +38,7 @@ class Task(LazyLogging):
archbuild_flags(list[str]): command flags for archbuild command archbuild_flags(list[str]): command flags for archbuild command
architecture(str): repository architecture architecture(str): repository architecture
build_command(str): build command build_command(str): build command
include_debug_packages(bool): whether to include debug packages or not
makechrootpkg_flags(list[str]): command flags for makechrootpkg command makechrootpkg_flags(list[str]): command flags for makechrootpkg command
makepkg_flags(list[str]): command flags for makepkg command makepkg_flags(list[str]): command flags for makepkg command
package(Package): package definitions package(Package): package definitions
@ -63,6 +64,7 @@ class Task(LazyLogging):
self.archbuild_flags = configuration.getlist("build", "archbuild_flags", fallback=[]) self.archbuild_flags = configuration.getlist("build", "archbuild_flags", fallback=[])
self.build_command = configuration.get("build", "build_command") self.build_command = configuration.get("build", "build_command")
self.include_debug_packages = configuration.getboolean("build", "include_debug_packages", fallback=True)
self.makepkg_flags = configuration.getlist("build", "makepkg_flags", fallback=[]) self.makepkg_flags = configuration.getlist("build", "makepkg_flags", fallback=[])
self.makechrootpkg_flags = configuration.getlist("build", "makechrootpkg_flags", fallback=[]) self.makechrootpkg_flags = configuration.getlist("build", "makechrootpkg_flags", fallback=[])
@ -99,15 +101,20 @@ class Task(LazyLogging):
environment=environment, environment=environment,
) )
# well it is not actually correct, but we can deal with it package_list_command = ["makepkg", "--packagelist"]
if not self.include_debug_packages:
package_list_command.append("OPTIONS=(!debug)") # disable debug flag manually
packages = check_output( packages = check_output(
"makepkg", "--packagelist", *package_list_command,
exception=BuildError.from_process(self.package.base), exception=BuildError.from_process(self.package.base),
cwd=sources_dir, cwd=sources_dir,
logger=self.logger, logger=self.logger,
environment=environment, environment=environment,
).splitlines() ).splitlines()
return [Path(package) for package in packages] # some dirty magic here
# the filter is applied in order to make sure that result will only contain packages which were actually built
# e.g. in some cases packagelist command produces debug packages which were not actually built
return list(filter(lambda path: path.is_file(), map(Path, packages)))
def init(self, sources_dir: Path, database: SQLite, local_version: str | None) -> str | None: def init(self, sources_dir: Path, database: SQLite, local_version: str | None) -> str | None:
""" """

View File

@ -176,6 +176,10 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"empty": False, "empty": False,
}, },
}, },
"include_debug_packages": {
"type": "boolean",
"coerce": "boolean",
},
"makepkg_flags": { "makepkg_flags": {
"type": "list", "type": "list",
"coerce": "list", "coerce": "list",

View File

@ -190,7 +190,8 @@ class Watcher(LazyLogging):
Returns: Returns:
list[PkgbuildPatch]: list of patches which are stored for the package list[PkgbuildPatch]: list of patches which are stored for the package
""" """
self.package_get(package_base) # patches are package base based, we don't know (and don't differentiate) to which package does them belong
# so here we skip checking if package exists or not
variables = [variable] if variable is not None else None variables = [variable] if variable is not None else None
return self.database.patches_list(package_base, variables).get(package_base, []) return self.database.patches_list(package_base, variables).get(package_base, [])

View File

@ -21,7 +21,6 @@ import aiohttp_apispec # type: ignore[import-untyped]
from aiohttp.web import HTTPNoContent, HTTPNotFound, Response, json_response from aiohttp.web import HTTPNoContent, HTTPNotFound, Response, json_response
from ahriman.core.exceptions import UnknownPackageError
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.schemas import AuthSchema, ErrorSchema, PatchNameSchema, PatchSchema from ahriman.web.schemas import AuthSchema, ErrorSchema, PatchNameSchema, PatchSchema
from ahriman.web.views.base import BaseView from ahriman.web.views.base import BaseView
@ -76,7 +75,7 @@ class PatchView(StatusViewGuard, BaseView):
200: {"description": "Success response", "schema": PatchSchema}, 200: {"description": "Success response", "schema": PatchSchema},
401: {"description": "Authorization required", "schema": ErrorSchema}, 401: {"description": "Authorization required", "schema": ErrorSchema},
403: {"description": "Access is forbidden", "schema": ErrorSchema}, 403: {"description": "Access is forbidden", "schema": ErrorSchema},
404: {"description": "Package base and/or patch name are unknown", "schema": ErrorSchema}, 404: {"description": "Patch name is unknown", "schema": ErrorSchema},
500: {"description": "Internal server error", "schema": ErrorSchema}, 500: {"description": "Internal server error", "schema": ErrorSchema},
}, },
security=[{"token": [GET_PERMISSION]}], security=[{"token": [GET_PERMISSION]}],
@ -91,15 +90,12 @@ class PatchView(StatusViewGuard, BaseView):
Response: 200 with package patch on success Response: 200 with package patch on success
Raises: Raises:
HTTPNotFound: if package base is unknown HTTPNotFound: if package patch is unknown
""" """
package_base = self.request.match_info["package"] package_base = self.request.match_info["package"]
variable = self.request.match_info["patch"] variable = self.request.match_info["patch"]
try: patches = self.service().patches_get(package_base, variable)
patches = self.service().patches_get(package_base, variable)
except UnknownPackageError:
raise HTTPNotFound(reason=f"Package {package_base} is unknown")
selected = next((patch for patch in patches if patch.key == variable), None) selected = next((patch for patch in patches if patch.key == variable), None)
if selected is None: if selected is None:

View File

@ -19,9 +19,8 @@
# #
import aiohttp_apispec # type: ignore[import-untyped] import aiohttp_apispec # type: ignore[import-untyped]
from aiohttp.web import HTTPBadRequest, HTTPNoContent, HTTPNotFound, Response, json_response from aiohttp.web import HTTPBadRequest, HTTPNoContent, Response, json_response
from ahriman.core.exceptions import UnknownPackageError
from ahriman.models.pkgbuild_patch import PkgbuildPatch from ahriman.models.pkgbuild_patch import PkgbuildPatch
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.schemas import AuthSchema, ErrorSchema, PackageNameSchema, PatchSchema from ahriman.web.schemas import AuthSchema, ErrorSchema, PackageNameSchema, PatchSchema
@ -50,7 +49,6 @@ class PatchesView(StatusViewGuard, BaseView):
200: {"description": "Success response", "schema": PatchSchema(many=True)}, 200: {"description": "Success response", "schema": PatchSchema(many=True)},
401: {"description": "Authorization required", "schema": ErrorSchema}, 401: {"description": "Authorization required", "schema": ErrorSchema},
403: {"description": "Access is forbidden", "schema": ErrorSchema}, 403: {"description": "Access is forbidden", "schema": ErrorSchema},
404: {"description": "Package base is unknown", "schema": ErrorSchema},
500: {"description": "Internal server error", "schema": ErrorSchema}, 500: {"description": "Internal server error", "schema": ErrorSchema},
}, },
security=[{"token": [GET_PERMISSION]}], security=[{"token": [GET_PERMISSION]}],
@ -63,15 +61,9 @@ class PatchesView(StatusViewGuard, BaseView):
Returns: Returns:
Response: 200 with package patches on success Response: 200 with package patches on success
Raises:
HTTPNotFound: if package base is unknown
""" """
package_base = self.request.match_info["package"] package_base = self.request.match_info["package"]
try: patches = self.service().patches_get(package_base, None)
patches = self.service().patches_get(package_base, None)
except UnknownPackageError:
raise HTTPNotFound(reason=f"Package {package_base} is unknown")
response = [patch.view() for patch in patches] response = [patch.view() for patch in patches]
return json_response(response) return json_response(response)

View File

@ -0,0 +1,19 @@
#
# Copyright (c) 2021-2024 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/>.
#

View File

@ -26,13 +26,28 @@ def test_repo_add(repo: Repo, mocker: MockerFixture) -> None:
def test_repo_init(repo: Repo, mocker: MockerFixture) -> None: def test_repo_init(repo: Repo, mocker: MockerFixture) -> None:
""" """
must call repo-add with empty package list on repo initializing must create empty database files
""" """
check_output_mock = mocker.patch("ahriman.core.alpm.repo.check_output") mocker.patch("pathlib.Path.exists", return_value=False)
touch_mock = mocker.patch("pathlib.Path.touch")
symlink_mock = mocker.patch("pathlib.Path.symlink_to")
repo.init() repo.init()
check_output_mock.assert_called_once() # it will be checked later touch_mock.assert_called_once_with(exist_ok=True)
assert check_output_mock.call_args[0][0] == "repo-add" symlink_mock.assert_called_once_with(repo.repo_path)
def test_repo_init_skip(repo: Repo, mocker: MockerFixture) -> None:
"""
must do not create files if database already exists
"""
mocker.patch("pathlib.Path.exists", return_value=True)
touch_mock = mocker.patch("pathlib.Path.touch")
symlink_mock = mocker.patch("pathlib.Path.symlink_to")
repo.init()
touch_mock.assert_not_called()
symlink_mock.assert_not_called()
def test_repo_remove(repo: Repo, mocker: MockerFixture) -> None: def test_repo_remove(repo: Repo, mocker: MockerFixture) -> None:

View File

@ -1,5 +1,8 @@
import pytest
from pathlib import Path from pathlib import Path
from pytest_mock import MockerFixture from pytest_mock import MockerFixture
from unittest.mock import call as MockCall
from ahriman.core.build_tools.task import Task from ahriman.core.build_tools.task import Task
from ahriman.core.database import SQLite from ahriman.core.database import SQLite
@ -9,9 +12,83 @@ def test_build(task_ahriman: Task, mocker: MockerFixture) -> None:
""" """
must build package must build package
""" """
local = Path("local")
check_output_mock = mocker.patch("ahriman.core.build_tools.task.check_output") check_output_mock = mocker.patch("ahriman.core.build_tools.task.check_output")
task_ahriman.build(Path("ahriman"))
check_output_mock.assert_called() task_ahriman.build(local)
check_output_mock.assert_has_calls([
MockCall(
"extra-x86_64-build", "-r", str(task_ahriman.paths.chroot), "--", "--", "--skippgpcheck",
exception=pytest.helpers.anyvar(int),
cwd=local,
logger=task_ahriman.logger,
user=task_ahriman.uid,
environment={},
),
MockCall(
"makepkg", "--packagelist",
exception=pytest.helpers.anyvar(int),
cwd=local,
logger=task_ahriman.logger,
environment={},
),
])
def test_build_environment(task_ahriman: Task, mocker: MockerFixture) -> None:
"""
must build package with environment variables set
"""
local = Path("local")
check_output_mock = mocker.patch("ahriman.core.build_tools.task.check_output")
environment = {"variable": "value"}
task_ahriman.build(local, **environment, empty=None)
check_output_mock.assert_has_calls([
MockCall(
"extra-x86_64-build", "-r", str(task_ahriman.paths.chroot), "--", "--", "--skippgpcheck",
exception=pytest.helpers.anyvar(int),
cwd=local,
logger=task_ahriman.logger,
user=task_ahriman.uid,
environment=environment,
),
MockCall(
"makepkg", "--packagelist",
exception=pytest.helpers.anyvar(int),
cwd=local,
logger=task_ahriman.logger,
environment=environment,
),
])
def test_build_no_debug(task_ahriman: Task, mocker: MockerFixture) -> None:
"""
must filter debug packages from result
"""
local = Path("local")
check_output_mock = mocker.patch("ahriman.core.build_tools.task.check_output")
task_ahriman.include_debug_packages = False
task_ahriman.build(local)
check_output_mock.assert_has_calls([
MockCall(
"extra-x86_64-build", "-r", str(task_ahriman.paths.chroot), "--", "--", "--skippgpcheck",
exception=pytest.helpers.anyvar(int),
cwd=local,
logger=task_ahriman.logger,
user=task_ahriman.uid,
environment={},
),
MockCall(
"makepkg", "--packagelist", "OPTIONS=(!debug)",
exception=pytest.helpers.anyvar(int),
cwd=local,
logger=task_ahriman.logger,
environment={},
),
])
def test_init(task_ahriman: Task, database: SQLite, mocker: MockerFixture) -> None: def test_init(task_ahriman: Task, database: SQLite, mocker: MockerFixture) -> None:

View File

@ -212,14 +212,6 @@ def test_patches_get(watcher: Watcher, package_ahriman: Package, mocker: MockerF
]) ])
def test_patches_get_failed(watcher: Watcher, package_ahriman: Package) -> None:
"""
must raise UnknownPackageError on patches in case of unknown package
"""
with pytest.raises(UnknownPackageError):
watcher.patches_get(package_ahriman.base, None)
def test_patches_remove(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None: def test_patches_remove(watcher: Watcher, package_ahriman: Package, mocker: MockerFixture) -> None:
""" """
must remove patches for the package must remove patches for the package

View File

@ -6,7 +6,7 @@ from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.changes import Changes from ahriman.models.changes import Changes
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.views.v1.status.changes import ChangesView from ahriman.web.views.v1.packages.changes import ChangesView
async def test_get_permission() -> None: async def test_get_permission() -> None:

View File

@ -5,7 +5,7 @@ from aiohttp.test_utils import TestClient
from ahriman.models.build_status import BuildStatusEnum from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.views.v1.status.logs import LogsView from ahriman.web.views.v1.packages.logs import LogsView
async def test_get_permission() -> None: async def test_get_permission() -> None:

View File

@ -6,7 +6,7 @@ from ahriman.models.build_status import BuildStatus, BuildStatusEnum
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.views.v1.status.package import PackageView from ahriman.web.views.v1.packages.package import PackageView
async def test_get_permission() -> None: async def test_get_permission() -> None:

View File

@ -6,7 +6,7 @@ from pytest_mock import MockerFixture
from ahriman.models.build_status import BuildStatusEnum from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.views.v1.status.packages import (PackagesView) from ahriman.web.views.v1.packages.packages import (PackagesView)
async def test_get_permission() -> None: async def test_get_permission() -> None:

View File

@ -6,7 +6,7 @@ from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.pkgbuild_patch import PkgbuildPatch from ahriman.models.pkgbuild_patch import PkgbuildPatch
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.views.v1.status.patch import PatchView from ahriman.web.views.v1.packages.patch import PatchView
async def test_get_permission() -> None: async def test_get_permission() -> None:
@ -70,17 +70,6 @@ async def test_get(client: TestClient, package_ahriman: Package) -> None:
assert patches == patch.view() assert patches == patch.view()
async def test_get_not_found(client: TestClient, package_ahriman: Package) -> None:
"""
must return not found for missing package
"""
response_schema = pytest.helpers.schema_response(PatchView.get, code=404)
response = await client.get(f"/api/v1/packages/{package_ahriman.base}/patches/random")
assert response.status == 404
assert not response_schema.validate(await response.json())
async def test_get_patch_not_found(client: TestClient, package_ahriman: Package) -> None: async def test_get_patch_not_found(client: TestClient, package_ahriman: Package) -> None:
""" """
must return not found for missing patch must return not found for missing patch

View File

@ -6,7 +6,7 @@ from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.pkgbuild_patch import PkgbuildPatch from ahriman.models.pkgbuild_patch import PkgbuildPatch
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.views.v1.status.patches import PatchesView from ahriman.web.views.v1.packages.patches import PatchesView
async def test_get_permission() -> None: async def test_get_permission() -> None:
@ -46,17 +46,6 @@ async def test_get(client: TestClient, package_ahriman: Package) -> None:
assert patches == [patch.view()] assert patches == [patch.view()]
async def test_get_not_found(client: TestClient, package_ahriman: Package) -> None:
"""
must return not found for missing package
"""
response_schema = pytest.helpers.schema_response(PatchesView.get, code=404)
response = await client.get(f"/api/v1/packages/{package_ahriman.base}/patches")
assert response.status == 404
assert not response_schema.validate(await response.json())
async def test_post(client: TestClient, package_ahriman: Package) -> None: async def test_post(client: TestClient, package_ahriman: Package) -> None:
""" """
must create patch must create patch

View File

@ -5,7 +5,7 @@ from aiohttp.test_utils import TestClient
from ahriman.models.build_status import BuildStatusEnum from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.views.v2.status.logs import LogsView from ahriman.web.views.v2.packages.logs import LogsView
async def test_get_permission() -> None: async def test_get_permission() -> None:

View File

@ -74,6 +74,8 @@ depends =
docs docs
allowlist_externals = allowlist_externals =
git git
passenv =
SSH_AUTH_SOCK
commands = commands =
git add package/archlinux/PKGBUILD src/ahriman/__init__.py docs/ahriman-architecture.svg package/share/man/man1/ahriman.1 package/share/bash-completion/completions/_ahriman package/share/zsh/site-functions/_ahriman git add package/archlinux/PKGBUILD src/ahriman/__init__.py docs/ahriman-architecture.svg package/share/man/man1/ahriman.1 package/share/bash-completion/completions/_ahriman package/share/zsh/site-functions/_ahriman
git commit -m "Release {posargs}" git commit -m "Release {posargs}"