release 1.13.4: monpages race-proof publish and content checks

Avoid false TOP/content ERRORs from mid-publish races: atomic HTML
write, rsync --delay-updates + settle, monpages fetch retries with
larger head windows, pre-publish soft content, bootstrap markers.
This commit is contained in:
Hernâni Marques 2026-07-19 02:55:56 +02:00
parent d5213adb7a
commit e450470429
No known key found for this signature in database
GPG key ID: CB5738652768F7E9
5 changed files with 179 additions and 73 deletions

View file

@ -280,9 +280,17 @@ if [ -x "${ROOT:-}/taler-monitoring.sh" ]; then
fi
done
# monpages inside PHASES runs *before* htmlify/publish — content failures would
# race with concurrent publishes or reflect last run's incomplete redirect stub.
# Soft-content there; post-check after rsync stays hard (authoritative).
case " $PHASES " in
*" monpages "*|*" pages "*) export MONPAGES_PRE_PUBLISH=1 ;;
*) unset MONPAGES_PRE_PUBLISH 2>/dev/null || true ;;
esac
# shellcheck disable=SC2086
./taler-monitoring.sh -d "$TALER_DOMAIN" $PHASES
ec=$?
unset MONPAGES_PRE_PUBLISH 2>/dev/null || true
fi
# --- always generate HTML (first run / missing pages / every run) ---
@ -304,21 +312,27 @@ write_bootstrap_html() {
if [ -n "$curl" ]; then
clink="<a href=\"$(printf '%s' "$curl" | sed 's/&/\&amp;/g')\">$cshort</a>"
fi
cat >"$out" <<EOF
local tmp
tmp=$(mktemp "${out}.XXXXXX")
cat >"$tmp" <<EOF
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"/>
<meta name="generated" content="${iso}"/>
<meta name="taler-mon-page" content="incomplete"/>
<title>monitoring ${mode} · ${host}</title>
<style>
body{margin:0;background:#0c0c0c;color:#c8c8c8;font-family:ui-monospace,monospace}
a{color:#61afef}.err{color:#ff5c5c}
.sticky-bar{position:sticky;top:0;z-index:100;padding:10px 14px;background:#2a1010f2;border-bottom:2px solid #a33}
.sticky-bar .pill{font-weight:800;color:#ff5c5c;margin-right:8px}
.version-link{color:#61afef}
main{padding:1.5rem}
</style></head><body>
<!-- taler-mon:top -->
<div class="sticky-bar" id="status-bar">
<span class="pill">BOOTSTRAP</span>
${PAGE_LABEL:-monitoring} · ${host} ·
<span class="version-link muted">bootstrap</span> ·
<span data-generated-iso="${iso}">generated ${gen}</span>
· source ${clink}
</div>
@ -326,8 +340,10 @@ main{padding:1.5rem}
<p class="err">Bootstrap page (converter missing or first install). See host-agent log.</p>
<pre style="white-space:pre-wrap;font-size:12px">$(tail -n 80 "$LOG" 2>/dev/null | sed 's/&/\&amp;/g;s/</\&lt;/g' || true)</pre>
</main>
<!-- taler-mon:bottom:incomplete -->
</body></html>
EOF
mv -f "$tmp" "$out"
echo "bootstrap html → $out"
}
@ -411,8 +427,11 @@ done
# Publish to live web root when possible (v1.3.1+: never silent-skip)
if [ -n "$DEPLOY_WWW" ]; then
if [ -w "$DEPLOY_WWW" ] 2>/dev/null; then
if rsync -a --delete "$HTML_BASE/" "$DEPLOY_WWW/"; then
echo "synced → $DEPLOY_WWW/"
# --delay-updates: write to temp names then rename (less partial-file exposure)
if rsync -a --delete --delay-updates "$HTML_BASE/" "$DEPLOY_WWW/"; then
echo "synced → $DEPLOY_WWW/ (delay-updates)"
# brief settle so concurrent monpages curls do not hit mid-rename FS views
sleep "${MONPAGES_PUBLISH_SETTLE_S:-0.3}" 2>/dev/null || sleep 1
else
echo "ERROR: rsync to DEPLOY_WWW_ROOT=$DEPLOY_WWW failed" >&2
ec=1
@ -441,12 +460,16 @@ if [ "${MONPAGES_POSTCHECK:-1}" = "1" ] && [ -x "$ROOT/check_monitoring_pages.sh
export MONPAGES_REQUIRE_PUBLIC="${MONPAGES_REQUIRE_PUBLIC:-1}"
# auto: GOA = all suite mon sites; FP = only FP mon hosts; job paths always included
export MONPAGES_INVENTORY="${MONPAGES_INVENTORY:-auto}"
# Hard check (not pre-publish soft)
unset MONPAGES_PRE_PUBLISH 2>/dev/null || true
export MONPAGES_PRE_PUBLISH=0
if ! bash "$ROOT/check_monitoring_pages.sh"; then
echo "ERROR: public monitoring page(s) missing or not suite HTML via FQDN" >&2
echo " staging HTML_OUT=${HTML_BASE} · DEPLOY_WWW=${DEPLOY_WWW:-}" >&2
ec=1
_monpages_failed=1
fi
unset MONPAGES_PRE_PUBLISH 2>/dev/null || true
fi
# If public check failed after first HTML write, rewrite pages so sticky bar shows monpages ERRORs