eleven / messenger Public

deploy: ops dev deploy --home — swap the dev home service too (#1267)

The dev-mesh deploy verb swapped only the control/router binary; the home
service (lchat-home on the dev apex box) had no verb at all, so home
changes were being hand-swapped — exactly the runbook drift ops exists to
close. --home builds ./home for each target's arch, stages it beside the
control binary (incoming/home-new), and swap_home moves it into place with
a home.prev-<ver> rollback + an is-active health check. Boxes without the
unit (Helsinki today) are skipped, never failed. Opt-in so a router-only
deploy doesn't restart home for no reason.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell 3685c1cf6c8e0c9e9bf4811669b1811724f014d8 parent 1a4e3fe
1 file changed, +41 −2
  • deploy/ops-dev.sh +41 −2
diff --git a/deploy/ops-dev.sh b/deploy/ops-dev.sh
index 9493b5b..d8639a8 100755
--- a/deploy/ops-dev.sh
+++ b/deploy/ops-dev.sh
@@ -5,6 +5,7 @@
# ./deploy/ops dev plan # tofu plan, with the AMI-replacement guard
# ./deploy/ops dev deploy [ie|fi] # build -> scp -> swap -> restart (both by default)
# ./deploy/ops dev deploy --stage-only # stop after scp (pair the swap with env edits)
+# ./deploy/ops dev deploy --home # ALSO swap the home service binary (lchat-home)
# ./deploy/ops dev provision [ie|fi] # refresh systemd units + route the short-link apex
# ./deploy/ops dev rebuild --yes # destroy + recreate the Dublin box (new keys)
#
@@ -76,7 +77,7 @@ scp_ie() { if [ -f "$KEY_IE" ]; then scp -i "$KEY_IE" "$@"; else scp "$@"; fi; }
usage() {
echo "usage: ops dev plan [tofu args] | ops dev apply [tofu args] |" >&2
- echo " ops dev deploy [ie|fi] [--stage-only] | ops dev provision [ie|fi] |" >&2
+ echo " ops dev deploy [ie|fi] [--stage-only] [--home] | ops dev provision [ie|fi] |" >&2
echo " ops dev rebuild [--yes]" >&2
exit 2
}
@@ -294,6 +295,33 @@ swap_box() {
fi
}
+# swap_home <ie|fi> <ver>: the home service rides its own binary (releases
+# ship it as lchat-home-linux-* via updaterservices.go; the dev mesh swaps it
+# directly, same as the control binary). A box without the unit (Helsinki
+# today — home runs on the dev apex box only) is skipped, never failed.
+swap_home() {
+ which_box="$1"; ver="$2"
+ if [ "$which_box" = ie ]; then box="$BOX_IE"; run() { ssh_ie "$box" "$@"; }
+ else box="$BOX_FI"; run() { ssh -o ConnectTimeout=10 "$box" "$@"; }
+ fi
+ if ! run 'systemctl list-unit-files lchat-home.service --no-legend 2>/dev/null' | grep -q lchat-home; then
+ echo " $which_box: no lchat-home unit — home skipped"
+ return 0
+ fi
+ run "sudo cp /opt/lchat/home /opt/lchat/home.prev-$ver 2>/dev/null || true; \
+ sudo mv /opt/lchat/incoming/home-new /opt/lchat/home \
+ && sudo chmod +x /opt/lchat/home \
+ && sudo systemctl restart lchat-home"
+ if run 'systemctl is-active --quiet lchat-home'; then
+ echo " $which_box: lchat-home running ($ver)"
+ else
+ echo "ops dev: $which_box lchat-home is NOT active after the swap" >&2
+ echo " inspect: ssh $box journalctl -u lchat-home -n 60 --no-pager" >&2
+ echo " rollback: ssh $box 'sudo mv /opt/lchat/home.prev-$ver /opt/lchat/home && sudo systemctl restart lchat-home'" >&2
+ exit 1
+ fi
+}
+
cmd="${1:-}"
[ $# -gt 0 ] && shift
case "$cmd" in
@@ -318,11 +346,12 @@ apply)
;;
deploy)
- targets="ie fi"; stage_only=no
+ targets="ie fi"; stage_only=no; with_home=no
for a in "$@"; do
case "$a" in
ie|fi) targets="$a" ;;
--stage-only) stage_only=yes ;;
+ --home) with_home=yes ;;
*) usage ;;
esac
done
@@ -343,6 +372,12 @@ deploy)
esac
echo "ops dev: building $ver for linux/$arch ($t)"
OUT="$tmp/lchat-$t" ARCH="$arch" "$here/build-linux.sh" "$ver"
+ if [ "$with_home" = yes ]; then
+ # The home service is its own package/binary (like release-server.sh's
+ # service builds) — no version stamp, the unit check gates the swap.
+ echo "ops dev: building home for linux/$arch ($t)"
+ GOOS=linux GOARCH="$arch" CGO_ENABLED=0 go build -o "$tmp/home-$t" ./home
+ fi
done
for t in $targets; do
@@ -354,14 +389,17 @@ deploy)
if [ "$t" = ie ]; then
ssh_ie "$box" 'sudo mkdir -p /opt/lchat/incoming'
scp_ie -q "$tmp/lchat-$t" "$box:/opt/lchat/incoming/lchat-new"
+ [ "$with_home" = yes ] && scp_ie -q "$tmp/home-$t" "$box:/opt/lchat/incoming/home-new"
else
ssh -o ConnectTimeout=10 "$box" 'sudo mkdir -p /opt/lchat/incoming'
scp -q "$tmp/lchat-$t" "$box:/opt/lchat/incoming/lchat-new"
+ [ "$with_home" = yes ] && scp -q "$tmp/home-$t" "$box:/opt/lchat/incoming/home-new"
fi
done
if [ "$stage_only" = yes ]; then
echo "ops dev: staged at /opt/lchat/incoming/lchat-new on: $targets (not swapped)"
+ [ "$with_home" = yes ] && echo " (home staged beside it as incoming/home-new)"
echo " swap by hand when ready (pairs with env edits — see the cutover runbook)"
exit 0
fi
@@ -369,6 +407,7 @@ deploy)
for t in $targets; do
echo "ops dev: swapping + restarting $t"
swap_box "$t" "$ver"
+ [ "$with_home" = yes ] && swap_home "$t" "$ver"
done
echo
echo "note: this opened dev-box SSH sessions — if this session hasn't written its"