From e1b5639d6584feb862bbcbfe35644d9ac99ed488 Mon Sep 17 00:00:00 2001 From: Ruakij Date: Tue, 27 Oct 2026 07:40:18 +0000 Subject: [PATCH] apt_updates: count a package as security when any version newer than the installed one has a security origin --- apt_updates/templates/apt-updates-metrics.j2 | 30 +++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/apt_updates/templates/apt-updates-metrics.j2 b/apt_updates/templates/apt-updates-metrics.j2 index 373b9cd..050bfff 100644 --- a/apt_updates/templates/apt-updates-metrics.j2 +++ b/apt_updates/templates/apt-updates-metrics.j2 @@ -13,10 +13,27 @@ trap 'rm -f "$tmp"' EXIT # packages. Each gets a row per kind even at 0, so a resolved backlog reads as 0 and not as a vanished series. archs="$(dpkg --print-architecture) $(dpkg --print-foreign-architectures | tr '\n' ' ') all" -# The simulated upgrade lists "Inst [] ( [])" per package. A version in -# several suites lists them all, comma separated. A package counts as security when any origin contains "security", -# everything else as regular. -pending=$(apt-get -s upgrade | awk -v host="$host" -v archs="$archs" ' +# The simulated upgrade lists "Inst [] ( [])" per package. The candidate +# is the newest version, which can come from regular updates while an older, still newer-than-installed version came +# from the security archive. So a package counts as security when any version above the installed one in its +# "apt-cache policy" table (newest first, installed marked with ***) has a security origin, everything else as regular. +sim=$(apt-get -s upgrade) +names=$(awk '/^Inst / { print $2 }' <<< "$sim") +security="" +if [[ -n $names ]]; then + # shellcheck disable=SC2086 + security=$(apt-cache policy $names | awk ' + /^[^ ]/ { pkg = $1; sub(/:$/, "", pkg); newer = 1; next } + /^ \*\*\* / { newer = 0; next } + /^ [0-9]+ / { if (newer && tolower($0) ~ /security/) print pkg } + ') +fi + +pending=$(SECURITY="$security" awk -v host="$host" -v archs="$archs" ' + BEGIN { + n = split(ENVIRON["SECURITY"], s, "\n") + for (i = 1; i <= n; i++) sec[s[i]] = 1 + } /^Inst / { line = $0 sub(/^[^(]*\(/, "", line) @@ -24,8 +41,7 @@ pending=$(apt-get -s upgrade | awk -v host="$host" -v archs="$archs" ' n = split(line, f, " ") pkg_arch = f[n] gsub(/\[|\]/, "", pkg_arch) - sub(/^[^ ]+ /, "", line) - kind = (tolower(line) ~ /security/) ? "security" : "regular" + kind = ($2 in sec) ? "security" : "regular" count[kind, pkg_arch]++ } END { @@ -38,7 +54,7 @@ pending=$(apt-get -s upgrade | awk -v host="$host" -v archs="$archs" ' split(key, k, SUBSEP) printf "apt_upgrades_pending{host=\"%s\",origin=\"%s\",arch=\"%s\"} %d\n", host, k[1], k[2], count[key] } - }') + }' <<< "$sim") held=$(apt-mark showhold | wc -l)