Rebuild packages when what they link against moves

A package that links Qt private API has to be rebuilt whenever qt6-base moves, because Qt_6_PRIVATE_API symbols are not covered by the soname and pacman upgrades Qt out from under the installed binary while the dependency stays unversioned. Nothing here noticed. Both version gates ask whether the package's own source moved, and for a VCS package pinned to a commit that answer stays no through every Qt release.

Unlocking the build gate would not have been enough on its own. A rebuild that reuses the published version string produces a package pacman never offers anyone, so the trigger has to edit git and bump pkgrel, which is why it sits beside sync-aur and sync-upstream rather than inside check-versions or the builder. Once pkgrel moves, both existing gates already do the right thing untouched.

Packages opt in with rebuild_on in .omarchy/package.json. bin/sync-rebuilds records what each was last bumped for in rebuilt_against and compares that to core, extra and multilib, ignoring testing and kde-unstable because those are not what the builder links against. A package with no record yet is only recorded, never bumped: what its published build linked against is not knowable from here, so the first run establishes the baseline. For an AUR-synced package the bump is written as the dotted Omarchy pkgrel suffix in the metadata as well, since the next sync replaces the PKGBUILD wholesale and would otherwise drop it.

🤖 Generated by Opus 5 in Claude Code.
This commit is contained in:
Omabot committed 2026-08-20 03:44:56 -07:00
1 parent dd01fcc560
commit 2fe4803bbe
4 files changed
+513 -1

No files matched your search

+45 -1
View File
@@ -10,9 +10,11 @@
# { "source": "aur", "release_ring": "fast" }
# { "source": "aur", "skip_build": true }
# { "source": "aur", "pkgrel": { "suffix": 1, "offset": 1 } }
# { "source": "aur", "rebuild_on": ["qt6-base"] }
# { "source": "local" }
#
# bin/sync-aur also writes upstream_commit for AUR-backed packages.
# bin/sync-aur also writes upstream_commit for AUR-backed packages, and
# bin/sync-rebuilds writes rebuilt_against for packages declaring rebuild_on.
if [[ -z "${PKGBUILDS_DIR:-}" ]]; then
if [[ -n "${BUILD_ROOT:-}" ]]; then
@@ -148,6 +150,33 @@ packages_for_upstream_sync() {
done
}
# Packages that must be rebuilt when a dependency they link against changes,
# even though nothing in their own source moved. `rebuild_on` names those
# dependencies; `rebuilt_against` records the versions the checked-in pkgrel was
# last bumped for.
package_rebuild_triggers() {
local pkgdir="$1"
local metadata
metadata=$(metadata_file_for_dir "$pkgdir")
[[ -f "$metadata" ]] || return 0
jq -r '(.rebuild_on // [])[]' "$metadata"
}
package_has_rebuild_triggers() {
local pkgdir="$1"
[[ -n "$(package_rebuild_triggers "$pkgdir")" ]]
}
packages_for_rebuild_sync() {
package_dirs | while IFS= read -r pkgdir; do
if package_has_rebuild_triggers "$pkgdir"; then
basename "$pkgdir"
fi
done
}
packages_for_mirror() {
local mirror="$1"
@@ -299,4 +328,19 @@ validate_package_metadata() {
echo "invalid upstream_commit for $(basename "$pkgdir"): must be a string"
return 1
fi
if ! jq -e '(.rebuild_on // []) | type == "array" and all(type == "string" and length > 0)' "$metadata" >/dev/null; then
echo "invalid rebuild_on for $(basename "$pkgdir"): must be an array of package names"
return 1
fi
if ! jq -e '(.rebuilt_against // {}) | type == "object" and (to_entries | all(.value | type == "string" and length > 0))' "$metadata" >/dev/null; then
echo "invalid rebuilt_against for $(basename "$pkgdir"): must be an object mapping package names to versions"
return 1
fi
if ! jq -e '((.rebuilt_against // {}) | keys) - (.rebuild_on // []) | length == 0' "$metadata" >/dev/null; then
echo "invalid rebuilt_against for $(basename "$pkgdir"): records a package that rebuild_on does not name"
return 1
fi
}