- OCaml 98.6%
- Standard ML 0.6%
- Shell 0.4%
- Perl 0.4%
| .forgejo/workflows | ||
| .gear | ||
| bin | ||
| completions | ||
| docs/plans | ||
| examples/builders.d | ||
| fuzz | ||
| lib | ||
| test | ||
| .duneignore | ||
| .gitignore | ||
| .ocamlformat | ||
| AUTHORS | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| dune | ||
| dune-project | ||
| dune-workspace | ||
| LICENSE | ||
| README.md | ||
| README.ru.md | ||
| TODO.md | ||
| zoryn.opam | ||
zoryn
Zoryn — maintainer assistant for ALT Linux.
The name comes from an ancient root meaning light and clear sight. Zoryn helps you see through the maze of upstream releases, spec files, and build queues — automating what can be automated, while keeping you in control of the process.
Repository: https://altlinux.space/rider/zoryn
Contents
- Installation
- Quick Start
- Configuration
- Commands
- zoryn up — update version from upstream
- zoryn build — local and remote hasher build
- zoryn builder — manage build machines
- zoryn submit — commit, tag, push and submit for build
- zoryn clone — clone package from sisyphus
- zoryn spec — spec file operations
- zoryn task — task management
- zoryn check — check for updates
- zoryn tag — tag operations
- zoryn gen — generate files
- Batch configs
Installation
apt-get install dune ocaml-cmdliner-devel ocaml-re-devel ocaml-curl-devel libcurl-devel ocaml-yojson-devel ocaml-opam-file-format-devel ocaml-parsexp-devel ocaml-alt-releases-matrix-devel ocaml-alcotest-devel ocaml-toml-devel ocaml-linenoise-devel ocaml-ppxlib-devel ocaml-lambda-term-devel libev-devel
dune build
dune install
To install to home directory instead of system-wide:
dune install --prefix=$HOME
Binaries will be in $HOME/bin, bash completions in $HOME/share/bash-completion/completions/.
To install binaries only (without completions and libraries):
dune install --prefix=$HOME --sections=bin
Bash Completion
After installation, enable bash completion by adding to ~/.bashrc:
# System-wide installation
source /usr/share/bash-completion/completions/zoryn
# Or user installation (--prefix=$HOME)
source ~/share/bash-completion/completions/zoryn
Quick Start
Initial Setup
# Generate configuration files (~/.zoryn, ~/.ssh/config, etc.)
zoryn gen environment
# Add remote builder (optional, for non-local builds)
zoryn builder add
Working with Packages
# Clone package from sisyphus
zoryn clone mypackage
cd mypackage
# Update package to new upstream version
zoryn up
# Submit package to sisyphus
zoryn submit
# Submit to stable branch
zoryn submit -B p11
# Check if new version available
zoryn check version
# Find spec file
zoryn spec find
Configuration
~/.zoryn
Global configuration file. Required for zoryn to work. Format: TOML.
[build]
command = "hsh -v --number={hasher_number} --mountpoint=/proc,/dev/pts,/dev/kvm --lazy-cleanup {hasher_dir}"
[builders]
default = "local"
default_arch = "x86_64"
parallel = "off"
results_download_dir = "{git_root}/hasher_out"
batch_repo = "~/zoryn-batch-repo"
[gitery]
host = "gitery"
remote = "gitery"
[gyle]
host = "gyle"
[sources]
srpms_path = "/mnt/ftp/pub/distributions/ALTLinux/Sisyphus/files/SRPMS/"
[rebuild]
command = "hsh -v --mountpoint=/proc,/dev/pts,/dev/kvm --lazy-cleanup"
log_dir = "/tmp/rebuild-logs"
[add_changelog]
up_template = "- {old_version} -> {new_version} {cves}"
[commands]
# Optional: override paths and arguments for external commands
# git = "/usr/local/bin/git"
# git.fetch = "{git} fetch --prune"
# ssh = "ssh -o ConnectTimeout=10"
# ssh.gitery = "{ssh} -p 2222 -i ~/.ssh/alt_key"
Section [commands] (optional):
- Override paths and global arguments for external commands (git, ssh, gear-*, rpm, etc.)
- Subcommands inherit from base command:
git.fetch = "{git} fetch --prune"— ifgitis overridden,git.fetchuses the override ~/and$HOMEin values are expanded to absolute paths- Shell metacharacters (
;,|,`,$()) are rejected at startup
Section [build]:
command— hsh command for local builds (default:hsh --lazy-cleanup). Note: usehsh, notgear-hsh— tarball is created separately withgear --commit. For parallel builds with multiple local hashers, use{hasher_number}and{hasher_dir}placeholders:hsh -v --number={hasher_number} --mountpoint=/proc,/dev/pts,/dev/kvm --lazy-cleanup {hasher_dir}.
Section [builders]:
default— default builder(s) forzoryn build,zoryn up,zoryn task rebuildwhen no--builderspecified. Comma-separated string or TOML array (e.g.,"local"or["local", "arm-server"]).default_arch— default architecture(s) for multi-builder mode. Comma-separated string or TOML array (e.g.,"x86_64"or["x86_64", "aarch64"]). When specified, enables multi-builder mode automatically if multiple architectures are listed.parallel— default parallel mode for multi-builder builds (onoroff, default:off). Can be overridden with--parallelor--sequentialflags.results_download_dir— directory for downloading remote build results (default:{git_root}/hasher_out). Supports{git_root}variable.batch_repo— directory for accumulating RPMs during batch builds. Used bydownload_rpmsandupload_rpmscommands.
Section [gitery]:
host— SSH alias for gitery, must match entry in~/.ssh/configremote— name of git remote pointing to gitery, used for push operations
Section [gyle]:
host— SSH alias for gyle build system
Section [sources]:
srpms_path— path to local SRPMS repository mirror (required forzoryn task rebuild)
Section [rebuild]:
command— hasher command for rebuilding packages (default:hsh -v --mountpoint=/proc,/dev/pts,/dev/kvm --lazy-cleanup)log_dir— base directory for build logs (default:/tmp/rebuild-logs)
Section [rdb]:
api_url— RDB API base URL (default:https://rdb.altlinux.org/api)
Section [add_changelog]:
up_template— changelog entry format forzoryn up(default:- updated from {old_version} to {new_version} {cves}){old_version}— previous version{new_version}— new version{cves}— CVE fixes as(Fixes: CVE-...)or empty string- Note:
.gear/version-up[add_changelog]section takes priority over~/.zoryn - trailing whitespace is trimmed automatically
Section [submit]:
run— whether to run task after creating/modifying (default:false)test_only— whether to mark task as test-only (default:true)
Example to restore old behavior (run with --commit by default):
[submit]
run = true
test_only = false
Minimal example:
[gitery]
remote = "gitery"
~/.config/zoryn/builders.d/
Builder configurations for remote and local build machines. Each .conf file defines one builder.
# ~/.config/zoryn/builders.d/arm-server.conf
[builder]
name = "arm-server"
type = "remote"
arch = "aarch64"
branch = "sisyphus"
host = "builder-arm.internal"
hasher_dir = "~/hasher"
remote_dir = "~/build"
# hasher_number = 1 # for parallel builds (requires hasher-useradd --number=N)
[commands]
upload = "rsync -av {tarball} {host}:{remote_dir}/"
build = "hsh -v --lazy-cleanup --apt-config=$HOME/hasher_{hasher_number}.env/{branch}/apt.conf {hasher_dir} {remote_dir}/{tarball_name}"
# download uses smart download by default (downloads only newly built packages)
cleanup = "ssh {host} \"rm -rf {remote_dir}/*\""
shell = "hsh-shell {hasher_dir}"
install = "hsh-install {hasher_dir} {packages}"
Section [builder]:
name— builder name (used for--builderoption)type—localorremotearch— target architecture (x86_64, aarch64, i586, etc.)branch— target branch (sisyphus, p11, etc.)host— SSH host for remote buildershasher_dir— hasher working directory (default:~/hasher)remote_dir— working directory on remote hosthasher_number— hasher subconfig number for parallel builds
Section [commands]:
upload— command to upload tarball (runs locally)build— build command (wrapped in SSH for remote builders)download— command to download results (runs locally). By default, uses smart download which downloads only newly built packages usingrsync --files-from. Old configs with full repo download are automatically migrated.list_rpms— command to list RPMs with mtimes in hasher repo (default:find {hasher_dir}/repo -name '*.rpm' -printf '%P\t%T@\n'). Used for smart download to detect new packages.cleanup— cleanup command after buildshell— command forzoryn builder shellinstall— command forzoryn builder installcheck_busy— command to check if builder is busy (auto-generated if not specified)download_rpms— command to download RPMs after build for batch sync (auto-generated if not specified)upload_rpms— command to upload RPMs before build for batch sync (auto-generated if not specified)
Variables for commands: {host}, {hasher_dir}, {remote_dir}, {tarball}, {tarball_name}, {results_download_dir}, {git_root}, {packages}, {batch_repo}, {arch}, {name}, {hasher_number}, {branch}.
.gear/version-up
Version mapping and merge configuration for zoryn up.
[version]
pattern = "{major:+}.{minor:+}.{patch:+}"
template = "{major}.{minor}.{patch}"
strip-prefix = "v"
create-alias = true
filter = "minor=4"
[changelog]
file = "CHANGELOG.md"
# or use remote URL:
# url = "https://curl.se/docs/vuln.json"
# parser = "osv-json"
# cve-format = "extended"
[merge]
use-theirs = ["meson.build", "configure.ac"]
[tarball]
gear-update-opts = "--all"
Section [version] describes how to convert upstream tags to RPM versions.
Pattern syntax
The pattern field uses placeholders to capture version components from git tags:
Placeholder format: {name:length}
name— capture group name (e.g.,major,minor,patch,year,month,day)length— digit count specifier:+or*— one or more digits (regex:[0-9]+)N(number) — exactly N digits (regex:[0-9]{N})
Literal characters:
.— matches literal dot-,_— match literal hyphen or underscore- Other characters — matched as-is
Template field: Uses captured group names without length specifier: {major}, {minor}, etc.
Pattern examples
| Upstream tag | pattern | template | RPM version |
|---|---|---|---|
v1.2.3 |
v{major:+}.{minor:+}.{patch:+} |
{major}.{minor}.{patch} |
1.2.3 |
release-1.2 |
release-{major:+}.{minor:+} |
{major}.{minor} |
1.2 |
20240115 |
{year:4}{month:2}{day:2} |
{year}.{month}.{day} |
2024.01.15 |
2.0.0-rc1 |
{major:+}.{minor:+}.{patch:+}-{pre:+} |
{major}.{minor}.{patch} |
2.0.0 |
camlidl113 |
camlidl{major:1}{minor:2} |
{major}.{minor} |
1.13 |
RELEASE_8_4_5 |
RELEASE_{major:+}_{minor:+}_{patch:+} |
{major}.{minor}.{patch} |
8.4.5 |
Filtering tags
The filter option limits which tags are considered. For example, filter = minor=4 only matches tags where the captured minor group equals "4". Multiple filters can be combined: filter = major=8, minor=4.
Section [changelog] specifies the source for CVE scanning:
file— path to local changelog file (e.g., CHANGELOG.md, NEWS)url— URL to fetch security advisories from (e.g., https://curl.se/docs/vuln.json)parser— parser type for URL content:auto— auto-detect based on content (default)osv-jsonorjson— OSV JSON format (used by curl, etc.)markdownormd— standard markdown changeloghtmlorhtml-table— HTML table with CVE info
cve_format— format for CVE entries in RPM changelog:compact(default) — inline format:(Fixes: CVE-..., CVE-...)extended— multiline with descriptions from OSV JSON
URL takes precedence over file if both are specified.
Section [merge] configures automatic conflict resolution:
use-theirs— list of files to take from upstream on conflict (comma or space separated). Useful for version files like meson.build, configure.ac
Section [tarball] configures tarball import via gear-update:
gear-update-opts— extra options forgear-updatecommand (e.g.,--allto extract all directories from archive instead of one)
Section [add_changelog] configures changelog entry format (overrides global ~/.zoryn):
up_template— changelog entry template forzoryn up- Supports variables:
{old_version},{new_version},{cves} - Example:
up_template = "- {old_version} -> {new_version} {cves}"
- Supports variables:
Example for date-based versions:
[version]
pattern = "{year:4}{month:2}{day:2}"
template = "{year}.{month}.{day}"
.gear/merge-up.d/
Scripts executed after merge with upstream tag, before spec file update.
Interface:
$1 — version (clean tag)
$TAG — full tag name
$COMMIT — commit SHA1
$SHORTCOMMIT — short SHA1
Example .gear/merge-up.d/01-vendor.sh:
#!/bin/bash
go mod vendor
.gear/up.d/
Scripts executed after spec file update, before commit.
Interface:
$1 — new version
Example .gear/up.d/10-version.sh:
#!/bin/bash
sed -i "s/VERSION=.*/VERSION=$1/" configure.ac
Hook Sandbox
Hooks are executed in a sandboxed environment by default to protect sensitive files.
Backends:
hybrid(default) — bwrap + hasher chroot: prepares chroot with package build dependencies, runs scripts in bwrapbwrap— bubblewrap with host system paths, lightweight namespace-based isolationdirect— no sandbox (legacy behavior)
CLI options:
zoryn up --sandbox=hybrid # use hybrid (default)
zoryn up --sandbox=bwrap # use bubblewrap with host paths
zoryn up --no-sandbox # disable sandbox
Configuration (~/.zoryn):
[sandbox]
runner = "hybrid"
path = "/usr/bin:/bin"
[sandbox.chroot]
prepare = "gear-hsh --commit -- --mountpoints=/proc,/dev/pts,/dev/kvm --lazy-cleanup --build-srpm-only" # command to prepare chroot
[sandbox.hasher]
workdir = "~/hasher"
Per-project (~/.config/zoryn/projects.d/<project>.toml):
[sandbox]
runner = "hybrid"
[sandbox.chroot]
prepare = "gear-hsh --commit -- --mountpoints=/proc,/dev/pts,/dev/kvm --lazy-cleanup --build-srpm-only"
In hybrid mode, hasher prepares a chroot with the package's build dependencies (from spec file),
then bwrap runs scripts using paths from this chroot. This gives both filesystem isolation and
access to required tools without needing setuid privileges at runtime.
Additional packages in .gear/version-up:
[sandbox]
packages = ["go", "make", "curl"]
The git package is always installed. Packages from this section are installed after chroot
preparation using hsh-install.
Environment
SSH aliases in ~/.ssh/config:
Host gitery
HostName gitery.altlinux.org
Port 222
User alt_username
Host gyle
HostName gyle.altlinux.org
Port 222
User alt_username
Commands
Global Options
--version Show version
-h, --help Show help
-d, --debug Enable debug output
-v, --verbose Enable verbose output
-C <dir> Change to directory before running
zoryn up
Automatic package update to new upstream version.
zoryn up [-t|--tarball] [--tag TAG] [--allow-unrelated-histories] [-f|--force] [-b|--builder NAME] [-a|--arch ARCH] [-B|--branch BRANCH] [--all-builders] [-p|--parallel] [-s|--sequential] [-w|--wait] [--skip-busy] [--skip-check=LIST] [-d] [-v]
Options:
-t, --tarball— force tarball mode (download and update instead of git merge)--tag TAG— use specific upstream tag for merge (skip version detection)--allow-unrelated-histories— merge unrelated histories (for packages with imported pristine upstream)-f, --force— force update from prerelease to stable release when no newer version exists-b, --builder NAME— use specific builder for post-update build (comma-separated for multiple)-a, --arch ARCH— select builder by target architecture (comma-separated for multiple)-B, --branch BRANCH— select builder by target branch (comma-separated for multiple)--all-builders— build on all configured builders (optionally filtered by--arch/--branch)-p, --parallel— run builds in parallel when using--all-builders-s, --sequential— run builds sequentially (overridesparallel = onin config)-w, --wait— wait for busy builder to become free--skip-busy— skip busy builders instead of waiting--skip-check=LIST— skip specified package check tools after build (comma-separated, orallto skip all)-v, --verbose— show build output on screen (in addition to log file)
Supported repository schemes
zoryn automatically detects and supports four repository maintenance schemes:
1. Git merge (standard)
Working tree contains upstream source code plus ALT Linux build files (.gear/, .spec). Examples: php, curl, nginx.
.gear/rules: tar: v@version@:.
Upstream code is merged directly into working tree. Patches are applied as commits on top of upstream. When updating, git merge integrates new upstream version with local changes.
2. Tarball download
Upstream tarball is downloaded and extracted into a subdirectory. ALT Linux build files (.spec, .gear/, patches) are stored alongside. Examples: many packages without VCS tag in spec.
.gear/rules: tar: @name@
copy?: *.patch
Used with zoryn up --tarball or auto-detected from watch file. The tarball is fetched from upstream URL specified in watch file and imported into the subdirectory.
3. Pristine tarball + history attachment
Working tree contains only ALT Linux build files (.spec, .gear/, *.patch). Upstream source code exists only in git history, attached via merge. Examples: libssh2, openssl.
.gear/rules: tar: @name@-@version@:.
copy?: *.patch
When updating, zoryn uses git merge -s ours — attaching upstream history without modifying working tree files. Patches are maintained manually as separate files.
Detection is automatic: zoryn compares files in HEAD vs upstream tag. If there are no common source files (only .spec, .patch, .gear/), the pristine tarball scheme is detected and -s ours strategy is used.
Importing with no common history: When the local branch has no common ancestor with upstream (e.g., fresh import of upstream sources), use --allow-unrelated-histories flag. This merges with -s ours --allow-unrelated-histories, then restores upstream files while preserving ALT-specific directories (.gear/, spec directory, copy directories from .gear/rules).
4. Subtree
Upstream source code lives in a subdirectory, ALT Linux build files in root. Examples: apache2-mod_auth_openidc.
.gear/rules: tar: v@version@:.
diff: v@version@:. mod_auth_openidc/
The diff: directive tells gear to create a patch from differences between the tag and the subdirectory. When updating, zoryn uses git subtree pull to update the subdirectory from upstream. Local changes in the subdirectory automatically become patches.
Detection is automatic: zoryn analyzes commit history for each subdirectory. If recent commits are predominantly "Merge commit 'HASH'" pattern (characteristic of git subtree pull --squash), the subtree scheme is detected.
Workflow
- Finds spec file and extracts current version
- Reads repository URL from VCS tag in spec file
- Adds upstream remote and fetches tags
- Applies version mapping from
.gear/version-up(if present) - Finds newer versions and selects latest
- Detects merge strategy (standard or
-s ours) - Merges upstream tag (or downloads tarball with
--tarball) - Runs hooks from
.gear/merge-up.d/ - Updates version in spec file, resets release to alt1
- Scans upstream changelog for CVEs (if configured)
- Adds changelog entry
- Runs hooks from
.gear/up.d/ - Updates gear tags
zoryn build
Run local or remote hasher build.
zoryn build [-v] [-l dir] [-C dir] [-d] [-b name] [-a arch] [-B branch]
[--all-builders] [-p] [-s] [--wait] [--skip-busy] [--top]
[--skip-check=LIST]
Reads build command from ~/.zoryn config or builder configuration. Supports both local and remote builders configured in ~/.config/zoryn/builders.d/.
If the package has batch configuration in .gear/version-up (specsubst with multiple values), builds are run for each specsubst value.
By default, build output is written only to log file (silent mode). Use -v to also show it on screen.
Options:
-v, --verbose— show build output on screen (in addition to log file)-l, --log-dir <dir>— save build logs to specified directory instead of.gear/-C <dir>— change to directory before running-d, --debug— enable debug output-b, --builder <name>— use specific builder by name (comma-separated for multiple)-a, --arch <arch>— select builder by architecture (comma-separated for multiple)-B, --branch <branch>— select builder by branch (comma-separated for multiple)--all-builders— build on all matching builders-p, --parallel— run builds in parallel when using--all-builders-s, --sequential— run builds sequentially (overridesparallel = onin config)-w, --wait— wait for busy builder to become free--skip-busy— skip busy builders without error--top— interactive TUI mode for monitoring builds (htop-like interface)--skip-check=LIST— skip specified package check tools after build (comma-separated, orallto skip all)
TUI mode (--top) provides an interactive interface with:
- Real-time builder status table with build stages
- Live log panel with scrolling (Up/Down, PgUp/PgDn, Home/End, mouse wheel)
- Regex search in logs (
/to search,n/Nfor next/prev) - TAB to switch between builders,
cto cancel,rto restart - Requires
ocaml-lambda-term-develpackage
Examples:
zoryn build # local build using ~/.zoryn config
zoryn build -v # build with output on screen
zoryn build --builder=shell64 # build on specific builder
zoryn build --builder=shell32,shell64 # build on multiple builders
zoryn build --arch=aarch64 # build on ARM64 builder
zoryn build --branch=p11 --wait # build for p11, wait if busy
zoryn build --all-builders # build on all builders
zoryn build --all-builders -p # parallel build on all builders
zoryn build --all-builders --arch=x86_64 # build on all x86_64 builders
zoryn build --all-builders --top # interactive TUI mode
zoryn builder
Manage build machines (builders).
zoryn builder <subcommand>
Subcommands:
list [--simple]— list available builders (--simplefor names only, one per line)status— check builder availability (free/busy)config [NAME]— show full builder configuration including defaultsshell [--builder=NAME]— open shell in hasherinstall [--builder=NAME] PKG...— install packages in hasheradd [options]— add a new builder configuration (interactive or non-interactive)copy SRC... DST— copy files into or out of hasher chroot (usebuilder:pathfor chroot paths)clean [--all|--all-local|--all-remote] [NAME...]— clean hasher chroot and auxiliary directories
The add command options:
--name=NAME— builder name (required for non-interactive mode)--type=TYPE— builder type: local or remote (default: remote)--host=HOST— remote host (SSH alias). Required for remote builders--arch=ARCH— target architecture. Auto-detected from host if not specified--branch=BRANCH— target branch (default: sisyphus)--hasher-dir=DIR— hasher directory (default: ~/hasher)--remote-dir=DIR— remote build directory (default: ~/build)--description=TEXT— human-readable description-n, --number=N— hasher number for parallel builds (default: 0)--based=NAME— copy settings from existing builder as defaults--create-hasher-users— automatically create hasher satellite users viasudo hasher-useradd-y, --yes— auto-confirm, don't ask for confirmation
The --create-hasher-users flag automatically creates hasher satellite users via sudo hasher-useradd. This requires passwordless sudo to be configured on the builder host.
Examples:
zoryn builder list # list all builders
zoryn builder list --simple # list builder names only (for scripts)
zoryn builder status # show status of all builders
zoryn builder status -b shell64 # show status of specific builder
zoryn builder config # show default local builder config
zoryn builder config arm-server # show config for specific builder
zoryn builder shell # open shell in default builder's hasher
zoryn builder shell -b arm-server # open shell on remote builder
zoryn builder run -- rpm -qa # run command in default builder's hasher
zoryn builder run my-builder -- ls -la # run command on specific builder
zoryn builder run --rooter -- cat /etc/shadow # run as pseudoroot
zoryn builder run --execute=./setup.sh # execute script in hasher
zoryn builder install vim nano # install packages in hasher
zoryn builder copy ./file.c mybuilder:src/ # copy file into builder chroot
zoryn builder copy mybuilder:build.log ./ # copy file from builder chroot
zoryn builder add # interactively create new builder
zoryn builder add --based shell64 # create builder based on existing one
zoryn builder add --name arm --host myserver -y # non-interactive with auto-detection
zoryn builder add --name local-i586 --type local --arch i586 -y # local builder
zoryn builder add --name arm --host user@myserver --number 3 --create-hasher-users -y # create with hasher users
zoryn builder clean local # clean specific builder
zoryn builder clean --all-local # clean all local builders
zoryn builder clean --all # clean all builders
zoryn builder clean --all --dry-run # preview what would be cleaned
zoryn submit
Full build cycle: commit, tag, push, submit for build.
zoryn submit [-B repo] [--with pkg] [--replace[=TASK]] [--subtask=N] [--run] [--no-run] [--test-only] [--commit] [--dry-run] [--skip-check] [-d]
By default, creates a task but does not run it (test-only mode). Use --run to start the build, and --commit to publish instead of test-only. Default behavior can be configured in ~/.zoryn [submit] section.
With -B submits to specified repository and automatically adds dependencies on tasks from fresher repositories. Multiple repositories can be specified as comma-separated list (e.g., sisyphus,p11), each subsequent submit depends on the previous task.
Options:
-B, --branch <repo>— target repository (default: sisyphus), supports TAB completion--with <pkg>— add to existing task containing package<pkg>. If the same tag already exists in task, auto-replaces. If package exists with different tag, prompts for action.--replace[=TASK]— replace subtask in existing task. Finds task containing current package (or uses specified TASK_ID), deletes old subtask and adds new one with current tag.--subtask=N— when replacing, select specific subtask by ID (useful when package appears multiple times in task)--run— run the task after creating/modifying-n, --no-run— don't run the task (override config)--test-only— mark task as test-only (don't publish)--commit— mark task for publishing (opposite of--test-only)--dry-run— preview all actions without executing--skip-check— skip spec file validation (seezoryn check spec)
Examples:
zoryn submit # create task (default: don't run, test-only)
zoryn submit --run # create and run test build
zoryn submit --run --commit # create and run for publishing
zoryn submit -B p11 # submit to p11, --deps on sisyphus tasks
zoryn submit -B sisyphus,p11 # submit to sisyphus first, then p11 with --deps
zoryn submit --with libva # add to task containing libva
zoryn submit --replace # replace subtask in existing task
zoryn submit --replace --run # replace and run
zoryn submit --no-run # explicitly don't run (override config)
zoryn submit --dry-run # preview all actions
When submitting to stable branches, build reason is detected automatically (new version, bugfix release, new package). If CVEs are found in spec changelog between versions, reason is marked "with security fixes".
zoryn spec
Spec file operations.
zoryn spec find
Find spec file in gear repository:
zoryn spec find
zoryn spec version
Extract or set version in spec file:
zoryn spec version # show current version
zoryn spec version set <version> # set new version
zoryn spec add changelog
Add changelog entry:
zoryn spec add changelog -e "- fix build" [specfile] # manual message
zoryn spec add changelog --auto [specfile] # auto-generate
zoryn spec add changelog --auto --from 1.2.3 [specfile] # auto with explicit old version
The --auto mode generates message like zoryn up does (OLD -> NEW with CVEs).
zoryn task
Task management operations.
zoryn task download
Download built RPMs from task to local hasher repository:
zoryn task download <package|task_id> [-b repo] [--arch arch] [-o dir] [-d]
Downloads all built binary RPMs from a task. The argument can be either a package name or a task ID. If the argument is a number, it is used directly as task ID; otherwise, the command searches for a task containing the specified package.
By default, the destination path is determined automatically from hsh --printenv. Use -o to specify a custom output directory (will be created if it doesn't exist).
Options:
-b <repo>— target repository (default: sisyphus, ignored when task ID is specified)--arch <arch>— target architecture (default: fromhsh --printenv, or x86_64 with-o)-o, --output <dir>— output directory (default: hasher repo directory)
Example:
zoryn task download 404784 # download RPMs by task ID
zoryn task download ffmpeg # download RPMs from sisyphus task
zoryn task download 404784 -o /tmp/rpms # download to custom directory
zoryn task download libva -b p11 # download RPMs from p11 task
zoryn task download ffmpeg --arch i586 # download i586 RPMs
zoryn task delete
Delete subtask from task by package name or subtask number:
zoryn task delete <task_id> <package|subtask> [-d]
Finds and deletes subtask from the task. The second argument can be:
4200— subtask number (numeric)php-sphinx— package namephp-sphinx.git— package name with .git suffixphp-sphinx.git=8.2.30-alt1— package name with tag (for copy-paste fromtask lsoutput)
zoryn task genbatch
Generate batch config from existing task:
zoryn task genbatch <task_id> [--output file] [--main pkg]
Reads task structure and generates batch config file for rebuilding.
zoryn task refresh
Refresh build in task (rerun with updated packages):
zoryn task refresh <task_id> [--dry-run]
zoryn task batch
Build a chain of related packages from a batch config:
zoryn task batch <config> [--basedir dir] [--no-build] [--create-task] [--refresh] [--dry-run] [--test] [--skip pkgs] [-b builder] [-B repo] [-d]
Reads package list from config file and builds each package in order. Useful for maintaining package groups like PHP extensions where all packages share common settings.
Options:
<config>— config name (from~/.config/zoryn/batch/) or path to .conf file--basedir <dir>— base directory for packages (overrides config, required if not in config)--no-build— skip local build, only commit/tag/push/submit--create-task— create new task if not found (adds main package automatically)--refresh— refresh packages with local changes (create new tag, push, replace subtask)--dry-run— show what would be done without making changes--test— local-only test build mode: build packages locally without gitery/gyle interaction--skip <pkgs>— skip packages (comma-separated names)-b <name>— select builder for local builds-B <repo>— target repository (default: sisyphus). Multiple repos can be specified as comma-separated list
Examples:
zoryn task batch php-8.4 # build from ~/.config/.../batch/php-8.4.conf
zoryn task batch ~/configs/mypackages.conf # build from explicit path
zoryn task batch php-8.4 --basedir ~/packages # override basedir
zoryn task batch php-8.4 --no-build # skip local builds
zoryn task batch php-8.4 --create-task # create task if not found
zoryn task batch php-8.4 --refresh # refresh packages with local changes
zoryn task batch php-8.4 --dry-run # preview without changes
zoryn task batch php-8.4 --test # test build locally, no submit
zoryn task batch php-8.4 --test -b arm-server # test on specific builder
zoryn task batch php-8.4 --skip php-xdebug # skip specific packages
zoryn task batch php-8.4 -B p11 # build to p11
zoryn task batch php-8.4 -B sisyphus,p11,p10 # build for 3 branches with dependencies
zoryn task rebuild
Rebuild packages that depend on a package in existing task:
zoryn task rebuild <task_id|package> [-b repo] [--from-log] [--deps-by-pkg <pkg>] [--dptype=TYPE] [--depth=N] [--up <basedir>] [--all-subtasks <basedir>] [--skip LIST] [--skip-gyle-done] [-f|--force] [builder options] [-d]
Queries RDB API for packages that have binary dependencies on the specified package, then rebuilds them locally using hasher and adds successful rebuilds to the task.
Options:
-b <repo>— target repository (default: sisyphus)--from-log— parse affected packages from FAILED task log instead of RDB API-f, --force— force rebuild all packages, ignore existing error logs--deps-by-pkg <pkg>— query dependencies by package name instead of task ID--up <basedir>— update packages from upstream instead of rebuilding (see below)--dptype=TYPE— dependency type for RDB query:source(default),binary, orboth--depth=N— dependency depth for RDB query (1-4, default: 1)--skip LIST— skip subtasks by number or package name (comma-separated, e.g.,--skip 340,440,vtkaddon)--skip-gyle-done— skip subtasks already built on gyle for the target architecture (only with--all-subtasks)
Builder options (same as zoryn build):
--builder=NAME— use specific builder by name (comma-separated for multiple)-a, --arch=ARCH— select builder by architecture (comma-separated for multiple)-B, --build-branch=BRANCH— select builder by branch (comma-separated for multiple, note:-bis reserved for target repo)--all-builders— build on all configured builders-p, --parallel— run builds in parallel when using multiple builders-s, --sequential— run builds sequentially (overridesparallel = onin config)-w, --wait— wait for busy builder to become free--skip-busy— skip busy builders
The --from-log option searches all available logs (iterations and tries) and finds the last one containing the "ACLs of affected packages" section. This is useful for FAILED tasks where the log shows exactly which packages need rebuilding. For old/deleted tasks, it displays the affected packages list without attempting rebuild.
Update mode (--up): Instead of rebuilding packages from repository, this mode updates each package from upstream. For each dependent package:
- Clone package to
<basedir>/<package>if not exists (usingzoryn clone) - Fetch and checkout
gears/sisyphusbranch - Run
zoryn upto update from upstream - If already up-to-date: add as rebuild subtask
- If updated: build locally and add as regular subtask
- On any error: stop immediately and return control to maintainer
Example:
zoryn task rebuild 404809 --up ~/packages
zoryn task copy
Copy task to another repository:
zoryn task copy -b <repo> <task_id> [-n|--no-run] [-d]
Copies all subtasks from an existing task to a new task in another repository. If the source task is not yet completed, the new task will depend on it.
Options:
-b <repo>— target repository (required)-n, --no-run— create task but don't run it<task_id>— source task ID to copy
Examples:
zoryn task copy -b p11 404765 # copy sisyphus task to p11
zoryn task copy -b p11 -n 404765 # create without running
zoryn task test-rebuild
Experimental: This command is under active development and may change.
Test rebuild dependent packages before submitting a task:
zoryn task test-rebuild <task_id> [--arch <arch>] [--all-builders] [--builder <name>]
[--dptype=TYPE] [--depth=N] [--continue] [--continue-no-refresh] [--top] [-d]
Downloads RPMs from a task, identifies dependent packages via RDB, and test-rebuilds each one locally. This helps verify that packages build correctly with new dependencies before committing to a task.
Options:
<task_id>— task ID to test--arch <arch>— architectures to test (comma-separated, e.g.,x86_64,aarch64)--all-builders— use all matching builders for parallel execution--builder <name>— specific builder(s) to use--dptype=TYPE— dependency type for RDB query:source(default),binary, orboth--depth=N— dependency depth for RDB query (1-4, default: 1)--continue— continue from previous run, refreshing package list from RDB--continue-no-refresh— continue from previous run without refreshing--top— interactive TUI mode with progress display-d, --debug— enable debug output
Features:
- Multi-architecture support with parallel execution on multiple builders
- Automatic RPM download from task by architecture
- Dependent package detection via RDB
- Incremental rebuild with
--continue/--continue-no-refresh - Statistics saved to
rebuild-stats.json - Host load monitoring to avoid overloading build machines
- TUI mode with
--topfor interactive progress display
Examples:
zoryn task test-rebuild 404809 # basic test on local builder
zoryn task test-rebuild 404809 --all-builders --arch=x86_64 # test on all x86_64 builders
zoryn task test-rebuild 404809 --continue # continue interrupted build
zoryn task test-rebuild 404809 --all-builders --top # interactive TUI mode
zoryn check
Check for updates.
zoryn check version
Check if new upstream version is available:
zoryn check version [-p|--package <name>] [-b <repo>]
Options:
-p, --package <name>— package name (default: from current directory)-b <repo>— branch to check against (default: sisyphus)
zoryn check upstream
Analyze upstream and determine update method:
zoryn check upstream [-p|--package <name>] [-b <repo>]
Returns information about upstream source, current version, and recommended update workflow (git-merge vs tarball).
zoryn check spec
Validate RPM spec file before submit:
zoryn check spec [--no-network] [SPECFILE] [-B BRANCH]
Checks:
- Required fields (Name, Version, Release, Summary, License, Group)
- Deprecated
Packagertag - Duplicate versions in changelog
- URL and VCS reachability (unless
--no-network) - Changelog vulnerability identifiers (CVE/BDU/OVE/MFSA) formatting for girar parser
- Changelog bug closure syntax — detects invalid formats not recognized by girar
(e.g.
(fix #N)instead of(Closes: #N)), out-of-range bug numbers, non-existent bugs, and already-closed bugs (via Bugzilla REST API, requires network)
Options:
--no-network— skip URL/VCS reachability checks and RDB queriesSPECFILE— path to spec file (default: auto-detect in gear repository)-B,--branch BRANCH— target branch for RDB version check (default: sisyphus)
Errors block zoryn submit, warnings are displayed but don't block. Use --skip-check on submit to bypass.
zoryn check packages
Run package quality checks (sisyphus_check, etc.) on RPM packages:
zoryn check packages [PATH...] [-b name] [--skip-check=LIST] [--tool=NAME]
Checks RPM packages for policy violations. By default, runs sisyphus_check --no-check=gpg on the host. If no paths are specified, checks packages in current builder's hasher repository (local) or downloaded results directory (remote).
Also runs automatically after every successful zoryn build and zoryn up. Use --skip-check=all to disable.
Options:
PATH...— RPM files or directories to check (default: builder's hasher repo)-b, --builder <name>— builder for template variable expansion (default: auto-detected)--skip-check=LIST— skip specified tools (comma-separated, orall)--tool=NAME— run only specified tool(s) (comma-separated)
Configuration in ~/.zoryn:
[check.tools.sisyphus_check]
command = "sisyphus_check --no-check=gpg {packages_dir}"
fatal = true
order = 10
zoryn tag
Tag operations.
zoryn tag find
Find tags for version and newer versions:
zoryn tag find <version> [-l|--latest]
Options:
-l, --latest— show only latest matching tag
Uses version mapping from .gear/version-up if present.
zoryn gen
Generate files.
zoryn gen opam2spec
Generate RPM spec from opam file:
zoryn gen opam2spec [options] <file.opam|package-name>
Options:
-o, --output <file>— output spec file (default: stdout)-p, --packager <name>— packager name for changelog--prefix <prefix>— package name prefix (default: ocaml-)--no-check— disable %check section--no-rules— disable .gear/rules generation--no-rdb-check— don't check RDB for existing packages--tag-prefix <prefix>— upstream tag prefix (default: v)-V <version>— override version--clone— clone repository and generate files--build— build after generation--verbose— verbose output
Examples:
zoryn gen opam2spec mypackage.opam # from local file
zoryn gen opam2spec dune -o ocaml-dune.spec # from opam repository
zoryn gen opam2spec ppx_deriving --clone # clone and generate
zoryn gen watch
Generate watch file from Debian, Gentoo or Arch Linux:
zoryn gen watch [options] [package]
Without a package name, uses the current directory's package name from spec file.
The command queries multiple sources (Debian, Gentoo, Arch) via Repology API and generates a Debian-style watch file. When multiple sources are found, a comparison table shows versions and URL patterns from each source.
Options:
--debian-pkg <name>— specify Debian package name explicitly (when ALT and Debian names differ, e.g.,--debian-pkg fox1.6for libfox)--gentoo-pkg <name>— specify Gentoo package name explicitly--arch-pkg <name>— specify Arch package name explicitly--no-compare— skip comparison table, use first found source-f, --force— overwrite existing watch file-p, --print— print watch file without saving
Source priority: Debian > Gentoo > Arch. When patterns match across sources, the source with newer version is preferred.
Examples:
zoryn gen watch # generate for current package
zoryn gen watch mac # generate for mac package
zoryn gen watch --debian-pkg fox1.6 # use explicit Debian name
zoryn gen watch --gentoo-pkg mac # use explicit Gentoo name
zoryn gen watch --no-compare # skip comparison, use first found
zoryn gen watch -p # preview without saving
zoryn gen environment
Initialize ALT Linux development environment configuration files:
zoryn gen environment [options]
Creates the following configuration files:
~/.zoryn— zoryn config with build, clone, sources sections~/.ssh/config— SSH aliases for gitery and gyle~/.hasher/config— hasher workdir and packager~/.rpmmacros— %packager macro~/.gitconfig— git user.name and user.email (if not set)
Also generates SSH key (ed25519) and GPG key (RSA 4096-bit) if they don't exist.
Options
| Option | Description |
|---|---|
--name NAME |
Your name in English (required for non-interactive mode) |
--email EMAIL |
Your email for changelog (required for non-interactive mode) |
--login LOGIN |
Your login for gitery/gyle (optional) |
--skip-keys |
Skip SSH and GPG key generation |
--update-config |
Update existing ~/.zoryn with missing default settings |
The --update-config option adds missing sections and keys to an existing config file
without overwriting existing values or removing comments. Useful after upgrading zoryn
to get new configuration options.
Examples
zoryn gen environment # interactive mode
zoryn gen environment --name 'Ivan Ivanov' --email ivan@altlinux.org --login ivan # non-interactive
zoryn gen environment --name 'Ivan Ivanov' --email ivan@example.org # without gitery/gyle
zoryn gen environment --skip-keys # skip key generation
zoryn gen environment --update-config # update existing config
zoryn gen version-up
Generate .gear/version-up configuration file based on the current package version:
zoryn gen version-up [--tag TAG] [--to-version VERSION] [--filter VERSION] [--force]
Finds the git tag matching the current spec version and generates a pattern/template
for version conversion. This config helps zoryn up filter tags correctly and handle
cases where tag format differs from version format (e.g., underscores vs dots).
Options:
--tag TAG— git tag corresponding to current version (auto-detected if omitted)--to-version VERSION— version that the tag converts to. Use with--tagwhen tag format differs--filter VERSION— version prefix to filter tags (e.g.,--filter 4.5generatesfilter = "major=4, minor=5"). If.gear/version-upalready exists, adds filter to existing config--force— overwrite existing.gear/version-upfile
Examples
zoryn gen version-up # auto-detect tag and generate
zoryn gen version-up --tag v1.2.3 # specify tag explicitly
zoryn gen version-up --tag osec-12_11_22.11 --to-version 12.11.22.11 # different tag format
zoryn gen version-up --force # overwrite existing config
zoryn gen version-up --filter 4.5 # add filter to existing config
zoryn gen version-up --tag v4.5.5 --to-version 4.5.5 --filter 4.5 # generate with filter
zoryn clone
Clone a package from sisyphus repository.
zoryn clone <package>
Automatically detects whether the package was built as gear or SRPM and clones from the appropriate repository:
- Gear packages:
https://git.altlinux.org/gears/<first-letter>/<package>.git - SRPM packages:
https://git.altlinux.org/srpms/<first-letter>/<package>.git
Sets gears as the remote name. Use --init-gitery to also create the repository on gitery and add a remote for pushing.
Configuration
The git base URL can be configured in ~/.zoryn:
[clone]
url = "git+ssh://gitus.alt"
Default: https://git.altlinux.org (public, read-only)
Examples
zoryn clone ocaml # Clone ocaml package
zoryn clone vcdimager # Clone vcdimager (SRPM package)
Batch configs
Batch configs define groups of related packages for building together.
Location
Config files are stored in ~/.config/zoryn/batch/ with .conf extension. You can reference them by name (without extension) or full path.
Format
TOML format with [batch] table for global settings and package tables.
[batch]
name = "PHP 8.4 extensions"
basedir = "~/packages/php8.4"
specsubst = "phpver=8.4"
main = "php"
main_branch = "8.4"
[php]
# Main package, version/tag derived from here
[php-memcached]
# Uses default settings
[pecl-imagick]
path = "~/packages/imagick"
# Custom path, not basedir/pecl-imagick
[php-unit]
mode = "rebuild"
# Rebuild instead of build from source
[php-xdebug]
skip = true
# Temporarily disabled
[php-pgsql]
exclude = ["p10", "c10f2"]
# Don't build for p10 and c10f2
[php-redis]
only = ["sisyphus", "p11"]
# Build only for sisyphus and p11
[php-sodium]
specsubst = "none"
# Disable specsubst for this package
[batch] section options
| Option | Description |
|---|---|
name |
Display name for the batch (default: config filename) |
basedir |
Base directory for packages, supports ~ expansion |
specsubst |
Default specsubst for gear-create-tag (e.g., phpver=8.4) |
main |
Main package name for version/tag derivation |
main_branch |
Git branch to read main package spec from |
tag_format |
Tag name template (default: {main_name}-{main_version}-{main_release}) |
tag_message |
Tag message template (default: same as tag_format) |
Tag format placeholders:
{main_name}— main package name (e.g.,php8.4){main_version}— main package version (e.g.,8.4.17){main_release}— main package release (e.g.,alt1){name}— current package name (e.g.,php8.4-apcu)
Package section options
| Option | Description |
|---|---|
path |
Custom path (overrides basedir/name), supports ~ |
mode |
build (default) or rebuild |
exclude |
TOML array or comma-separated string of repos where package is excluded |
only |
TOML array or comma-separated string of repos where package is included (exclusive) |
skip |
true to temporarily disable |
specsubst |
Override specsubst, or none to disable |
Fuzzing
QuickCheck mode (random inputs, runs in seconds):
dune runtest fuzz/
AFL mode (coverage-guided mutation, requires afl-fuzz):
opam install afl-persistent
OCAMLPARAM="_,afl-instrument=1" dune build fuzz/fuzz_watch.exe
afl-fuzz -m none -i fuzz/corpus/watch -o _fuzz_out/watch -- ./_build/default/fuzz/fuzz_watch.exe @@
Note: -m none is required for OCaml 5.x.
License
GPL-3.0