Skip to content

validate_submission #171

validate_submission

validate_submission #171

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"