1
0
Fork 0
forked from rider/zoryn
No description
  • OCaml 98.6%
  • Standard ML 0.6%
  • Shell 0.4%
  • Perl 0.4%
Find a file
2026-02-12 11:10:43 +00:00
.forgejo/workflows feat(fuzz): add AFL fuzzer for aptconf and sources_list parsers 2026-02-08 18:24:57 +00:00
.gear feat: add sisyphus_check runtime dependency 2026-02-09 18:49:47 +00:00
bin fix(build, builder): update help text examples from gear-hsh to hsh 2026-02-12 11:10:43 +00:00
completions feat (zoryn): add fish completion for zoryn 2026-02-10 16:17:18 +03:00
docs/plans feat(check): move post-build checks to parent process, add to zoryn up 2026-02-09 18:49:25 +00:00
examples/builders.d feat(build): add smart download for built packages 2026-01-21 09:29:23 +00:00
fuzz feat(fuzz): add AFL fuzzer for aptconf and sources_list parsers 2026-02-08 18:24:57 +00:00
lib feat(builder): validate builder name to alphanumeric only 2026-02-11 17:12:50 +00:00
test fix(gen environment): add Port 222 to SSH config, fix username docs 2026-02-12 10:33:04 +00:00
.duneignore build: add .duneignore to skip large directories 2026-01-01 09:00:34 +00:00
.gitignore Ignore .worktreee 2026-01-21 10:58:52 +03:00
.ocamlformat Update ocamlformat - disable removing empty lines 2025-12-08 20:37:18 +03:00
AUTHORS docs: add Alexey Shabalin to AUTHORS 2026-02-10 14:01:08 +00:00
CHANGELOG.md fix(gen environment): add Port 222 to SSH config, fix username docs 2026-02-12 10:33:04 +00:00
CLAUDE.md docs: add copyright header rules to CLAUDE.md 2026-02-07 10:51:57 +00:00
dune security: fix shell injection vulnerabilities and add compile-time detection 2026-01-16 10:34:36 +00:00
dune-project release: version 0.16.0 2026-02-08 18:44:06 +00:00
dune-workspace build: add dune-workspace for worktree support 2026-01-22 07:43:35 +00:00
LICENSE license: change to GPL-2.0-or-later 2026-01-15 21:00:38 +00:00
README.md fix(gen environment): add Port 222 to SSH config, fix username docs 2026-02-12 10:33:04 +00:00
README.ru.md fix(gen environment): add Port 222 to SSH config, fix username docs 2026-02-12 10:33:04 +00:00
TODO.md docs: add rdb rebuild history feature to TODO 2026-02-11 14:13:48 +00:00
zoryn.opam release: version 0.16.0 2026-02-08 18:44:06 +00:00

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

  1. Installation
  2. Quick Start
  3. Configuration
  4. Commands
  5. 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" — if git is overridden, git.fetch uses the override
  • ~/ and $HOME in 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: use hsh, not gear-hsh — tarball is created separately with gear --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) for zoryn build, zoryn up, zoryn task rebuild when no --builder specified. 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 (on or off, default: off). Can be overridden with --parallel or --sequential flags.
  • 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 by download_rpms and upload_rpms commands.

Section [gitery]:

  • host — SSH alias for gitery, must match entry in ~/.ssh/config
  • remote — 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 for zoryn 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 for zoryn 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 --builder option)
  • typelocal or remote
  • arch — target architecture (x86_64, aarch64, i586, etc.)
  • branch — target branch (sisyphus, p11, etc.)
  • host — SSH host for remote builders
  • hasher_dir — hasher working directory (default: ~/hasher)
  • remote_dir — working directory on remote host
  • hasher_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 using rsync --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 build
  • shell — command for zoryn builder shell
  • install — command for zoryn builder install
  • check_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-json or json — OSV JSON format (used by curl, etc.)
    • markdown or md — standard markdown changelog
    • html or html-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 for gear-update command (e.g., --all to extract all directories from archive instead of one)

Section [add_changelog] configures changelog entry format (overrides global ~/.zoryn):

  • up_template — changelog entry template for zoryn up
    • Supports variables: {old_version}, {new_version}, {cves}
    • Example: up_template = "- {old_version} -> {new_version} {cves}"

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 bwrap
  • bwrap — bubblewrap with host system paths, lightweight namespace-based isolation
  • direct — 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 (overrides parallel = on in 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, or all to 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

  1. Finds spec file and extracts current version
  2. Reads repository URL from VCS tag in spec file
  3. Adds upstream remote and fetches tags
  4. Applies version mapping from .gear/version-up (if present)
  5. Finds newer versions and selects latest
  6. Detects merge strategy (standard or -s ours)
  7. Merges upstream tag (or downloads tarball with --tarball)
  8. Runs hooks from .gear/merge-up.d/
  9. Updates version in spec file, resets release to alt1
  10. Scans upstream changelog for CVEs (if configured)
  11. Adds changelog entry
  12. Runs hooks from .gear/up.d/
  13. 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 (overrides parallel = on in 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, or all to 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/N for next/prev)
  • TAB to switch between builders, c to cancel, r to restart
  • Requires ocaml-lambda-term-devel package

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 (--simple for names only, one per line)
  • status — check builder availability (free/busy)
  • config [NAME] — show full builder configuration including defaults
  • shell [--builder=NAME] — open shell in hasher
  • install [--builder=NAME] PKG... — install packages in hasher
  • add [options] — add a new builder configuration (interactive or non-interactive)
  • copy SRC... DST — copy files into or out of hasher chroot (use builder:path for 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 via sudo 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 (see zoryn 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: from hsh --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 name
  • php-sphinx.git — package name with .git suffix
  • php-sphinx.git=8.2.30-alt1 — package name with tag (for copy-paste from task ls output)

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, or both
  • --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: -b is 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 (overrides parallel = on in 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:

  1. Clone package to <basedir>/<package> if not exists (using zoryn clone)
  2. Fetch and checkout gears/sisyphus branch
  3. Run zoryn up to update from upstream
  4. If already up-to-date: add as rebuild subtask
  5. If updated: build locally and add as regular subtask
  6. 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, or both
  • --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 --top for 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 Packager tag
  • 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 queries
  • SPECFILE — 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, or all)
  • --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.6 for 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 --tag when tag format differs
  • --filter VERSION — version prefix to filter tags (e.g., --filter 4.5 generates filter = "major=4, minor=5"). If .gear/version-up already exists, adds filter to existing config
  • --force — overwrite existing .gear/version-up file

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