Skip to content
zoryn/ maintainer-assistant

zoryn up

Automatic package update to a new upstream version. A state-aware pipeline that can be paused, resumed and rolled back.

Synopsis

zoryn up [-t|--tarball] [--tag TAG] [--allow-unrelated-histories] [-f|--force]
         [--reset-to-gear]
         [-r|--rebuild] [--top] [--switch-to-upstream-git]
         [--sandbox=RUNNER] [--no-sandbox]
         [-b|--builder PATTERN] [-a|--arch ARCH] [-B|--branch BRANCH]
         [-p|--parallel] [-s|--sequential] [--fail-if-busy] [--skip-busy]
         [--skip-check[=LIST]] [--batch-pkgs=PKGS] [-d] [-v]

Options

  • -t, --tarball — force tarball mode (download and update instead of git merge).
  • --tag TAG — use a 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.
  • --reset-to-gear — before updating, hard-reset the package to its published state in the ALT repository. Discards local divergence, uncommitted changes, ahead/behind drift, and untracked files (ignored build artifacts are kept), then repairs the gitery remote and resets the branch planned for the update — the current branch if it is a known ALT branch (sisyphus, p11, …), otherwise sisyphus — regardless of which branch is currently checked out. Skipped with a warning for packages not yet in RDB. Only applies on a normal run (the detect stage); ignored with --continue/--abort and with --stage/--from past detect. Use it to start an update from a clean published baseline.
  • -b, --builder PATTERN — select builders by name or pattern (see Builder Patterns).
  • -a, --arch ARCH — select builder by target architecture (comma-separated for multiple).
  • -B, --branch BRANCH — select builder by target branch (comma-separated for multiple).
  • -p, --parallel — run builds in parallel when using multiple builders.
  • -s, --sequential — run builds sequentially (overrides parallel = on in config).
  • --fail-if-busy — exit immediately if builder is busy (default: wait).
  • --skip-busy — skip busy builders without error.
  • --skip-check[=LIST] — skip specified checks (comma-separated). Values: rpmbuild (skip %check), tool names like sisyphus_check, all. Without a value — skips everything.
  • --batch-pkgs=PKGS — build only specified batch values (comma-separated) instead of all values from [batch].
  • -r, --rebuild — use hsh-rebuild instead of hsh (rebuild in existing hasher without recreating chroot).
  • --top — interactive TUI for monitoring builds (htop-like).
  • --switch-to-upstream-git — migrate tarball-based repo to upstream-git scheme (see below).
  • --sandbox=RUNNER — sandbox backend for hooks: hybrid (default), bwrap, or direct.
  • --no-sandbox — disable sandbox for hooks.
  • --no-python-auto-deps — disable automatic pyproject_deps.json update and rebuild retry when Python dependencies change.
  • -v, --verbose — show build output on screen (in addition to log file).

Pipeline control

If a stage fails, you can resume, abort, or isolate stages:

FlagDescription
--continueResume from the last failed stage
--abortRollback changes to pre-update state
--restartDiscard saved state, start fresh
--stage=STAGERun a single stage in isolation
--from=STAGERun from a specific stage to the end

Available stages: detect, fetch, find-version, merge, merge-hooks, spec, gear-tags, up-hooks, build, batch-build.

Pipeline state is stored under the active git directory — .git/zoryn-up-state.json in a normal clone, or .git/worktrees/<name>/zoryn-up-state.json inside a git worktree — so each worktree resumes its own pipeline independently.

Supported repository schemes

zoryn auto-detects and supports four 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 the working tree. Patches are applied as commits on top of upstream. When updating, git merge integrates the 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. Used with zoryn up --tarball or auto-detected from the watch file.

.gear/rules: tar: @name@
             copy?: *.patch

The tarball is fetched from the upstream URL in the 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 the upstream tag. If there are no common source files (only .spec, .patch, .gear/), the pristine-tarball scheme is detected and -s ours 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. 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 the root. Example: 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 analyses commit history for each subdirectory. If recent commits are predominantly of the "Merge commit 'HASH'" pattern (characteristic of git subtree pull --squash), the subtree scheme is detected.

Workflow

  1. Finds the spec file and extracts the current version.
  2. Syncs the local clone with the public ALT mirror (git.altlinux.org/gears/<x>/<pkg>.git or srpms/) using the current local branch as the public ref name. Only runs when the local branch is a known ALT branch (sisyphus, p11, p10, c10f2, ...); topic branches (master, wip-*, feature-*) are skipped silently with an explanatory line. Fast-forwards when local is behind; performs an automatic merge when histories diverged. Also skipped when the package is not yet in RDB, when the working tree is dirty, when HEAD is detached, or when the public fetch fails. Aborts the pipeline on hard sync failures (unresolved merge conflicts, or a refused fast-forward) so the maintainer fixes them before the spec is touched.
  3. Checks if the URL: tag points to pypi.org/project/<name>/ — if so, uses PyPI as the version source (filters yanked/pre-release per PEP 440, creates alias tags when PEP 440 normalisation differs from the git tag). --tag bypasses PyPI detection.
  4. Reads the repository URL from the VCS: tag in the spec file.
  5. Adds the upstream remote and fetches tags. The URL may live in .gear/upstream/remotes, the spec VCS: tag, or the spec URL: tag; the first candidate that is a known public forge (GitHub/GitLab/codeberg/sourcehut) or that git ls-remote can reach is used — so a self-hosted Gitea/Forgejo/cgit also works. ALT-internal hosts are excluded so a package's own gear/srpm repo is never mistaken for upstream.
  6. Applies version mapping from .gear/version-up (if present).
  7. Finds newer versions and selects the latest.
  8. Detects merge strategy (standard or -s ours).
  9. Merges the upstream tag (or downloads a tarball with --tarball).
  10. Runs hooks from .gear/merge-up.d/.
  11. Updates version in the spec file, resets release to alt1.
  12. Scans the upstream changelog for CVEs (if configured).
  13. Adds a changelog entry.
  14. Runs hooks from .gear/up.d/.
  15. Updates gear tags.

