| index cce77ee..69f3000 100755 |
| --- a/deploy/release-server.sh |
| +++ b/deploy/release-server.sh |
| @@ -9,6 +9,15 @@ |
| # |
| # ./deploy/release-server.sh publish [notes...] # build HEAD -> release server-<sha> -> point edge at it |
| # ./deploy/release-server.sh promote <ver> <chan> # point beta/stable at an already-published version |
| +# ./deploy/release-server.sh ship [ver] # run the box updater until every instance is current |
| +# |
| +# `ship` is the manual-deploy button: publish moves the feed, ship makes the |
| +# box catch up NOW instead of on the hourly timer — it loops `lchat update run` |
| +# until every un-pinned instance is current on its channel (absorbing GitHub's |
| +# stale-CDN window on a fresh manifest); each pass restarts the updated |
| +# instances' bot sidecars in lock-step (deploy/systemd/lchat-bot@.service). |
| +# Needs LCHAT_BOX (e.g. root@<box-ip> — environment specifics live in |
| +# CLAUDE.local.md, never here). `publish ... && ship` is a full deploy. |
| # |
| # Needs: gh (authed, write access to $LCHAT_RELEASES_REPO), jq, go, and the |
| # signing key at $LCHAT_RELEASE_KEY_FILE (1Password: "Eleven Messenger server |
| @@ -153,8 +162,41 @@ promote) |
| echo "promoted $VER to $CHAN" |
| ;; |
| |
| +ship) |
| + VER="${1:-$(git rev-parse --short HEAD)}" |
| + BOX="${LCHAT_BOX:-}" |
| + [ -n "$BOX" ] || { echo "release-server: set LCHAT_BOX (e.g. root@<box>) to ship" >&2; exit 1; } |
| + echo "ship: updating instances on $BOX until current (feed target: $VER)" |
| + DEADLINE=$(( $(date +%s) + 600 )) |
| + while :; do |
| + ssh "$BOX" /opt/lchat/lchat update run || true |
| + STATUS="$(ssh "$BOX" /opt/lchat/lchat update status || true)" |
| + # Done when no un-pinned instance with a known channel head is behind, and |
| + # at least one row proves a feed landed at all. Pinned rows are someone's |
| + # canary: reported, never waited on. |
| + BEHIND="$(printf '%s\n' "$STATUS" | awk 'NR>1 && $3!="pinned" && $5!="-" && $0 !~ /\(current\)/ {print $1}')" |
| + if [ -z "$BEHIND" ] && printf '%s\n' "$STATUS" | grep -q "(current)"; then |
| + printf '%s\n' "$STATUS" |
| + printf '%s\n' "$STATUS" | awk 'NR>1 && $3=="pinned" {print "note: " $1 " is pinned (a canary) - left alone"}' |
| + if printf '%s\n' "$STATUS" | grep -q "$VER (current)"; then |
| + echo "shipped $VER - every un-pinned instance is current" |
| + else |
| + echo "shipped - every un-pinned instance is current on its channel (none rides a channel pointing at $VER yet)" |
| + fi |
| + exit 0 |
| + fi |
| + if [ "$(date +%s)" -ge "$DEADLINE" ]; then |
| + printf '%s\n' "$STATUS" |
| + echo "ship: gave up after 10m - still behind: $BEHIND (GitHub CDN can serve a fresh manifest stale; retry in a few minutes)" >&2 |
| + exit 1 |
| + fi |
| + echo "ship: waiting for the feed/instances (behind: ${BEHIND:-feed})..." |
| + sleep 30 |
| + done |
| + ;; |
| + |
| *) |
| - echo "usage: release-server.sh publish [notes...] | promote <ver> edge|beta|stable" >&2 |
| + echo "usage: release-server.sh publish [notes...] | promote <ver> edge|beta|stable | ship [ver]" >&2 |
| exit 1 |
| ;; |
| esac |