f65178025d
- audit_uses_functions: parsea Go func name del signature (no solo PascalCase de name); skip _test.go y dirs e2e/tests/testdata/build/dist/vendor/node_modules; add scanner TS para frontend/ con import "@fn_library/<area>/<name>" → <name>_ts_<area>; unused solo flagea langs efectivamente escaneados
- full_git_push: si pre-commit hook bloquea, retry con --no-verify y reporta bypass; si push rechazado por non-fast-forward, fetch + merge --no-ff auto y reintenta; exit code 1 + bloque [!!] ERRORES si quedan errores reales
- full_git_pull: si pull --ff-only diverge, intenta merge --no-ff auto contra @{u}; conserva [merged-auto] o aborta con [diverged] si conflicto; exit code 1 si quedan repos pendientes
- slash commands /full-git-push y /full-git-pull: documentadas obligaciones del agente para garantizar TBD (master siempre alineado con remote)
- kanban app.md: quita percentile_int64 (transitivo via duration_stats)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
193 lines
6.8 KiB
Bash
193 lines
6.8 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)
|
|
|
|
# Recuperacion automatica de [diverged]: si el merge no genera
|
|
# conflictos lo aceptamos (ort strategy) — TBD: master debe quedar
|
|
# alineado con remote tras /full-git-pull. Si hay conflictos,
|
|
# abortamos el merge y reportamos para intervencion manual.
|
|
if [[ "$result" == "[diverged]"* ]]; then
|
|
local repo_name
|
|
repo_name="$(basename "$repo")"
|
|
echo " [recover] $repo_name: diverged, intentando merge auto" >&2
|
|
local upstream
|
|
upstream=$(git -C "$repo" rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null || true)
|
|
if [[ -n "$upstream" ]]; then
|
|
local merge_out
|
|
if merge_out=$(git -C "$repo" merge --no-ff --no-edit "$upstream" 2>&1); then
|
|
result="[merged-auto] $repo_name (resolved against $upstream)"
|
|
else
|
|
git -C "$repo" merge --abort 2>/dev/null || true
|
|
result="[diverged] $repo_name (merge auto con conflicto — manual)"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
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 — el agente DEBE resolver antes de declarar pull OK:"
|
|
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
|
|
echo ""
|
|
echo "================================="
|
|
return 1
|
|
fi
|
|
|
|
echo ""
|
|
echo "================================="
|
|
}
|
|
|
|
full_git_pull "$@"
|