verify-tracked-sources: first-party redbear-* drift is fatal

redbear-* recipes are not vendored upstream code -- they are Red Bear's own
programs and exist nowhere else. A vendored tree can be restored from its
tarball or git remote; first-party source cannot. If a recipe sed or an `rm`
damages it and that gets committed, the work is gone.

Not hypothetical. Seven redbear-* recipes rewrite their own source during the
build (greeter, btusb, btctl, ime, dnsd, accessibility, keymapd), and all seven
are exempt from out-of-tree staging because their cargo manifests carry path
dependencies escaping the source tree. They are simultaneously the least
protected and the most irreplaceable code here.

Uncommitted drift in them now fails preflight instead of printing a note that
scrolls past. Vendored trees keep the existing warn-by-default behaviour.
Override: REDBEAR_ALLOW_DIRTY_FIRSTPARTY=1.

Verified: gate is silent on a clean tree, fires on a one-line edit to
redbear-authd, and the tree restores cleanly.
This commit is contained in:
2026-08-04 19:30:37 +03:00
parent 130f37de8b
commit 8eaf54d87f
+33
View File
@@ -203,6 +203,39 @@ for f in "${MODIFIED[@]}"; do
[ -n "${known[$f]:-}" ] && baseline_dirty=$(( baseline_dirty + 1 ))
done
# 3a. FIRST-PARTY source is always fatal, never a note.
#
# redbear-* recipes are not vendored upstream code -- they are Red Bear's own
# programs and exist NOWHERE ELSE. A vendored tree can be restored from its
# upstream tarball or git remote; first-party source cannot. If a recipe sed or
# an `rm` damages it and the damage is committed, the work is simply gone.
#
# This is not hypothetical: seven redbear-* recipes rewrite their own source
# during the build (redbear-greeter, -btusb, -btctl, -ime, -dnsd,
# -accessibility, -keymapd), and all seven are exempt from out-of-tree staging
# because their cargo manifests carry path dependencies that escape the source
# tree. They are therefore the LEAST protected and the MOST irreplaceable code
# in the repository, so uncommitted drift in them stops the build outright
# rather than printing a note that scrolls past.
firstparty_dirty=0
for f in "${MODIFIED[@]}" "${DELETED[@]}"; do
[ -z "$f" ] && continue
case "$f" in
*/redbear-*/source/*) firstparty_dirty=$(( firstparty_dirty + 1 )) ;;
esac
done
if [ "$firstparty_dirty" -gt 0 ]; then
echo ">>> ERROR: $firstparty_dirty uncommitted change(s) in FIRST-PARTY redbear-* source." >&2
echo " This code exists nowhere but this project -- there is no upstream to restore" >&2
echo " from. Commit it, or revert it with: git checkout -- <path>" >&2
for f in "${MODIFIED[@]}" "${DELETED[@]}"; do
case "$f" in */redbear-*/source/*) echo " $f" >&2 ;; esac
done
echo " Override (accepts the risk): REDBEAR_ALLOW_DIRTY_FIRSTPARTY=1" >&2
[ "${REDBEAR_ALLOW_DIRTY_FIRSTPARTY:-0}" = "1" ] || rc=1
fi
if [ "$baseline_dirty" -gt 0 ]; then
if [ "${REDBEAR_STRICT_TRACKED_SOURCES:-0}" = "1" ]; then
echo ">>> ERROR: $baseline_dirty uncommitted change(s) in tracked source trees" \