Skip to content

Commit e70de7d

Browse files
authored
feat(tools): fallback to previous release when asset is missing (#11660)
When fetch_and_deploy_gh_release fails to find a matching asset in the target release (binary/prebuild/singlefile modes), scan up to 15 older releases for a compatible asset. Prompts the user with a 60s timeout (default: yes) before using the fallback version. Addresses issues like SigNoz #11652 where the latest release has no matching OTel collector binary.
1 parent 4933714 commit e70de7d

1 file changed

Lines changed: 154 additions & 0 deletions

File tree

misc/tools.func

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,7 +2317,105 @@ function fetch_and_deploy_codeberg_release() {
23172317
#
23182318
# # 4. Single binary (chmod +x) like Argus, Promtail etc.
23192319
# fetch_and_deploy_gh_release "argus" "release-argus/Argus" "singlefile" "0.26.3" "/opt/argus" "Argus-.*linux-amd64"
2320+
#
2321+
# Notes:
2322+
# - For binary/prebuild/singlefile modes: if the target release has no
2323+
# matching asset, the function scans older releases and prompts the user
2324+
# (60s timeout, default yes) to use a previous version that has the asset.
2325+
# ------------------------------------------------------------------------------
2326+
2327+
# ------------------------------------------------------------------------------
2328+
# Scans older GitHub releases for a matching asset when the latest release
2329+
# is missing the expected file. Used internally by fetch_and_deploy_gh_release.
2330+
#
2331+
# Arguments:
2332+
# $1 - GitHub repo (owner/repo)
2333+
# $2 - mode (binary|prebuild|singlefile)
2334+
# $3 - asset_pattern (glob pattern for asset filename)
2335+
# $4 - tag to skip (the already-checked release)
2336+
#
2337+
# Output:
2338+
# Prints the release JSON of the first older release that has a matching asset.
2339+
# Returns 0 on success, 1 if no matching release found or user declined.
23202340
# ------------------------------------------------------------------------------
2341+
_gh_scan_older_releases() {
2342+
local repo="$1"
2343+
local mode="$2"
2344+
local asset_pattern="$3"
2345+
local skip_tag="$4"
2346+
2347+
local header=()
2348+
[[ -n "${GITHUB_TOKEN:-}" ]] && header=(-H "Authorization: token $GITHUB_TOKEN")
2349+
2350+
local releases_list
2351+
releases_list=$(curl --connect-timeout 10 --max-time 30 -fsSL \
2352+
-H 'Accept: application/vnd.github+json' \
2353+
-H 'X-GitHub-Api-Version: 2022-11-28' \
2354+
"${header[@]}" \
2355+
"https://api.github.com/repos/${repo}/releases?per_page=15" 2>/dev/null) || return 1
2356+
2357+
local count
2358+
count=$(echo "$releases_list" | jq 'length')
2359+
2360+
for ((i = 0; i < count; i++)); do
2361+
local rel_tag rel_draft rel_prerelease
2362+
rel_tag=$(echo "$releases_list" | jq -r ".[$i].tag_name")
2363+
rel_draft=$(echo "$releases_list" | jq -r ".[$i].draft")
2364+
rel_prerelease=$(echo "$releases_list" | jq -r ".[$i].prerelease")
2365+
2366+
# Skip drafts, prereleases, and the tag we already checked
2367+
[[ "$rel_draft" == "true" || "$rel_prerelease" == "true" ]] && continue
2368+
[[ "$rel_tag" == "$skip_tag" ]] && continue
2369+
2370+
local has_match=false
2371+
2372+
if [[ "$mode" == "binary" ]]; then
2373+
local arch
2374+
arch=$(dpkg --print-architecture 2>/dev/null || uname -m)
2375+
[[ "$arch" == "x86_64" ]] && arch="amd64"
2376+
[[ "$arch" == "aarch64" ]] && arch="arm64"
2377+
2378+
# Check with explicit pattern first, then arch heuristic, then any .deb
2379+
if [[ -n "$asset_pattern" ]]; then
2380+
has_match=$(echo "$releases_list" | jq -r --arg pat "$asset_pattern" ".[$i].assets[].name" | while read -r name; do
2381+
case "$name" in $asset_pattern) echo true; break ;; esac
2382+
done)
2383+
fi
2384+
if [[ "$has_match" != "true" ]]; then
2385+
has_match=$(echo "$releases_list" | jq -r ".[$i].assets[].browser_download_url" | grep -qE "($arch|amd64|x86_64|aarch64|arm64).*\.deb$" && echo true)
2386+
fi
2387+
if [[ "$has_match" != "true" ]]; then
2388+
has_match=$(echo "$releases_list" | jq -r ".[$i].assets[].browser_download_url" | grep -qE '\.deb$' && echo true)
2389+
fi
2390+
2391+
elif [[ "$mode" == "prebuild" || "$mode" == "singlefile" ]]; then
2392+
has_match=$(echo "$releases_list" | jq -r ".[$i].assets[].name" | while read -r name; do
2393+
case "$name" in $asset_pattern) echo true; break ;; esac
2394+
done)
2395+
fi
2396+
2397+
if [[ "$has_match" == "true" ]]; then
2398+
local rel_version="$rel_tag"
2399+
[[ "$rel_tag" =~ ^v ]] && rel_version="${rel_tag:1}"
2400+
2401+
local use_fallback="y"
2402+
if [[ -t 0 ]]; then
2403+
msg_warn "Release ${skip_tag} has no matching asset. Previous release ${rel_tag} has a compatible asset."
2404+
read -rp "Use version ${rel_tag} instead? [Y/n] (auto-yes in 60s): " -t 60 use_fallback || use_fallback="y"
2405+
use_fallback="${use_fallback:-y}"
2406+
fi
2407+
2408+
if [[ "${use_fallback,,}" == "y" || "${use_fallback,,}" == "yes" ]]; then
2409+
echo "$releases_list" | jq ".[$i]"
2410+
return 0
2411+
else
2412+
return 1
2413+
fi
2414+
fi
2415+
done
2416+
2417+
return 1
2418+
}
23212419
23222420
function fetch_and_deploy_gh_release() {
23232421
local app="$1"
@@ -2458,6 +2556,33 @@ function fetch_and_deploy_gh_release() {
24582556
done
24592557
fi
24602558
2559+
# Fallback: scan older releases for a matching .deb asset
2560+
if [[ -z "$url_match" ]]; then
2561+
local fallback_json
2562+
if fallback_json=$(_gh_scan_older_releases "$repo" "binary" "$asset_pattern" "$tag_name"); then
2563+
json="$fallback_json"
2564+
tag_name=$(echo "$json" | jq -r '.tag_name // .name // empty')
2565+
[[ "$tag_name" =~ ^v ]] && version="${tag_name:1}" || version="$tag_name"
2566+
msg_info "Fetching GitHub release: $app ($version)"
2567+
assets=$(echo "$json" | jq -r '.assets[].browser_download_url')
2568+
if [[ -n "$asset_pattern" ]]; then
2569+
for u in $assets; do
2570+
case "${u##*/}" in $asset_pattern) url_match="$u"; break ;; esac
2571+
done
2572+
fi
2573+
if [[ -z "$url_match" ]]; then
2574+
for u in $assets; do
2575+
if [[ "$u" =~ ($arch|amd64|x86_64|aarch64|arm64).*\.deb$ ]]; then url_match="$u"; break; fi
2576+
done
2577+
fi
2578+
if [[ -z "$url_match" ]]; then
2579+
for u in $assets; do
2580+
[[ "$u" =~ \.deb$ ]] && url_match="$u" && break
2581+
done
2582+
fi
2583+
fi
2584+
fi
2585+
24612586
if [[ -z "$url_match" ]]; then
24622587
msg_error "No suitable .deb asset found for $app"
24632588
rm -rf "$tmpdir"
@@ -2506,6 +2631,21 @@ function fetch_and_deploy_gh_release() {
25062631
esac
25072632
done
25082633
2634+
# Fallback: scan older releases for a matching asset
2635+
if [[ -z "$asset_url" ]]; then
2636+
local fallback_json
2637+
if fallback_json=$(_gh_scan_older_releases "$repo" "prebuild" "$pattern" "$tag_name"); then
2638+
json="$fallback_json"
2639+
tag_name=$(echo "$json" | jq -r '.tag_name // .name // empty')
2640+
[[ "$tag_name" =~ ^v ]] && version="${tag_name:1}" || version="$tag_name"
2641+
msg_info "Fetching GitHub release: $app ($version)"
2642+
for u in $(echo "$json" | jq -r '.assets[].browser_download_url'); do
2643+
filename_candidate="${u##*/}"
2644+
case "$filename_candidate" in $pattern) asset_url="$u"; break ;; esac
2645+
done
2646+
fi
2647+
fi
2648+
25092649
[[ -z "$asset_url" ]] && {
25102650
msg_error "No asset matching '$pattern' found"
25112651
rm -rf "$tmpdir"
@@ -2603,6 +2743,20 @@ function fetch_and_deploy_gh_release() {
26032743
esac
26042744
done
26052745
2746+
# Fallback: scan older releases for a matching asset
2747+
if [[ -z "$asset_url" ]]; then
2748+
local fallback_json
2749+
if fallback_json=$(_gh_scan_older_releases "$repo" "singlefile" "$pattern" "$tag_name"); then
2750+
json="$fallback_json"
2751+
tag_name=$(echo "$json" | jq -r '.tag_name // .name // empty')
2752+
[[ "$tag_name" =~ ^v ]] && version="${tag_name:1}" || version="$tag_name"
2753+
msg_info "Fetching GitHub release: $app ($version)"
2754+
for u in $(echo "$json" | jq -r '.assets[].browser_download_url'); do
2755+
filename_candidate="${u##*/}"
2756+
case "$filename_candidate" in $pattern) asset_url="$u"; break ;; esac
2757+
done
2758+
fi
2759+
fi
26062760
[[ -z "$asset_url" ]] && {
26072761
msg_error "No asset matching '$pattern' found"
26082762
rm -rf "$tmpdir"

0 commit comments

Comments
 (0)