feat(updates): seamless release flow — push-notify, VERSION copy, robust mirror
- self-updater: per-instance notify secret (auto-generated), notifyAndApply() triggers an immediate check+apply for the publishing host - routes: POST /api/system/update-notify (X-DashCaddy-Notify-Secret gated, added to public-routes allowlist so TOTP doesn't block machine-to-machine) - dashcaddy-update.sh: include VERSION in backup/deploy/rollback copy lists; belt-and-suspenders write trigger.json commit to VERSION post-deploy. Fixes drift where /app/VERSION stayed at the old commit after self-update. - release.sh: mirror failures are non-fatal+loud; HTTP-verify get2 after rsync; auto-notify co-located instance via /opt/dashcaddy/updates/notify-secret (or honour DASHCADDY_NOTIFY_TARGETS for multi-instance setups).
This commit is contained in:
+62
-2
@@ -116,9 +116,59 @@ ssh "$RELEASE_HOST" "set -e
|
||||
EOF
|
||||
"
|
||||
|
||||
# ── 6. Mirror to backup host ──────────────────────────────────────────────
|
||||
# ── 6. Mirror to backup host (non-fatal — primary is canonical) ───────────
|
||||
echo "[6/6] Mirroring to $MIRROR_HOST"
|
||||
ssh "$RELEASE_HOST" "rsync -aq --delete /var/www/get.dashcaddy.net/release/ $MIRROR_HOST:/var/www/get2.dashcaddy.net/release/"
|
||||
MIRROR_OK=true
|
||||
if ssh "$RELEASE_HOST" "rsync -aq --delete /var/www/get.dashcaddy.net/release/ $MIRROR_HOST:/var/www/get2.dashcaddy.net/release/" 2>&1; then
|
||||
echo " → mirrored"
|
||||
else
|
||||
MIRROR_OK=false
|
||||
echo " ! MIRROR FAILED — get2.dashcaddy.net is stale. Primary continues." >&2
|
||||
fi
|
||||
|
||||
# ── Optional: notify known instances to update immediately ────────────────
|
||||
# Set DASHCADDY_NOTIFY_TARGETS="<url>|<secret>,<url>|<secret>" to push.
|
||||
# If unset, we try the co-located instance at localhost:3001 using the
|
||||
# generated secret at /opt/dashcaddy/updates/notify-secret (silently skipped
|
||||
# if either is missing).
|
||||
if [[ -n "${DASHCADDY_NOTIFY_TARGETS:-}" ]]; then
|
||||
echo "[notify] pushing release to configured targets"
|
||||
IFS=',' read -ra TARGETS <<< "$DASHCADDY_NOTIFY_TARGETS"
|
||||
for t in "${TARGETS[@]}"; do
|
||||
url="${t%%|*}"
|
||||
secret="${t#*|}"
|
||||
[[ "$url" == "$secret" ]] && { echo " ! malformed target ($t) — need url|secret" >&2; continue; }
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 -X POST \
|
||||
-H "X-DashCaddy-Notify-Secret: $secret" \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d "{\"version\":\"$VERSION\",\"commit\":\"$COMMIT\"}" \
|
||||
"$url" || true)
|
||||
if [[ "$code" =~ ^2[0-9][0-9]$ ]]; then
|
||||
echo " → $url notified (HTTP $code)"
|
||||
else
|
||||
echo " ! $url notify FAILED (HTTP $code)" >&2
|
||||
fi
|
||||
done
|
||||
else
|
||||
# Co-located default
|
||||
LOCAL_NOTIFY=$(ssh "$RELEASE_HOST" '
|
||||
if [[ -r /opt/dashcaddy/updates/notify-secret ]] && curl -fsS --max-time 2 http://localhost:3001/api/health >/dev/null 2>&1; then
|
||||
secret=$(cat /opt/dashcaddy/updates/notify-secret)
|
||||
curl -s -o /dev/null -w "%{http_code}" --max-time 5 -X POST \
|
||||
-H "X-DashCaddy-Notify-Secret: $secret" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"version\":\"'"$VERSION"'\",\"commit\":\"'"$COMMIT"'\"}" \
|
||||
http://localhost:3001/api/system/update-notify
|
||||
else
|
||||
echo skip
|
||||
fi
|
||||
' 2>/dev/null || true)
|
||||
case "$LOCAL_NOTIFY" in
|
||||
2*) echo "[notify] co-located instance on $RELEASE_HOST → HTTP $LOCAL_NOTIFY" ;;
|
||||
skip) ;; # no secret or instance not up — silent
|
||||
*) echo "[notify] co-located instance notify failed (HTTP $LOCAL_NOTIFY)" >&2 ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# ── Verify ───────────────────────────────────────────────────────────────
|
||||
echo
|
||||
@@ -132,5 +182,15 @@ SHA_HTTP="$(curl -fsSL --max-time 30 "https://get.dashcaddy.net/release/dashcadd
|
||||
[[ "$SHA_LOCAL" == "$SHA_HTTP" ]] || { echo "SHA mismatch on served tarball" >&2; exit 1; }
|
||||
echo " tarball sha256 → $SHA_HTTP ✓"
|
||||
|
||||
if [[ "$MIRROR_OK" == "true" ]]; then
|
||||
GET2_VER="$(curl -fsSL --max-time 5 https://get2.dashcaddy.net/release/version.json 2>/dev/null | node -p "try{JSON.parse(require('fs').readFileSync('/dev/stdin')).version}catch{'unreachable'}" 2>/dev/null || echo unreachable)"
|
||||
if [[ "$GET2_VER" == "$VERSION" ]]; then
|
||||
echo " get2.dashcaddy.net → $GET2_VER ✓"
|
||||
else
|
||||
echo " ! get2.dashcaddy.net serves '$GET2_VER' (expected $VERSION) — check Caddy/DNS for get2" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Done. v$VERSION published from commit $COMMIT."
|
||||
[[ "$MIRROR_OK" == "true" ]] || echo "(reminder: mirror to get2 failed — investigate $MIRROR_HOST)"
|
||||
|
||||
Reference in New Issue
Block a user