validate_submission #169
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: Validate Java Exercise | |
| on: | |
| repository_dispatch: | |
| types: [validate_submission] | |
| jobs: | |
| test-and-report: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Cache Maven dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.m2/repository | |
| key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-maven- | |
| - name: Setup Java 11 | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: '11' | |
| distribution: 'temurin' | |
| - name: Display received payload | |
| run: | | |
| echo "Submission ID: ${{ github.event.client_payload.submissionId }}" | |
| echo "Exercise ID: ${{ github.event.client_payload.exerciseId }}" | |
| echo "User ID: ${{ github.event.client_payload.userId }}" | |
| - name: Fetch exercise test code from Firestore | |
| id: fetch_test | |
| env: | |
| FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }} | |
| run: | | |
| echo "📥 Obteniendo código de test desde Firestore..." | |
| echo "🔑 Project ID: $FIREBASE_PROJECT_ID" | |
| echo "📝 Exercise ID: ${{ github.event.client_payload.exerciseId }}" | |
| EXERCISE_RESPONSE=$(curl -s \ | |
| "https://firestore.googleapis.com/v1/projects/$FIREBASE_PROJECT_ID/databases/(default)/documents/exercises/${{ github.event.client_payload.exerciseId }}") | |
| # Debug: mostrar respuesta completa | |
| echo "🔍 Respuesta de Firestore (primeros 500 caracteres):" | |
| echo "$EXERCISE_RESPONSE" | head -c 500 | |
| echo "" | |
| echo "---" | |
| # Verificar si hay error en la respuesta | |
| ERROR_CODE=$(echo "$EXERCISE_RESPONSE" | jq -r '.error.code // empty') | |
| if [ ! -z "$ERROR_CODE" ]; then | |
| echo "❌ Error de Firestore: $ERROR_CODE" | |
| echo "$EXERCISE_RESPONSE" | jq '.error' | |
| exit 1 | |
| fi | |
| # Extract testCode field from Firestore response | |
| TEST_CODE=$(echo "$EXERCISE_RESPONSE" | jq -r '.fields.testCode.stringValue // empty') | |
| echo "📏 Longitud del testCode: ${#TEST_CODE}" | |
| # Si no hay testCode, intentar con tests (viejo formato) | |
| if [ -z "$TEST_CODE" ]; then | |
| echo "⚠️ No se encontró campo 'testCode'" | |
| echo "🔍 Campos disponibles en el documento:" | |
| echo "$EXERCISE_RESPONSE" | jq '.fields | keys' | |
| # Usar el test por defecto que ya existe en el repo | |
| if [ ! -f "example/actions-ejemplo/src/test/java/com/javatutor/AppTest.java" ]; then | |
| echo "❌ No se encontró código de test para este ejercicio" | |
| exit 1 | |
| fi | |
| echo "✅ Usando test existente en el repositorio" | |
| else | |
| # Create test directory | |
| mkdir -p example/actions-ejemplo/src/test/java/com/javatutor | |
| # Write test code to AppTest.java | |
| echo "$TEST_CODE" > example/actions-ejemplo/src/test/java/com/javatutor/AppTest.java | |
| echo "✅ Test descargado y guardado desde Firestore" | |
| fi | |
| echo "📄 Contenido del test:" | |
| cat example/actions-ejemplo/src/test/java/com/javatutor/AppTest.java | |
| - name: Verify project structure | |
| run: | | |
| echo "📂 Verificando estructura del proyecto..." | |
| ls -la example/actions-ejemplo/ || echo "❌ No existe example/actions-ejemplo/" | |
| ls -la example/actions-ejemplo/build.gradle || echo "❌ No existe build.gradle" | |
| ls -la example/actions-ejemplo/src/test/java/com/javatutor/ || echo "❌ No existen tests" | |
| - name: Create student code file | |
| run: | | |
| echo "📝 Creando archivo con código del estudiante..." | |
| # Borrar App.java existente para evitar conflictos | |
| rm -f example/actions-ejemplo/src/main/java/com/javatutor/App.java | |
| # Crear directorio | |
| mkdir -p example/actions-ejemplo/src/main/java/com/javatutor | |
| # Guardar el código del estudiante | |
| cat > example/actions-ejemplo/src/main/java/com/javatutor/App.java << 'EOFCODE' | |
| ${{ github.event.client_payload.studentCode }} | |
| EOFCODE | |
| echo "✅ Código del estudiante guardado:" | |
| cat example/actions-ejemplo/src/main/java/com/javatutor/App.java | |
| echo "📏 Número de líneas:" | |
| wc -l example/actions-ejemplo/src/main/java/com/javatutor/App.java | |
| - name: Verify files before compilation | |
| run: | | |
| echo "🔍 Verificando archivos antes de compilar..." | |
| echo "📁 Archivos en src/main/java/com/javatutor/:" | |
| ls -la example/actions-ejemplo/src/main/java/com/javatutor/ | |
| echo "📁 Archivos en src/test/java/com/javatutor/:" | |
| ls -la example/actions-ejemplo/src/test/java/com/javatutor/ | |
| echo "📄 Contenido de App.java:" | |
| cat example/actions-ejemplo/src/main/java/com/javatutor/App.java | |
| - name: Run Maven tests | |
| id: maven_test | |
| continue-on-error: true | |
| working-directory: example/actions-ejemplo | |
| run: | | |
| echo "🧪 Ejecutando tests con Maven..." | |
| # Ejecutar tests con flags de optimización | |
| mvn test -B -q -T 1C \ | |
| -Dmaven.test.failure.ignore=false \ | |
| -Dmaven.javadoc.skip=true \ | |
| -Drat.skip=true \ | |
| -Dcheckstyle.skip=true \ | |
| -Denforcer.skip=true | |
| echo "exit_code=$?" >> $GITHUB_OUTPUT | |
| echo "📁 Archivos generados por Maven:" | |
| ls -la target/surefire-reports/ 2>/dev/null || echo "⚠️ No se generaron resultados de tests" | |
| - name: Parse test results | |
| id: parse_results | |
| run: | | |
| echo "🔍 Parseando resultados de tests..." | |
| # Buscar archivo XML de Maven | |
| XML_FILE=$(find example/actions-ejemplo/target/surefire-reports -name "*.xml" -type f 2>/dev/null | head -n 1) | |
| if [ -f "$XML_FILE" ]; then | |
| echo "✅ Archivo XML encontrado: $XML_FILE" | |
| # Usar grep/sed en lugar de xmllint (más rápido, no requiere instalar paquetes) | |
| TESTS_RUN=$(grep -oP 'tests="\K[^"]+' "$XML_FILE" | head -1) | |
| TESTS_FAILED=$(grep -oP 'failures="\K[^"]+' "$XML_FILE" | head -1) | |
| TESTS_ERRORS=$(grep -oP 'errors="\K[^"]+' "$XML_FILE" | head -1) | |
| TESTS_SKIPPED=$(grep -oP 'skipped="\K[^"]+' "$XML_FILE" | head -1) | |
| # Valores por defecto si están vacíos | |
| TESTS_RUN=${TESTS_RUN:-0} | |
| TESTS_FAILED=${TESTS_FAILED:-0} | |
| TESTS_ERRORS=${TESTS_ERRORS:-0} | |
| TESTS_SKIPPED=${TESTS_SKIPPED:-0} | |
| # Calcular tests pasados | |
| TESTS_PASSED=$((TESTS_RUN - TESTS_FAILED - TESTS_ERRORS - TESTS_SKIPPED)) | |
| echo "📊 Resultados extraídos del XML:" | |
| echo " Tests run: $TESTS_RUN" | |
| echo " Tests passed: $TESTS_PASSED" | |
| echo " Tests failed: $TESTS_FAILED" | |
| echo " Tests errors: $TESTS_ERRORS" | |
| echo "tests_run=$TESTS_RUN" >> $GITHUB_OUTPUT | |
| echo "tests_passed=$TESTS_PASSED" >> $GITHUB_OUTPUT | |
| echo "tests_failed=$TESTS_FAILED" >> $GITHUB_OUTPUT | |
| # Determinar status | |
| if [ "$TESTS_FAILED" -eq "0" ] && [ "$TESTS_ERRORS" -eq "0" ] && [ "$TESTS_RUN" -gt "0" ]; then | |
| echo "status=success" >> $GITHUB_OUTPUT | |
| echo "error_report=" >> $GITHUB_OUTPUT | |
| echo "✅ Todos los tests pasaron" | |
| elif [ "$TESTS_RUN" -eq "0" ]; then | |
| echo "status=error" >> $GITHUB_OUTPUT | |
| echo "error_report=No se ejecutaron tests" >> $GITHUB_OUTPUT | |
| echo "⚠️ No se ejecutaron tests" | |
| else | |
| echo "status=failed" >> $GITHUB_OUTPUT | |
| # Extraer mensaje de error del XML (usando grep/sed, más rápido) | |
| ERROR_MSG=$(grep -oP '<failure[^>]*>\K[^<]+' "$XML_FILE" 2>/dev/null | head -1) | |
| if [ -z "$ERROR_MSG" ]; then | |
| ERROR_MSG=$(grep -oP '<error[^>]*>\K[^<]+' "$XML_FILE" 2>/dev/null | head -1) | |
| fi | |
| if [ -z "$ERROR_MSG" ]; then | |
| ERROR_MSG="Tests fallaron sin mensaje de error" | |
| fi | |
| # Limitar longitud del error | |
| ERROR_MSG="${ERROR_MSG:0:500}" | |
| ERROR_MSG=$(echo "$ERROR_MSG" | sed 's/"/\\"/g' | tr '\n' ' ') | |
| echo "error_report=$ERROR_MSG" >> $GITHUB_OUTPUT | |
| echo "❌ Tests fallaron: $ERROR_MSG" | |
| fi | |
| else | |
| # Si no hay XML, asumir que el exit code indica el resultado | |
| echo "⚠️ XML no encontrado, usando exit code de Maven" | |
| EXIT_CODE="${{ steps.maven_test.outputs.exit_code }}" | |
| if [ "$EXIT_CODE" = "0" ]; then | |
| echo "status=success" >> $GITHUB_OUTPUT | |
| echo "tests_run=1" >> $GITHUB_OUTPUT | |
| echo "tests_passed=1" >> $GITHUB_OUTPUT | |
| echo "tests_failed=0" >> $GITHUB_OUTPUT | |
| echo "error_report=" >> $GITHUB_OUTPUT | |
| else | |
| echo "status=failed" >> $GITHUB_OUTPUT | |
| echo "tests_run=1" >> $GITHUB_OUTPUT | |
| echo "tests_passed=0" >> $GITHUB_OUTPUT | |
| echo "tests_failed=1" >> $GITHUB_OUTPUT | |
| echo "error_report=Test execution failed" >> $GITHUB_OUTPUT | |
| fi | |
| fi | |
| - name: Report results to Firestore | |
| env: | |
| FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }} | |
| run: | | |
| JSON_PAYLOAD=$(cat <<EOF | |
| { | |
| "fields": { | |
| "submissionId": {"stringValue": "${{ github.event.client_payload.submissionId }}"}, | |
| "userId": {"stringValue": "${{ github.event.client_payload.userId }}"}, | |
| "exerciseId": {"stringValue": "${{ github.event.client_payload.exerciseId }}"}, | |
| "status": {"stringValue": "${{ steps.parse_results.outputs.status }}"}, | |
| "testsRun": {"integerValue": "${{ steps.parse_results.outputs.tests_run }}"}, | |
| "testsPassed": {"integerValue": "${{ steps.parse_results.outputs.tests_passed }}"}, | |
| "testsFailed": {"integerValue": "${{ steps.parse_results.outputs.tests_failed }}"}, | |
| "errorReport": {"stringValue": "${{ steps.parse_results.outputs.error_report }}"}, | |
| "completedAt": {"timestampValue": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"}, | |
| "githubRunId": {"stringValue": "${{ github.run_id }}"} | |
| } | |
| } | |
| EOF | |
| ) | |
| echo "Enviando resultados a Firestore..." | |
| curl -X POST \ | |
| "https://firestore.googleapis.com/v1/projects/$FIREBASE_PROJECT_ID/databases/(default)/documents/results" \ | |
| -H "Content-Type: application/json" \ | |
| -d "$JSON_PAYLOAD" | |
| echo "✅ Resultados enviados a Firestore" |