#!/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 "$@"