#!/usr/bin/env sh # ๐Ÿค– ops pages โ€” push committed status-page files from web/status/ to the # status box's pages dir, where the 5-minute publisher # (deploy/status-publish.sh) uploads them to status.elevenmessenger.com. # # ./deploy/ops pages push [file...] # default: carbon.json # # This is the encoded form of the accrual runbook's last step (docs/status.md # ยง Keeping the carbon tally accruing): accrue โ†’ commit (tiny PR, merged # promptly) โ†’ push the file here. Files are named by basename and always read # from web/status/ โ€” they are COMMITTED data, so a file with uncommitted local # changes is refused (commit and merge first; the box must never carry a state # main doesn't). # # Write path: the pages dir is setgid, group-writable by lchat-operators, but # the files themselves may be owned by another operator (mode 644) โ€” a direct # scp onto one fails with permission denied. So each file lands as a temp name # and an mv replaces it: a rename needs only the directory write bit, and it's # atomic, so the publisher can never read a half-copied file. set -eu BOX=${LCHAT_STATUS_BOX:-elevenbox} PAGES_DIR=${LCHAT_PAGES_DIR:-/opt/lchat/status-pages} here="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)" repo="$(CDPATH= cd -- "$here/.." && pwd)" usage() { echo "usage: ops pages push [file...] # basenames under web/status/; default: carbon.json" >&2 echo " (box: \$LCHAT_STATUS_BOX, default elevenbox; dir: \$LCHAT_PAGES_DIR)" >&2 exit 2 } cmd="${1:-}" [ $# -gt 0 ] && shift case "$cmd" in push) files="${*:-carbon.json}" for f in $files; do case "$f" in */*) echo "ops pages: '$f' โ€” basenames only (files live in web/status/)" >&2; exit 1 ;; esac src="$repo/web/status/$f" [ -f "$src" ] || { echo "ops pages: no such file web/status/$f" >&2; exit 1; } if ! git -C "$repo" diff --quiet HEAD -- "web/status/$f"; then echo "ops pages: web/status/$f has uncommitted changes โ€” commit (and merge) first" >&2 exit 1 fi done for f in $files; do tmp="$PAGES_DIR/.$f.tmp.$$" echo "ops pages: $f -> $BOX:$PAGES_DIR/" scp -o ConnectTimeout=10 -q "$repo/web/status/$f" "$BOX:$tmp" ssh -o ConnectTimeout=10 "$BOX" "mv '$tmp' '$PAGES_DIR/$f'" done echo "ops pages: done โ€” the publisher uploads within ~5 minutes" echo echo "note: this opened box SSH sessions โ€” if this session hasn't written its" echo " access-ledger why-entry yet: ./deploy/ops ledger \"...\"" ;; -h|--help|help|"") usage ;; *) echo "ops pages: unknown subcommand '$cmd'" >&2; usage ;; esac