fix(version): add error handling to version check subcommand

Add defensive programming to the execution chain of the version check
subcommand for graceful error handling of subprocesses as well as errors
returned from nvchecker itself indicated in the returned JSON.

Furthermore this fixes a bug when processing multiple packages where the
pkgbase variable is stuck for subsequent packages that do not declare a
pkgbase variable itself.

Component: pkgctl version check
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
This commit is contained in:
Levente Polyak 2024-01-13 14:33:09 +01:00 committed by Christian Heusel
parent 6054c869e1
commit 03d5c928cf
No known key found for this signature in database
GPG Key ID: C047D4F328B52585
1 changed files with 93 additions and 14 deletions

View File

@ -11,7 +11,7 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
source /usr/share/makepkg/util/message.sh source /usr/share/makepkg/util/message.sh
set -e set -eo pipefail
pkgctl_version_check_usage() { pkgctl_version_check_usage() {
local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}} local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
@ -34,8 +34,7 @@ _EOF_
pkgctl_version_check() { pkgctl_version_check() {
local path local path
local pkgbases=() local pkgbases=()
local path pkgbase upstream_version local path pkgbase upstream_version result
while (( $# )); do while (( $# )); do
case $1 in case $1 in
@ -78,15 +77,28 @@ pkgctl_version_check() {
die "No PKGBUILD found for ${path}" die "No PKGBUILD found for ${path}"
fi fi
# shellcheck disable=SC2119 # reset common PKGBUILD variables
upstream_version=$(get_upstream_version) unset pkgbase pkgname arch source pkgver pkgrel validpgpkeys
# TODO: parse .SRCINFO file
# shellcheck source=contrib/makepkg/PKGBUILD.proto # shellcheck source=contrib/makepkg/PKGBUILD.proto
. ./PKGBUILD . ./PKGBUILD
pkgbase=${pkgbase:-$pkgname} pkgbase=${pkgbase:-$pkgname}
if (( $(vercmp "${upstream_version}" "${pkgver}") > 0 )); then if ! result=$(get_upstream_version); then
msg_error "${pkgbase}: ${result}"
popd >/dev/null
continue
fi
upstream_version=${result}
if ! result=$(vercmp "${upstream_version}" "${pkgver}"); then
result="${BOLD}${pkgbase}${ALL_OFF}: failed to compare version ${upstream_version} against ${pkgver}"
msg_error "${result}"
popd >/dev/null
continue
fi
if (( result > 0 )); then
msg2 "New ${pkgbase} version ${upstream_version} is available upstream" msg2 "New ${pkgbase} version ${upstream_version} is available upstream"
fi fi
@ -95,13 +107,80 @@ pkgctl_version_check() {
} }
get_upstream_version() { get_upstream_version() {
local config=${1:-.nvchecker.toml} local config=.nvchecker.toml
local upstream_version local output errors upstream_version
local output
if [[ ! -f $config ]]; then # check nvchecker config file
die "No $config found" if ! errors=$(nvchecker_check_config "${config}"); then
printf "%s" "${errors}"
return 1
fi fi
upstream_version=$(nvchecker -c "$config" --logger json | jq --raw-output 'select( .version ) | .version') if ! output=$(nvchecker --file "${config}" --logger json 2>&1 | \
printf "%s" "$upstream_version" jq --raw-output 'select(.level != "debug")'); then
printf "failed to run nvchecker: %s" "${output}"
return 1
fi
if ! errors=$(nvchecker_check_error "${output}"); then
printf "%s" "${errors}"
return 1
fi
if ! upstream_version=$(jq --raw-output --exit-status '.version' <<< "${output}"); then
printf "failed to select version from result"
return 1
fi
printf "%s" "${upstream_version}"
return 0
}
nvchecker_check_config() {
local config=$1
local restricted_properties=(keyfile httptoken token)
local property
# check if the config file exists
if [[ ! -f ${config} ]]; then
printf "configuration file not found: %s" "${config}"
return 1
fi
# check if config contains any restricted properties like secrets
for property in "${restricted_properties[@]}"; do
if grep --max-count=1 --quiet "^${property}" < "${config}"; then
printf "restricted property in %s: %s" "${config}" "${property}"
return 1
fi
done
# check if the config contains a pkgbase section
if [[ -n ${pkgbase} ]] && ! grep --max-count=1 --quiet "^\\[${pkgbase}\\]" < "${config}"; then
printf "missing pkgbase section in %s: %s" "${config}" "${pkgbase}"
return 1
fi
# check if the config contains any section other than pkgbase
if [[ -n ${pkgbase} ]] && property=$(grep --max-count=1 --perl-regexp "^\\[(?!${pkgbase}\\]).+\\]" < "${config}"); then
printf "none pkgbase section not supported in %s: %s" "${config}" "${property}"
return 1
fi
}
nvchecker_check_error() {
local result=$1
local errors
if ! errors=$(jq --raw-output --exit-status \
'select(.level == "error") | "\(.event)" + if .error then ": \(.error)" else "" end' \
<<< "${result}"); then
return 0
fi
mapfile -t errors <<< "${errors}"
printf "%s\n" "${errors[@]}"
return 1
} }