upd latam #140
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [ main ] | |
| pull_request: | |
| branches: [ main ] | |
| jobs: | |
| python-lint-and-test: | |
| name: Verificación Python - Lint y Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| lfs: true | |
| submodules: false | |
| - name: Configurar Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.x' | |
| - name: Instalar dependencias Python | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install pyyaml | |
| - name: Verificar sintaxis Python | |
| run: | | |
| python -m py_compile scripts/install.py | |
| python -m py_compile .github/scripts/check-english.py | |
| python -m py_compile .github/scripts/check-mappings.py | |
| python -m py_compile .github/scripts/test_install.py | |
| python -m py_compile .github/scripts/test_sanitize.py | |
| - name: Comprobar bit ejecutable en archivos con shebang | |
| run: | | |
| set -e | |
| fail=0 | |
| files=$(git ls-files || true) | |
| if [ -n "$files" ]; then | |
| for f in $files; do | |
| if [ -f "$f" ]; then | |
| if head -n1 "$f" | grep -q '^#!'; then | |
| mode=$(git ls-files --stage "$f" | awk '{print $1}') | |
| if [ "$mode" != "100755" ]; then | |
| echo "$f tiene shebang pero no es ejecutable en el índice (modo: $mode). Ejecuta: git update-index --chmod=+x $f" | |
| fail=1 | |
| fi | |
| fi | |
| fi | |
| done | |
| fi | |
| if [ "$fail" -eq 1 ]; then exit 1; fi | |
| - name: Verificar no reintroducción de texto en inglés (i18n) | |
| run: | | |
| python .github/scripts/check-english.py | |
| lfs-and-submodule-check: | |
| name: LFS y submódulos | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| lfs: true | |
| submodules: false | |
| - name: Detectar submódulos en .gitmodules (sin acceso de red) | |
| run: | | |
| # Intencionalmente NO intentamos obtener o actualizar submódulos desde CI. | |
| # Algunos submódulos son privados y accesibles solo con la clave SSH del mantenedor. | |
| # En su lugar comprobamos que .gitmodules exista y contenga entradas de submódulos. | |
| if [ -f .gitmodules ]; then | |
| echo ".gitmodules found:"; cat .gitmodules | |
| # List submodule paths and urls | |
| git config -f .gitmodules --get-regexp '^submodule\..*\.path' || true | |
| git config -f .gitmodules --get-regexp '^submodule\..*\.url' || true | |
| COUNT=$(git config -f .gitmodules --get-regexp '^submodule\..*\.path' | wc -l || true) | |
| if [ "$COUNT" -gt 0 ]; then | |
| echo "SUBMODULES_PRESENT=true" >> $GITHUB_ENV | |
| else | |
| echo "SUBMODULES_PRESENT=false" >> $GITHUB_ENV | |
| fi | |
| else | |
| echo ".gitmodules not present" | |
| echo "SUBMODULES_PRESENT=false" >> $GITHUB_ENV | |
| fi | |
| - name: Validar submódulos | |
| if: env.SUBMODULES_PRESENT == 'true' | |
| run: | | |
| git submodule status --recursive | |
| - name: Omitir validación de submódulos (no disponible) | |
| if: env.SUBMODULES_PRESENT == 'false' | |
| run: | | |
| echo "Submódulos no disponibles en este runner (probablemente URLs SSH-only). Omitiendo validación." | |
| - name: Comprobar assets rastreados por LFS | |
| run: | | |
| git lfs ls-files || true | |
| - name: Comprobar que .gitattributes incluya assets/** | |
| run: | | |
| grep -E '^assets/\*\* filter=lfs' .gitattributes | |
| python-install-test: | |
| name: Verificación de Instalación Python | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| lfs: true | |
| submodules: false | |
| - name: Configurar Python | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.x' | |
| - name: Instalar dependencias Python | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install pyyaml | |
| - name: Instalar herramientas (git-lfs) | |
| run: | | |
| sudo apt-get update | |
| # git-lfs es usado por el repo; rsync se requiere para que el instalador copie módulos | |
| sudo apt-get install -y git-lfs rsync || true | |
| - name: Verificar instalador y mapeos | |
| run: | | |
| set -e | |
| TMP=$(mktemp -d) | |
| echo "Testing installer against temp target: $TMP" | |
| # Ejecutar test y capturar salida | |
| echo "=== Ejecutando test_install.py ===" | |
| python .github/scripts/test_install.py 2>&1 | tee /tmp/test-mappings.log | |
| # Verificar que no haya NOTAs críticas (solo permitir las de archivos opcionales conocidos) | |
| echo "" | |
| echo "=== Verificando NOTAs ===" | |
| if grep -q "^NOTA:" /tmp/test-mappings.log; then | |
| echo "⚠️ Se encontraron NOTAs en el test:" | |
| grep "^NOTA:" /tmp/test-mappings.log || true | |
| # Contar NOTAs | |
| nota_count=$(grep -c "^NOTA:" /tmp/test-mappings.log || echo "0") | |
| echo "" | |
| echo "Total de NOTAs: $nota_count" | |
| # Fallar si hay más de 5 NOTAs (archivos opcionales esperados) | |
| if [ "$nota_count" -gt 5 ]; then | |
| echo "❌ ERROR: Demasiadas NOTAs ($nota_count). Se esperan máximo 5 (archivos opcionales)." | |
| exit 1 | |
| else | |
| echo "⚠️ NOTAs dentro del rango aceptable (archivos opcionales conocidos)" | |
| fi | |
| else | |
| echo "✅ No se encontraron NOTAs - Test perfecto!" | |
| fi | |
| - name: Comprobar archivos top-level en módulos que podrían contaminar $HOME | |
| run: | | |
| set -e | |
| cd modules | |
| FAIL=0 | |
| # Construir expresión regular ALLOWED a partir de install-mappings.yml si existe (claves antes de ':'), en caso contrario usar fallback | |
| ALLOWED='' | |
| if [ -f ../install-mappings.yml ]; then | |
| # Extraer claves y generar patrones que acepten tanto la clave completa | |
| # (p. ej. "cargo/config") como su basename (p. ej. "config"). | |
| raw_keys=$(sed -n 's/^[[:space:]]*//;s/#.*//;s/:.*$//;s/|.*$//;p' ../install-mappings.yml | sed '/^[[:space:]]*-/d' | sed '/^$/d' || true) | |
| if [ -n "$raw_keys" ]; then | |
| # Build a list of patterns: for each key produce both the full key and its basename, | |
| # then join with '|' to become a regex alternation. | |
| pats=$(printf '%s\n' "$raw_keys" | awk -F: ' | |
| /^[[:space:]]*#/ { next } | |
| /^[[:space:]]*$/ { next } | |
| { line=$1; sub(/^[[:space:]]*/, "", line); sub(/[[:space:]]*$/, "", line); sub(/\|.*$/, "", line); | |
| n=split(line, parts, "/"); base=parts[n]; | |
| printf "%s|%s\n", line, base | |
| } | |
| ' | tr '\n' '|' | sed 's/|$//' || true) | |
| esc=$(printf '%s' "$pats" | sed -E 's/([^a-zA-Z0-9_\-\.\/|])/\\\\\1/g' || true) | |
| ALLOWED="^$(printf '%s' "$esc" | sed 's/|/\$|^/g')$|^\..+" | |
| fi | |
| fi | |
| if [ -z "$ALLOWED" ]; then | |
| # por defecto solo permitir dotfiles en ausencia de mapeos explícitos | |
| ALLOWED='^\..+' | |
| fi | |
| for m in */ ; do | |
| m=$(basename "$m") | |
| # buscar archivos en la raíz del módulo (no dotfiles) que no estén en la lista permitida | |
| while IFS= read -r -d $'\0' f; do | |
| fname=$(basename "$f") | |
| if [[ ! "$fname" =~ $ALLOWED ]] && [[ ! "$fname" =~ ^\..+ ]]; then | |
| echo "ERROR: El módulo $m contiene un archivo en la raíz que puede instalarse en \$HOME y no está declarado en install-mappings.yml: $fname" >&2 | |
| echo "Ruta conflictiva: $m/$fname" >&2 | |
| FAIL=1 | |
| fi | |
| done < <(find "$m" -maxdepth 1 -type f -print0 || true) | |
| done | |
| if [ "$FAIL" -eq 1 ]; then | |
| echo "Se detectaron archivos en la raíz de módulos que podrían contaminar \$HOME. Agrega un mapeo en install-mappings.yml o renombra/cambia el archivo raíz a un dotfile." >&2 | |
| exit 1 | |
| fi | |
| - name: Forzar cobertura de mapeo para archivos raíz de módulos | |
| run: | | |
| python .github/scripts/check-mappings.py | |
| - name: Ejecutar test completo de instalación | |
| run: | | |
| python .github/scripts/test_install.py | |
| - name: Verificar comportamiento del instalador con permisos | |
| run: | | |
| # Verificar que el instalador maneja correctamente los permisos | |
| # (El instalador Python verifica que no se ejecute como root) | |
| if [ "$(id -u)" = "0" ]; then | |
| echo "Advertencia: Los tests se están ejecutando como root. Esto no es recomendado." >&2 | |
| else | |
| echo "✅ Tests ejecutándose como usuario normal (no root)" | |
| fi | |
| - name: Limpieza | |
| run: | | |
| echo "Limpieza completada" |