zoryn devenv¶
zoryn devenv готовит изолированное окружение для сборки и тестирования пакета: разрешает зависимости сборки (BuildRequires) и устанавливает их под нужную ветку ALT, а каталог проекта монтирует на чтение и запись. В нём можно:
- собирать и тестировать пакет под конкретный сценарий — ветку, набор зависимостей, инструменты;
- править код — и на хосте, и прямо в окружении — и сразу перезапускать сборку;
- обустраивать окружение под себя — декларативно, через конфигурацию (
packages, шагиbuild/build_user, фичи), доставлять в него пакеты и сторонние инструменты, либо доустанавливать их на лету командойzoryn devenv install; - добавлять пакеты из тестового сборочного задания gyle (
--with-task-repo) или выходного репозитория билдера (--with-builder-repo) и отлаживать сборку на них; - запускать LLM-помощников (claude, codex, opencode, kimi) в изоляции от хоста.
Окружение кэшируется и переиспользуется между запусками.
Экспериментально
zoryn devenv — экспериментальная команда. Интерфейс и поведение кэширования могут измениться в будущих версиях.
Использование¶
zoryn devenv # подготовить (или переиспользовать) окружение и открыть shell
zoryn devenv --backend bwrap # использовать бэкенд bubblewrap
zoryn devenv --backend podman # использовать бэкенд podman
zoryn devenv --image registry.altlinux.org/p11/alt:latest # переопределить базовый образ podman
zoryn devenv --profile p11 # использовать профиль конфигурации [devenv.profiles.p11]
zoryn devenv --branch p11 # разовый оверрайд ветки (без правки конфига)
zoryn devenv --backend podman -u root # только podman: войти под указанным пользователем
zoryn devenv --rebuild # снести контейнер+образ окружения и пересоздать (кэш слоёв)
zoryn devenv --rebuild --no-cache # то же, полностью с нуля (podman build --no-cache)
zoryn devenv -s # тихо: скрыть вывод podman build/install
zoryn devenv -- make check # запустить команду вместо интерактивного shell
zoryn devenv -- rpmbuild -bi *.spec # запустить rpmbuild внутри окружения
zoryn вычисляет BuildRequires: пакета, раскрывая макросы спека внутри подготовленного окружения (две итерации, см. Набор зависимостей), объединяет с настроенными дополнительными пакетами (см. Конфигурация) и открывает shell в текущем каталоге пакета. Каталог проекта монтируется read-write, поэтому правки на хосте сразу видны внутри.
zoryn devenv -- CMD запускает CMD без выделения TTY (подходит для пайпов и CI). Интерактивный shell открывается только когда stdin является терминалом.
При подготовке вывод podman build и установки зависимостей идёт в реальном времени, приглушённым цветом. Флаг -v/--verbose показывает его как есть, без приглушения; -s/--silent скрывает вывод, оставляя только отметки стадий. После раскрытия спека печатается итоговый список BuildRequires.
Бэкенды¶
bwrap¶
Существенно беднее podman
Бэкенд bwrap/hasher лишь устанавливает BuildRequires: спека в chroot и монтирует каталог проекта. Возможности, доступные только в podman, — фичи, шаги сборки образа build/build_user, свой prompt, outbound_interface, проброс SSH-агента, --with-task-repo и установка на лету zoryn devenv install — здесь недоступны. (Дополнительные mounts и --mount-bind на bwrap поддерживаются — монтируются в момент входа.) Для полного набора функций используйте podman; bwrap — только там, где podman недоступен.
Использует bubblewrap поверх chroot, подготовленного через hasher. BuildRequires: пакета устанавливаются в chroot через hasher; каталог проекта монтируется read-write поверх. Повторный вход в кэшированное окружение происходит быстро — chroot переиспользуется без повторной установки пакетов.
git всегда включён в bwrap-chroot.
По умолчанию hasher инициализирует chroot из apt-конфигурации хоста, поэтому bwrap-бэкенд не следует за branch автоматически. Задайте [devenv].apt_config — путь к apt-конфигу хоста: файл в формате apt.conf, файл sources.list или каталог с любым из них — и chroot наполнится из выбранных вами репозиториев (например, apt-конфиг p11 для сборки под p11). Сам hsh --apt-config принимает только файл в формате apt.conf, поэтому apt.conf передаётся как есть, а sources.list автоматически оборачивается в сгенерированный apt.conf в ~/.cache/zoryn/devenv-aptconf/. Значение раскрывает тильду и должно существовать; изменение пересобирает chroot (входит в ключ кэша). Только машинная конфигурация (~/.zoryn, projects.d/). Бэкенд podman тоже учитывает apt_config: используется как sources.list контейнера, если в том же слое конфигурации не задан apt_builder или apt_sources.
Требует bubblewrap и hasher.
podman¶
Сначала настройте rootless podman
Бэкенд podman запускает контейнеры в режиме rootless. Заранее настройте podman на хосте (диапазоны subuid/subgid, хранилище, реестры) по руководству ALT Linux: https://www.altlinux.org/Podman. Доменным учётным записям (LDAP/AD/SSSD) особенно важны явные записи в /etc/subuid и /etc/subgid (например, через usermod --add-subuids/--add-subgids) — без них rootless podman вообще не сможет ни собирать, ни запускать. zoryn дополнительно переназначает host-id вне диапазона на фиксированный id при сборке и использует --userns=keep-id:uid=…,gid=… (podman 4.3+), чтобы контейнер по-прежнему сопоставлялся с вашим реальным id; см. ниже.
Бэкенд podman готовит окружение в два этапа: один раз собирает небольшой производный образ, затем запускает из него постоянный контейнер, который переиспользуется при каждом последующем входе.
Сборка образа. При первой подготовке zoryn собирает на основе образа ALT производный образ — zdevenv-<пакет>-<ветка>:<ключ> (имя каталога пакета, ветка и короткий хеш ключа кэша). Базовый образ берётся директивой FROM (по умолчанию registry.altlinux.org/<ветка>/alt:latest; меняется через image в [devenv] или флагом --image). Образ наполняется во время сборки от имени root — до того, как включится переотображение идентификаторов пользователя (user namespace), — поэтому каталоги блокировок и кэша apt доступны на запись. На этом этапе образ:
- выполняет
apt-get update && apt-get dist-upgrade -y(обновление обязательно: базовые образы ALT часто устаревают); - ставит набор зависимостей плюс
sudo,bash,gitиrpm-build; - запекает пользователя, соответствующего вашим UID/GID на хосте, с беспарольным
sudo. Если ваш id вне диапазона — больше 60000, например доменная учётная запись (LDAP/AD/SSSD), — пользователь запекается с фиксированным id из диапазона (1000), посколькуuseradd(tcb-shadow в ALT) иchownв rootless-сборке не могут использовать id вне вашего диапазонаsubuid.
Постоянный контейнер. Затем zoryn запускает по одному контейнеру на ключ кэша (с именем zdevenv-<пакет>-<ветка>-<ключ>) через podman run -d --userns=keep-id … sleep infinity, монтируя каталог проекта read-write через -v:
- ремап uid (keep-id) выполняется один раз, при создании контейнера; если пользователь запечён с переназначенным id, zoryn использует
--userns=keep-id:uid=1000,gid=1000, чтобы ваш реальный id на хосте по-прежнему сопоставлялся с ним и примонтированные файлы оставались вашими; USERобраза — это запечённый пользователь с вашими UID/GID, поэтомуpodman execвходит под вами (не root), и файлы, записанные в примонтированный проект, остаются вашими;- так как контейнер сохраняется, последующие входы и
install(который тожеexecв тот же контейнер) — мгновенные; - передайте
--user/-u(только podman), чтобы войти под другим пользователем — например,-u rootили-u 1000:1000; это отображается наpodman exec --user.
Сбор зомби и лимит pid. Контейнер запускается с --init, чтобы минимальный PID 1 пожинал зомби: sleep infinity этого не делает, и подпроцессы сборки/тестов (в частности фоновый авто-git gc после коммитов) иначе копятся как defunct-процессы и исчерпывают лимит pid. Лимит задаётся --pids-limit=<n> из [devenv].pids_limit (по умолчанию 4096 — дефолт podman 2048 мал для параллельных сборок; 0 или отрицательное значение — без лимита). В ключ кэша он не входит, поэтому изменение вступает в силу только при следующем пересоздании контейнера (например, через --rebuild).
Прочее. Контейнеру задаётся отдельный --hostname (по имени каталога пакета), чтобы приглашение shell внутри визуально отличалось от хоста. zoryn devenv install добавляет пакеты на лету в работающий контейнер от имени root внутри контейнера (podman exec --user root … apt-get install) — без пересборки образа. --rebuild сносит контейнер и образ и пересоздаёт их с нуля (добавьте --no-cache, чтобы сбросить и кэш слоёв podman build; сам по себе --no-cache — лишь модификатор сборки, он ничего не пересобирает и не удаляет). Базовый образ должен быть доступен для загрузки (image / --image); обновляйте его вручную при необходимости (например, podman pull registry.altlinux.org/sisyphus/alt:latest).
Произвольные шаги сборки образа (build, build_user)¶
Два массива shell-команд, становящихся строками RUN в Containerfile на этапе сборки образа:
build— от root, после установки зависимостей и до создания пользователя (USER) — системная настройка (собрать/поставить инструмент, положить конфиг).build_user— от пользователя хоста, послеUSER, в егоHOME— для per-user установщиков. Например, claude (curl … | bash) ставится в~/.local/bin; черезbuildэто попало бы в/root(невидимо в твоей оболочке), поэтому клади вbuild_user— встанет в твойHOMEи будет вPATH. Для root-шагов здесь есть беспарольныйsudo.
Оба выполняются в /bin/sh контейнера, записываются дословно и входят в ключ кэша (изменение любого пересобирает образ).
Это только машинная конфигурация — принимается в ~/.zoryn и ~/.config/zoryn/projects.d/<проект>.toml, но не в закоммиченном .gear/devenv (предупреждение о неизвестном ключе). Шаги сборки — выбор машины и разработчика, их нельзя выполнять из закоммиченного файла репозитория.
[devenv]
build = ["ln -s /usr/bin/python3 /usr/local/bin/python"] # от root, до USER
build_user = ["curl -fsSL https://claude.ai/install.sh | bash"] # от тебя, после USER
Требует podman.
Дополнительные bind-монтирования (mounts)¶
Ключ mounts в [devenv] — это массив путей хоста, монтируемых в постоянный контейнер, в дополнение к каталогу проекта (он всегда монтируется на чтение и запись). Каждая запись — одно из:
- чистый путь хоста — монтируется по тому же пути внутри контейнера; либо
- спецификация
host:container[:opts], передаваемая вpodman run -vбез изменений (например,/data:/data:ro).
Поведение:
- Начальный
~/~/раскрывается в$HOMEна обеих сторонах записи (podman тильду не раскрывает; при--userns=keep-idдомашний каталог контейнера совпадает с$HOMEхоста). Поле опций (например,ro) остаётся без изменений. - Монтирования становятся флагами
-vпри создании контейнера, поэтому их изменение пересоздаёт контейнер (список монтирований входит в ключ кэша). - Источник в пределах
$HOME, которого ещё нет, создаётся до запуска контейнера — как пустой файл, если имя выглядит как файл (например,~/.claude.json), иначе как каталог — чтобы podman не создал каталог там, где ожидается файл. - Источник только для чтения (
:ro) не создаётся автоматически, если отсутствует: он считается входными данными от пользователя (отсутствующий~/.vimrcостаётся отсутствующим, а не создаётся пустым).
Это только машинная конфигурация — mounts принимается в ~/.zoryn и ~/.config/zoryn/projects.d/<проект>.toml, но не в закоммиченном .gear/devenv (там ключ mounts вызовет предупреждение о неизвестном ключе).
mounts поддерживается обоими бэкендами. В podman монтирования становятся флагами -v при создании контейнера. В bwrap они монтируются в chroot в момент входа как --bind (или --ro-bind для спецификации с :ro), причём только если источник на хосте существует; описанное выше автосоздание источников в $HOME действует только для podman.
Разовый --mount-bind¶
Чтобы добавить монтирование на один запуск, не правя конфиг, передайте --mount-bind SPEC (флаг можно повторять). SPEC использует ровно тот же синтаксис, что и запись mounts, и эти спецификации добавляются после настроенных в конфиге. Относительный путь на стороне хоста разрешается относительно текущего каталога (после применения -C/--chdir):
zoryn devenv --mount-bind /srv/data # rw, один и тот же путь с обеих сторон
zoryn devenv --mount-bind ~/ref:~/ref:ro # только для чтения
zoryn devenv --mount-bind ../OpenUSD # относительный → преобразуется в абсолютный
zoryn devenv --mount-bind /a:/a --mount-bind /b:/b # сразу несколько
podman: изменение монтирований пересоздаёт контейнер
podman фиксирует bind-монтирования в момент создания контейнера — к уже созданному контейнеру монтирование подключить нельзя. Поэтому --mount-bind входит в ключ кэша контейнера: запуск, чей набор монтирований отличается от набора существующего контейнера, создаёт новый контейнер из закэшированного образа. Это дёшево (слои образа переиспользуются), но изменения, сделанные внутри файловой системы прежнего контейнера — вне смонтированных путей, — в новый не переносятся. Повторный запуск с тем же набором --mount-bind переиспользует тот же контейнер, а запуск без флага возвращает к прежнему. Контейнеры, оставшиеся после смены монтирований, удаляет zoryn devenv clean.
В bwrap монтирование выполняется в момент входа, поэтому подключается к уже подготовленному chroot без пересборки.
Пользовательское приглашение оболочки (prompt)¶
Ключ prompt в [devenv] — это строка bash PS1, встраиваемая в производный образ: она дописывается в ~/.bashrc пользователя хоста во время сборки образа, поэтому интерактивная оболочка podman exec … bash использует именно её. Значение сохраняется дословно (внутри заключается в одинарные кавычки), поэтому обычные escape-последовательности приглашения — \u (пользователь), \h (хост), \w (рабочий каталог) и цветовые последовательности вроде \[\e[32m\]…\[\e[0m\] — интерпретируются bash в момент вывода приглашения. Изменение значения пересобирает образ (приглашение входит в ключ кэша).
Это только машинная конфигурация — prompt принимается в ~/.zoryn и ~/.config/zoryn/projects.d/<проект>.toml, но не в закоммиченном .gear/devenv (там ключ prompt вызовет предупреждение о неизвестном ключе). Применяется только к бэкенду podman.
Требует podman.
Исходящий интерфейс (outbound_interface)¶
Ключ outbound_interface в [devenv] — это имя сетевого интерфейса хоста (например, eth1, wg0, eth0.10). Если он задан, контейнер переключается с режима по умолчанию --network host на rootless-сеть pasta в отдельном сетевом пространстве имён, исходящий трафик которой форсится через этот интерфейс через --outbound-if4/--outbound-if6 (pasta биндит свои хостовые сокеты к интерфейсу через SO_BINDTODEVICE), поэтому все исходящие соединения контейнера выходят именно через него, независимо от таблицы маршрутизации хоста. Привязываются только реально присутствующие на интерфейсе семьи адресов — интерфейс только с IPv4 (например, WireGuard wg0) не тянет за собой падающую привязку IPv6. Если ключ не задан, сохраняется поведение по умолчанию --network host. Тот же --network применяется и при сборке образа, поэтому apt на этапе сборки тоже идёт через выбранный интерфейс.
Интерфейс используется только для выхода трафика, а не как шаблон pasta: у point-to-point / tun / WireGuard-интерфейсов нет пригодного L2, и шаблоном они быть не могут (External interface not usable). Поэтому шаблоном (-i) передаётся интерфейс маршрута по умолчанию хоста — контейнер видит адреса/маршруты обычного интерфейса, а трафик уходит через выбранный. На выбранном интерфейсе должен быть хотя бы один пригодный IP-адрес, и должен существовать маршрут по умолчанию, иначе создание контейнера завершится с понятной ошибкой. Итоговый аргумент: --network pasta:-i,<интерфейс-по-умолчанию>,--outbound-if4,<интерфейс>.
Если на выбранном интерфейсе есть только одна семья адресов, pasta ограничивается ей (-4 или -6). Это убирает неиспользуемую семью из контейнера и, что важно, предотвращает утечку: у шаблонного интерфейса может быть другая семья, трафик которой иначе ушёл бы по маршруту шаблона, а не через выбранный интерфейс. Так интерфейс только с IPv4 (WireGuard wg0) даёт контейнер только с IPv4 и без какого-либо пути для IPv6.
Поскольку контейнер получает собственное сетевое пространство имён, сервисы на хостовом localhost больше не разделяются так, как при --network host (сервис, который хост слушает на 127.0.0.1, недоступен изнутри контейнера, и наоборот). Изменение значения пересоздаёт контейнер (интерфейс входит в ключ кэша). Имя проверяется по безопасному набору символов (буквы, цифры, . _ @ -).
Это только машинная конфигурация — outbound_interface принимается в ~/.zoryn и ~/.config/zoryn/projects.d/<проект>.toml, но не в закоммиченном .gear/devenv (там ключ outbound_interface вызовет предупреждение о неизвестном ключе). Применяется только к бэкенду podman.
Требует podman (с поддержкой pasta; в современном podman pasta — сетевой режим rootless по умолчанию).
Проброс SSH-агента (forward_ssh_agent / --ssh-agent)¶
Включает проброс SSH-агента хоста в контейнер, чтобы инструменты внутри (git по SSH, ssh на удалённые билдеры) пользовались ключами вашего агента — в том числе ключами, проброшенными в ваш логин через ssh -A. Включается флагом --ssh-agent (-A) либо постоянно через [devenv].forward_ssh_agent = true; флаг приоритетнее конфига.
Когда включено, zoryn монтирует хостовый $SSH_AUTH_SOCK на фиксированный путь внутри контейнера (/run/ssh-agent.sock) и выставляет туда SSH_AUTH_SOCK, так что podman exec (команда входа) его наследует. $SSH_AUTH_SOCK должен быть задан на хосте и указывать на существующий сокет, иначе проброс пропускается с предупреждением.
Сокет агента не входит в ключ кэша — его путь меняется на каждый вход (например, ssh -A создаёт новый /tmp/ssh-XXXX/agent.<pid> на сессию). Вместо этого путь сокета записывается на контейнер меткой zoryn.ssh_auth_sock; при следующем zoryn devenv, если он отличается от текущего $SSH_AUTH_SOCK (новый вход или переключение проброса), контейнер пересоздаётся, чтобы привязать живой сокет. Сборка образа при этом — попадание в кэш слоёв, но у пересозданного контейнера заново резолвятся и доустанавливаются BuildRequires спека. В рамках одного входа сокет стабилен, поэтому повторные входы мгновенны.
Только машинный конфиг (~/.zoryn, projects.d/), только бэкенд podman.
Конфигурация apt (podman)¶
Бэкенд podman может сгенерировать собственный sources.list, заменяя источники базового образа, и монтировать локальные репозитории file: (только для чтения), чтобы apt мог работать с ними как на этапе сборки образа, так и при установке пакетов.
Конфигурацию apt можно задать одним из четырёх способов (приоритет: --apt-conf > конфиг проекта > глобальный конфиг; в рамках одного слоя задайте только один ключ):
--apt-conf <путь>— файлsources.listили каталог apt-конфига в стиле builder--apt-conf builder:ИМЯ— взять apt-конфиг из билдераИМЯapt_builder = "ИМЯ"(конфиг) — переиспользовать apt-конфиг билдераapt_config = "<путь>"(конфиг) — файл sources.list, файл apt.conf или каталог apt-конфига (также используется бэкендом bwrap, нормализуется в apt.conf дляhsh --apt-config)apt_sources = ["rpm file:///… x86_64 classic", …](конфиг) — строки источников напрямую
Локальные репозитории file: монтируются внутрь контейнера только для чтения по тому же пути; если указанный путь не существует на хосте — это ошибка.
Если заданный источник разрешается в файл без записей репозиториев (пустой или только комментарии — например, пустой /etc/apt/sources.list, когда настоящие записи живут в sources.list.d/), zoryn выводит предупреждение с именем файла и оставляет стандартные источники apt контейнера, а не завершается с ошибкой.
Только машинная конфигурация (~/.zoryn, projects.d/); apt_builder и apt_sources — только бэкенд podman.
Репозиторий вывода билдера (--with-builder-repo BUILDER)¶
--with-builder-repo BUILDER добавляет аддитивный источник apt-rpm типа rpm-dir, указывающий на выходной репозиторий hasher-билдера, — так только что собранные локально пакеты можно устанавливать внутри dev-окружения наряду с пакетами из обычных репозиториев.
- Локальные билдеры: выходной каталог hasher-а (
<hasher_dir>/repo) монтируется в контейнер только для чтения по тому же пути хоста; копирование не производится. - Удалённые билдеры: выходной репозиторий синхронизируется с хоста билдера через rsync в
~/.cache/zoryn/devenv-repos/<builder>/repo/до подготовки окружения; затем используется локальный кэш. - Архитектура билдера должна совпадать с архитектурой devenv (
--arch); при несоответствии zoryn завершается с ошибкой. - Бэкенд podman: дроп-ин
sources.list.d(zoryn-extra.list) записывается в контейнер, не затрагивая настроенные базовые репозитории. - Бэкенд bwrap: строка репозитория объединяется с существующими источниками apt (из
apt_configили/etc/apt/sources.list, если не задан), и вhsh --apt-configпередаётся сгенерированный apt.conf, ссылающийся на объединённый sources.list; базовые репозитории остаются нетронутыми. - Строка репозитория и путь к нему входят в ключ кэша, поэтому изменение или удаление флага пересобирает окружение.
- Взаимно исключает
--with-task-repo.
Репозиторий задачи gyle (--with-task-repo TASK_ID)¶
--with-task-repo TASK_ID загружает RPM-пакеты, собранные задачей gyle, в локальный кэш и открывает их как аддитивный источник apt-rpm типа rpm-dir внутри dev-окружения, — так пакеты из выполняющейся или завершённой задачи gyle можно устанавливать наряду с пакетами из обычных репозиториев.
- RPM-пакеты задачи загружаются по HTTP в
~/.cache/zoryn/devenv-task-repos/<TASK_ID>/до подготовки окружения; кэш переиспользуется при следующих запусках, если не задан--no-cache. - Кэш загруженных RPM в
~/.cache/zoryn/devenv-task-repos/<TASK_ID>/не удаляется командойzoryn devenv clean— при необходимости его можно удалить вручную. - Среди загруженных RPM должны быть пакеты для архитектуры devenv (
--arch); если пакеты этой архитектуры отсутствуют, zoryn завершается с ошибкой. - Только бэкенд podman — на остальных бэкендах (
--backend bwrapи др.) сразу завершается с ошибкой. - Взаимно исключает
--with-builder-repo. - Строка репозитория и каталог кэша входят в ключ кэша, поэтому изменение или удаление флага пересобирает окружение.
hasher (зарезервировано)¶
Имя бэкенда hasher зарезервировано для будущего использования. Передача --backend hasher завершается ошибкой (project-mount scheme TBD).
Конфигурация¶
Секция [devenv] управляет дополнительными пакетами и выбором бэкенда.
Источники конфигурации¶
[devenv] можно задать в трёх местах с разной областью действия:
| Файл | Область | Допустимые ключи |
|---|---|---|
~/.zoryn | Глобально — все пакеты на машине | backend, packages, image, branch, build, build_user, mounts, pids_limit, prompt, outbound_interface, forward_ssh_agent, apt_config, apt_builder, apt_sources, default_profile; таблицы [devenv.features.<id>] |
~/.config/zoryn/projects.d/<проект>.toml | Конкретный проект, локально на машине | то же, что ~/.zoryn |
.gear/devenv | Конкретный пакет, закоммичен, общий для команды | только packages |
.gear/devenv намеренно не принимает backend, image, branch, build, build_user, mounts, pids_limit, prompt, outbound_interface, forward_ssh_agent, профили и таблицы [devenv.features.<id>] — это выбор машины и разработчика, который не следует хранить в репозитории.
Профили¶
Профиль — именованная, полностью независимая конфигурация [devenv], задаётся как [devenv.profiles.<имя>] (в ~/.zoryn или projects.d/<проект>.toml). Выбирается флагом --profile <имя>/-p <имя>; если флаг не задан, используется [devenv].default_profile, а если и он не задан — применяется только базовая секция. Профили удобны, чтобы держать рядом, например, окружения sisyphus и p11 и переключаться между ними.
Когда профиль активен, каждый ключ [devenv] (backend, packages, image, branch, build, build_user, mounts, pids_limit, prompt, outbound_interface, forward_ssh_agent, apt_config, apt_builder, apt_sources и [devenv.features.*]) читается только из [devenv.profiles.<имя>]. Базовая секция [devenv] при этом не учитывается — её значения не наследуются и не объединяются с профилем. База применяется только когда профиль не активен. Ключ, отсутствующий в активном профиле, просто не задан, а не берётся из базы.
Единственное исключение: собственные BuildRequires пакета (вычисленные из его spec) и пакеты, закоммиченные в .gear/devenv, устанавливаются всегда, независимо от профиля — они описывают сам пакет, а не окружение разработчика.
Сам default_profile всегда читается из базовой [devenv] (выбирать профиль изнутри профиля было бы циклично).
Ключ branch задаёт целевую ветку ALT (по умолчанию sisyphus); когда image не задан, из неё выводится базовый образ registry.altlinux.org/<ветка>/alt:latest. zoryn devenv --branch <имя>/-B — разовый оверрайд, который побеждает настроенный branch без правки конфига. Каждый разрешённый профиль (или --branch) даёт своё кэшированное окружение (ветка, пакеты и образ входят в ключ кэша), поэтому два сосуществуют и оба видны в zoryn devenv list.
Как branch влияет на окружение, зависит от бэкенда: podman тянет соответствующий базовый образ, поэтому его apt-репозитории действительно принадлежат этой ветке; bwrap использует hasher, который читает apt-конфиг хоста, поэтому branch только именует/разделяет кэшированный chroot — направьте hasher на репозитории ветки через apt_config (ниже).
[devenv]
packages = ["gdb"] # используется ТОЛЬКО когда профиль не активен
default_profile = "sisyphus" # используется, когда --profile не задан
[devenv.profiles.sisyphus]
branch = "sisyphus"
packages = ["gdb"] # независимо: укажите здесь, если нужно
[devenv.profiles.p11]
branch = "p11"
packages = ["vim"] # → только vim (базовый "gdb" НЕ наследуется)
Фичи¶
Фича — именованный переиспользуемый набор: добавляет в окружение разработки пакеты, шаги установки и bind-монтирования. Описывается файлом feature.toml.
Фичи задаются таблицей, а не списком. Фича подключается добавлением таблицы [devenv.features.<id>] в конфигурацию. Пустая таблица подключает фичу без опций; ключи внутри таблицы — её типизированные опции.
[devenv.features.claude] # выбрана, без опций
[devenv.features.opam] # выбрана, с опцией (локальная фича opam)
version = "5.3.0"
Профили: фичи подключаются послойно. Как и любой другой ключ [devenv], набор фич определяется слоем, а профиль полностью независим от базы:
- Профиль не активен — действуют только таблицы
[devenv.features.<id>](базовый слой). - Профиль активен — действуют только таблицы
[devenv.profiles.<p>.features.<id>](слой профиля); базовые[devenv.features.*]не наследуются.
[devenv.features.claude] # только без --profile
[devenv.profiles.p11.features.gdb] # только с --profile p11 (claude НЕ включается)
Опции фичи берутся из её таблицы в активном слое. Между файлами (глобальный ~/.zoryn + проектный) идентификаторы объединяются, а опции берутся из проектного файла (приоритет выше) — в рамках активного слоя.
Фича добавляет:
packages— объединяется сapt installвместе сBuildRequires:из спека и вашими собственнымиpackages.run— массив shell-команд, выполняемых от root (аналогbuild) при сборке образа.run_user— массив shell-команд, выполняемых от пользователя хоста (аналогbuild_user) после переключенияUSER.mounts— дополнительные bind-монтирования в контейнер.
Шаги фич выполняются до ваших команд build/build_user (фичи — первыми). Типизированные опции options фичи передаются её командам как переменные окружения: имя каждой опции переводится в верхний регистр и экспортируется в окружение команды (например, channel → CHANNEL). Префикс с переменными добавляется к каждой записи run/run_user по отдельности.
Подстановки ${VAR} в тексте команды нет
zoryn не выполняет подстановку ${VAR} в строке команды. Если написать ${CHANNEL} дословно в записи run/run_user, оно не будет раскрыто в значение опции — префикс CHANNEL='latest' cmd не делает ${CHANNEL} видимым в списке аргументов самой cmd в POSIX sh (раскрытие параметра происходит до того, как присваивание вступает в силу, поэтому оно пустое). Значение доходит до программы только через окружение: команда (или установщик, в который она пайпит) должна сама прочитать $CHANNEL через getenv.
Внутри записи mounts, напротив, на опцию можно сослаться как ${NAME} (имя опции в верхнем регистре) — оно подставляется текстуально значением опции до того, как монтирование станет флагом -v (например, ~/.x:~/.x:${CONFIG_ACCESS} при config_access = "ro" даёт ~/.x:~/.x:ro). Это дополнение к экспорту опций в переменные окружения для run/run_user; так опция может параметризовать монтирование (спецификация -v — не shell-команда, поэтому механизм env-префикса там не работает).
Приоритет при поиске: локальное определение ~/.config/zoryn/devenv/features/<id>/feature.toml имеет приоритет над встроенным с тем же id.
Встроенные фичи:
claude— устанавливает Claude Code CLI в~/.local/bin; монтирует~/.claudeи~/.claude.json, чтобы авторизация и настройки сохранялись между запусками контейнера.GLM-claude-code— то же, чтоclaude, но монтирует отдельный профиль: хостовый~/.config/claude-glm→~/.config/claudeв контейнере и хостовый~/.claude-glm.json→~/.claude.json, чтобы держать GLM-авторизацию и настройки отдельно от профиляclaude.codex— устанавливает OpenAI Codex CLI официальным инсталлером; монтирует~/.codex, чтобы логин сохранялся.opencode— устанавливает opencode CLI; монтирует~/.local/share/opencode,~/.config/opencodeи~/.agents, чтобы логин, настройки и описания агентов сохранялись.kimi— устанавливает Kimi Code CLI (MoonshotAI) в~/.local/kimi(бинарник лежит вне монтируемого каталога состояния) и монтирует~/.kimi-code, чтобы логин,config.toml, MCP-серверы и сессии сохранялись.vim— устанавливаетvim-consoleиvim-plugin-spec_alt-ftplugin, монтирует конфигурацию vim хоста:~/.vimrc— только для чтения, и~/.vim— по умолчанию тоже только для чтения. Задайте[devenv.features.vim] config_access = "rw", чтобы монтировать~/.vimна чтение и запись, иначе рабочие записи vim (swap, undo, netrwhist, проверка орфографии, данные плагинов) будут падать с ошибкой.~/.viminfoлежит в$HOME, а не в~/.vim, поэтому история сохраняется в любом случае.ssh— устанавливаетopenssh-clientsи монтирует~/.sshхоста только для чтения, чтобы ключи,configиknown_hostsбыли доступны внутри (например, для git-over-ssh и удалённых билдеров). Из-за режима только для чтения измененияknown_hostsизнутри контейнера не сохраняются.zoryn— устанавливает пакетzorynиз репозитория ветки контейнера и монтирует конфигурацию zoryn хоста (~/.zorynи~/.config/zoryn, где лежитbuilders.d/) только для чтения, чтобы внутри окруженияzorynработал с вашими хостовыми билдерами/настройками, не имея возможности их изменить. Agent Skill пакет ставит сам в/usr/share/zoryn/skills/, поэтому монтировать скиллы не нужно. Пакет должен присутствовать в репозитории целевой ветки.
Это только машинная конфигурация — таблицы [devenv.features.<id>] принимаются в ~/.zoryn и ~/.config/zoryn/projects.d/<проект>.toml, но не в закоммиченном .gear/devenv. Только бэкенд podman; если фича не объявляет текущий бэкенд в своём списке backends, она пропускается с предупреждением.
Пример определения локальной фичи:
# ~/.config/zoryn/devenv/features/claude/feature.toml
id = "claude"
version = "1"
backends = ["podman"]
packages = ["curl"]
run_user = ["curl -fsSL https://claude.ai/install.sh | bash"]
mounts = ["~/.claude", "~/.claude.json"]
[options.channel]
type = "enum"
values = ["stable", "latest"]
default = "stable"
Опция channel экспортируется как CHANNEL в окружение установщика, поэтому скрипт install.sh подхватит её, если читает $CHANNEL (через getenv); в саму строку команды значение не подставляется.
Разовый --feature¶
-F ID, --feature ID — разовое включение фичи devenv ID для текущего запуска, поверх фич из [devenv.features] или активного профиля (с устранением дубликатов; ничего не удаляется). Можно указывать несколько раз. Неизвестный ID — ошибка. Для фичи, уже описанной в конфиге, используются её опции из конфига; фича, включённая только через --feature, берёт значения по умолчанию.
# Подключить фичу 'claude' на один запуск, не трогая конфиг
zoryn devenv --feature claude
# Сразу несколько
zoryn devenv -F claude -F vim
Набор зависимостей¶
Окружение наполняется из двух источников:
1. BuildRequires: из спека, вычисляемые внутри окружения в две итерации (по образцу hasher hsh-rebuild), так что rpm-макросы и условия %if раскрываются настоящим rpmbuild для нужной архитектуры — а не текстовым парсом на хосте:
- Итерация 1 ставит
BuildRequires(pre):(пакеты, определяющие макросы, напримерrpm-build-python3), взятые из сырого спека с отбрасыванием токенов-макросов. - Итерация 2 запускает
rpmbuild -bEна спеке (макро-пакеты уже установлены) и ставит полный раскрытый наборBuildRequires. Так же подхватываются динамические сборочные зависимости, которые добавляют макросы из тела спека (%pyproject_build,%set_gcc_versionи подобные). Такие зависимости попадают не в преамбулу, а в макрос%_buildrequires_build, поэтому zoryn раскрывает копию спека, дописав после тела строку%{?_buildrequires_build}, и устанавливает всё, что окажется в этом списке (например,python3-module-pyproject-installer, который требуется макросам%pyproject_*).
rpm-build всегда присутствует в окружении, чтобы спек можно было раскрыть. Capability-зависимости (pkgconfig(...), perl(...)) резолвятся apt (podman) / hasher (bwrap). Ограничения версий отбрасываются — окружение разработки ставит по имени. Пакеты, чьи скриптлеты требуют hasher-окружение (например, rpm-build-vm-run, проверяющий /.host, /.in, /.out), получают эти каталоги-маркеры, создаваемые в podman-контейнере заранее, чтобы установка прошла (бэкенд bwrap и так является hasher-чрутом). Если спеку нужен KVM для VM-сборки (BuildRequires /dev/kvm или KVM-тянущий пакет вроде rpm-build-vm-run) и на хосте есть /dev/kvm, он прокидывается в podman-контейнер через --device /dev/kvm.
2. Настроенные дополнительные пакеты — объединение (без дублей) packages из [devenv] в ~/.zoryn (личный набор, например gdb, vim, strace), .gear/devenv (общекомандные) и ~/.config/zoryn/projects.d/<проект>.toml (локальные для проекта).
Изменение спека пересоздаёт окружение (его дайджест входит в ключ кэша).
Для шаблонных спеков с gear-плейсхолдерами specsubst (например, Name: kernel-image-@kflavour@ у kernel-image) значения @var@ раскрываются перед вычислением зависимостей — так же, как zoryn build делает для short-circuit сборки секции — беря каждое значение из git config gear.specsubst.<var> или секции [specsubst] файла .gear/version-up. Если значение не задано, zoryn devenv останавливается и просит его задать.
Порядок приоритета бэкенда¶
Флаг --backend → ~/.config/zoryn/projects.d/<проект>.toml → ~/.zoryn → уже подготовленное кэшированное окружение пакета → по умолчанию (podman, если установлен, иначе bwrap).
Если бэкенд не задан, zoryn devenv автоматически входит в существующее кэшированное окружение: если ровно у одного из podman/bwrap есть подготовленное окружение для текущего набора зависимостей, используется он. Поэтому после однократной сборки podman-окружения обычный zoryn devenv входит в него без пересборки. Если кэша тоже нет, по умолчанию используется podman (когда podman установлен), иначе bwrap.
Порядок приоритета образа (только podman)¶
Флаг --image → ~/.config/zoryn/projects.d/<проект>.toml → ~/.zoryn → registry.altlinux.org/<ветка>/alt:latest.
Задайте image (или передайте --image), если образ по умолчанию недоступен на хосте (например, вы используете локальное зеркало или реестр с другой схемой тегов).
Пример ~/.zoryn¶
[devenv]
backend = "bwrap"
packages = ["gdb", "vim", "strace", "ltrace"]
# image = "registry.example.com/alt/sisyphus" # если образ по умолчанию недоступен
# build = ["go install golang.org/x/tools/cmd/goimports@latest"] # podman: доп. шаги RUN при сборке образа
Пример .gear/devenv¶
Пример ~/.config/zoryn/projects.d/<проект>.toml¶
zoryn devenv install¶
zoryn devenv install gdb strace # добавить gdb и strace в подготовленное окружение
zoryn devenv install --save heaptrack # добавить heaptrack и запомнить в .gear/devenv
zoryn devenv install --backend podman ltrace
zoryn devenv install --container blender-abc123 gdb # в конкретный контейнер
zoryn devenv install --container . gdb # в контейнер текущего каталога
Устанавливает дополнительные пакеты в подготовленное окружение текущего пакета (кэшированную базу), чтобы они были доступны в следующей сессии zoryn devenv без полной пересборки. Эта команда выполняется на хосте, потому что shell-среда bwrap работает без привилегий поверх read-only chroot — установить пакеты изнутри неё нельзя.
Если окружение ещё не подготовлено, install сначала подготавливает его (полный разрешённый набор зависимостей, как это сделала бы zoryn devenv), а затем устанавливает дополнительные пакеты поверх. Для бэкенда podman они устанавливаются на лету в работающий контейнер от имени root внутри контейнера (podman exec --user root … apt-get install), без пересборки образа; для bwrap установка идёт в кэшированный chroot.
--container¶
По умолчанию целевое окружение вычисляется из конфигурации текущего каталога — тот же ключ кэша, что использовал бы обычный zoryn devenv. --container CONTAINER (только podman) вместо этого устанавливает пакеты прямо в указанный существующий контейнер (имя/ID как в zoryn devenv list, либо . — контейнер текущего каталога), не разрешая конфигурацию проекта — работает из любого каталога, как zoryn devenv enter. Используйте его, когда ключ кэша контейнера отличается от обычной конфигурации, например для контейнера, созданного с разовым --mount-bind. Флаги выбора окружения (--backend, --image, --apt-conf, …) при --container игнорируются.
--save по-прежнему пишет в .gear/devenv текущего каталога, поэтому сочетать его с --container можно только когда контейнер принадлежит текущему каталогу (его метка zoryn.project совпадает); иначе команда откажет до установки чего-либо.
--save¶
Дополнительно добавляет указанные пакеты в [devenv].packages в .gear/devenv как отсортированное объединение без дублей с уже имеющимися записями. Это позволяет пакетам пережить пересборку кэша и делает их общими для команды (файл коммитится). Прочие ключи файла сохраняются. Если каталога .gear/ нет, сохранение пропускается с предупреждением.
Бэкенд hasher здесь не поддерживается (та же ошибка project-mount scheme TBD, что и у zoryn devenv).
zoryn devenv feature add¶
Добавляет одну или несколько фич devenv в уже запущенный podman-контейнер текущего проекта, на месте — без пересоздания. Это аналог zoryn devenv install, но для фич: пакеты фичи (packages) устанавливаются, а её шаги run/run_user выполняются прямо в работающем контейнере через podman exec.
В отличие от --feature/-F, которая включает фичу в идентичность окружения и потому пересоздаёт контейнер, чтобы собрать его с этой фичей, feature add действует на уже запущенном контейнере. Поэтому эффект временный: как и пакеты, добавленные через zoryn devenv install, фича живёт только в этом контейнере и исчезает при следующей полной пересборке (--rebuild или zoryn devenv clean).
Ограничения:
- Только podman. Если окружение ещё не подготовлено, сначала выполните
zoryn devenv. - Фичу, которая объявляет bind-mount, к уже запущенному контейнеру подключить нельзя, поэтому команда откажет — используйте
zoryn devenv -F ID, чтобы пересоздать окружение уже с этим mount'ом. - Неизвестный id фичи — ошибка.
zoryn devenv clean¶
zoryn devenv clean # удалить кэш окружения для текущего пакета
zoryn devenv clean --backend podman # удалить именно кэш бэкенда podman
zoryn devenv clean --all # podman: удалить ВСЕ окружения этого проекта (любой ключ кэша)
zoryn devenv clean --project /path/to/proj # podman: удалить окружения указанного проекта, из любого места
Удаляет кэшированную базу окружения текущего пакета, чтобы следующий запуск zoryn devenv собрал его заново с нуля.
- bwrap: запускает
hsh-rmchrootдля демонтажа chroot (требуется, так как подкаталог chroot принадлежит hasher-priv subuids и не может быть удалён обычнымrm), затем удаляет весь каталог кэша. - podman: удаляет постоянный контейнер командой
podman rm -fи собранный образ (zdevenv-<пакет>-<ветка>:<ключ>) командойpodman rmi -f.
Целевое окружение определяется по текущим значениям бэкенда, набора пакетов, архитектуры, ветки и образа. Смена --backend, ветки или образа (через конфигурацию) затрагивает другой кэш.
--all (podman)¶
Обычный clean удаляет только одно окружение, соответствующее текущей конфигурации. Изменение параметров, входящих в ключ кэша — prompt, дополнительные packages, mounts, outbound_interface, образ — создаёт новый образ и контейнер, а прежний остаётся работать, поэтому устаревшие окружения со временем накапливаются.
zoryn devenv clean --all удаляет все окружения текущего проекта сразу, независимо от ключа кэша. Контейнеры при создании помечаются меткой zoryn.project=<каталог-проекта>; --all удаляет все контейнеры с меткой текущего проекта, затем делает rmi их образов (без -f, поэтому образ, на который ссылается контейнер другого проекта, сохраняется). Окружения других проектов не затрагиваются. Контейнеры, созданные до появления этой метки, её не имеют и удаляются вручную (podman rm -f <имя>).
--project PATH (podman)¶
zoryn devenv clean --project PATH удаляет все окружения проекта по PATH — это путь к каталогу проекта (значение zoryn.project, которое показывает zoryn devenv list) или его basename — из любого места, не находясь в этом каталоге. Удобно освобождать место от окружений другого проекта прямо по выводу list. Не требует подготовленного окружения или разрешимой конфигурации в текущем каталоге (поэтому работает, даже когда конфиг текущего пакета не разрешается). Образы удаляются rmi без -f. Имеет приоритет над --all и над целью «текущий каталог».
--all применяется только к бэкенду podman; для bwrap удаляется лишь текущий chroot (chroot’ы bwrap общие по набору зависимостей, а не по проекту).
Если кэшированного окружения нет, clean ничего не делает и выводит соответствующее сообщение.
Бэкенд hasher не поддерживается (та же ошибка project-mount scheme TBD, что и у zoryn devenv).
zoryn devenv list¶
Показывает все окружения, созданные zoryn, по всем проектам и ключам кэша — удобно находить устаревшие, накопившиеся при смене конфигурации или зависимостей (каждая отдельная конфигурация получает своё окружение).
- podman: каждый контейнер с меткой
zoryn.devenv, в виде<каталог-проекта> <имя-контейнера> <статус>. - bwrap: подготовленные кэш-каталоги chroot под
~/.cache/zoryn/devenv/(адресуются по набору зависимостей, поэтому без имени проекта — только путь).
Удаление: zoryn devenv clean --all (из проекта — сносит его podman-окружения), zoryn devenv clean (текущей конфигурации) или podman rm -f <имя> для конкретного контейнера.
zoryn devenv enter¶
zoryn devenv enter # войти в контейнер текущего каталога
zoryn devenv enter <CONTAINER> # войти в существующий контейнер по имени/ID
zoryn devenv enter <CONTAINER> --root # войти под root
zoryn devenv enter <CONTAINER> -u 1000 # войти под указанным пользователем
zoryn devenv enter <CONTAINER> -- make # выполнить команду вместо shell
zoryn devenv enter . -- make # выполнить команду в контейнере по умолчанию
Входит в уже созданный podman-контейнер dev-окружения напрямую по имени или ID (как показывает zoryn devenv list), запуская его, если он остановлен. В отличие от обычного zoryn devenv, здесь не разрешается конфигурация проекта и не нужно находиться в каталоге пакета — удобно сразу зайти в конкретный контейнер (например, принадлежащий другому проекту). Shell открывается в рабочем каталоге контейнера (том проекте, для которого он создан).
CONTAINER можно не указывать: тогда выбирается (самый свежий) контейнер, созданный для текущего каталога, а если каталогу не соответствует ни один — единственный существующий контейнер. . — явный placeholder того же умолчания: с ним можно совместить контейнер по умолчанию и команду, например zoryn devenv enter . -- make.
Войти можно только в контейнеры, созданные zoryn devenv (с меткой zoryn.devenv); любое другое имя отклоняется. --root — шорткат для --user root (имеет приоритет над явным --user). Команда после -- выполняется вместо интерактивного shell.
--mount-bind здесь нет: podman не умеет подключать bind-mount к уже созданному контейнеру. Чтобы добавить или изменить монтирования, запустите обычный zoryn devenv --mount-bind SPEC из каталога проекта — контейнер пересоздастся с новыми монтированиями (слои образа переиспользуются, так что это дёшево).
zoryn devenv remove¶
Удаляет один podman-контейнер dev-окружения напрямую по имени или ID (как показывает zoryn devenv list) вместе с его образом (образ удаляется без -f, поэтому используемый другим контейнером сохраняется). Не разрешает конфигурацию проекта и не требует находиться в каталоге пакета. Удалить можно только контейнеры, созданные zoryn devenv (с меткой zoryn.devenv); любое другое имя отклоняется.
Используй, чтобы убрать одно конкретное окружение из вывода list; zoryn devenv clean --project PATH сносит все окружения проекта сразу, а zoryn devenv clean — то, что соответствует текущей конфигурации.
zoryn devenv inspect¶
Печатает конфигурацию zoryn, записанную в podman-контейнер dev-окружения при создании — ключ кэша, образ, ветку, архитектуру, настроенные packages, выбранные features, mounts, шаги build/build_user, prompt/outbound_interface/apt_config и digest спека. Всё хранится как метки zoryn.* контейнера, так что каждое окружение самоописывается — из чего оно собрано.
Также печатает фактически установленные resolved BuildRequires, записанные внутрь контейнера при подготовке и разделённые по проходам hasher — build_requires(pre) (проход 1, пакеты BuildRequires(pre), определяющие макросы) и build_requires (проход 2, полный раскрытый набор) — чтобы стадии можно было различать и сравнивать по отдельности.
Удобно понять непрозрачную запись в zoryn devenv list или сравнить два окружения одного пакета — inspect обоих и сравни вывод, чтобы увидеть, какой именно вход отличается (например, изменился spec_hash, добавилась фича или другой packages/build_requires). Контейнеры, созданные до появления этих меток, покажут только базовые. (Данные меток также в podman inspect <name> --format '{{json .Config.Labels}}'; build-deps — в /var/lib/zoryn-devenv/ внутри контейнера.)
Спек не входит в podman-ключ кэша. Идентичность podman-окружения — это его конфиг (образ, ветка, packages, features, mounts, build-шаги, …), а не спек, поэтому правка спека никогда не создаёт новый контейнер. Вместо этого при следующем zoryn devenv существующий контейнер переиспользуется, а сборочные зависимости сверяются:
- zoryn сравнивает digest спека до секции
%changelog(spec_hash, записанный внутри контейнера какbr_digest). Совпал → сразу вход; не совпал → зависимости резолвятся заново, недостающие доустанавливаются, запись обновляется. - При изменении zoryn заново резолвит
BuildRequiresспека внутри контейнера иapt-ставит только недостающие (идемпотентно — уже стоящие = no-op). - Тело сборки входит в digest, потому что именно оно порождает динамические
BuildRequires(%pyproject_buildи подобные) — значит, его правка тоже запускает повторный резолв; из digest исключён только%changelog(он часто меняется и на зависимости не влияет). - Добавление
BuildRequiresпросто доустанавливает пакет — без пересборки. УдалённыеBuildRequiresостаются установленными (безвредно для dev-среды; для чистого состояния —zoryn devenv clean).
Бэкенд bwrap по-прежнему завязан на спек (его chroot пересобирается при смене спека, а не сверяется).
zoryn devenv profile list¶
zoryn devenv profile list # только имена
zoryn devenv profile list --verbose # итоговая конфигурация каждого профиля
Выводит имена всех профилей [devenv.profiles.<name>], объявленных в машинной конфигурации (~/.zoryn) и в локальной конфигурации проекта (projects.d/<project>.toml), по одному в строке, отсортированными и без повторов. Профили, которые встречаются только через вложенный заголовок [devenv.profiles.<name>.features.<id>], тоже попадают в список.
С флагом --verbose вместо имён выводится итоговая конфигурация [devenv] каждого профиля — ключи и фичи, к которым он разрешается (backend, image, branch, packages, build, features, …), со слиянием машинной и локальной конфигураций проекта так же, как это делает рантайм. Показываются только заданные ключи.
Именно простую форму этой команды вызывает автодополнение оболочки, чтобы предложить корректные значения для zoryn devenv --profile <TAB>, поэтому подсказки всегда отражают ваши реальные профили, а не жёстко прописанный список.
Кэширование¶
Подготовленные окружения кэшируются в ~/.cache/zoryn/devenv/<ключ>/ (bwrap), где ключ вычисляется из набора пакетов, бэкенда, архитектуры, ветки и — для бэкенда podman — базового образа image. Поэтому изменение image затрагивает другое окружение, а не переиспользует устаревшее. Кэш переиспользуется при следующих запусках без повторной установки пакетов.
Архитектура входит в ключ, но окружение всегда собирается под архитектуру хоста — кросс-архитектурная эмуляция не выполняется.
Для бэкенда podman кэш — это собранный образ (zdevenv-<пакет>-<ветка>:<ключ>) плюс созданный из него постоянный контейнер (zdevenv-<пакет>-<ветка>-<ключ>), а не каталог. Контейнер переиспользуется — перезапускается, если был остановлен — при каждом запуске; zoryn devenv clean удаляет и контейнер, и образ.
Монтирование каталога проекта в контейнер фиксируется при его создании. Рабочий каталог не входит в ключ кэша, поэтому если каталог пакета позже переместится (или вы запустите zoryn devenv для него по другому абсолютному пути), переиспользуемый контейнер будет по-прежнему примонтирован к исходному пути, и ваши правки не будут видны внутри. Выполните zoryn devenv clean (или --rebuild), чтобы пересоздать контейнер для нового расположения.
Передайте --rebuild, чтобы снести кэшированное окружение и пересоздать его (для podman это пересобирает образ и пересоздаёт контейнер); добавьте --no-cache, чтобы заодно сбросить кэш слоёв podman build и заново выполнить каждый слой (apt dist-upgrade, зависимости). Сам по себе --no-cache — лишь модификатор сборки, он ничего не пересобирает и не удаляет. Пересборка полезна после изменения BuildRequires: или когда базовый образ устарел с момента подготовки.
См. также¶
- Конфигурация — справочник
~/.zoryn - Песочница — изоляция на основе bubblewrap и hasher для хуков zoryn