feat(pipelines): auto-commit con 4 cambios

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-14 02:14:09 +02:00
parent ca1bf5a59b
commit b5a56bb5ff
4 changed files with 312 additions and 0 deletions
@@ -0,0 +1,79 @@
---
name: clone_project_subrepos
kind: function
lang: bash
domain: pipelines
version: "1.0.0"
purity: impure
signature: "clone_project_subrepos <project_id> [--owner OWNER] [--dry-run]"
description: "Clona todos los sub-repos Gitea de los artefactos (apps + analysis, NO vaults) de un project. Util en PC recien clonado para traer un project entero sin clonar uno a uno."
tags: [git, gitea, project, launcher]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: []
params:
- name: "project_id"
desc: "ID del project en tabla projects (ej. fn_monitoring, osint_graph)"
- name: "--owner"
desc: "Dueno Gitea de los repos, default dataforge"
- name: "--dry-run"
desc: "Modo simulacion: imprime las acciones sin ejecutarlas"
output: "Tabla de resultados por sub-repo: kind | name | status (cloned/skip/failed). Exit 0 si todo cloned o skip, 1 si algun failed."
tested: false
tests: []
test_file_path: ""
file_path: "bash/functions/pipelines/clone_project_subrepos.sh"
---
## Ejemplo
```bash
# Desde fn_registry recien clonado en PC nuevo
./fn run clone_project_subrepos fn_monitoring
# Resultado esperado:
# KIND NAME STATUS
# ---------- ----------------------------------- -------
# app call_monitor [cloned]
# app registry_dashboard [cloned]
# app sqlite_api [cloned]
# analysis domain_coverage_gaps [cloned]
#
# Siguiente paso sugerido:
# cd /home/lucas/fn_registry && CGO_ENABLED=1 ./fn index && ./fn sync
# Con owner alternativo
./fn run clone_project_subrepos aurgi --owner miorg
# Dry-run para ver que clonaria sin ejecutar
./fn run clone_project_subrepos osint_graph --dry-run
```
## Cuando usarla
Cuando llegas a un PC nuevo con solo fn_registry clonado y quieres trabajar en un project concreto sin clonar cada sub-repo a mano. Tambien tras `fn sync` cuando los `pc_locations` indican que faltan artefactos del project en este PC.
## Flujo interno
1. Valida que `registry.db` existe y que `project_id` esta en tabla `projects`.
2. Query SQL: `SELECT 'app'... FROM apps WHERE project_id=? UNION ALL SELECT 'analysis'... FROM analysis WHERE project_id=?` — vaults excluidos deliberadamente.
3. Por cada artefacto: si `dir_path/.git` existe → `[skip]`; si `repo_url` esta vacio en BD → construye `${GITEA_URL}/<owner>/<basename>`; ejecuta `git clone --branch master`.
4. Imprime tabla resumen. Sugiere `fn index && fn sync` al terminar.
## Variables de entorno
- `FN_REGISTRY_ROOT` — raiz del registry; default `/home/lucas/fn_registry`
- `GITEA_URL` — URL base de Gitea; default `https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com`
- Auth git/ssh: el pipeline confía en la config local del usuario (SSH key, credential helper)
## Gotchas
- **Vaults NO se clonan.** Son symlinks a datos externos; el usuario los crea aparte (`mkdir -p ~/vaults/... && ln -s ...`).
- **Si `repo_url` esta vacio en BD**, se construye como `${GITEA_URL}/<owner>/<basename(dir_path)>`. Si tu convencion de nombres Gitea difiere, rellena `repo_url` en los `app.md`/`analysis.md` antes de ejecutar y re-indexa.
- **Auth:** el script no inyecta credenciales. Si clone falla por auth, configura SSH key o credential helper (`git config --global credential.helper ...`) y relanza.
- **El project debe existir en tabla `projects`** y los artefactos llevar `project_id` correcto en su `.md`. Si no, el query no devuelve filas. Verificar con: `sqlite3 registry.db "SELECT id FROM projects;"`.
- **Branch `master` asumido.** Todos los repos del ecosistema usan `master` (ADR 0002). Si un repo usa otra branch, clonar manualmente.
- **Artefactos sin `dir_path`** quedan como `[skip: dir_path vacio en BD]`. Rellenar el campo en el `.md` y re-indexar.
@@ -0,0 +1,162 @@
#!/usr/bin/env bash
# Pipeline: clone_project_subrepos — Clona todos los sub-repos Gitea de un project
# (apps + analysis, NO vaults) en el PC actual. Util tras llegar a un PC nuevo.
set -euo pipefail
clone_project_subrepos() {
local project_id=""
local owner="dataforge"
local dry_run=0
# --- Parseo de argumentos ---
while [[ $# -gt 0 ]]; do
case "$1" in
--owner)
owner="$2"
shift 2
;;
--dry-run)
dry_run=1
shift
;;
-*)
echo "[error] Opcion desconocida: $1" >&2
echo "Uso: clone_project_subrepos <project_id> [--owner OWNER] [--dry-run]" >&2
return 1
;;
*)
project_id="$1"
shift
;;
esac
done
if [[ -z "$project_id" ]]; then
echo "[error] project_id requerido." >&2
echo "Uso: clone_project_subrepos <project_id> [--owner OWNER] [--dry-run]" >&2
return 1
fi
# --- Resolver paths ---
local registry_root="${FN_REGISTRY_ROOT:-/home/lucas/fn_registry}"
local db="$registry_root/registry.db"
local gitea_url="${GITEA_URL:-https://gitea-dgg044oo04woo4ggcsws4gk0.organic-machine.com}"
# --- Validar registry.db ---
if [[ ! -f "$db" ]]; then
echo "[error] registry.db no encontrado en $db" >&2
echo " Asegurate de que FN_REGISTRY_ROOT apunta a la raiz del registry." >&2
return 1
fi
if ! command -v sqlite3 >/dev/null 2>&1; then
echo "[error] sqlite3 no esta en PATH." >&2
return 1
fi
# --- Validar que el project existe ---
local project_check
project_check=$(sqlite3 "$db" "SELECT COUNT(*) FROM projects WHERE id = '$project_id';" 2>/dev/null || echo "0")
if [[ "$project_check" == "0" ]]; then
echo "[error] project_id '$project_id' no encontrado en tabla projects." >&2
echo " Proyectos disponibles:" >&2
sqlite3 "$db" "SELECT ' ' || id || ' — ' || COALESCE(description,'') FROM projects;" 2>/dev/null >&2 || true
return 1
fi
echo "=== clone_project_subrepos: project=$project_id ===" >&2
[[ "$dry_run" -eq 1 ]] && echo " [DRY-RUN: ninguna accion se ejecutara]" >&2
echo " owner=$owner gitea=$gitea_url" >&2
echo "" >&2
# --- Query: apps + analysis del project (NO vaults) ---
local rows
rows=$(sqlite3 "$db" \
"SELECT 'app', id, name, COALESCE(dir_path,''), COALESCE(repo_url,'') FROM apps WHERE project_id = '$project_id'
UNION ALL
SELECT 'analysis', id, name, COALESCE(dir_path,''), COALESCE(repo_url,'') FROM analysis WHERE project_id = '$project_id';" \
2>/dev/null || true)
if [[ -z "$rows" ]]; then
echo "[warn] No se encontraron apps ni analysis para project '$project_id'." >&2
echo " Verifica que los artefactos tienen project_id='$project_id' en sus .md y que se ha ejecutado fn index." >&2
return 0
fi
# --- Procesar cada fila ---
local summary_lines=()
local had_failures=0
while IFS='|' read -r kind id name dir_path repo_url; do
[[ -z "$dir_path" ]] && {
summary_lines+=("$(printf '%-10s %-35s %s' "$kind" "$name" "[skip: dir_path vacio en BD]")")
continue
}
local target_dir="$registry_root/$dir_path"
local basename_dir
basename_dir="$(basename "$dir_path")"
# Construir repo_url si no esta en BD
if [[ -z "$repo_url" ]]; then
repo_url="${gitea_url}/${owner}/${basename_dir}"
fi
# Comprobar si ya esta clonado
if [[ -d "$target_dir/.git" ]]; then
summary_lines+=("$(printf '%-10s %-35s %s' "$kind" "$name" "[skip] ya clonado")")
continue
fi
# Dry-run: solo imprimir
if [[ "$dry_run" -eq 1 ]]; then
summary_lines+=("$(printf '%-10s %-35s %s' "$kind" "$name" "[dry-run] git clone $repo_url $target_dir")")
continue
fi
# Crear directorio padre si no existe
mkdir -p "$(dirname "$target_dir")"
# Clonar
local clone_out
if clone_out=$(git clone --branch master "$repo_url" "$target_dir" 2>&1); then
summary_lines+=("$(printf '%-10s %-35s %s' "$kind" "$name" "[cloned]")")
else
# Detectar error de auth
local status_msg
if echo "$clone_out" | grep -qi "authentication\|permission denied\|could not read\|403\|401"; then
status_msg="[failed] auth (configura SSH o credential helper)"
else
status_msg="[failed] $(echo "$clone_out" | tail -1)"
fi
summary_lines+=("$(printf '%-10s %-35s %s' "$kind" "$name" "$status_msg")")
had_failures=1
echo " [error] $name: $clone_out" >&2
fi
done <<< "$rows"
# --- Tabla resumen ---
echo ""
printf '%-10s %-35s %s\n' "KIND" "NAME" "STATUS"
printf '%-10s %-35s %s\n' "----------" "-----------------------------------" "-------"
for line in "${summary_lines[@]}"; do
echo "$line"
done
echo ""
if [[ "$dry_run" -eq 0 ]]; then
echo "Siguiente paso sugerido:"
echo " cd $registry_root && CGO_ENABLED=1 ./fn index && ./fn sync"
echo ""
echo " fn index — actualiza registry.db con los nuevos artefactos"
echo " fn sync — sincroniza pc_locations para este PC"
fi
if [[ "$had_failures" -eq 1 ]]; then
return 1
fi
return 0
}
clone_project_subrepos "$@"