docs: add check if docs are updated

This commit is contained in:
2025-06-18 17:57:52 +03:00
parent 1f22a27360
commit e119f092b4
17 changed files with 89 additions and 79 deletions

View File

@ -1,6 +0,0 @@
skips:
- B101
- B104
- B105
- B106
- B404

View File

@ -21,18 +21,18 @@ jobs:
packages: write packages: write
steps: steps:
- uses: docker/setup-qemu-action@v2 - uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v2 - uses: docker/setup-buildx-action@v3
- name: Login to docker hub - name: Login to docker hub
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to github container registry - name: Login to github container registry
uses: docker/login-action@v2 uses: docker/login-action@v3
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
@ -40,7 +40,7 @@ jobs:
- name: Extract docker metadata - name: Extract docker metadata
id: meta id: meta
uses: docker/metadata-action@v3 uses: docker/metadata-action@v5
with: with:
images: | images: |
arcan1s/ahriman arcan1s/ahriman
@ -50,7 +50,7 @@ jobs:
type=edge type=edge
- name: Build an image and push - name: Build an image and push
uses: docker/build-push-action@v4 uses: docker/build-push-action@v6
with: with:
file: docker/Dockerfile file: docker/Dockerfile
push: true push: true

View File

@ -37,8 +37,6 @@ jobs:
- repo:/var/lib/ahriman - repo:/var/lib/ahriman
steps: steps:
- uses: actions/checkout@v3
- run: pacman -Sy - run: pacman -Sy
- name: Init repository - name: Init repository

View File

@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Extract version - name: Extract version
id: version id: version
@ -27,8 +27,7 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
filter: 'Release \d+\.\d+\.\d+' filter: 'Release \d+\.\d+\.\d+'
- name: Install dependencies - uses: ConorMacBride/install-package@v1.1.0
uses: ConorMacBride/install-package@v1.1.0
with: with:
apt: tox apt: tox
@ -38,7 +37,7 @@ jobs:
VERSION: ${{ steps.version.outputs.VERSION }} VERSION: ${{ steps.version.outputs.VERSION }}
- name: Publish release - name: Publish release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v2
with: with:
body: | body: |
${{ steps.changelog.outputs.compareurl }} ${{ steps.changelog.outputs.compareurl }}

View File

@ -24,7 +24,7 @@ jobs:
- ${{ github.workspace }}:/build - ${{ github.workspace }}:/build
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Setup the minimal service in arch linux container - name: Setup the minimal service in arch linux container
run: .github/workflows/setup.sh minimal run: .github/workflows/setup.sh minimal
@ -40,7 +40,7 @@ jobs:
options: --privileged -w /build options: --privileged -w /build
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Setup the service in arch linux container - name: Setup the service in arch linux container
run: .github/workflows/setup.sh run: .github/workflows/setup.sh

View File

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

View File

@ -26,7 +26,16 @@ jobs:
- ${{ github.workspace }}:/build - ${{ github.workspace }}:/build
steps: steps:
- uses: actions/checkout@v3 - run: pacman --noconfirm -Syu base-devel git python-tox
- name: Run check and tests in arch linux container - run: git config --global --add safe.directory *
run: .github/workflows/tests.sh
- uses: actions/checkout@v4
- name: Run check and tests
run: tox
- name: Generate documentation and check if there are untracked changes
run: |
tox -e docs
[ -z "$(git status --porcelain docs/*.rst)" ]

View File

@ -413,10 +413,11 @@ Web application
Web application requires the following python packages to be installed: Web application requires the following python packages to be installed:
* Core part requires ``aiohttp`` (application itself), ``aiohttp_jinja2`` and ``Jinja2`` (HTML generation from templates). * Core part requires ``aiohttp`` (application itself), ``aiohttp_jinja2`` and ``Jinja2`` (HTML generation from templates).
* Additional web features also require ``aiohttp-apispec`` (autogenerated documentation), ``aiohttp_cors`` (CORS support, required by documentation). * Additional web features also require ``aiohttp-apispec`` (autogenerated documentation, optional), ``aiohttp_cors`` (CORS support, required by documentation).
* In addition, authorization feature requires ``aiohttp_security``, ``aiohttp_session`` and ``cryptography``. * In addition, authorization feature requires ``aiohttp_security``, ``aiohttp_session`` and ``cryptography``.
* In addition to base authorization dependencies, OAuth2 also requires ``aioauth-client`` library. * In addition to base authorization dependencies, OAuth2 also requires ``aioauth-client`` library.
* In addition if you would like to disable authorization for local access (recommended way in order to run the application itself with reporting support), the ``requests-unixsocket2`` library is required. * In addition if you would like to disable authorization for local access (recommended way in order to run the application itself with reporting support), the ``requests-unixsocket2`` library is required.
* Application metrics will be automatically enabled after installing ``aiohttp-openmetrics`` package.
Middlewares Middlewares
^^^^^^^^^^^ ^^^^^^^^^^^

View File

@ -1,36 +1,36 @@
# This file was autogenerated by uv via the following command: # This file was autogenerated by uv via the following command:
# uv pip compile --group ../pyproject.toml:docs --extra s3 --extra validator --extra web --output-file ../docs/requirements.txt ../pyproject.toml # uv pip compile --group pyproject.toml:docs --extra s3 --extra validator --extra web --output-file docs/requirements.txt pyproject.toml
aiohappyeyeballs==2.6.1 aiohappyeyeballs==2.6.1
# via aiohttp # via aiohttp
aiohttp==3.11.18 aiohttp==3.11.18
# via # via
# ahriman (../pyproject.toml) # ahriman (pyproject.toml)
# aiohttp-cors # aiohttp-cors
# aiohttp-jinja2 # aiohttp-jinja2
aiohttp-cors==0.8.1 aiohttp-cors==0.8.1
# via ahriman (../pyproject.toml) # via ahriman (pyproject.toml)
aiohttp-jinja2==1.6 aiohttp-jinja2==1.6
# via ahriman (../pyproject.toml) # via ahriman (pyproject.toml)
aiosignal==1.3.2 aiosignal==1.3.2
# via aiohttp # via aiohttp
alabaster==1.0.0 alabaster==1.0.0
# via sphinx # via sphinx
argparse-manpage==4.6 argparse-manpage==4.6
# via ahriman (../pyproject.toml:docs) # via ahriman (pyproject.toml:docs)
attrs==25.3.0 attrs==25.3.0
# via aiohttp # via aiohttp
babel==2.17.0 babel==2.17.0
# via sphinx # via sphinx
bcrypt==4.3.0 bcrypt==4.3.0
# via ahriman (../pyproject.toml) # via ahriman (pyproject.toml)
boto3==1.38.11 boto3==1.38.11
# via ahriman (../pyproject.toml) # via ahriman (pyproject.toml)
botocore==1.38.11 botocore==1.38.11
# via # via
# boto3 # boto3
# s3transfer # s3transfer
cerberus==1.3.7 cerberus==1.3.7
# via ahriman (../pyproject.toml) # via ahriman (pyproject.toml)
certifi==2025.4.26 certifi==2025.4.26
# via requests # via requests
charset-normalizer==3.4.2 charset-normalizer==3.4.2
@ -51,7 +51,7 @@ idna==3.10
imagesize==1.4.1 imagesize==1.4.1
# via sphinx # via sphinx
inflection==0.5.1 inflection==0.5.1
# via ahriman (../pyproject.toml) # via ahriman (pyproject.toml)
jinja2==3.1.6 jinja2==3.1.6
# via # via
# aiohttp-jinja2 # aiohttp-jinja2
@ -73,37 +73,37 @@ propcache==0.3.1
# aiohttp # aiohttp
# yarl # yarl
pydeps==3.0.1 pydeps==3.0.1
# via ahriman (../pyproject.toml:docs) # via ahriman (pyproject.toml:docs)
pyelftools==0.32 pyelftools==0.32
# via ahriman (../pyproject.toml) # via ahriman (pyproject.toml)
pygments==2.19.1 pygments==2.19.1
# via sphinx # via sphinx
python-dateutil==2.9.0.post0 python-dateutil==2.9.0.post0
# via botocore # via botocore
requests==2.32.3 requests==2.32.3
# via # via
# ahriman (../pyproject.toml) # ahriman (pyproject.toml)
# sphinx # sphinx
roman-numerals-py==3.1.0 roman-numerals-py==3.1.0
# via sphinx # via sphinx
s3transfer==0.12.0 s3transfer==0.12.0
# via boto3 # via boto3
shtab==1.7.2 shtab==1.7.2
# via ahriman (../pyproject.toml:docs) # via ahriman (pyproject.toml:docs)
six==1.17.0 six==1.17.0
# via python-dateutil # via python-dateutil
snowballstemmer==3.0.0.1 snowballstemmer==3.0.0.1
# via sphinx # via sphinx
sphinx==8.2.3 sphinx==8.2.3
# via # via
# ahriman (../pyproject.toml:docs) # ahriman (pyproject.toml:docs)
# sphinx-argparse # sphinx-argparse
# sphinx-rtd-theme # sphinx-rtd-theme
# sphinxcontrib-jquery # sphinxcontrib-jquery
sphinx-argparse==0.5.2 sphinx-argparse==0.5.2
# via ahriman (../pyproject.toml:docs) # via ahriman (pyproject.toml:docs)
sphinx-rtd-theme==3.0.2 sphinx-rtd-theme==3.0.2
# via ahriman (../pyproject.toml:docs) # via ahriman (pyproject.toml:docs)
sphinxcontrib-applehelp==2.0.0 sphinxcontrib-applehelp==2.0.0
# via sphinx # via sphinx
sphinxcontrib-devhelp==2.0.0 sphinxcontrib-devhelp==2.0.0

