feat: refs #6695 run parallel e2e in local
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
gitea/salix-front/pipeline/pr-dev There was a failure building this commit
Details
This commit is contained in:
parent
47d53e9c87
commit
9d67bbd8ae
|
@ -5,20 +5,19 @@ cleanup() {
|
||||||
|
|
||||||
# Detener todos los procesos en paralelo
|
# Detener todos los procesos en paralelo
|
||||||
kill "${pids[@]}" 2>/dev/null
|
kill "${pids[@]}" 2>/dev/null
|
||||||
|
for pid in "${pids[@]}"; do
|
||||||
|
if kill -0 "$pid" 2>/dev/null; then
|
||||||
|
echo "→ ⏹️ Matando proceso $pid"
|
||||||
|
kill "$pid"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# Buscar y eliminar contenedores que comiencen con NETWORK
|
# Buscar y eliminar contenedores que comiencen con NETWORK
|
||||||
containers=$(docker ps -aq --filter "name=^${NETWORK}")
|
containers=$(docker ps -aq --filter "name=^${NETWORK}")
|
||||||
if [[ -n "$containers" ]]; then
|
if [[ -n "$containers" ]]; then
|
||||||
# echo "🧹 Eliminando contenedores: $containers"
|
# echo "🧹 Eliminando contenedores: $containers"
|
||||||
docker rm -fv $containers >/dev/null 2>&1 || true
|
docker rm -fv $containers >/dev/null 2>&1 || true
|
||||||
echo "✅ → ⏹🧹 Detenido y eliminado contenedores correctamente"
|
echo "⏹ Detenido y eliminado contenedores correctamente"
|
||||||
fi
|
|
||||||
|
|
||||||
# Buscar y eliminar redes que comiencen con NETWORK
|
|
||||||
networks=$(docker network ls --format '{{.Name}}' | grep "^${NETWORK}" || true)
|
|
||||||
if [[ -n "$networks" ]]; then
|
|
||||||
# echo "🧹 Eliminando redes: $networks"
|
|
||||||
docker network rm $networks >/dev/null 2>&1 || true
|
|
||||||
echo "✅ → 🧹 Redes eliminadas correctamente"
|
|
||||||
fi
|
fi
|
||||||
|
exit 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,28 +5,53 @@ source "$(dirname "$0")/cleanup.sh"
|
||||||
source "$(dirname "$0")/setup.sh"
|
source "$(dirname "$0")/setup.sh"
|
||||||
source "$(dirname "$0")/run_group.sh"
|
source "$(dirname "$0")/run_group.sh"
|
||||||
source "$(dirname "$0")/summary.sh"
|
source "$(dirname "$0")/summary.sh"
|
||||||
|
source "$(dirname "$0")/wait_for_api_ready.sh"
|
||||||
|
|
||||||
# Manejo de señales para limpiar si se interrumpe el script
|
# Manejo de señales para limpiar si se interrumpe el script
|
||||||
trap cleanup SIGINT
|
trap cleanup SIGINT
|
||||||
# docker-compose -p lilium-e2e -f docker-compose.e2e.local.yml build cypress-setup >/dev/null 2>&1
|
|
||||||
|
# Docker setup
|
||||||
echo "💿 Construyendo CypressSetup"
|
echo "💿 Construyendo CypressSetup"
|
||||||
docker build -t cypress-setup:latest -f ./test/cypress/Dockerfile . >/dev/null 2>&1
|
docker build -t cypress-setup:latest -f ./test/cypress/Dockerfile . >/dev/null 2>&1
|
||||||
echo "💿 Descargando imagenes actualizadas"
|
echo "💿 Descargando imágenes actualizadas"
|
||||||
docker-compose -f docker-compose.e2e.yml pull back front vn-database
|
docker-compose -f docker-compose.e2e.yml pull back front vn-database
|
||||||
echo "📀 Actualizadas"
|
echo "💿 Levantando los contenedores"
|
||||||
|
docker-compose -p lilium-e2e -f docker-compose.e2e.yml up -d >/dev/null 2>&1
|
||||||
|
|
||||||
# Ejecutar grupos en paralelo y almacenar PIDs
|
wait_for_api_ready "Aplicación" "front" 9000 "/api/Applications/status" "lilium-e2e_default"
|
||||||
for i in "${!groups[@]}"; do
|
echo "📀 Lanzando E2E"
|
||||||
run_group "${groups[$i]}" "$((i+1))" & # Ejecutar en segundo plano
|
|
||||||
pids+=($!) # Guardar el PID del proceso
|
# Lista global de PIDs
|
||||||
|
declare -A running
|
||||||
|
|
||||||
|
# Índice de ejecución de carpetas
|
||||||
|
INDEX_FILE="/tmp/index_file"
|
||||||
|
index=$((numParallelGroups - 1))
|
||||||
|
echo $index > "$INDEX_FILE"
|
||||||
|
|
||||||
|
# 🔹 Lanzar los primeros `numParallelGroups` procesos
|
||||||
|
for ((i = 0; i < numParallelGroups && i < ${#folders[@]}; i++)); do
|
||||||
|
run_group "${folders[$i]}" $i &
|
||||||
done
|
done
|
||||||
|
|
||||||
# Esperar a que terminen todos los procesos en segundo plano
|
# 🔹 Esperar a que todos los procesos terminen
|
||||||
wait "${pids[@]}"
|
while [[ $((index + 2)) -lt ${#folders[@]} ]] || [[ $(docker ps --filter "ancestor=cypress-setup" --format "{{.ID}}" | wc -l) -gt 0 ]]; do
|
||||||
|
# Actualizar index desde el archivo compartido
|
||||||
|
next_index=$(cat "$INDEX_FILE")
|
||||||
|
index=$next_index
|
||||||
|
|
||||||
|
# Mostrar los contenedores en ejecución si hay alguno con imagen "cypress-setup"
|
||||||
|
if [[ $(docker ps --filter "ancestor=cypress-setup" --format "{{.ID}}" | wc -l) -gt 0 ]]; then
|
||||||
|
docker ps --filter "ancestor=cypress-setup" --format " 🔹 ID: {{.ID}} | Nombre: {{.Names}}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 1 # Pausa antes de volver a comprobar
|
||||||
|
done
|
||||||
|
|
||||||
|
docker-compose -p lilium-e2e -f docker-compose.e2e.yml down
|
||||||
|
|
||||||
# Generar el resumen final
|
# Generar el resumen final
|
||||||
generate_summary
|
generate_summary
|
||||||
|
|
||||||
# Limpiar contenedores al finalizar
|
# Limpiar contenedores al finalizar
|
||||||
cleanup
|
cleanup
|
||||||
exit 0
|
|
||||||
|
|
|
@ -1,103 +1,48 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Función para esperar a que un servicio devuelva un JSON con `{ "status": true }` en la red de Docker
|
# Función para esperar a que un servicio devuelva un JSON con `{ "status": true }` en la red de Docker
|
||||||
wait_for_api_ready() {
|
|
||||||
local service_name="$1"
|
|
||||||
local container_name="$2"
|
|
||||||
local port="$3"
|
|
||||||
local path="$4"
|
|
||||||
local network="${5,,}"
|
|
||||||
local max_retries=30 # Máximo de intentos (30 segundos)
|
|
||||||
local retries=0
|
|
||||||
local url="http://$container_name:$port$path"
|
|
||||||
|
|
||||||
# echo "⏳ Esperando a que $service_name devuelva exactamente 'true' en $url..."
|
|
||||||
|
|
||||||
while [[ $retries -lt $max_retries ]]; do
|
|
||||||
response=$(docker run --rm --network="$network" curlimages/curl -s "$url" || echo "error")
|
|
||||||
|
|
||||||
# echo "🔍 Respuesta recibida de $service_name: '$response'"
|
|
||||||
|
|
||||||
if [[ "$response" == "true" ]]; then
|
|
||||||
# echo "✅ Conectado al servicio $service_name → $url!"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
sleep 1
|
|
||||||
((retries++))
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "❌ ERROR: $service_name no respondió con 'true' en $url después de $max_retries intentos."
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
run_group() {
|
run_group() {
|
||||||
local group="$1"
|
local testFolder=$1
|
||||||
local parallelIndex="$2"
|
local parallelIndex=$2
|
||||||
local groupIndex=1
|
local folderName=$(basename "$testFolder" | tr -cd 'a-zA-Z0-9_-')
|
||||||
|
local uniqueName=lilium-e2e
|
||||||
|
|
||||||
|
echo "🔹 Lanzado - $folderName (Grupo: $parallelIndex)"
|
||||||
|
|
||||||
echo "=== Ejecutando grupo paralelo ${parallelIndex} ==="
|
# 🚀 Ejecutar Cypress en modo detach y capturar el container ID
|
||||||
|
containerId=$(docker run -d --name ${uniqueName}_${folderName}_cypress \
|
||||||
|
--network ${uniqueName}_default \
|
||||||
|
-e TZ=Europe/Madrid \
|
||||||
|
-e DOCKER=true \
|
||||||
|
-v "$(pwd)":/app \
|
||||||
|
-w /app \
|
||||||
|
cypress-setup \
|
||||||
|
pnpm exec cypress run --browser chromium --spec test/cypress/integration/${folderName}/**/*.spec.js)
|
||||||
|
|
||||||
for testFolder in $group; do
|
# 🔹 Esperar activamente a que el contenedor finalice
|
||||||
folderName=$(basename "$testFolder" | tr -cd 'a-zA-Z0-9_-')
|
while true; do
|
||||||
uniqueName="${NETWORK}_${folderName}_${parallelIndex}_${groupIndex}"
|
container_status=$(docker inspect -f '{{.State.Running}}' "$containerId" 2>/dev/null || echo "false")
|
||||||
|
if [[ "$container_status" == "false" ]]; then
|
||||||
echo "🔹 $folderName (Grupo: $parallelIndex, Índice: $groupIndex) - Levantado"
|
break
|
||||||
|
|
||||||
export CYPRESS_SPEC="test/cypress/integration/${folderName}/**/*.spec.js"
|
|
||||||
|
|
||||||
# Iniciar servicios del backend y frontend
|
|
||||||
docker-compose -p "$uniqueName" -f docker-compose.e2e.local.yml up -d back >/dev/null 2>&1
|
|
||||||
docker-compose -p "$uniqueName" -f docker-compose.e2e.local.yml up -d front >/dev/null 2>&1
|
|
||||||
|
|
||||||
# 🔹 Esperar a que la API en /api/Applications/status devuelva { "status": true }
|
|
||||||
wait_for_api_ready "Aplicación" "front" 9000 "/api/Applications/status" "${uniqueName}_default"
|
|
||||||
echo "🌐 $folderName (Grupo: $parallelIndex, Índice: $groupIndex) - Conectado"
|
|
||||||
|
|
||||||
# 🚀 Ejecutar pruebas en modo detach
|
|
||||||
docker-compose -p "$uniqueName" -f docker-compose.e2e.local.yml up -d e2e >/dev/null 2>&1
|
|
||||||
|
|
||||||
# 🔹 Esperar hasta que el contenedor de Cypress finalice
|
|
||||||
container_id=""
|
|
||||||
max_retries=10
|
|
||||||
retries=0
|
|
||||||
while [[ -z "$container_id" && $retries -lt $max_retries ]]; do
|
|
||||||
sleep 2
|
|
||||||
container_id=$(docker-compose -p "$uniqueName" -f docker-compose.e2e.local.yml ps -q e2e)
|
|
||||||
((retries++))
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ -z "$container_id" ]]; then
|
|
||||||
echo "⚠️ No se pudo obtener el contenedor para ${folderName} después de $max_retries intentos"
|
|
||||||
failedTests+=("$folderName")
|
|
||||||
continue
|
|
||||||
fi
|
fi
|
||||||
|
sleep 1
|
||||||
# echo "📦 Contenedor $container_id encontrado. Esperando a que finalice..."
|
|
||||||
|
|
||||||
# 🔹 Esperar activamente a que el contenedor finalice
|
|
||||||
while true; do
|
|
||||||
container_status=$(docker inspect -f '{{.State.Running}}' "$container_id" 2>/dev/null || echo "false")
|
|
||||||
if [[ "$container_status" == "false" ]]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
|
|
||||||
# Verificar el código de salida
|
|
||||||
exit_code=$(docker inspect -f '{{.State.ExitCode}}' "$container_id" 2>/dev/null || echo "1")
|
|
||||||
|
|
||||||
if [[ "$exit_code" -ne 0 ]]; then
|
|
||||||
echo "❌ Error en la ejecución de ${folderName} (Exit Code: $exit_code)"
|
|
||||||
buildResult="UNSTABLE"
|
|
||||||
docker logs "$container_id" > "test/cypress/docker/logs/${uniqueName}.log" 2>/dev/null || true
|
|
||||||
failedTests+=("$folderName")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Limpiar contenedores
|
|
||||||
docker-compose -p "$uniqueName" -f docker-compose.e2e.local.yml down >/dev/null 2>&1 || true
|
|
||||||
|
|
||||||
((groupIndex++))
|
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Verificar el código de salida
|
||||||
|
exit_code=$(docker inspect -f '{{.State.ExitCode}}' "$containerId" 2>/dev/null || echo "1")
|
||||||
|
|
||||||
|
if [[ "$exit_code" -ne 0 ]]; then
|
||||||
|
# echo "❌ Error en la ejecución de ${folderName} (Exit Code: $exit_code)"
|
||||||
|
docker logs "$containerId" > "test/cypress/docker/logs/${uniqueName}_${folderName}_log" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
docker rm -f ${uniqueName}_${folderName}_cypress >/dev/null 2>&1 || true
|
||||||
|
|
||||||
|
next_index=$(cat "$INDEX_FILE")
|
||||||
|
next_index=$((next_index + 1))
|
||||||
|
echo "$next_index" > "$INDEX_FILE"
|
||||||
|
|
||||||
|
if [[ $next_index -lt ${#folders[@]} ]]; then
|
||||||
|
run_group "${folders[$next_index]}" $parallelIndex &
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,18 @@
|
||||||
numParallelGroups=${1:-4}
|
numParallelGroups=${1:-4}
|
||||||
NETWORK="lilium-e2e"
|
NETWORK="lilium-e2e"
|
||||||
pids=() # Para almacenar los procesos en paralelo
|
pids=() # Para almacenar los procesos en paralelo
|
||||||
failedTests=() # Para almacenar las carpetas que fallaron
|
|
||||||
|
|
||||||
# Limpiar la carpeta de logs antes de cada ejecución
|
# Limpiar la carpeta de logs antes de cada ejecución
|
||||||
LOG_DIR="test/cypress/docker/logs"
|
LOG_DIR="test/cypress/docker/logs"
|
||||||
|
SCREEN_SHOTS_DIR="test/cypress/screenshots"
|
||||||
if [[ -d "$LOG_DIR" ]]; then
|
if [[ -d "$LOG_DIR" ]]; then
|
||||||
echo "🧹 Borrando logs anteriores en $LOG_DIR..."
|
echo "🧹 Borrando logs anteriores en $LOG_DIR..."
|
||||||
rm -rf "$LOG_DIR"
|
echo "🧹 Borrando screenshots anteriores en $SCREEN_SHOTS_DIR..."
|
||||||
|
sudo rm -rf "$LOG_DIR"
|
||||||
|
sudo rm -rf "$SCREEN_SHOTS_DIR"
|
||||||
fi
|
fi
|
||||||
mkdir -p "$LOG_DIR"
|
mkdir -p "$LOG_DIR"
|
||||||
|
mkdir -p "$SCREEN_SHOTS_DIR"
|
||||||
|
|
||||||
# Verificar si se pasó una carpeta específica como segundo parámetro
|
# Verificar si se pasó una carpeta específica como segundo parámetro
|
||||||
if [[ -n "$2" ]]; then
|
if [[ -n "$2" ]]; then
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
wait_for_api_ready() {
|
||||||
|
local service_name="$1"
|
||||||
|
local container_name="$2"
|
||||||
|
local port="$3"
|
||||||
|
local path="$4"
|
||||||
|
local network="${5,,}"
|
||||||
|
local max_retries=30 # Máximo de intentos (30 segundos)
|
||||||
|
local retries=0
|
||||||
|
local url="http://$container_name:$port$path"
|
||||||
|
|
||||||
|
# echo "⏳ Esperando a que $service_name devuelva exactamente 'true' en $url..."
|
||||||
|
|
||||||
|
while [[ $retries -lt $max_retries ]]; do
|
||||||
|
response=$(docker run --rm --network="$network" curlimages/curl -s "$url" || echo "error")
|
||||||
|
|
||||||
|
# echo "🔍 Respuesta recibida de $service_name: '$response'"
|
||||||
|
|
||||||
|
if [[ "$response" == "true" ]]; then
|
||||||
|
# echo "✅ Conectado al servicio $service_name → $url!"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
((retries++))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "❌ ERROR: $service_name no respondió con 'true' en $url después de $max_retries intentos."
|
||||||
|
exit 1
|
||||||
|
}
|
Loading…
Reference in New Issue