Three coordinated fixes from the upgrade-flow redesign plan (/home/bunker-admin/.claude/plans/okay-so-we-can-enumerated-hejlsberg.md): 1. scripts/lib/mkdocs-snapshot.sh (NEW): pre-upgrade tarball snapshot of the entire mkdocs/ directory into the install root as mkdocs-backup-<timestamp>.tar.gz. Discoverable via `ls`, retained last 5. No-regrets fallback if anything in the upgrade goes sideways. Sourced by upgrade.sh (and later by image-upgrade.sh under Approach B). 2. scripts/upgrade.sh Phase 6 self-destruct fix: previously, the broad `docker compose up -d` recreated the ccp-agent container that was running the script, sending SIGKILL to the bash process before write_result could land result.json. Marcelle's test upgrade hit this tonight. Fix: temporarily remove `ccp-agent` from COMPOSE_PROFILES during Phase 6's broad up -d, then schedule a detached `nohup ... & disown` restart at the very end of the script (after write_result and archive_success_to_history). The deferred subshell sleeps 3s, then recreates ccp-agent under its profile, picking up the new image. 3. scripts/upgrade-stash-cleanup.sh (NEW): one-shot utility to list and drop accumulated `upgrade-*` git stashes left over by older upgrade.sh runs whose pop failed silently (Pride Corner has three from 2026-03-09 alone). Warns loudly if any stash holds tenant mkdocs.yml content so operators verify recovery before dropping. The .gitignore now excludes /mkdocs-backup-*.tar.gz so the rescue archives don't leak into commits. This is Phase 1 of three: Approach B (image-only upgrade mode) and Approach C (CCP template re-render) follow in subsequent commits. Bunker Admin
82 lines
3.1 KiB
Bash
Executable File
82 lines
3.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# =============================================================================
|
|
# mkdocs-snapshot.sh — shared library function
|
|
# =============================================================================
|
|
# Defines snapshot_mkdocs(): writes a tarball of mkdocs/ into the install root
|
|
# as mkdocs-backup-<timestamp>.tar.gz, keeping the last 5 snapshots.
|
|
#
|
|
# Sourced by scripts/upgrade.sh and scripts/image-upgrade.sh (and may be
|
|
# invoked agent-side by changemaker-control-panel during template re-render).
|
|
#
|
|
# Why the install root instead of backups/?
|
|
# - Discoverable: operators see mkdocs-backup-*.tar.gz with a plain `ls`.
|
|
# - The agent's /app/instance bind mount maps directly to the install root,
|
|
# so the agent can restore from this archive without path translation.
|
|
# - backups/ is owned by root in some installs (DB dumps via container)
|
|
# and gets rotated on a different schedule than docs snapshots.
|
|
#
|
|
# Restoration one-liner:
|
|
# tar xzf "$(ls -t mkdocs-backup-*.tar.gz | head -1)" -C . \
|
|
# && docker compose restart mkdocs mkdocs-site-server
|
|
#
|
|
# Requires: $PROJECT_DIR (absolute path to install root), info() function
|
|
# from the caller (falls back to plain echo if info is not defined).
|
|
# =============================================================================
|
|
|
|
# Fallback log function if caller didn't define one (e.g. when sourcing standalone)
|
|
if ! declare -F info >/dev/null 2>&1; then
|
|
info() { echo "[INFO] $*"; }
|
|
fi
|
|
if ! declare -F warn >/dev/null 2>&1; then
|
|
warn() { echo "[WARN] $*" >&2; }
|
|
fi
|
|
|
|
# snapshot_mkdocs — take a tarball of mkdocs/ into the install root.
|
|
#
|
|
# Returns 0 if successful (or if mkdocs/ doesn't exist — non-fatal).
|
|
# Returns non-zero only if tar itself fails AND $SNAPSHOT_REQUIRED is true.
|
|
#
|
|
# Optional env vars:
|
|
# PROJECT_DIR (required) Install root containing mkdocs/
|
|
# SNAPSHOT_KEEP Number of snapshots to retain (default 5)
|
|
# SNAPSHOT_REQUIRED If "true", failure to snapshot aborts (default false)
|
|
snapshot_mkdocs() {
|
|
if [[ -z "${PROJECT_DIR:-}" ]]; then
|
|
warn "snapshot_mkdocs: PROJECT_DIR not set; skipping"
|
|
return 0
|
|
fi
|
|
|
|
if [[ ! -d "${PROJECT_DIR}/mkdocs" ]]; then
|
|
# No mkdocs dir = nothing to snapshot. Common on minimal installs.
|
|
return 0
|
|
fi
|
|
|
|
local stamp
|
|
stamp="$(date +%Y%m%d_%H%M%S)"
|
|
local archive="${PROJECT_DIR}/mkdocs-backup-${stamp}.tar.gz"
|
|
local keep="${SNAPSHOT_KEEP:-5}"
|
|
|
|
if tar czf "$archive" -C "$PROJECT_DIR" mkdocs 2>/dev/null; then
|
|
local size
|
|
size="$(du -h "$archive" 2>/dev/null | cut -f1)"
|
|
info "Tenant docs snapshot: $(basename "$archive") (${size})"
|
|
else
|
|
warn "snapshot_mkdocs: tar failed for $archive"
|
|
rm -f "$archive" 2>/dev/null
|
|
if [[ "${SNAPSHOT_REQUIRED:-false}" == "true" ]]; then
|
|
return 1
|
|
fi
|
|
return 0
|
|
fi
|
|
|
|
# Retention: keep the most recent N snapshots, prune older ones.
|
|
# ls -t lists newest first; tail -n +N+1 selects items after the Nth.
|
|
local prune_from=$((keep + 1))
|
|
# shellcheck disable=SC2012 # ls is intentional for mtime sort
|
|
ls -t "${PROJECT_DIR}"/mkdocs-backup-*.tar.gz 2>/dev/null \
|
|
| tail -n +${prune_from} \
|
|
| xargs -r rm -f
|
|
|
|
return 0
|
|
}
|