View File

@ -6,6 +6,7 @@ from pytest_mock import MockerFixture
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers.copy import Copy from ahriman.application.handlers.copy import Copy
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.repository import Repository from ahriman.core.repository import Repository
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
@ -30,11 +31,12 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository, def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None: database: SQLite, package_ahriman: Package, mocker: MockerFixture) -> None:
""" """
must run command must run command
""" """
args = _default_args(args) args = _default_args(args)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman]) mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
application_mock = mocker.patch("ahriman.application.handlers.copy.Copy.copy_package") application_mock = mocker.patch("ahriman.application.handlers.copy.Copy.copy_package")
@ -51,12 +53,13 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
def test_run_remove(args: argparse.Namespace, configuration: Configuration, repository: Repository, def test_run_remove(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None: database: SQLite, package_ahriman: Package, mocker: MockerFixture) -> None:
""" """
must run command and remove packages afterward must run command and remove packages afterward
""" """
args = _default_args(args) args = _default_args(args)
args.remove = True args.remove = True
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman]) mocker.patch("ahriman.core.repository.Repository.packages", return_value=[package_ahriman])
mocker.patch("ahriman.application.handlers.copy.Copy.copy_package") mocker.patch("ahriman.application.handlers.copy.Copy.copy_package")
@ -69,12 +72,13 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, repo
def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository, def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None: database: SQLite, mocker: MockerFixture) -> None:
""" """
must raise ExitCode exception on empty result must raise ExitCode exception on empty result
""" """
args = _default_args(args) args = _default_args(args)
args.exit_code = True args.exit_code = True
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.packages", return_value=[]) mocker.patch("ahriman.core.repository.Repository.packages", return_value=[])
mocker.patch("ahriman.application.application.Application.update") mocker.patch("ahriman.application.application.Application.update")
check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status") check_mock = mocker.patch("ahriman.application.handlers.handler.Handler.check_status")

View File

@ -9,6 +9,7 @@ from urllib.parse import quote_plus as url_encode
from ahriman.application.handlers.setup import Setup from ahriman.application.handlers.setup import Setup
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite
from ahriman.core.exceptions import MissingArchitectureError from ahriman.core.exceptions import MissingArchitectureError
from ahriman.core.repository import Repository from ahriman.core.repository import Repository
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
@ -44,11 +45,12 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository, def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
repository_paths: RepositoryPaths, mocker: MockerFixture) -> None: database: SQLite, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
""" """
must run command must run command
""" """
args = _default_args(args) args = _default_args(args)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
ahriman_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_ahriman") ahriman_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_ahriman")
devtools_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_devtools") devtools_configuration_mock = mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_devtools")
@ -88,12 +90,13 @@ def test_run_no_architecture_or_repository(configuration: Configuration) -> None
def test_run_with_server(args: argparse.Namespace, configuration: Configuration, repository: Repository, def test_run_with_server(args: argparse.Namespace, configuration: Configuration, repository: Repository,
mocker: MockerFixture) -> None: database: SQLite, mocker: MockerFixture) -> None:
""" """
must run command with server specified must run command with server specified
""" """
args = _default_args(args) args = _default_args(args)
args.server = "server" args.server = "server"
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_ahriman") mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_ahriman")
mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_makepkg") mocker.patch("ahriman.application.handlers.setup.Setup.configuration_create_makepkg")

View File

