Skip to content

Commit 6ea7313

Browse files
committed
fix(offline): honor OFFLINE_WORK in git-ref2info and memoize TTL
Fixes #6439. memoized_git_ref_to_info() unconditionally ran 'git ls-remote' against the upstream source even with OFFLINE_WORK=yes; when the remote was unreachable the build aborted with a misleading network error. Two coordinated guards: * memoize-cached.sh: when OFFLINE_WORK=yes, serve the cache file regardless of TTL (alternative is a network call that will fail). The "stale cache served" event is logged. * git-ref2info.sh: early offline guard before the ls-remote loop. For ref_type=commit the SHA1 is taken from the ref itself (no network); for branch/tag we look up a pinned SHA1 in config/sources/git_sources.json. If neither is available, exit_with_error with a clear message instead of letting curl/ls-remote surface as 502. Same guard applied to the include_makefile_body block (curl to git host) since there is no local-bare fallback in scope here. Behaviour matrix unchanged for OFFLINE_WORK=no (default). Assisted-by: Claude:claude-opus-4.7
1 parent b9aa902 commit 6ea7313

2 files changed

Lines changed: 54 additions & 7 deletions

File tree

lib/functions/general/git-ref2info.sh

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@
77
# This file is a part of the Armbian Build Framework
88
# https://github.com/armbian/build/
99

