The rc channel's Arch base can sit anywhere between stable's snapshot and edge's, so a package built against stable's libraries is not necessarily correct for rc. Copying stable's fast-ring artifacts into rc therefore shipped possibly-mislinked packages to RC testers. Fast-ring packages now build natively for all three channels, each in its own image against its own base mirror, and the stable release's replication step is gone. That required separating 'may be built here' from 'whose version wins'. The release pair is now marked "pinned": its version is set per release on the rc branch, so it builds for rc only from that branch's worktree (OMARCHY_RC_PINS=1, set by omarchy-release rc) — master's shipped pins can never overwrite an in-flight RC, even though check-versions now discovers rc work like it does for edge and stable.
186 lines
5.7 KiB
Bash
Executable File
186 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 rc
|
|
check_mirror stable
|
|
|
|
print_success "Version check complete!"
|