--- name: ensure_project_gitignore kind: function lang: bash domain: infra version: "1.0.0" purity: impure signature: "ensure_project_gitignore(project_dir: string) -> void" description: "Garantiza de forma idempotente que el .gitignore de un directorio de project contiene las lineas canonicas que excluyen del repo del project el contenido de sus sub-repos hijos (apps y analyses son repos Gitea independientes) y sus vaults (datos fuera de git). Evita el doble-tracking al hacer push del project." tags: [git, gitignore, projects, infra] params: - name: project_dir desc: "Ruta al directorio del project (p. ej. projects/aurgi). Debe existir; si no, error a stderr y return 1. El .gitignore se escribe/actualiza en /.gitignore." output: "Sin salida en stdout. A stderr informa de la accion realizada: 'created' si creo el .gitignore, 'updated: anadidas N lineas' si anadio lineas faltantes, u 'ok: ya completo' si nada cambiaba. Codigo de salida 0 en exito, 1 si project_dir falta o no existe." uses_functions: [] uses_types: [] returns: [] returns_optional: false error_type: "error_go_core" imports: [] tested: false tests: [] test_file_path: "" file_path: "bash/functions/infra/ensure_project_gitignore.sh" --- ## Ejemplo ```bash source bash/functions/infra/ensure_project_gitignore.sh # Asegura que projects/aurgi/.gitignore excluye el contenido de sus hijos. ensure_project_gitignore projects/aurgi # stderr: ensure_project_gitignore: created projects/aurgi/.gitignore # (o: updated: anadidas 2 lineas / ok: ya completo) ``` Las lineas canonicas que la funcion garantiza son: ``` apps/*/ analysis/*/ vaults/* !vaults/.gitkeep !vaults/vault.yaml ``` ## Cuando usarla Llamala justo despues de crear un project nuevo (`mkdir -p projects//{apps,analysis,vaults}`) y antes de inicializar su repo Gitea con `ensure_repo_synced`, para que el repo del project nunca trackee el contenido de sus sub-repos hijos. Tambien al adoptar un project existente que aun no tiene estas exclusiones, o como paso de saneamiento cuando `git status` del project muestra contenido de `apps/`/`analysis/` que deberia estar ignorado. ## Gotchas - La funcion modifica el filesystem (escribe en `/.gitignore`): es impura. No commitea ni hace push — solo deja el `.gitignore` correcto. - La comparacion para no duplicar es linea-exacta (`grep -Fxq`). Una linea equivalente pero con espacios extra, comentario adjunto o glob distinto (p. ej. `apps/*` sin la barra final) NO se considera presente y la canonica se anade igualmente; podrian quedar ambas formas. Mantener el `.gitignore` con las lineas canonicas tal cual evita ruido. - Si el `.gitignore` existente no termina en salto de linea, la funcion anade uno antes de apendar para no pegar la primera linea nueva al final de la ultima existente. - Solo gestiona las exclusiones de sub-repos hijos y vaults del nivel-project; no toca otras reglas que el `.gitignore` ya contenga ni las reordena. - Si una linea canonica ya existia con su forma exacta, no se vuelve a anadir (idempotente): re-ejecutar es seguro.