name: Test and Deploy to k3s on: push: branches: [main] workflow_dispatch: env: K3S_HOST: "100.67.198.92" K3S_USER: "andres" NAMESPACE: "academia" DOMAIN: "academia.ingeniumcodex.com" jobs: test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: "10.0.x" - name: Restore dependencies run: dotnet restore - name: Build run: dotnet build --no-restore - name: Run Unit Tests run: dotnet test tests/Domain.Tests --no-build --verbosity normal - name: Run Application Tests run: dotnet test tests/Application.Tests --no-build --verbosity normal - name: Run Integration Tests run: dotnet test tests/Integration.Tests --no-build --verbosity normal 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: Sync code to k3s run: | rsync -az --delete \ --exclude '.git' \ --exclude 'node_modules' \ --exclude 'dist' \ --exclude 'bin' \ --exclude 'obj' \ --exclude '.angular' \ ./ ${{ env.K3S_USER }}@${{ env.K3S_HOST }}:~/academia/ - name: Build images (parallel) run: | ssh ${{ env.K3S_USER }}@${{ env.K3S_HOST }} << 'ENDSSH' cd ~/academia export DOCKER_BUILDKIT=1 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 ENDSSH - name: Import to k3s run: | ssh ${{ env.K3S_USER }}@${{ env.K3S_HOST }} << 'ENDSSH' 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 -' ENDSSH - name: Setup namespace if needed run: | ssh ${{ env.K3S_USER }}@${{ env.K3S_HOST }} << 'ENDSSH' cd ~/academia/deploy/k3s if ! echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl get ns academia &>/dev/null; then echo "Creating namespace and resources..." echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl apply -k . fi ENDSSH - name: Deploy run: | ssh ${{ env.K3S_USER }}@${{ env.K3S_HOST }} << 'ENDSSH' cd ~/academia/deploy/k3s echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl apply -k . echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl rollout restart \ deployment/student-api deployment/student-frontend -n academia ENDSSH - name: Wait rollout run: | ssh ${{ env.K3S_USER }}@${{ env.K3S_HOST }} << 'ENDSSH' echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl rollout status \ deployment/student-api -n academia --timeout=120s echo "${{ secrets.K3S_SUDO_PASS }}" | sudo -S kubectl rollout status \ deployment/student-frontend -n academia --timeout=60s ENDSSH - name: Health check run: | sleep 10 curl -sf https://${{ env.DOMAIN }}/health || exit 1 curl -sf https://${{ env.DOMAIN }}/ || exit 1 - name: Rollback on failure if: failure() 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 2>/dev/null || true ENDSSH