- workplans/RAIL-BS-WP-0004-safety-net.md: ADR-001 workplan file for current-env-safety-net workstream (7e8b0c20), T01-T04 done, T05-T06 todo - tools/cmd/railiance-preflight: update REPOS to OAS S1-S5 stack (railiance-infra/cluster/platform/enablement/apps) + project repos; remove stale railiance-bootstrap reference - docs/backup-restore.md: fix Step 5 clone commands to current repo names - Makefile: add make backup and make preflight targets Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
102 lines
3.7 KiB
Bash
Executable File
102 lines
3.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# tools/cmd/railiance-preflight — pre-migration safety gate
|
||
# Exit 0 = safe to proceed. Exit 1 = do NOT touch infrastructure.
|
||
set -euo pipefail
|
||
|
||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||
source "${ROOT}/lib/railiance-print.sh"
|
||
|
||
# ── Configuration ─────────────────────────────────────────────────────────────
|
||
BACKUP_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/railiance/backups"
|
||
MAX_AGE_HOURS=24
|
||
REPOS=(
|
||
# OAS Stack (S1–S5) — railiance-infra/docs/adr/ADR-003
|
||
/home/worsch/railiance-infra
|
||
/home/worsch/railiance-cluster
|
||
/home/worsch/railiance-platform
|
||
/home/worsch/railiance-enablement
|
||
/home/worsch/railiance-apps
|
||
# Core infrastructure
|
||
/home/worsch/the-custodian
|
||
# Project repos
|
||
/home/worsch/markitect_project
|
||
/home/worsch/activity-core
|
||
/home/worsch/net-kingdom
|
||
/home/worsch/issue-facade
|
||
/home/worsch/binect-js
|
||
/home/worsch/kaizen-agentic
|
||
)
|
||
|
||
# ── Helpers ───────────────────────────────────────────────────────────────────
|
||
fail=0
|
||
pass() { ok "$1" "$2"; }
|
||
fail() { bad "$1" "$2"; fail=1; }
|
||
|
||
backup_age_hours() {
|
||
local file="$1"
|
||
echo $(( ( $(date +%s) - $(stat -c %Y "$file") ) / 3600 ))
|
||
}
|
||
|
||
# ── Checks ────────────────────────────────────────────────────────────────────
|
||
print_hdr "Railiance Preflight Check"
|
||
|
||
# 1. DB backup freshness
|
||
latest_db="$(find "${BACKUP_DIR}" -name "db-*.sql.age" 2>/dev/null | sort -r | head -1)"
|
||
if [[ -z "$latest_db" ]]; then
|
||
fail "db-backup" "no backup found — run: bin/railiance backup"
|
||
else
|
||
h="$(backup_age_hours "$latest_db")"
|
||
if [[ $h -lt $MAX_AGE_HOURS ]]; then
|
||
pass "db-backup" "fresh (${h}h old) — $(basename "$latest_db")"
|
||
else
|
||
fail "db-backup" "stale (${h}h old) — run: bin/railiance backup"
|
||
fi
|
||
fi
|
||
|
||
# 2. Config backup freshness
|
||
latest_cfg="$(find "${BACKUP_DIR}" -name "config-*.tar.gz.age" 2>/dev/null | sort -r | head -1)"
|
||
if [[ -z "$latest_cfg" ]]; then
|
||
fail "cfg-backup" "no backup found — run: bin/railiance backup"
|
||
else
|
||
h="$(backup_age_hours "$latest_cfg")"
|
||
if [[ $h -lt $MAX_AGE_HOURS ]]; then
|
||
pass "cfg-backup" "fresh (${h}h old)"
|
||
else
|
||
fail "cfg-backup" "stale (${h}h old) — run: bin/railiance backup"
|
||
fi
|
||
fi
|
||
|
||
# 3. Git repo state
|
||
for repo in "${REPOS[@]}"; do
|
||
name="$(basename "$repo")"
|
||
if [[ ! -d "$repo/.git" ]]; then
|
||
fail "git:${name}" "not a git repo at ${repo}"
|
||
continue
|
||
fi
|
||
if ! git -C "$repo" diff --quiet 2>/dev/null || \
|
||
! git -C "$repo" diff --cached --quiet 2>/dev/null; then
|
||
fail "git:${name}" "uncommitted changes"
|
||
elif [[ -n "$(git -C "$repo" log --oneline '@{u}..' 2>/dev/null || true)" ]]; then
|
||
fail "git:${name}" "unpushed commits"
|
||
else
|
||
pass "git:${name}" "clean and pushed"
|
||
fi
|
||
done
|
||
|
||
# 4. age key present
|
||
if [[ -f "${HOME}/.config/age/railiance-backup.key" ]]; then
|
||
pass "age-key" "present at ~/.config/age/railiance-backup.key"
|
||
else
|
||
fail "age-key" "missing — run: age-keygen -o ~/.config/age/railiance-backup.key"
|
||
fi
|
||
|
||
# ── Summary ───────────────────────────────────────────────────────────────────
|
||
echo
|
||
if [[ $fail -eq 0 ]]; then
|
||
ok "PREFLIGHT" "all checks passed — safe to proceed"
|
||
exit 0
|
||
else
|
||
bad "PREFLIGHT" "checks failed — do NOT proceed with infrastructure work"
|
||
exit 1
|
||
fi
|