Compare commits
2 Commits
73174acd73
...
cfac85275b
| Author | SHA1 | Date |
|---|---|---|
|
|
cfac85275b | |
|
|
34fbe9886e |
|
|
@ -12,25 +12,9 @@ env:
|
||||||
DOMAIN: "academia.ingeniumcodex.com"
|
DOMAIN: "academia.ingeniumcodex.com"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# Job 1: Build y Test (obligatorio)
|
# Job único: Build, Test y Deploy en K3s (más eficiente en recursos)
|
||||||
test:
|
build-test-deploy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Restore & Build
|
|
||||||
run: dotnet build --configuration Release --verbosity minimal
|
|
||||||
|
|
||||||
- name: Run Tests
|
|
||||||
run: |
|
|
||||||
dotnet test tests/Domain.Tests --no-build -c Release --verbosity minimal
|
|
||||||
dotnet test tests/Application.Tests --no-build -c Release --verbosity minimal
|
|
||||||
|
|
||||||
# Job 2: Deploy (siempre después de tests)
|
|
||||||
deploy:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: test
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
@ -42,22 +26,29 @@ jobs:
|
||||||
chmod 600 ~/.ssh/id_rsa
|
chmod 600 ~/.ssh/id_rsa
|
||||||
ssh-keyscan -H ${{ env.K3S_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
ssh-keyscan -H ${{ env.K3S_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
||||||
|
|
||||||
- name: Deploy to K3s
|
- name: Build, Test & Deploy
|
||||||
run: |
|
run: |
|
||||||
ssh ${{ env.K3S_USER }}@${{ env.K3S_HOST }} << 'ENDSSH'
|
ssh ${{ env.K3S_USER }}@${{ env.K3S_HOST }} << 'ENDSSH'
|
||||||
set -e
|
set -e
|
||||||
cd ~/academia
|
cd ~/academia
|
||||||
|
|
||||||
# Pull latest changes
|
# Pull latest changes
|
||||||
|
echo "=== Pulling latest code ==="
|
||||||
git fetch origin main
|
git fetch origin main
|
||||||
git reset --hard origin/main
|
git reset --hard origin/main
|
||||||
|
|
||||||
# Build images
|
# Run tests (en el servidor que tiene más recursos)
|
||||||
echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S docker build \
|
echo "=== Running tests ==="
|
||||||
|
dotnet test tests/Domain.Tests --verbosity minimal || exit 1
|
||||||
|
dotnet test tests/Application.Tests --verbosity minimal || exit 1
|
||||||
|
|
||||||
|
# Build Docker images
|
||||||
|
echo "=== Building images ==="
|
||||||
|
echo '${{ secrets.K3S_SUDO_PASS }}' | sudo -S docker build \
|
||||||
-f deploy/docker/Dockerfile.api -t student-api:latest . &
|
-f deploy/docker/Dockerfile.api -t student-api:latest . &
|
||||||
PID_API=$!
|
PID_API=$!
|
||||||
|
|
||||||
echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S docker build \
|
echo '${{ secrets.K3S_SUDO_PASS }}' | sudo -S docker build \
|
||||||
-f deploy/docker/Dockerfile.frontend -t student-frontend:latest . &
|
-f deploy/docker/Dockerfile.frontend -t student-frontend:latest . &
|
||||||
PID_FE=$!
|
PID_FE=$!
|
||||||
|
|
||||||
|
|
@ -65,27 +56,30 @@ jobs:
|
||||||
wait $PID_FE || exit 1
|
wait $PID_FE || exit 1
|
||||||
|
|
||||||
# Import to k3s
|
# Import to k3s
|
||||||
echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S sh -c \
|
echo "=== Importing to K3s ==="
|
||||||
|
echo '${{ secrets.K3S_SUDO_PASS }}' | sudo -S sh -c \
|
||||||
'docker save student-api:latest | k3s ctr images import -'
|
'docker save student-api:latest | k3s ctr images import -'
|
||||||
echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S sh -c \
|
echo '${{ secrets.K3S_SUDO_PASS }}' | sudo -S sh -c \
|
||||||
'docker save student-frontend:latest | k3s ctr images import -'
|
'docker save student-frontend:latest | k3s ctr images import -'
|
||||||
|
|
||||||
# Deploy
|
# Deploy
|
||||||
echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl apply -k deploy/k3s/
|
echo "=== Deploying ==="
|
||||||
echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl rollout restart \
|
echo '${{ secrets.K3S_SUDO_PASS }}' | sudo -S kubectl apply -k deploy/k3s/
|
||||||
|
echo '${{ secrets.K3S_SUDO_PASS }}' | sudo -S kubectl rollout restart \
|
||||||
deployment/student-api deployment/student-frontend -n academia
|
deployment/student-api deployment/student-frontend -n academia
|
||||||
|
|
||||||
# Wait for rollout
|
# Wait for rollout
|
||||||
echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl rollout status \
|
echo "=== Waiting for rollout ==="
|
||||||
|
echo '${{ secrets.K3S_SUDO_PASS }}' | sudo -S kubectl rollout status \
|
||||||
deployment/student-api -n academia --timeout=180s
|
deployment/student-api -n academia --timeout=180s
|
||||||
echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl rollout status \
|
echo '${{ secrets.K3S_SUDO_PASS }}' | sudo -S kubectl rollout status \
|
||||||
deployment/student-frontend -n academia --timeout=60s
|
deployment/student-frontend -n academia --timeout=60s
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
|
||||||
# Job 3: Smoke Tests en Producción
|
# Smoke Tests en Producción
|
||||||
smoke-tests:
|
smoke-tests:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: deploy
|
needs: build-test-deploy
|
||||||
steps:
|
steps:
|
||||||
- name: Wait for services
|
- name: Wait for services
|
||||||
run: sleep 15
|
run: sleep 15
|
||||||
|
|
@ -93,35 +87,25 @@ jobs:
|
||||||
- name: Health Check API
|
- name: Health Check API
|
||||||
run: |
|
run: |
|
||||||
response=$(curl -sf https://${{ env.DOMAIN }}/health)
|
response=$(curl -sf https://${{ env.DOMAIN }}/health)
|
||||||
echo "Health response: $response"
|
echo "Health: $response"
|
||||||
echo "$response" | grep -q '"status":"Healthy"' || exit 1
|
echo "$response" | grep -q '"status":"Healthy"' || exit 1
|
||||||
|
|
||||||
- name: Health Check Frontend
|
- name: Frontend Check
|
||||||
run: |
|
run: curl -sf https://${{ env.DOMAIN }}/ | grep -q 'Sistema de Estudiantes' || exit 1
|
||||||
curl -sf https://${{ env.DOMAIN }}/ | grep -q 'Sistema de Estudiantes' || exit 1
|
|
||||||
|
|
||||||
- name: GraphQL Endpoint Check
|
- name: GraphQL Check
|
||||||
run: |
|
run: |
|
||||||
response=$(curl -sf -X POST https://${{ env.DOMAIN }}/graphql \
|
response=$(curl -sf -X POST https://${{ env.DOMAIN }}/graphql \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"query":"{ __typename }"}')
|
-d '{"query":"{ subjects { id name } }"}')
|
||||||
echo "GraphQL response: $response"
|
echo "GraphQL: $response"
|
||||||
echo "$response" | grep -q '"data"' || exit 1
|
|
||||||
|
|
||||||
- name: Database Connectivity Check
|
|
||||||
run: |
|
|
||||||
response=$(curl -sf https://${{ env.DOMAIN }}/health)
|
|
||||||
echo "$response" | grep -q '"name":"database","status":"Healthy"' || exit 1
|
|
||||||
|
|
||||||
- name: Subjects Query Test
|
|
||||||
run: |
|
|
||||||
response=$(curl -sf -X POST https://${{ env.DOMAIN }}/graphql \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"query":"{ subjects { id name credits } }"}')
|
|
||||||
echo "Subjects response: $response"
|
|
||||||
echo "$response" | grep -q '"subjects"' || exit 1
|
echo "$response" | grep -q '"subjects"' || exit 1
|
||||||
|
|
||||||
# Job 4: Rollback automático si smoke tests fallan
|
- name: Database Check
|
||||||
|
run: |
|
||||||
|
curl -sf https://${{ env.DOMAIN }}/health | grep -q '"name":"database","status":"Healthy"' || exit 1
|
||||||
|
|
||||||
|
# Rollback si smoke tests fallan
|
||||||
rollback:
|
rollback:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: smoke-tests
|
needs: smoke-tests
|
||||||
|
|
@ -134,9 +118,9 @@ jobs:
|
||||||
chmod 600 ~/.ssh/id_rsa
|
chmod 600 ~/.ssh/id_rsa
|
||||||
ssh-keyscan -H ${{ env.K3S_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
ssh-keyscan -H ${{ env.K3S_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
||||||
|
|
||||||
- name: Rollback Deployments
|
- name: Rollback
|
||||||
run: |
|
run: |
|
||||||
ssh ${{ env.K3S_USER }}@${{ env.K3S_HOST }} << 'ENDSSH'
|
ssh ${{ env.K3S_USER }}@${{ env.K3S_HOST }} << 'ENDSSH'
|
||||||
echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl rollout undo \
|
echo '${{ secrets.K3S_SUDO_PASS }}' | sudo -S kubectl rollout undo \
|
||||||
deployment/student-api deployment/student-frontend -n academia
|
deployment/student-api deployment/student-frontend -n academia
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
|
|
||||||
45
README.md
45
README.md
|
|
@ -204,8 +204,13 @@ dotnet build
|
||||||
dotnet run --project Host
|
dotnet run --project Host
|
||||||
dotnet watch run --project Host # Hot reload
|
dotnet watch run --project Host # Hot reload
|
||||||
|
|
||||||
# Tests
|
# Tests - Todos
|
||||||
dotnet test
|
dotnet test tests/Application.Tests
|
||||||
|
dotnet test tests/Domain.Tests
|
||||||
|
dotnet test tests/Integration.Tests
|
||||||
|
|
||||||
|
# Tests - Solo Auth
|
||||||
|
dotnet test tests/Application.Tests --filter "FullyQualifiedName~Auth"
|
||||||
|
|
||||||
# Migraciones EF Core
|
# Migraciones EF Core
|
||||||
dotnet ef migrations add <Nombre> -p Adapters/Driven/Persistence -s Host
|
dotnet ef migrations add <Nombre> -p Adapters/Driven/Persistence -s Host
|
||||||
|
|
@ -222,8 +227,44 @@ npx ng serve # Desarrollo
|
||||||
npx ng build --configuration prod # Producción
|
npx ng build --configuration prod # Producción
|
||||||
npx ng test # Tests unitarios
|
npx ng test # Tests unitarios
|
||||||
npx ng lint # Linting
|
npx ng lint # Linting
|
||||||
|
|
||||||
|
# E2E Tests
|
||||||
|
npx playwright test # Todos
|
||||||
|
npx playwright test auth.spec.ts # Solo auth
|
||||||
|
npx playwright test --reporter=html # Con reporte HTML
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Tests Automatizados
|
||||||
|
|
||||||
|
### Resumen
|
||||||
|
|
||||||
|
| Tipo | Cantidad | Estado |
|
||||||
|
|------|----------|--------|
|
||||||
|
| Application Tests | 98 | ✅ 100% |
|
||||||
|
| Domain Tests | 30 | ✅ 100% |
|
||||||
|
| Integration Tests | 5 | ✅ 100% |
|
||||||
|
| E2E Tests | 97 | ⚠️ 26% |
|
||||||
|
| **Total** | **230** | |
|
||||||
|
|
||||||
|
### Tests de Auth (Backend)
|
||||||
|
|
||||||
|
| Handler | Tests | Cobertura |
|
||||||
|
|---------|-------|-----------|
|
||||||
|
| LoginCommand | 6 | Credenciales válidas/inválidas |
|
||||||
|
| RegisterCommand | 8 | Registro, duplicados, validaciones |
|
||||||
|
| ResetPasswordCommand | 8 | Reset válido/inválido |
|
||||||
|
| ActivateAccountCommand | 10 | Activación, expiración, JWT |
|
||||||
|
|
||||||
|
### Tests E2E (Playwright)
|
||||||
|
|
||||||
|
| Categoría | Tests | Descripción |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| Autenticación | 15 | Login, registro, reset |
|
||||||
|
| Control de Acceso | 16 | Roles Admin/Student |
|
||||||
|
| Reglas de Negocio | 16 | Max 3 materias, mismo profesor |
|
||||||
|
| Activación | 18 | Flujo completo de activación |
|
||||||
|
| CRUD | 32 | Estudiantes, inscripciones, compañeros |
|
||||||
|
|
||||||
### Docker
|
### Docker
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue