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>
168 lines
5.7 KiB
Bash
168 lines
5.7 KiB
Bash
#!/usr/bin/env bash
|
|
# Pipeline: full_git_pull — Pull automatico de fn_registry + sub-repos + submodules + fn sync
|
|
# Descubre repos locales, stashea dirty trees, hace pull --ff-only, actualiza submodules,
|
|
# regenera registry.db y ejecuta fn sync.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
INFRA_DIR="$SCRIPT_DIR/../infra"
|
|
|
|
source "$INFRA_DIR/discover_git_repos.sh"
|
|
source "$INFRA_DIR/git_pull_with_stash.sh"
|
|
source "$INFRA_DIR/pass_get.sh"
|
|
|
|
full_git_pull() {
|
|
# Resolver raiz del registry
|
|
local registry_root="${FN_REGISTRY_ROOT:-/home/lucas/fn_registry}"
|
|
cd "$registry_root"
|
|
|
|
echo "=== full_git_pull: inicio ===" >&2
|
|
echo "Registry root: $registry_root" >&2
|
|
|
|
# --- Paso 1: Descubrir repos ---
|
|
echo "" >&2
|
|
echo "[1/5] Descubriendo repos git..." >&2
|
|
local repos
|
|
repos=$(discover_git_repos "$registry_root")
|
|
local n_repos
|
|
n_repos=$(echo "$repos" | grep -c . || true)
|
|
echo " Encontrados: $n_repos repos" >&2
|
|
|
|
# --- Paso 2: Pull de cada repo ---
|
|
echo "" >&2
|
|
echo "[2/5] Pullando repos..." >&2
|
|
local pull_summary=""
|
|
local diverged=()
|
|
local conflicts=()
|
|
|
|
while IFS= read -r repo; do
|
|
[[ -z "$repo" ]] && continue
|
|
local result
|
|
result=$(git_pull_with_stash "$repo" 2>/dev/null || true)
|
|
if [[ -n "$result" ]]; then
|
|
echo " $result" >&2
|
|
pull_summary="$pull_summary"$'\n'" $result"
|
|
if [[ "$result" == "[diverged]"* ]]; then
|
|
diverged+=("$repo")
|
|
elif [[ "$result" == "[stash-conflict]"* ]]; then
|
|
conflicts+=("$repo")
|
|
fi
|
|
fi
|
|
done <<< "$repos"
|
|
|
|
# --- Paso 3: Submodules del repo principal ---
|
|
echo "" >&2
|
|
echo "[3/5] Actualizando submodulos del repo principal..." >&2
|
|
local submodule_summary=" [skip] sin submodulos"
|
|
if [[ -f "$registry_root/.gitmodules" ]]; then
|
|
local sub_out
|
|
sub_out=$(git -C "$registry_root" submodule update --init --recursive 2>&1 | tail -10 || true)
|
|
echo "$sub_out" >&2
|
|
submodule_summary=" OK: $sub_out"
|
|
fi
|
|
|
|
# --- Paso 3b: Pull de ~/.password-store ---
|
|
echo "" >&2
|
|
echo "[3b] Pullando ~/.password-store..." >&2
|
|
local pass_dir="${PASSWORD_STORE_DIR:-$HOME/.password-store}"
|
|
local pass_summary=" [skip] password-store: no encontrado"
|
|
if [[ -d "$pass_dir/.git" ]]; then
|
|
local pass_result
|
|
pass_result=$(git_pull_with_stash "$pass_dir" 2>/dev/null || true)
|
|
echo " $pass_result" >&2
|
|
pass_summary=" $pass_result"
|
|
if [[ "$pass_result" == "[diverged]"* ]]; then
|
|
diverged+=("$pass_dir")
|
|
elif [[ "$pass_result" == "[stash-conflict]"* ]]; then
|
|
conflicts+=("$pass_dir")
|
|
fi
|
|
fi
|
|
|
|
# --- Paso 4: Regenerar registry.db ---
|
|
echo "" >&2
|
|
echo "[4/5] Regenerando registry.db..." >&2
|
|
local index_summary=" [skip] fn no encontrado"
|
|
local fn_bin="$registry_root/fn"
|
|
if [[ -x "$fn_bin" ]]; then
|
|
local index_out
|
|
index_out=$(CGO_ENABLED=1 "$fn_bin" index 2>&1 | tail -3 || true)
|
|
echo "$index_out" >&2
|
|
index_summary=" OK: $index_out"
|
|
else
|
|
echo " [warn] $fn_bin no encontrado — intentando build..." >&2
|
|
if command -v go >/dev/null 2>&1; then
|
|
CGO_ENABLED=1 go build -tags fts5 -o "$fn_bin" "$registry_root/cmd/fn/" 2>&1 >&2 || true
|
|
if [[ -x "$fn_bin" ]]; then
|
|
local index_out
|
|
index_out=$(CGO_ENABLED=1 "$fn_bin" index 2>&1 | tail -3 || true)
|
|
echo "$index_out" >&2
|
|
index_summary=" OK (post-build): $index_out"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# --- Paso 5: fn sync ---
|
|
echo "" >&2
|
|
echo "[5/5] Ejecutando fn sync..." >&2
|
|
local sync_summary=" [skip] fn sync: credenciales no disponibles"
|
|
if [[ -x "$fn_bin" ]]; then
|
|
local api_user api_pass api_token
|
|
api_user=$(pass_get registry/basicauth-user | head -n1 2>/dev/null || true)
|
|
api_pass=$(pass_get registry/basicauth-pass | head -n1 2>/dev/null || true)
|
|
api_token=$(pass_get registry/api-token | head -n1 2>/dev/null || true)
|
|
|
|
if [[ -n "$api_user" && -n "$api_pass" && -n "$api_token" ]]; then
|
|
export FN_REGISTRY_API="https://${api_user}:${api_pass}@registry.organic-machine.com"
|
|
export REGISTRY_API_TOKEN="$api_token"
|
|
local sync_out
|
|
sync_out=$("$fn_bin" sync 2>&1) && {
|
|
sync_summary=" OK: $sync_out"
|
|
} || {
|
|
sync_summary=" [error] fn sync: $sync_out"
|
|
}
|
|
echo " $sync_summary" >&2
|
|
else
|
|
echo " [warn] Credenciales registry no disponibles — omitiendo fn sync" >&2
|
|
fi
|
|
fi
|
|
|
|
# --- Resumen ---
|
|
echo ""
|
|
echo "===== RESUMEN full_git_pull ====="
|
|
echo ""
|
|
echo "Pull status por repo:"
|
|
if [[ -n "$pull_summary" ]]; then
|
|
echo "$pull_summary"
|
|
else
|
|
echo " (ninguno)"
|
|
fi
|
|
echo ""
|
|
echo "pass-secrets:"
|
|
echo "$pass_summary"
|
|
echo ""
|
|
echo "Submodulos:"
|
|
echo "$submodule_summary"
|
|
echo ""
|
|
echo "fn index:"
|
|
echo "$index_summary"
|
|
echo ""
|
|
echo "fn sync:"
|
|
echo "$sync_summary"
|
|
|
|
if [[ ${#diverged[@]} -gt 0 || ${#conflicts[@]} -gt 0 ]]; then
|
|
echo ""
|
|
echo "ATENCION — Repos que requieren intervencion manual:"
|
|
for r in "${diverged[@]+"${diverged[@]}"}"; do
|
|
echo " [diverged] $r → git rebase o git merge manual"
|
|
done
|
|
for r in "${conflicts[@]+"${conflicts[@]}"}"; do
|
|
echo " [stash-conflict] $r → resolver conflicto y git stash drop"
|
|
done
|
|
fi
|
|
|
|
echo ""
|
|
echo "================================="
|
|
}
|
|
|
|
full_git_pull "$@"
|