diff --git a/.github/workflows/validate-docker-compose.yml b/.github/workflows/validate-docker-compose.yml index ddd16aab..25d4eaf3 100644 --- a/.github/workflows/validate-docker-compose.yml +++ b/.github/workflows/validate-docker-compose.yml @@ -17,13 +17,10 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 with: - fetch-depth: 0 # Necesitamos el historial completo para comparar con base + fetch-depth: 0 - name: Set up Docker Compose - run: | - echo "🐳 Setting up Docker Compose..." - # Docker Compose V2 viene preinstalado en ubuntu-latest - docker compose version + run: docker compose version - name: Set up Node.js uses: actions/setup-node@v4 @@ -36,282 +33,89 @@ jobs: version: 8 - name: Install dependencies - run: | - echo "πŸ“¦ Installing Node.js dependencies..." - cd build-scripts && pnpm install + run: cd build-scripts && pnpm install - - name: Get changed files - id: changed-files + - name: Detect changed blueprints + id: changed run: | - echo "πŸ” Detecting changed files..." - - # Obtener la rama base BASE_SHA=$(git merge-base HEAD origin/${{ github.base_ref }}) - # Encontrar todos los archivos docker-compose.yml y template.toml modificados/agregados - CHANGED_COMPOSE=$(git diff --name-only --diff-filter=ACMRT $BASE_SHA HEAD | grep -E 'blueprints/.*/docker-compose\.yml$' || true) - CHANGED_TOML=$(git diff --name-only --diff-filter=ACMRT $BASE_SHA HEAD | grep -E 'blueprints/.*/template\.toml$' || true) + # Obtener todos los blueprints que tienen cambios (en docker-compose.yml o template.toml) + CHANGED_BLUEPRINTS=$(git diff --name-only --diff-filter=ACMRT $BASE_SHA HEAD | \ + grep -E 'blueprints/[^/]+/(docker-compose\.yml|template\.toml)$' | \ + sed 's|blueprints/\([^/]*\)/.*|\1|' | \ + sort -u) - # Crear lista de directorios ΓΊnicos que tienen cambios - CHANGED_DIRS=$(echo -e "$CHANGED_COMPOSE\n$CHANGED_TOML" | sed 's|blueprints/\([^/]*\)/.*|\1|' | sort -u) - - echo "Changed compose files:" - echo "$CHANGED_COMPOSE" | while read file; do [ -n "$file" ] && echo " - $file"; done - - echo "Changed TOML files:" - echo "$CHANGED_TOML" | while read file; do [ -n "$file" ] && echo " - $file"; done - - echo "Changed directories:" - echo "$CHANGED_DIRS" | while read dir; do [ -n "$dir" ] && echo " - $dir"; done - - # Guardar para usar en siguientes pasos - echo "compose_files<> $GITHUB_OUTPUT - echo "$CHANGED_COMPOSE" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - echo "toml_files<> $GITHUB_OUTPUT - echo "$CHANGED_TOML" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - echo "directories<> $GITHUB_OUTPUT - echo "$CHANGED_DIRS" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - - name: Validate Docker Compose files syntax - id: validate-compose-syntax - run: | - echo "πŸ” Validating Docker Compose files syntax..." - - ERROR=0 - COMPOSE_FILES="${{ steps.changed-files.outputs.compose_files }}" - - if [ -z "$COMPOSE_FILES" ]; then - echo "ℹ️ No docker-compose.yml files changed, skipping validation" - exit 0 - fi - - echo "$COMPOSE_FILES" | while read -r compose_file; do - if [ -z "$compose_file" ]; then - continue - fi - - TEMPLATE_DIR=$(dirname "$compose_file") - TEMPLATE_NAME=$(basename "$TEMPLATE_DIR") - - echo "" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "πŸ“¦ Validating syntax: $TEMPLATE_NAME" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - - # Validar sintaxis de docker-compose.yml usando docker compose - echo "πŸ” Validating docker-compose.yml syntax..." - if ! docker compose -f "$compose_file" config > /dev/null 2>&1; then - echo "❌ ERROR: docker-compose.yml syntax is invalid in $TEMPLATE_NAME" - echo "Running docker compose config to show errors:" - docker compose -f "$compose_file" config 2>&1 || true - ERROR=1 - else - echo "βœ… docker-compose.yml syntax is valid" - fi - - # Obtener lista de servicios del compose - SERVICES=$(docker compose -f "$compose_file" config --services 2>/dev/null || echo "") - echo "πŸ“‹ Services found in docker-compose.yml:" - echo "$SERVICES" | while read service; do - [ -n "$service" ] && echo " - $service" - done - - # Guardar servicios para validaciΓ³n posterior - echo "$SERVICES" > "/tmp/${TEMPLATE_NAME}_services.txt" + echo "Changed blueprints:" + echo "$CHANGED_BLUEPRINTS" | while read blueprint; do + [ -n "$blueprint" ] && echo " - $blueprint" done - if [ $ERROR -eq 1 ]; then - echo "" - echo "❌ Docker Compose syntax validation failed" - exit 1 - else - echo "" - echo "βœ… All Docker Compose files have valid syntax" - fi + # Guardar lista de blueprints (una por lΓ­nea) + echo "blueprints<> $GITHUB_OUTPUT + echo "$CHANGED_BLUEPRINTS" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT - - name: Validate Docker Compose best practices - id: validate-compose-practices + - name: Validate blueprints run: | - echo "πŸ” Validating Docker Compose best practices..." + BLUEPRINTS="${{ steps.changed.outputs.blueprints }}" - ERROR=0 - COMPOSE_FILES="${{ steps.changed-files.outputs.compose_files }}" - - if [ -z "$COMPOSE_FILES" ]; then - echo "ℹ️ No docker-compose.yml files changed, skipping validation" + if [ -z "$BLUEPRINTS" ] || [ "$BLUEPRINTS" = "" ]; then + echo "ℹ️ No blueprints changed, skipping validation" exit 0 fi - # Convert to array to avoid subshell issues with pipe - # This ensures ERROR=1 inside the loop propagates to the parent shell - mapfile -t COMPOSE_ARRAY <<< "$COMPOSE_FILES" - - for compose_file in "${COMPOSE_ARRAY[@]}"; do - if [ -z "$compose_file" ]; then - continue - fi - - TEMPLATE_DIR=$(dirname "$compose_file") - TEMPLATE_NAME=$(basename "$TEMPLATE_DIR") - - echo "" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "πŸ“¦ Validating best practices: $TEMPLATE_NAME" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - - # Validar usando el script de TypeScript - if ! (cd build-scripts && pnpm exec tsx validate-docker-compose.ts --file "../$compose_file" --verbose); then - ERROR=1 - fi - done - - if [ $ERROR -eq 1 ]; then - echo "" - echo "❌ Docker Compose best practices validation failed" - exit 1 - else - echo "" - echo "βœ… All Docker Compose files follow best practices" - fi - - - name: Validate template.toml files - id: validate-toml - run: | - echo "πŸ” Validating template.toml files..." - ERROR=0 - DIRECTORIES="${{ steps.changed-files.outputs.directories }}" - if [ -z "$DIRECTORIES" ]; then - echo "ℹ️ No template directories changed, skipping TOML validation" - exit 0 - fi + # Convertir a array para evitar problemas con subshells + mapfile -t BLUEPRINT_ARRAY <<< "$BLUEPRINTS" - # Convert to array to avoid subshell issues with pipe - # This ensures ERROR=1 inside the loop propagates to the parent shell - mapfile -t DIRS_ARRAY <<< "$DIRECTORIES" - - for template_dir in "${DIRS_ARRAY[@]}"; do - if [ -z "$template_dir" ]; then - continue - fi + # Iterar sobre cada blueprint + for blueprint in "${BLUEPRINT_ARRAY[@]}"; do + [ -z "$blueprint" ] && continue - TEMPLATE_PATH="blueprints/$template_dir" - TOML_FILE="$TEMPLATE_PATH/template.toml" - - if [ ! -f "$TOML_FILE" ]; then - echo "⚠️ WARNING: template.toml not found in $template_dir (might be deleted)" - continue - fi + BLUEPRINT_PATH="blueprints/$blueprint" + COMPOSE_FILE="$BLUEPRINT_PATH/docker-compose.yml" + TOML_FILE="$BLUEPRINT_PATH/template.toml" echo "" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "πŸ“ Validating: $template_dir/template.toml" + echo "πŸ“¦ Validating: $blueprint" echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - # Validar usando el script de TypeScript con tsx - # Ejecutar desde build-scripts para tener acceso a node_modules - if ! (cd build-scripts && pnpm exec tsx validate-template.ts --dir "../$TEMPLATE_PATH" --verbose); then - ERROR=1 - fi - done - - if [ $ERROR -eq 1 ]; then - echo "" - echo "❌ template.toml validation failed" - exit 1 - else - echo "" - echo "βœ… All template.toml files are valid" - fi - - - name: Test Docker Compose (dry-run) - id: test-compose - run: | - echo "πŸ§ͺ Testing Docker Compose files (dry-run)..." - - ERROR=0 - DIRECTORIES="${{ steps.changed-files.outputs.directories }}" - - if [ -z "$DIRECTORIES" ]; then - echo "ℹ️ No template directories changed, skipping dry-run test" - exit 0 - fi - - echo "$DIRECTORIES" | while read -r template_dir; do - if [ -z "$template_dir" ]; then - continue - fi - - COMPOSE_FILE="blueprints/$template_dir/docker-compose.yml" - + # 1. Validar best practices de docker-compose.yml if [ ! -f "$COMPOSE_FILE" ]; then + echo "⚠️ WARNING: docker-compose.yml not found" + ERROR=1 + continue + fi + echo "πŸ” Validating docker-compose.yml best practices..." + if ! (cd build-scripts && pnpm exec tsx validate-docker-compose.ts --file "../$COMPOSE_FILE" --verbose); then + ERROR=1 continue fi - echo "" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "πŸ§ͺ Testing: $template_dir" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - - # Cambiar al directorio del template para resolver rutas relativas - cd "blueprints/$template_dir" - - # Validar que docker-compose puede parsear el archivo completamente - echo "πŸ” Running docker compose config (full validation)..." - if docker compose config > /dev/null 2>&1; then - echo "βœ… Docker Compose file is fully valid and can be processed" - - # Mostrar informaciΓ³n ΓΊtil - echo "πŸ“‹ Configuration summary:" - docker compose config --services | while read service; do - [ -n "$service" ] && echo " Service: $service" - done + # 3. Validar template.toml + if [ -f "$TOML_FILE" ]; then + echo "πŸ” Validating template.toml..." + if ! (cd build-scripts && pnpm exec tsx validate-template.ts --dir "../$BLUEPRINT_PATH" --verbose); then + ERROR=1 + continue + fi else - echo "❌ ERROR: Docker Compose file failed full validation" - docker compose config 2>&1 || true + echo "⚠️ WARNING: template.toml not found" ERROR=1 + continue fi - cd - > /dev/null + echo "βœ… All validations passed for $blueprint" done if [ $ERROR -eq 1 ]; then echo "" - echo "❌ Docker Compose dry-run test failed" + echo "❌ Validation failed for one or more blueprints" exit 1 else echo "" - echo "βœ… All Docker Compose files passed dry-run test" + echo "βœ… All blueprints validated successfully" fi - - - name: Summary - if: always() - run: | - echo "" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - echo "πŸ“Š Validation Summary" - echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" - - if [ "${{ steps.validate-compose-syntax.outcome }}" == "success" ] && \ - [ "${{ steps.validate-compose-practices.outcome }}" == "success" ] && \ - [ "${{ steps.validate-toml.outcome }}" == "success" ] && \ - [ "${{ steps.test-compose.outcome }}" == "success" ]; then - echo "βœ… All validations passed!" - echo "" - echo "Your Docker Compose and template.toml files are valid and ready to merge." - else - echo "❌ Some validations failed. Please review the errors above." - echo "" - echo "Common issues to check:" - echo " - docker-compose.yml syntax errors" - echo " - template.toml syntax errors" - echo " - serviceName in template.toml must match service names in docker-compose.yml" - echo " - Avoid using container_name, explicit networks, or port mappings" - fi -