Repository navigation
v2.0.4
⚠️ Behaviour change: merged images now need --force to remove
updex features disable --now and updex catalog remove now refuse to remove an image that systemd-sysext has merged, unless you pass --force (#445, fixes #444).
This was always the documented behaviour, but updex did not detect merged images on most hosts. It only looked at a legacy CurrentSymlink (which updex itself removes on install) and /run/extensions (a search directory, not merged state). On those hosts the commands unmerged, deleted the image, and refreshed at once.
updex now reads the merged state that systemd-sysext records in each hierarchy (/usr/.systemd-sysext/, /opt/.systemd-sysext/):
- systemd 258 and later:
origingives the merged file, so the refusal names the version. - Older systemd:
extensionsgives the name only, so the refusal showsversion unknown. - If that metadata cannot be read, the guard fails closed: the component shows
merge state unknownand the command needs--force. - Nothing changes when the image is not merged.
Migration
- Scripts or automation that run
features disable --noworcatalog removeon a host with the image merged must add--force. Without it, the command now exits with an error and changes nothing. - With
--force, the image is removed; the merged copy stays active until the next reboot orsystemd-sysext refresh, as documented. - Plain
features disable(without--now) is unchanged. - SDK callers:
GetActiveVersion/GetActiveVersionAtuse the new signal; the newsysext.GetActiveVersionWith(t, sysext.ActiveStatePaths{...})takes explicit paths, andRuntimePaths.SysextHierarchies(default/usr,/opt) sets them per client.GetActiveVersionInkeeps its old behaviour. See ADR-0015.
SDK: legacy sysext runners are refused for real installs
A ClientConfig.SysextRunner that implements only the original 4-method sysext.SysextRunner (no LinkToSysextAt) now gets updex.ErrLegacySysextRunner (test with errors.Is) from any non-dry-run operation that links an image — CatalogAdd, EnableFeature{Now: true}, and updates — before anything is changed (#405). Previously it silently linked into the package-global sysext.SysextDir, ignoring RuntimePaths.SysextLinkDir. Dry runs still work with any runner. The interface is unchanged; add LinkToSysextAt to make a custom runner usable. The CLI is not affected.
Dependency updates
github.com/frostyard/stdv0.2.2 → v0.3.0 (#442): reporters stop writing after the first write error instead of retrying each event; nil writers becomeio.Discard. Output on a healthy writer is unchanged.github.com/ProtonMail/go-crypto1.4.1 → 1.5.2 (#430)github.com/klauspost/compress1.19.2 → 1.20.1 (#429)github.com/ulikunitz/xz0.5.16 → 0.5.17 (#422)
Build and CI (no change to the shipped binary)
make cinow runs the docs-integrity gate (#403).- Release-config check warns instead of failing on Dependabot PRs without
GORELEASER_KEY; push and merge-queue runs still require it (#443). - Node 20 (EOL) → 24 LTS for tooling (#408).
- Actions:
codecov/codecov-action7.1.1 (#424),actions/setup-node7.1.0 (#437),goreleaser/goreleaser-action7.3.0 (#436),jdx/mise-action5.1.2 (#435).
Full Changelog: v2.0.3...v2.0.4