README.md

Сборщик KDE RPM через mock

build-kde собирает бинарные RPM из SRPM. При каждом запуске он строит граф зависимостей по заголовкам и встроенным spec-файлам выбранных SRPM. Это позволяет учесть явные Provides бинарных подпакетов до первой сборки. Те BuildRequires, которые не предоставляет набор SRPM, проверяются через dnf repoquery по развёрнутой конфигурации выбранного mock. Скрипт запускается через Python 3.14, установленный с помощью asdf, а изолированные окружения сборки создаёт mock.

Шаблон рабочих параметров находится в config.example.json. Перед первым запуском скопируйте его в локальный config.json; этот файл намеренно не отслеживается Git, чтобы в нём можно было хранить настройки конкретного builder. Командная строка может переопределить только путь к конфигурации: --config PATH.

Структура кода

build-kde — короткая исполняемая точка входа. Реализация находится в пакете build_kde: app.py координирует запуск, settings.py читает конфигурацию и рассчитывает ресурсы, models.py содержит общие неизменяемые модели данных, а state.py отвечает за сохранение состояния и форматирование прогресса.

Настройка окружения

Ниже приведён вариант для RedOS/RPM-системы. В других дистрибутивах установите эквивалентные пакеты разработки Python, mock, rpm и createrepo_c.

sudo dnf install -y git curl gcc make bzip2-devel xz-devel readline-devel \
  sqlite-devel openssl-devel libffi-devel zlib-devel mock rpm rpm-build cpio dnf createrepo_c

Установка asdf и Python 3.14:

mkdir -p "$HOME/.asdf/bin"
curl --fail --location \
  https://github.com/asdf-vm/asdf/releases/download/v0.18.0/asdf-v0.18.0-linux-amd64.tar.gz \
  -o /tmp/asdf.tar.gz
tar -xzf /tmp/asdf.tar.gz -C "$HOME/.asdf/bin"
export PATH="$HOME/.asdf/bin:$HOME/.asdf/shims:$PATH"
asdf plugin add python https://github.com/asdf-community/asdf-python.git
asdf install python 3.14.7
asdf set -u python 3.14.7

Чтобы эти программы были доступны в новых shell-сеансах, добавьте в ~/.bashrc:

export PATH="$HOME/.asdf/bin:$HOME/.asdf/shims:$PATH"

У сборщика нет сторонних Python-зависимостей во время работы. Для инструментов разработки и тестирования создайте локальное виртуальное окружение; пакеты не устанавливаются в пользовательский или системный Python:

cd /path/to/build-kde
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements-dev.txt

Mock запускается без sudo, но пользователь должен состоять в группе mock. После установки пакета добавьте в неё текущего пользователя и начните новый сеанс входа (либо выполните newgrp mock):

sudo usermod -aG mock "$USER"

Проверка после обновления групп:

mock --version

Участники группы mock могут запускать часть кода Mock с root-привилегиями; добавляйте в неё только доверенных пользователей.

Настройка

Создайте локальную конфигурацию на основе шаблона:

cp config.example.json config.json

Все относительные пути разрешаются относительно расположения конфигурационного файла. В составе проекта есть самодостаточный файл mock/redos-8-kde67-build.cfg, поэтому на builder не нужно устанавливать отдельную системную конфигурацию Mock. Шаблон содержит следующие значения:

{
  "srpm_dir": "SRPMS",
  "build_dir": "mock-build",
  "mock_config": "mock/redos-8-kde67-build.cfg",
  "parallel_packages": 2,
  "memory_per_build_mib": 2048,
  "heavy_package_patterns": ["qt6-qtwebengine"],
  "heavy_package_jobs": 6,
  "build_limit": null,
  "results_dir": "RPMS",
  "logs_dir": "logs",
  "state_file": "state.json"
}
Параметр Назначение
srpm_dir Каталог исходных SRPM. Значения srpm в графе — только имена файлов из этого каталога.
build_dir Базовый каталог временных chroot mock. Для каждого пакета создаётся собственный подкаталог.
parallel_packages Число одновременных сборок. Если оно превышает доступные слоты, используется число слотов. null выбирает число слотов.
memory_per_build_mib Объём доступной RAM, необходимый для одного слота сборки.
heavy_package_patterns Список подстрок имени SRPM (без учёта регистра), по которым пакет считается тяжёлым. Пустой список отключает это определение.
heavy_package_jobs Статическое число потоков (-j) для тяжёлого пакета.
build_limit Максимальное число пакетов, запускаемых в одной команде build-kde. null или отсутствие параметра (по умолчанию) не ограничивает сборку. Уже собранные пакеты из state_file не учитываются, поэтому следующий запуск продолжает с оставшихся.
results_dir Каталог для собранных RPM и метаданных локального репозитория каждого пакета.
logs_dir / state_file Местоположения логов и состояния возобновления.
mock_config Имя системного файла mock без .cfg либо путь к .cfg относительно config.json. Конфигурация должна содержать те же BaseOS/bootstrap-репозитории, которые будут доступны сборкам.