@ -51,7 +51,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, database: S
update_mock.assert_called_once_with(user) update_mock.assert_called_once_with(user)
def test_run_empty_salt(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None: def test_run_empty_salt(args: argparse.Namespace, configuration: Configuration, database: SQLite,
mocker: MockerFixture) -> None:
""" """
must process users with empty password salt must process users with empty password salt
""" """
@ -59,6 +60,7 @@ def test_run_empty_salt(args: argparse.Namespace, configuration: Configuration,
args = _default_args(args) args = _default_args(args)
user = User(username=args.username, password=args.password, access=args.role, user = User(username=args.username, password=args.password, access=args.role,
packager_id=args.packager, key=args.key) packager_id=args.packager, key=args.key)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.models.user.User.hash_password", return_value=user) mocker.patch("ahriman.models.user.User.hash_password", return_value=user)
create_user_mock = mocker.patch("ahriman.application.handlers.users.Users.user_create", return_value=user) create_user_mock = mocker.patch("ahriman.application.handlers.users.Users.user_create", return_value=user)
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update") update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")

View File

@ -1,6 +1,8 @@
import datetime import datetime
import pytest import pytest
import tempfile
from collections.abc import Generator
from pathlib import Path from pathlib import Path
from pytest_mock import MockerFixture from pytest_mock import MockerFixture
from typing import Any, TypeVar from typing import Any, TypeVar
@ -265,16 +267,19 @@ def configuration(repository_id: RepositoryId, resource_path_root: Path) -> Conf
@pytest.fixture @pytest.fixture
def database(configuration: Configuration) -> SQLite: def database(configuration: Configuration) -> Generator[SQLite, None, None]:
""" """
database fixture database fixture
Args: Args:
configuration(Configuration): configuration fixture configuration(Configuration): configuration fixture
Returns: Yields:
SQLite: database test instance SQLite: database test instance
""" """
database_file = tempfile.mktemp(dir=configuration.repository_paths.root) # nosec
configuration.set_option("settings", "database", database_file)
database = SQLite.load(configuration) database = SQLite.load(configuration)
yield database yield database
database.path.unlink() database.path.unlink()

View File

@ -62,8 +62,8 @@ def test_validate_is_ip_address(validator: Validator, mocker: MockerFixture) ->
validator._validate_is_ip_address([], "field", "localhost") validator._validate_is_ip_address([], "field", "localhost")
validator._validate_is_ip_address([], "field", "127.0.0.1") validator._validate_is_ip_address([], "field", "127.0.0.1")
validator._validate_is_ip_address([], "field", "::") validator._validate_is_ip_address([], "field", "::") # nosec
validator._validate_is_ip_address([], "field", "0.0.0.0") validator._validate_is_ip_address([], "field", "0.0.0.0") # nosec
validator._validate_is_ip_address([], "field", "random string") validator._validate_is_ip_address([], "field", "random string")

View File

@ -12,6 +12,8 @@ def test_load(configuration: Configuration, mocker: MockerFixture) -> None:
must correctly load instance must correctly load instance
""" """
init_mock = mocker.patch("ahriman.core.database.SQLite.init") init_mock = mocker.patch("ahriman.core.database.SQLite.init")
configuration.set_option("settings", "database", "ahriman.db")
SQLite.load(configuration) SQLite.load(configuration)
init_mock.assert_called_once_with() init_mock.assert_called_once_with()

View File

@ -1,7 +1,6 @@
[settings] [settings]
include = . include = .
logging = logging.ini logging = logging.ini
database = ../../../ahriman-test.db
[alpm] [alpm]
database = /var/lib/pacman database = /var/lib/pacman

40
tox.ini
View File

@ -6,8 +6,14 @@ labels =
dependencies = -e .[journald,pacman,reports,s3,shell,stats,unixsocket,validator,web,web_api-docs,web_auth,web_oauth2,web_metrics] dependencies = -e .[journald,pacman,reports,s3,shell,stats,unixsocket,validator,web,web_api-docs,web_auth,web_oauth2,web_metrics]
project_name = ahriman project_name = ahriman
[mypy] [flags]
flags = --implicit-reexport --strict --allow-untyped-decorators --allow-subclassing-any autopep8 = --max-line-length 120 -aa --in-place
bandit = --configfile .bandit.yml
manpage = --author "ahriman team" --author-email "" --description "ArcH linux ReposItory MANager" --manual-title "ArcH linux ReposItory MANager" --project-name ahriman --url https://github.com/arcan1s/ahriman
mypy = --implicit-reexport --strict --allow-untyped-decorators --allow-subclassing-any
pydeps = --no-config --cluster
pylint = --rcfile .pylint.toml
shtab = --prefix ahriman --prog ahriman ahriman.application.ahriman._parser
[pytest] [pytest]
addopts = --cov=ahriman --cov-report=term-missing:skip-covered --no-cov-on-fail --cov-fail-under=100 --spec addopts = --cov=ahriman --cov-report=term-missing:skip-covered --no-cov-on-fail --cov-fail-under=100 --spec
@ -33,19 +39,17 @@ setenv =
CFLAGS="-Wno-unterminated-string-initialization" CFLAGS="-Wno-unterminated-string-initialization"
MYPYPATH=src MYPYPATH=src
commands = commands =
autopep8 --exit-code --max-line-length 120 -aa -i -j 0 -r "src/{[tox]project_name}" "tests/{[tox]project_name}" autopep8 {[flags]autopep8} --exit-code --jobs 0 --recursive "src/{[tox]project_name}" "tests/{[tox]project_name}"
pylint --rcfile=.pylint.toml "src/{[tox]project_name}" pylint {[flags]pylint} "src/{[tox]project_name}"
bandit -c .bandit.yml -r "src/{[tox]project_name}" bandit {[flags]bandit} --recursive "src/{[tox]project_name}"
bandit -c .bandit-test.yml -r "tests/{[tox]project_name}" bandit {[flags]bandit} --skip B101,B105,B106 --recursive "tests/{[tox]project_name}"
mypy {[mypy]flags} -p "{[tox]project_name}" --install-types --non-interactive mypy {[flags]mypy} --install-types --non-interactive --package "{[tox]project_name}"
[testenv:docs] [testenv:docs]
description = Generate source files for documentation description = Generate source files for documentation
allowlist_externals = allowlist_externals =
bash bash
find find
mv
changedir = src
dependency_groups = dependency_groups =
docs docs
depends = depends =
@ -55,18 +59,18 @@ deps =
uv uv
pip_pre = true pip_pre = true
setenv = setenv =
PYTHONPATH=src
SPHINX_APIDOC_OPTIONS=members,no-undoc-members,show-inheritance SPHINX_APIDOC_OPTIONS=members,no-undoc-members,show-inheritance
commands = commands =
bash -c 'shtab --shell bash --prefix ahriman --prog ahriman ahriman.application.ahriman._parser > ../package/share/bash-completion/completions/_ahriman' bash -c 'shtab {[flags]shtab} --shell bash > package/share/bash-completion/completions/_ahriman'
bash -c 'shtab --shell zsh --prefix ahriman --prog ahriman ahriman.application.ahriman._parser > ../package/share/zsh/site-functions/_ahriman' bash -c 'shtab {[flags]shtab} --shell zsh > package/share/zsh/site-functions/_ahriman'
argparse-manpage --module ahriman.application.ahriman --function _parser --author "ahriman team" --project-name ahriman --author-email "" --url https://github.com/arcan1s/ahriman --output ../package/share/man/man1/ahriman.1 argparse-manpage {[flags]manpage} --module ahriman.application.ahriman --function _parser --output ../package/share/man/man1/ahriman.1
pydeps ahriman --no-output --show-dot --dot-output architecture.dot --no-config --cluster pydeps {[flags]pydeps} --no-output --show-dot --dot-output {tox_root}{/}docs/_static/architecture.dot src/ahriman
mv architecture.dot ../docs/_static/architecture.dot
# remove autogenerated modules rst files # remove autogenerated modules rst files
find ../docs -type f -name "{[tox]project_name}*.rst" -delete find docs -type f -name "{[tox]project_name}*.rst" -delete
sphinx-apidoc -o ../docs . sphinx-apidoc --output-dir docs src
# compile list of dependencies for rtd.io # compile list of dependencies for rtd.io
uv pip compile --group ../pyproject.toml:docs --extra s3 --extra validator --extra web --output-file ../docs/requirements.txt --quiet ../pyproject.toml uv pip compile --group pyproject.toml:docs --extra s3 --extra validator --extra web --output-file docs/requirements.txt --quiet pyproject.toml
[testenv:html] [testenv:html]
description = Generate html documentation description = Generate html documentation
@ -77,7 +81,7 @@ deps =
pip_pre = true pip_pre = true
recreate = true recreate = true
commands = commands =
sphinx-build -b html -a -j auto -W docs {envtmpdir}{/}html sphinx-build --builder html --write-all --jobs auto --fail-on-warning docs {envtmpdir}{/}html
[testenv:publish] [testenv:publish]
description = Create and publish release to GitHub description = Create and publish release to GitHub