625569485f
Adds `fn doctor` read-only diagnostic command with subcommands artefacts, services, sync, uses-functions, unused, and --json flag for agents. Each subcommand wraps a registry function in functions/infra/. New functions: - artefact_doctor, services_status, pc_locations_drift, audit_uses_functions, find_unused_functions (Go diagnostics) - backup_sqlite_db, rotate_backups, wait_for_http, wait_for_port, port_kill, tail_journal, pre_commit_hook_install (bash utilities) - notify_telegram (Go HTTP) - backup_all pipeline (tag launcher) Plus prior session leftovers (scan_secrets_in_dirty, append_diary_entry, git utilities, http_session_cookie_middleware, compile/full-git pipelines). Fixes pc_locations_drift filepath.Join bug with absolute dir_path. Documents fn doctor in CLAUDE.md, .claude/rules/fn_doctor.md (rule 23), docs/architecture.md, CHANGELOG.md (2026-05-07), and diary entry. First fn doctor uses-functions run found drift in 7/12 apps (deuda para sincronizar app.md con imports reales). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
107 lines
3.6 KiB
Bash
107 lines
3.6 KiB
Bash
#!/usr/bin/env bash
|
|
# rotate_backups — retention policy estilo rsnapshot (daily/weekly/monthly)
|
|
|
|
rotate_backups() {
|
|
local dir="$1"
|
|
local new_file="$2"
|
|
local daily=7
|
|
local weekly=4
|
|
local monthly=12
|
|
|
|
# Parsear args posicionales o key=value
|
|
local i=3
|
|
for arg in "${@:3}"; do
|
|
case "$arg" in
|
|
daily=*) daily="${arg#daily=}" ;;
|
|
weekly=*) weekly="${arg#weekly=}" ;;
|
|
monthly=*) monthly="${arg#monthly=}" ;;
|
|
*)
|
|
case $i in
|
|
3) daily="$arg" ;;
|
|
4) weekly="$arg" ;;
|
|
5) monthly="$arg" ;;
|
|
esac
|
|
;;
|
|
esac
|
|
((i++))
|
|
done
|
|
|
|
# Validar numericos
|
|
if ! [[ "$daily" =~ ^[0-9]+$ ]] || ! [[ "$weekly" =~ ^[0-9]+$ ]] || ! [[ "$monthly" =~ ^[0-9]+$ ]]; then
|
|
echo "ERROR: daily, weekly y monthly deben ser enteros positivos" >&2
|
|
return 3
|
|
fi
|
|
|
|
# Validar new_file
|
|
if [[ ! -e "$new_file" ]]; then
|
|
echo "ERROR: new_file no existe: $new_file" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Crear directorio si no existe
|
|
if ! mkdir -p "$dir" 2>/dev/null; then
|
|
echo "ERROR: no se pudo crear el directorio: $dir" >&2
|
|
return 2
|
|
fi
|
|
|
|
local dow
|
|
dow=$(date +%w) # 0=domingo
|
|
local dom
|
|
dom=$(date +%d) # 01-31
|
|
|
|
local rotated_daily=0
|
|
local rotated_weekly=0
|
|
local rotated_monthly=0
|
|
|
|
# --- Monthly: si dia 1, rotar desde weekly.<weekly-1> ANTES de borrar ---
|
|
if [[ "$dom" == "01" ]] && (( monthly > 0 )); then
|
|
local weekly_src="$dir/weekly.$((weekly - 1))"
|
|
if [[ -e "$weekly_src" ]]; then
|
|
# Borrar monthly mas viejo
|
|
local oldest_monthly="$dir/monthly.$((monthly - 1))"
|
|
[[ -e "$oldest_monthly" ]] && rm -rf "$oldest_monthly"
|
|
# Desplazar monthly.<i> → monthly.<i+1>
|
|
for (( j = monthly - 2; j >= 0; j-- )); do
|
|
[[ -e "$dir/monthly.$j" ]] && mv "$dir/monthly.$j" "$dir/monthly.$((j+1))"
|
|
done
|
|
cp -a "$weekly_src" "$dir/monthly.0"
|
|
rotated_monthly=1
|
|
fi
|
|
fi
|
|
|
|
# --- Weekly: si domingo, rotar desde daily.<daily-1> ANTES de borrarlo ---
|
|
if [[ "$dow" == "0" ]] && (( weekly > 0 )); then
|
|
local daily_src="$dir/daily.$((daily - 1))"
|
|
if [[ -e "$daily_src" ]]; then
|
|
# Borrar weekly mas viejo
|
|
local oldest_weekly="$dir/weekly.$((weekly - 1))"
|
|
[[ -e "$oldest_weekly" ]] && rm -rf "$oldest_weekly"
|
|
# Desplazar weekly.<i> → weekly.<i+1>
|
|
for (( j = weekly - 2; j >= 0; j-- )); do
|
|
[[ -e "$dir/weekly.$j" ]] && mv "$dir/weekly.$j" "$dir/weekly.$((j+1))"
|
|
done
|
|
cp -a "$daily_src" "$dir/weekly.0"
|
|
rotated_weekly=1
|
|
fi
|
|
fi
|
|
|
|
# --- Daily: borrar el mas viejo, desplazar, mover new_file a daily.0 ---
|
|
local oldest_daily="$dir/daily.$((daily - 1))"
|
|
[[ -e "$oldest_daily" ]] && rm -rf "$oldest_daily"
|
|
|
|
for (( j = daily - 2; j >= 0; j-- )); do
|
|
[[ -e "$dir/daily.$j" ]] && mv "$dir/daily.$j" "$dir/daily.$((j+1))"
|
|
done
|
|
|
|
mv "$new_file" "$dir/daily.0"
|
|
rotated_daily=1
|
|
|
|
# Contar slots ocupados para el reporte
|
|
local cnt_daily=0 cnt_weekly=0 cnt_monthly=0
|
|
for (( j = 0; j < daily; j++ )); do [[ -e "$dir/daily.$j" ]] && ((cnt_daily++)); done
|
|
for (( j = 0; j < weekly; j++ )); do [[ -e "$dir/weekly.$j" ]] && ((cnt_weekly++)); done
|
|
for (( j = 0; j < monthly; j++ )); do [[ -e "$dir/monthly.$j" ]] && ((cnt_monthly++)); done
|
|
|
|
echo "ROTATED daily=$cnt_daily weekly=$cnt_weekly monthly=$cnt_monthly dir=$dir"
|
|
}
|