Repository navigation
SOW 0.5.0 makes SOW practical for existing flat YUM repositories and closes the integrity,
recovery, and publication findings of a full pre-release review. The main addition is
sow create --metadata-timestamp SECONDS: a publisher can keep a valid, nondecreasing
publication time when replacing another metadata generator, including repositories served
to EL7 YUM clients.
The sow/v3 configuration and the public pool/ + dists/ layout do not change.
Full release notes: English · 中文
⚠️ Upgrading a 0.3 or 0.4 Managed workspace requires an explicit migration
Stop all Workspace writers and back up the whole Workspace with a tool that preserves hard
links: DEB by-hash entries are hard links, and macOS cp -a does not keep them (use GNU
cp -a, rsync -aH, or tar). Install 0.5.0, then migrate each Repository before any
ordinary read or write:
sow repo migrate REPOSITORY -C /srv/sow # reports schema=12->13
sow build -r REPOSITORY -C /srv/sow
sow check -r REPOSITORY -C /srv/sowSchema v13 indexes candidate pool paths, so add no longer scans unrelated publication
history. The updated RPM authentication and APT metadata contracts require one rebuild of
affected Dists; afterwards, unchanged RPMs reuse matching Built evidence. Until a Repository
is migrated, its write commands exit 5 and name the command to run. The transition is
one-way: do not reopen a migrated database with an older binary.
Highlights
Publication time for existing YUM repositories. create --metadata-timestamp writes an
explicit time to the three RPM repomd.xml data records. The default stays 0, so output
remains reproducible; package bytes, compressed XML, and DEB indexes are unaffected. SOW does
not read the wall clock for you, and the publisher still signs the new repomd.xml. The
YUM migration guide covers the
surrounding maintenance flow.
Safer mutations. Incompatible signing policies and colliding pool paths are rejected
before Desired state commits. Pool paths are compared case-insensitively, even for identical
bytes, and case-insensitive workspaces and filesystem targets also reject source directories
that differ only by case. Historical Dist-removal cleanup no longer deletes a package that was
re-added to another Dist.
Publication integrity. Payload URLs are reserved against local and historical publication
identities, and no backend ever overwrites an immutable payload. Local gc ignores inventory
entries that exist only remotely, such as payloads kept by report-only R2 maintenance. R2
target GC remains report-only; do not delete reported objects by hand, because the next
publish requires the remote prefix to match its recorded inventory exactly.
Recovery and interruption. Ctrl-C (SIGINT) and SIGTERM return 130 only for the
command's own interruption; a failed operation is recorded before its temporary package bytes
are removed, and the next write command finishes any cleanup that exceeded its budget.
Interrupted v0.4.0 operations, including adds that omitted a non-empty, fully excluded Dist,
now have bounded recovery paths.
Signing. New GPG metadata signatures use SHA-256 regardless of local preferences, and new
builds require a currently usable metadata key. Agent signing freezes GnuPG time, including
for a signature made within the current second, and pins the actual usable subkey. APT
verification accepts GnuPG's final-newline convention without relaxing content binding.
Toolchain and packaging
Building from source now requires Go 1.27.1; the dependency graph uses x/crypto v0.56.0
and the release workflows pin GoReleaser v2.18.2. Archives, RPMs, and DEBs now ship
THIRD_PARTY_NOTICES generated from all four release package graphs. Source govulncheck
on the release commit reports no reachable vulnerabilities; the required x/crypto module still
carries advisory GO-2026-5932 (no fixed version yet), whose affected package SOW does not
import, so scans of stripped binaries can still report the module.
The S3-compatible integration test now runs against a digest-pinned
pgsty/silo image, the MinIO-compatible object store
maintained by PGSTY, because the upstream minio/minio image is no longer available on
Docker Hub.
RPM format v6 signatures are not supported in 0.5.0; use RPM format v4 packages for
package-signing workflows.
Verification
The release commit passed the full Go suite, race tests, vet, staticcheck, dead-code
reachability, vulnerability and RPM-fork provenance checks, clean source delivery, archive and
package verification in CI, and repository-client and S3-compatible publication tests in
Integration.
The release set contains four Linux/macOS archives (amd64, arm64), two RPMs, two DEBs, and
SHA256SUMS. Every archive contains sow, README.md, CHANGELOG.md, LICENSE, and
THIRD_PARTY_NOTICES. Platform-specific install commands are on the
download page.
Changelog
4045dd30update project readme with more info2c3ecf39chore: consolidate documentation and QA layoutd4aabb72fix(create): support YUM metadata publication timestampsb2c71721build: require Go 1.27.1 and x/crypto v0.56.0267894e9build: ship third-party license notices and pin GoReleaser8df8e180fix: resolve v0.5.0 pre-release review findings9c299061fix(path): tolerate concurrent read-locked hardlinks during authentication (J5-r4-1, J5-pre-1)79f1f83cfix(state): reject case-variant spellings of known pool paths even for identical bytes (C2-r4-1)5a9514a0fix(gc): skip remote-only inventory roots without local objects (C2-r4-5)dc2d72bdfix(cli): map exit 130 only to the command's own cancellation (E16-r4-1)e8cd88bbfix(check): treat any terminal operation's stage tail as cleanup (A2-r4-1)c78eafb8fix(signing): wait until GnuPG can freeze the current-second signing time (C12-r4-1)103ffde0fix(recovery): finish v0.4.0 applied adds that omitted a non-empty excluded Dist (B2-r4-1)e89ee5abfix(schema): report an old schema as migration required and point to repo migrate (E4-r4-2)4a41e3b7perf(add): query pool path owners only for new coordinates (C2-r4-3)0aa4ffdbfix(add): reject source-directory case aliases on case-insensitive workspaces (B23-r4-1)6825dc37fix(publish): refuse case aliases before an attempt on case-insensitive filesystem targets (C2-r4-2); report cancellation instead of digest mismatch0cf672cefix(cli): strip exactly one optional 0x/0X signing key prefix (I6-r4-1)bae9e173fix(r2): reject non-regular credential files without blocking (C8)7d453f87fix(add): tell the user the next write finishes interrupted cleanup (A3-r4-1)75b91f67feat(migrate): report schema before and after an explicit migration (E4-r4-1)500039fefix(lock): classify a symlinked lock parent as integrity without a nil wrap (LOCK-pre)c65754a0fix: reject abort without an attempt, hint at case-alias exits, avoid duplicate cancellation text7fe0b88dchore(release): prepare v0.5.0c41aba47test(r2): replace the withdrawn MinIO fixture with pinned PGSTY Silo
Full Changelog: v0.4.0...v0.5.0