10+
# Returns the pinned sha1 for a given git source+branch from
11+
# config/sources/git_sources.json, or nothing if the file or entry is absent.
12+
# Uses jq --arg so source/branch values can't break or inject into the jq program.
13+
function _git_sources_pinned_sha1() {
14+
declare json="${SRC}/config/sources/git_sources.json"
15+
[[ -f "${json}" ]] || return 0
16+
jq --raw-output --arg s "${1}" --arg b "${2}" \
17+
'[.[] | select(.source == $s and .branch == $b) | .sha1] | first // empty' "${json}"
18+
}
19+
1020
# This works under memoize-cached.sh::run_memoized() -- which is full of tricks.
1121
# Nested functions are used because the source of the momoized function is used as part of the cache hash.
1222
function memoized_git_ref_to_info() {
@@ -31,6 +41,21 @@ function memoized_git_ref_to_info() {
3141
# Get the SHA1 of the commit
3242
declare sha1
3343

44+
# OFFLINE_WORK guard: do not perform 'git ls-remote' when offline (#6439).
45+
# Honored sources, in order: ref_type=commit (sha1 from ref itself); pinned in
46+
# config/sources/git_sources.json (branch refs only). If neither yields a sha1 we
47+
# fail with a clear message instead of letting the network call surface as a
48+
# misleading 502/timeout.
49+
if [[ "${OFFLINE_WORK}" == "yes" && "${ref_type}" != "commit" ]]; then
50+
sha1="$(_git_sources_pinned_sha1 "${MEMO_DICT[GIT_SOURCE]}" "${ref_name}")"
51+
if [[ "${sha1}" =~ ^[0-9a-f]{40}$ ]]; then
52+
display_alert "OFFLINE_WORK: using pinned SHA1 from git_sources.json" "${ref_name} -> ${sha1}" "info"
53+
refs_to_try=() # skip ls-remote loop below
54+
else
55+
exit_with_error "OFFLINE_WORK=yes but no SHA1 available for '${MEMO_DICT[GIT_SOURCE]}' '${ref_type}' '${ref_name}' - run online once to populate cache, or pin sha1 in config/sources/git_sources.json"
56+
fi
57+
fi
58+
3459
# Enter loop. The first that resolves to a valid sha1 wins.
3560
declare to_try
3661
for to_try in "${refs_to_try[@]}"; do
@@ -93,10 +118,15 @@ function memoized_git_ref_to_info() {
93118
} 5<> "${SRC}"/output/info/git_sources.json 6<> "${SRC}"/output/info/git_sources.json.new
94119
fi
95120

96-
if [[ -f "${SRC}"/config/sources/git_sources.json && ${ref_type} == "branch" ]]; then
97-
cached_revision=$(jq --raw-output '.[] | select(.source == "'${MEMO_DICT[GIT_SOURCE]}'" and .branch == "'$ref_name'") |.sha1' "${SRC}"/config/sources/git_sources.json)
98-
display_alert "Found cached git version" "${cached_revision}" "info"
99-
[[ -z "${cached_revision}" ]] || sha1=${cached_revision}
121+
if [[ "${ref_type}" == "branch" ]]; then
122+
declare cached_revision
123+
cached_revision="$(_git_sources_pinned_sha1 "${MEMO_DICT[GIT_SOURCE]}" "${ref_name}")"
124+
if [[ "${cached_revision}" =~ ^[0-9a-f]{40}$ ]]; then
125+
display_alert "Found cached git version" "${cached_revision}" "info"
126+
sha1="${cached_revision}"
127+
elif [[ -n "${cached_revision}" ]]; then
128+
exit_with_error "Invalid pinned SHA1 '${cached_revision}' for '${MEMO_DICT[GIT_SOURCE]}' '${ref_name}' in config/sources/git_sources.json"
129+
fi
100130
fi
101131

102132
MEMO_DICT+=(["SHA1"]="${sha1}")
@@ -228,6 +258,14 @@ function memoized_git_ref_to_info() {
228258
return 0
229259
}
230260

261+
# OFFLINE_WORK guard: Makefile body is fetched via curl to git host(s) — no
262+
# network when offline. We have no local fallback here (no bare-clone path in
263+
# scope), so fail with a clear message instead of letting curl surface as a
264+
# misleading 'undetermined' kernel version downstream (#6439).
265+
if [[ "${OFFLINE_WORK}" == "yes" ]]; then
266+
exit_with_error "OFFLINE_WORK=yes but Makefile body for '${MEMO_DICT[GIT_SOURCE]}' '${ref_name}' (sha1 ${sha1}) not in cache - run online once to populate ${SRC}/cache/memoize/"
267+
fi
268+
231269
display_alert "Fetching Makefile body" "${ref_name}" "debug"
232270
declare makefile_body makefile_url
233271
declare makefile_version makefile_codename makefile_full_version

lib/functions/general/memoize-cached.sh

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ function run_memoized() {
5050
# Lock is held by another process, inform user and wait with periodic feedback
5151
display_alert "Waiting for lock" "another build may be running; check: docker ps -a | grep armbian" "info"
5252

53-
declare -i lock_wait_interval=${MEMOIZE_FLOCK_WAIT_INTERVAL:-10} # seconds between retries/messages
54-
declare -i lock_max_wait=${MEMOIZE_FLOCK_MAX_WAIT:-0} # 0 = infinite (default for compatibility)
53+
declare -i lock_wait_interval=${MEMOIZE_FLOCK_WAIT_INTERVAL:-10} # seconds between retries/messages
54+
declare -i lock_max_wait=${MEMOIZE_FLOCK_MAX_WAIT:-0} # 0 = infinite (default for compatibility)
5555
declare -i lock_total_wait=0
5656
declare -i lock_acquired=0
5757

@@ -79,8 +79,17 @@ function run_memoized() {
7979
if [[ -f "${disk_cache_file}" ]]; then
8080
declare disk_cache_file_mtime_seconds
8181
disk_cache_file_mtime_seconds="$(stat -c %Y "${disk_cache_file}")"
82-
# if disk_cache_file is older than the ttl, delete it and continue.
82+
declare cache_is_stale="no"
8383
if [[ "${disk_cache_file_mtime_seconds}" -lt "$(($(date +%s) - memoize_cache_ttl))" ]]; then
84+
cache_is_stale="yes"
85+
fi
86+
# OFFLINE_WORK: serve any cached entry regardless of TTL — the alternative is
87+
# a network call that will fail (#6439). Surface that we're using a stale entry.
88+
if [[ "${cache_is_stale}" == "yes" && "${OFFLINE_WORK}" == "yes" ]]; then
89+
display_alert "OFFLINE_WORK: using stale cache" "${var_n}" "info"
90+
cache_is_stale="no"
91+
fi
92+
if [[ "${cache_is_stale}" == "yes" ]]; then
8493
display_alert "Deleting stale cache file" "${disk_cache_file}" "debug"
8594
rm -f "${disk_cache_file}"
8695
else

0 commit comments

Comments
 (0)