#!/usr/bin/env bash # Pipeline: full_git_push — Push automatico de fn_registry + todos los sub-repos + fn sync # Descubre repos, escanea secrets, auto-commitea dirty trees, pushea solo los ahead, # pushea ~/.password-store, y ejecuta fn sync para sincronizar metadata no regenerable. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" INFRA_DIR="$SCRIPT_DIR/../infra" CYBERSEC_DIR="$SCRIPT_DIR/../cybersecurity" source "$INFRA_DIR/discover_git_repos.sh" source "$INFRA_DIR/git_auto_commit_dirty.sh" source "$INFRA_DIR/git_push_if_ahead.sh" source "$INFRA_DIR/pass_get.sh" source "$INFRA_DIR/ensure_repo_synced.sh" source "$CYBERSEC_DIR/scan_secrets_in_dirty.sh" full_git_push() { local commit_message="${1:-}" # Resolver raiz del registry local registry_root="${FN_REGISTRY_ROOT:-/home/lucas/fn_registry}" cd "$registry_root" echo "=== full_git_push: inicio ===" >&2 echo "Registry root: $registry_root" >&2 # --- Paso 1: Descubrir repos --- echo "" >&2 echo "[1/6] Descubriendo repos git..." >&2 local repos repos=$(discover_git_repos "$registry_root") # --- Paso 1b: Auto-inicializar apps/analyses sin .git --- echo "" >&2 echo "[1b] Verificando apps/analyses sin git..." >&2 local gitea_url gitea_token gitea_url=$(pass_get agentes/gitea-url | head -n1 2>/dev/null || true) gitea_token=$(pass_get gitea/dataforge-git-token | head -n1 2>/dev/null || true) if [[ -n "$gitea_url" && -n "$gitea_token" ]]; then export GITEA_URL="$gitea_url" export GITEA_TOKEN="$gitea_token" export FN_REGISTRY_INFRA_DIR="$INFRA_DIR" local missing_dirs=() for pattern in "apps/*/" "analysis/*/" "projects/*/apps/*/" "projects/*/analysis/*/"; do while IFS= read -r d; do d="${d%/}" if [[ -d "$d" && ! -d "$d/.git" ]]; then missing_dirs+=("$d") fi done < <(find "$registry_root" -maxdepth 4 -type d -name "$(basename "$pattern")" 2>/dev/null | grep -E "$pattern" || true) done # Forma mas directa: iterar directorios conocidos for pattern in apps analysis; do if [[ -d "$registry_root/$pattern" ]]; then for d in "$registry_root/$pattern"/*/; do d="${d%/}" [[ -d "$d" ]] || continue [[ -d "$d/.git" ]] && continue echo " auto-init: $d" >&2 ensure_repo_synced "$d" dataforge "$(basename "$d")" master "chore: initial sync" || \ echo " [warn] fallo inicializando $d" >&2 done fi done for proj in "$registry_root"/projects/*/; do for subdir in apps analysis; do [[ -d "$proj$subdir" ]] || continue for d in "$proj$subdir"/*/; do d="${d%/}" [[ -d "$d" ]] || continue [[ -d "$d/.git" ]] && continue echo " auto-init: $d" >&2 ensure_repo_synced "$d" dataforge "$(basename "$d")" master "chore: initial sync" || \ echo " [warn] fallo inicializando $d" >&2 done done done else echo " [skip] GITEA_URL/GITEA_TOKEN no disponibles — omitiendo auto-init" >&2 fi # Redescubrir repos tras posibles inicializaciones repos=$(discover_git_repos "$registry_root") # --- Paso 2: Escanear secrets --- echo "" >&2 echo "[2/6] Escaneando secrets en dirty trees..." >&2 local secret_matches="" while IFS= read -r repo; do [[ -z "$repo" ]] && continue local matches matches=$(scan_secrets_in_dirty "$repo" 2>/dev/null || true) if [[ -n "$matches" ]]; then secret_matches="$secret_matches"$'\n'"--- $repo ---"$'\n'"$matches" fi done <<< "$repos" if [[ -n "$secret_matches" ]]; then echo "" >&2 echo "ABORTANDO: archivos sospechosos detectados antes de commitear:" >&2 echo "$secret_matches" >&2 echo "" >&2 echo "Gestiona esos archivos (.gitignore, mover, o decidir si entran) y reintenta." >&2 return 1 fi echo " OK: sin archivos sospechosos" >&2 # --- Paso 3: Auto-commitear dirty trees --- echo "" >&2 echo "[3/6] Auto-commiteando dirty trees..." >&2 local commits_summary="" while IFS= read -r repo; do [[ -z "$repo" ]] && continue local subject subject=$(git_auto_commit_dirty "$repo" "$commit_message" 2>/dev/null || true) if [[ -n "$subject" ]]; then local repo_name repo_name="$(basename "$repo")" echo " commit: $repo_name — $subject" >&2 commits_summary="$commits_summary"$'\n'" $repo_name: $subject" fi done <<< "$repos" # --- Paso 4: Push de repos con commits locales --- echo "" >&2 echo "[4/6] Pusheando repos adelantados..." >&2 local push_summary="" while IFS= read -r repo; do [[ -z "$repo" ]] && continue local status_line status_line=$(git_push_if_ahead "$repo" 2>/dev/null || true) if [[ -n "$status_line" ]]; then echo " $status_line" >&2 push_summary="$push_summary"$'\n'" $status_line" fi done <<< "$repos" # --- Paso 5: Push de ~/.password-store (sin commitear) --- echo "" >&2 echo "[5/6] Verificando ~/.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_dirty pass_dirty=$(git -C "$pass_dir" status --porcelain | wc -l) if [[ "$pass_dirty" -gt 0 ]]; then echo " [warn] ~/.password-store tiene cambios sin commitear; pass debe commitear solo. Saltando push." >&2 pass_summary=" [warn] password-store: dirty (pass no commiteo)" else local pass_status pass_status=$(git_push_if_ahead "$pass_dir" 2>/dev/null || true) echo " $pass_status" >&2 pass_summary=" $pass_status" fi fi # --- Paso 6: fn sync --- echo "" >&2 echo "[6/6] Ejecutando fn sync..." >&2 local sync_summary=" [skip] fn sync: credenciales no disponibles" local fn_bin="$registry_root/fn" 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 else echo " [warn] $fn_bin no encontrado — omitiendo fn sync" >&2 fi # --- Resumen --- echo "" echo "===== RESUMEN full_git_push =====" echo "" echo "Commits creados:" if [[ -n "$commits_summary" ]]; then echo "$commits_summary" else echo " (ninguno)" fi echo "" echo "Push status:" if [[ -n "$push_summary" ]]; then echo "$push_summary" else echo " (ninguno)" fi echo "" echo "pass-secrets:" echo "$pass_summary" echo "" echo "fn sync:" echo "$sync_summary" echo "" echo "=================================" } full_git_push "$@"