Запуск

Проверка конфигурации, графа, доступных ресурсов, утилит и прав без сборки:

./build-kde --check-only

Сборка активного графа:

./build-kde

Перед запуском вычисляется общее число слотов сборки: минимум из числа доступных CPU и целой части от доступной памяти, делённой на memory_per_build_mib. Затем оно делится нацело на число параллельных сборок; результат — число слотов и потоков для одной обычной сборки. Оба значения выводятся в терминал. Например, 5 доступных слотов и parallel_packages: 2 дают две параллельные сборки с -j2; пятый слот остаётся неиспользованным. Если явно заданное parallel_packages превышает число доступных слотов, сборка не начинается с ошибкой конфигурации ресурсов. Аналогично, heavy_package_jobs не может быть больше числа доступных CPU.

Число потоков передаётся через _smp_ncpus_max, _smp_build_ncpus, MAKEFLAGS, CMake и Ninja. Тяжёлый узел определяется по heavy_package_patterns; сравнение выполняется без учёта регистра. Он всегда запускается эксклюзивно: ожидает завершения остальных сборок и занимает все слоты, поэтому другие пакеты не запускаются до его окончания. Для него всегда используется статическое значение heavy_package_jobs. После успешной сборки createrepo_c публикует RPM пакета как локальный репозиторий, который подключается mock для прямых потомков графа. Метаданные публикуются атомарно; после каждой успешной публикации старые неактивные каталоги .repodata-generations удаляются. После каждого пакета его mock-root сразу очищается.

При Ctrl-C скрипт прекращает запускать новые задачи и ждёт остановки активных mock-процессов; сами они получают SIGINT непосредственно от терминала. Их пакеты возвращаются в pending, а повторный запуск продолжает сборку. Ошибка блокирует только потомков неуспешного узла; независимые ветви продолжают выполняться.

Если граф нельзя построить (например, SRPM повреждён, его spec не удаётся извлечь или обработать, в наборе повторяется имя исходного пакета или обнаружен цикл), скрипт не запускает сборку. Для остальных BuildRequires он проверяет развёрнутые репозитории из mock_config через dnf repoquery с изолированным кэшем. Недоступная capability блокирует только соответствующий SRPM в текущей волне, а не весь запуск. Когда все доступные пакеты волны собраны, их runtime-репозиторий подключается к следующей проверке и ожидающие SRPM проверяются повторно. Это позволяет увидеть автоматические RPM provides (например, cmake(...)), которых нет в заголовке SRPM. Если новая волна не даёт кандидатов, прогресс и итог показывают число incomplete пакетов и число несобранных пакетов.

В штатной конфигурации проекта также подключён локальный build-only репозиторий bootstrap-repos/nvcodec: он содержит nv-codec-headers-control, который нужен только для исторической сборки ffmpeg и не публикуется среди runtime RPM. Конфигурация mock/redos-8-kde67-build.cfg самодостаточна: в ней нет include, путей к дереву kde6-redos8-6.7.4-20260911 или ссылок на готовый KDE runtime-репозиторий. Она использует только RedOS BaseOS/Updates и этот bootstrap-репозиторий, вычисляемый относительно собственного файла. Его наличие проверяется тем же solver до старта сборки.

Расположение mock и конфигурации

Для имени mock_config: "redos-80-x86_64" используется файл /etc/mock/redos-80-x86_64.cfg; путь к .cfg берётся непосредственно из настроек. Chroot пакета foo создаётся в <build_dir>/<имя-mock-config>-kde67-foo/; параметр build_dir полностью заменяет системный путь mock по умолчанию. После сборки скрипт запускает mock --clean, поэтому содержимое chroot не сохраняется.

Тесты

python -m pytest -q
Описание
Конвейеры
0 успешных
0 с ошибкой
Разработчики