Files
omarchy-pkgs/bin/check-versions
T
Ryan Hughes 7c3cfc50e9 Fix silent notifications and stop stale checkouts queueing rebuild loops
Two failures from the first live run:

notify_basecamp declared 'local BASECAMP_CHATBOT_URL' and then called
release_chatbot_url, whose fallback reads that same global — bash locals are
visible to called functions, so the fallback saw the empty local and every
notification silently went nowhere for anyone with only the legacy variable
set. The local is now named 'url'.

check-versions compared PKGBUILD and published versions with !=, so a checkout
BEHIND the channel queued a rebuild of an older version every cycle: the
builder produced it and promotion refused it, because that exact filename is
already published with different bytes. It now skips (with a warning naming
the package) when an artifact for the PKGBUILD's version already exists in the
channel, whichever direction the versions differ.
2026-08-27 01:10:33 -04:00

185 lines
5.7 KiB
Bash
Executable File

#!/bin/bash
# Check PKGBUILD versions against published repo versions
# Creates state files for edge and/or stable if any packages need building
set -e
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
source "$BUILD_ROOT/helpers/message-helpers.sh"
source "$BUILD_ROOT/helpers/paths.sh"
source "$BUILD_ROOT/helpers/package-metadata.sh"
source "$BUILD_ROOT/helpers/lock-helpers.sh"
STATE_DIR="${OMARCHY_STATE_DIR:-/root/.state}"
ARCH="${ARCH:-x86_64}"
PULL=false
[[ "${1:-}" == "--pull" ]] && PULL=true
mkdir -p "$STATE_DIR"
# Runs on a tight schedule, so it must never disturb a build in progress:
# comparing versions reads the PKGBUILDs a running build is reading, and
# --pull would swap them underneath it. Take the lock non-blocking and skip
# the tick when a release owns it — the queue is unchanged, so the next tick
# picks up exactly where this one left off.
if ! try_release_lock; then
exit 0
fi
print_header "Package Version Check"
# The scheduled run pulls; a manual run leaves the operator's tree alone.
if [[ "$PULL" == true ]]; then
print_info "Updating repository..."
git -C "$BUILD_ROOT" pull --ff-only || print_warning "git pull failed — checking the current tree"
fi
get_repo_version() {
local pkg="$1"
local mirror="$2"
local repo_db="$REPO_ROOT/$mirror/$ARCH/omarchy.db.tar.zst"
[[ -f "$repo_db" ]] || return 0
tar -xOf "$repo_db" --wildcards '*/desc' 2>/dev/null | awk -v pkg="$pkg" '
function reset() { name=""; base=""; version="" }
function emit() {
if (!found && version != "" && (name == pkg || base == pkg)) {
print version
found=1
}
reset()
}
$0 == "%FILENAME%" { emit(); next }
$0 == "%NAME%" { if (name != "" && version != "") emit(); getline; name=$0; next }
$0 == "%BASE%" { getline; base=$0; next }
$0 == "%VERSION%" { getline; version=$0; next }
END { emit() }
'
}
get_pkgbuild_version() {
local pkgdir="$1"
if [[ -f "$pkgdir/PKGBUILD" ]]; then
(cd "$pkgdir" && bash -c 'source PKGBUILD 2>/dev/null; if [[ -n "$epoch" ]]; then echo "${epoch}:${pkgver}-${pkgrel}"; else echo "${pkgver}-${pkgrel}"; fi')
fi
}
check_vcs_unchanged() {
local pkgdir="$1"
local repo_version="$2"
local pkgbuild="$pkgdir/PKGBUILD"
[[ -f "$pkgbuild" ]] || return 1
grep -qE '^pkgver[[:space:]]*\(\)' "$pkgbuild" || return 1
[[ -n "$repo_version" ]] || return 1
# If epoch or pkgrel changed in PKGBUILD, release even if upstream is unchanged.
local pkgbuild_epoch pkgbuild_pkgrel
pkgbuild_epoch=$(cd "$pkgdir" && bash -c 'source PKGBUILD 2>/dev/null; echo "${epoch:-}"')
pkgbuild_pkgrel=$(cd "$pkgdir" && bash -c 'source PKGBUILD 2>/dev/null; echo "${pkgrel}"')
local repo_pkgrel="${repo_version##*-}"
local repo_no_pkgrel="${repo_version%-*}"
local repo_epoch=""
if [[ "$repo_no_pkgrel" == *:* ]]; then
repo_epoch="${repo_no_pkgrel%%:*}"
fi
[[ "$pkgbuild_epoch" != "$repo_epoch" ]] && return 1
[[ "$pkgbuild_pkgrel" != "$repo_pkgrel" ]] && return 1
local repo_hash upstream_hash
repo_hash=$(package_extract_vcs_hash_from_version "$repo_version")
[[ -n "$repo_hash" ]] || return 1
upstream_hash=$(package_git_upstream_hash "$pkgdir")
[[ -n "$upstream_hash" ]] || return 1
[[ "$repo_hash" == "$upstream_hash" ]]
}
check_package() {
local pkg="$1"
local pkgdir="$2"
local mirror="$3"
local pkgbuild_version repo_version
pkgbuild_version=$(get_pkgbuild_version "$pkgdir")
repo_version=$(get_repo_version "$pkg" "$mirror")
if [[ -z "$pkgbuild_version" ]]; then
return 1
fi
if grep -qE '^pkgver[[:space:]]*\(\)' "$pkgdir/PKGBUILD"; then
if [[ -n "$repo_version" && -n "$(package_extract_vcs_hash_from_version "$repo_version")" ]]; then
if check_vcs_unchanged "$pkgdir" "$repo_version"; then
return 1
else
return 0
fi
elif [[ "$pkgbuild_version" == "$repo_version" ]]; then
return 1
else
return 0
fi
fi
if [[ "$pkgbuild_version" == "$repo_version" ]]; then
return 1
fi
# Different is not the same as newer. A checkout behind the published state
# — a stale branch, an un-pulled host — otherwise queues a REBUILD OF AN
# OLDER VERSION every cycle: the builder produces it, and promotion refuses
# it because that exact filename is already published with different bytes.
# If the artifact for this version already exists in the channel, there is
# nothing to build regardless of which direction the versions differ.
if compgen -G "$REPO_ROOT/$mirror/$ARCH/${pkg}-${pkgbuild_version}-*.pkg.tar."[!s]* >/dev/null 2>&1; then
print_warning "$pkg $pkgbuild_version is already published — this checkout is behind the channel; not queueing"
return 1
fi
return 0
}
check_mirror() {
local mirror="$1"
local state_file="$STATE_DIR/.sync-needed-$mirror"
local needs_build=false
local packages=()
print_info "Checking $mirror packages..."
while IFS= read -r pkg; do
local pkgdir="$PKGBUILDS_DIR/$pkg"
if check_package "$pkg" "$pkgdir" "$mirror"; then
needs_build=true
packages+=("$pkg")
fi
done < <(packages_for_unscoped_build "$mirror")
echo ""
if [[ "$needs_build" == true ]]; then
# Record WHAT is queued, not just THAT something is: the release run reads
# this to name the packages in its start report, which is the difference
# between "a build is running" and "your package is in this build".
printf '%s\n' "${packages[@]}" >"$state_file"
print_success "${mirror^} needs building (${#packages[@]} packages)"
print_info "Packages: ${packages[*]}"
print_info "State file created: $state_file"
else
print_info "${mirror^} is up to date"
fi
echo ""
}
check_mirror edge
check_mirror stable
print_success "Version check complete!"