name: CI/CD Pipeline on: push: branches: [main] workflow_dispatch: env: K3S_HOST: "100.67.198.92" K3S_USER: "andres" NAMESPACE: "academia" DOMAIN: "academia.ingeniumcodex.com" jobs: # Job 1: Build y Test (obligatorio) test: 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: - name: Checkout uses: actions/checkout@v4 - name: Setup SSH run: | mkdir -p ~/.ssh echo "${{ secrets.K3S_SSH_KEY }}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan -H ${{ env.K3S_HOST }} >> ~/.ssh/known_hosts 2>/dev/null - name: Deploy to K3s run: | ssh ${{ env.K3S_USER }}@${{ env.K3S_HOST }} << 'ENDSSH' set -e cd ~/academia # Pull latest changes git fetch origin main git reset --hard origin/main # Build images echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S docker build \ -f deploy/docker/Dockerfile.api -t student-api:latest . & PID_API=$! echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S docker build \ -f deploy/docker/Dockerfile.frontend -t student-frontend:latest . & PID_FE=$! wait $PID_API || exit 1 wait $PID_FE || exit 1 # Import to k3s echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S sh -c \ 'docker save student-api:latest | k3s ctr images import -' echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S sh -c \ 'docker save student-frontend:latest | k3s ctr images import -' # Deploy 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 # Wait for rollout echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl rollout status \ deployment/student-api -n academia --timeout=180s echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl rollout status \ deployment/student-frontend -n academia --timeout=60s ENDSSH # Job 3: Smoke Tests en Producción smoke-tests: runs-on: ubuntu-latest needs: deploy steps: - name: Wait for services run: sleep 15 - name: Health Check API run: | response=$(curl -sf https://${{ env.DOMAIN }}/health) echo "Health response: $response" echo "$response" | grep -q '"status":"Healthy"' || exit 1 - name: Health Check Frontend run: | curl -sf https://${{ env.DOMAIN }}/ | grep -q 'Sistema de Estudiantes' || exit 1 - name: GraphQL Endpoint Check run: | response=$(curl -sf -X POST https://${{ env.DOMAIN }}/graphql \ -H "Content-Type: application/json" \ -d '{"query":"{ __typename }"}') echo "GraphQL response: $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 # Job 4: Rollback automático si smoke tests fallan rollback: runs-on: ubuntu-latest needs: smoke-tests if: failure() steps: - name: Setup SSH run: | mkdir -p ~/.ssh echo "${{ secrets.K3S_SSH_KEY }}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan -H ${{ env.K3S_HOST }} >> ~/.ssh/known_hosts 2>/dev/null - name: Rollback Deployments run: | ssh ${{ env.K3S_USER }}@${{ env.K3S_HOST }} << 'ENDSSH' echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl rollout undo \ deployment/student-api deployment/student-frontend -n academia ENDSSH