Skip to content

sow build

Converge Desired Membership and renderer configuration into a complete Built Generation.

sow build is the explicit Desired-to-Built convergence command. It acquires the Repository write lock, recovers any decidable unfinished Operation, renders and verifies a complete Generation, then switches protocol pointers last.

Synopsis

sow build [-j|--jobs N] [-C|--workdir DIR] [-r|--repo NAME] [-d|--dist NAME]... [-T|--timeout DUR | -N|--no-wait] [--json]
Flag Meaning Default
-j, --jobs N Parallel workers; must be at least 1 logical CPU count
-C, --workdir DIR Workspace discovery start directory current directory
-r, --repo NAME Select a Repository selection rules
-d, --dist NAME Build named Dists; repeatable all affected Dists
-T, --timeout DUR Maximum lock wait; 0 waits indefinitely 0
-N, --no-wait Fail immediately when the lock is held false
--json Wrap the result in the sow.cli/v1 envelope false

Without -d, SOW converges every affected Dist in the selected Repository. With -d, only those Dists converge; unselected changes remain dirty.

Result

Without --json, build prints one human-readable summary:

sow build -r demo -d el9
built repository=demo operation=2769214987359113555 dists=el9 revision=4 generation=00000000000000000005 dirty=false

Use --json for the command-specific object inside the standard envelope.

No-op builds

When membership, relevant policy, renderer settings, and signing configuration already match the Built Generation, build is an idempotent no-op and does not increment the Generation:

sow build -r demo -d el9
build repository=demo dists=el9 already current (noop) revision=4 generation=00000000000000000005 dirty=false

Policy convergence

build re-evaluates the current exclude and limit policy. Tightening policy may remove Desired Membership. Loosening policy does not reconstruct historical members from leftover pool bytes; run sow add again for packages you want to restore.

Commit and recovery

SOW stages new metadata on the same filesystem, verifies it, then switches mutable protocol pointers last. RPM checksum-named metadata and APT by-hash keep old and new readers self-consistent.

Pending package promotion is a bounded, single-writer group commit. Each batch contains at most 512 objects or 1 GiB: SOW creates Pool links, persists every distinct target parent, then removes pending names and persists the shared pending directory. An interruption can leave a pending-only, exact dual-link, or Pool-only state, all recoverable from the journal; it cannot durably lose both names.

One Operation may cover several Dists. Each Dist always exposes a complete view; when build returns, every included Dist belongs to the same Built Generation.

Before starting new work, build attempts forward recovery or safe rollback of a non-terminal Operation. If journal, database, and filesystem evidence contradict each other, the Repository enters error and build refuses to guess. There is no force-repair flag.

Progress events

Long builds append structured build_progress records to the Operation log. Each event contains phase, completed, total, and jobs. Current phases are:

  • rendering;
  • promoting_payload;
  • publishing_dists;
  • normalizing_public_tree;
  • finalizing.

These events do not advance the Operation state and deliberately do not checkpoint SQLite after every update. They are audit/observability records, not recovery decisions. Inspect them with sow log OPERATION.

Metadata signing

Managed metadata signing is configured only in sow.yml; there is no command-line key override. Changing a configured key reference or fingerprint makes affected Dists dirty, and the next build re-signs their metadata.

  • RPM: always writes repodata/repomd.xml; writes repomd.xml.asc when configured.
  • DEB: always writes Release; writes InRelease and Release.gpg when configured.

Exit codes

Code Trigger
0 Converged successfully or nothing to do
1 Renderer, signing, or filesystem failure
2 Usage error, Workspace not found, or implicit Repository selection is ambiguous
4 Repository write lock unavailable
5 Recovery cannot complete safely, or Repository is in error
6 Explicit scope is not configured, or current configuration rejects existing state

See also