#!/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-.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 }