Migrating to upstream-git scheme

--switch-to-upstream-git is a one-way migration that converts a tarball-based package (schemes #2 or #3) into the standard git-merge scheme (#1). After migration, the working tree contains upstream source code plus .gear/, and every subsequent zoryn up uses git merge instead of downloading a tarball.

Quick start

zoryn up --switch-to-upstream-git              # auto-detect upstream tag from current Version:
zoryn up --switch-to-upstream-git --tag v2007f # use the given tag explicitly

The repository must be clean (no uncommitted changes) and the spec file must declare the upstream git URL via a VCS: tag — for example VCS: https://github.com/owner/repo. If VCS: is missing the command refuses to run.

What happens, step by step

  1. Validate. Refuses to run on a dirty working tree, on a non-gear directory, or on a repository already on the upstream-git scheme (detected by tar: @version@:. already being present in .gear/rules).
  2. Detect upstream URL. Reads the VCS: tag from the spec file and normalises it (drops trailing .git, strips fragments, etc.).
  3. Parse .gear/rules. Looks at the existing copy: / copy?: / patch: directives to discover whether altlinux files live in a common subdirectory or at the repo root.
  4. Move altlinux files into .gear/.
    • The spec file is moved to .gear/<name>.spec.
    • A legacy .gear-rules is renamed to .gear/rules.
    • Patches and other copy: entries that are not yet under .gear/ are moved there (glob patterns are expanded first).
    • If the existing layout already keeps altlinux files under a common subdirectory, that subdirectory is preserved — only patch: entries living outside it are relocated.
  5. Commit the moves. A single commit switch: move altlinux files to .gear/ is created. If files were already in .gear/, this step is silently skipped.
  6. Add the upstream remote. Idempotent — if upstream already points at the right URL the step is a no-op; if it points at a different URL the command stops and tells you to remove it manually.
  7. Fetch upstream branches and tags.
  8. Resolve the upstream tag.
    • With --tag TAG the tag is checked against the fetched tag list and used as-is.
    • Without --tag, the current Version: from the spec is matched against fetched tags using the same heuristics as zoryn up (handles v prefix, name-version, release_X_Y_Z, etc.).
    • On no match the command prints the first 15 available tags and exits, so you can rerun with --tag.
  9. Rewrite .gear/rules. The legacy tar: line is replaced with tar: <resolved-tag>:. (preserving the subdirectory layout when one was detected); obsolete copy: / patch: entries that are now redundant are dropped.
  10. Merge upstream history. Performs git merge --allow-unrelated-histories -s ours <tag> and then restores upstream files into the working tree while keeping .gear/ (and the preserved subdirectory, if any) intact. If the merge fails, .gear/rules is rolled back to its pre-merge state so you can fix the cause and rerun the same command.
  11. Pin the scheme. Writes scheme = "git-merge" to the [merge] section of .gear/version-up so that future zoryn up runs use the git-merge code path even before tags catch up to the new layout.

What happens after the migration succeeds

If the resolved upstream tag is newer than the current spec Version:, zoryn up continues with the regular post-merge tail:

  • Version: in the spec is bumped to the new version, Release: is reset to alt1.
  • A changelog entry for the version bump is added.
  • gear-update-tag -a -c updates the gear tags.
  • The package is built on the configured builder(s); on success a desktop notification is sent.

If the resolved tag matches the current version, the spec is left as-is and only gear tags + a rebuild are run.

Resulting repository layout

After the command finishes you have:

  • Working tree filled with upstream source code (from the merged tag).
  • .gear/ directory containing the spec file, rules, patches, and any preserved copy entries.
  • .gear/rules rewritten to tar: <tag>:. (or tar: <tag>:. <subdir>/ for subdir layouts).
  • Two new commits: switch: move altlinux files to .gear/ and a merge commit attaching upstream history.
  • upstream remote pointing at the URL from VCS:.
  • .gear/version-up with [merge] scheme = "git-merge".

The package is ready for zoryn submit once you have reviewed git log --oneline -5 and verified the build artefacts.

Recovering from a failed migration

The command is idempotent with respect to file moves and the upstream remote — if it fails at the merge step, just rerun:

zoryn up --switch-to-upstream-git --tag <TAG>

The earlier file moves and the remote setup will be detected and skipped; only the merge is reattempted. If you want to back out completely, use git reset --hard to the commit before switch: move altlinux files to .gear/ and git remote remove upstream.

See also