Skip to content

chore(tests): Bump @types/node from 24.9.2 to 25.0.3 in /tests/RentalManager.E2ETests #345

chore(tests): Bump @types/node from 24.9.2 to 25.0.3 in /tests/RentalManager.E2ETests

chore(tests): Bump @types/node from 24.9.2 to 25.0.3 in /tests/RentalManager.E2ETests #345

Workflow file for this run

# Copyright (c) RentalManager. All Rights Reserved.
# Licensed under the MIT License. See LICENSE in the project root for license information.
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
workflow_dispatch:
inputs:
skip_tests:
description: 'Skip tests (faster build)'
required: false
type: boolean
default: false
permissions:
contents: read
actions: read
security-events: write
pull-requests: write
checks: write
env:
DOTNET_VERSION: '9.0.x'
NODE_VERSION: '18'
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
jobs:
# Backend Build and Test
backend:
name: Backend - Build & Test
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: CoreDb_Test
ports:
- 5433:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
redis:
image: redis:7-alpine
ports:
- 6380:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Restore dependencies
run: dotnet restore src/backend/RentalManager.sln
- name: Build backend
run: dotnet build src/backend/RentalManager.sln --configuration Release --no-restore
- name: Run unit tests
run: dotnet test tests/RentalManager.UnitTests/RentalManager.UnitTests.csproj --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=unit-test-results.trx"
- name: Run integration tests
run: dotnet test tests/RentalManager.IntegrationTests/RentalManager.IntegrationTests.csproj --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=integration-test-results.trx"
env:
ConnectionStrings__DefaultConnection: "Host=localhost;Port=5433;Database=CoreDb_Test;Username=postgres;Password=postgres"
Redis__Configuration: "localhost:6380"
- name: Upload test results
if: always()
uses: actions/upload-artifact@v5
with:
name: backend-test-results
path: |
tests/RentalManager.UnitTests/TestResults/*.trx
tests/RentalManager.IntegrationTests/TestResults/*.trx
# Frontend Build and Test
frontend:
name: Frontend - Build & Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
cache-dependency-path: src/frontend/package-lock.json
- name: Install dependencies
working-directory: src/frontend
run: npm ci
- name: Lint frontend code
working-directory: src/frontend
run: npm run lint
- name: Check formatting
working-directory: src/frontend
run: npm run format:check
- name: Type check
working-directory: src/frontend
run: npm run type-check
- name: Build frontend
working-directory: src/frontend
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v5
with:
name: frontend-build
path: src/frontend/dist
# E2E Tests
e2e:
name: E2E Tests
runs-on: ubuntu-latest
needs: [backend, frontend]
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
- name: Start Docker services and capture logs
continue-on-error: true
run: |
echo "Starting Docker services..."
docker compose -f docker-compose.ci.yml up -d || true
# Give containers a moment to start or crash
sleep 5
echo ""
echo "=== Container Status (after startup) ==="
docker ps -a || true
echo ""
echo "=== Backend Container Exit Code ==="
docker inspect rentalmanager-backend-ci --format='{{.State.ExitCode}}' 2>/dev/null || echo "Container not found or failed to inspect"
echo ""
echo "=== Backend Container Status ==="
docker inspect rentalmanager-backend-ci --format='Status: {{.State.Status}}, Error: {{.State.Error}}, Started: {{.State.StartedAt}}' 2>/dev/null || echo "Container not found"
echo ""
echo "=== Full Backend Container Logs ==="
docker logs rentalmanager-backend-ci 2>&1 || echo "Could not retrieve backend logs"
echo ""
echo "=== Backend Container Environment ==="
docker inspect rentalmanager-backend-ci --format='{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null || echo "Could not retrieve environment"
echo ""
echo "=== All Container Logs (for debugging) ==="
docker compose -f docker-compose.ci.yml logs --tail=100 2>&1 || echo "Could not retrieve compose logs"
echo ""
echo "=== Docker Compose PS (all services) ==="
docker compose -f docker-compose.ci.yml ps -a || true
echo ""
echo "=== Frontend Container Status ==="
docker inspect rentalmanager-frontend-ci --format='Status: {{.State.Status}}, Exit Code: {{.State.ExitCode}}, Started: {{.State.StartedAt}}' 2>/dev/null || echo "Frontend container not found or failed to inspect"
echo ""
echo "=== Frontend Container Logs ==="
docker logs rentalmanager-frontend-ci 2>&1 || echo "Could not retrieve frontend logs"
echo ""
echo "=== Frontend Container Environment ==="
docker inspect rentalmanager-frontend-ci --format='{{range .Config.Env}}{{println .}}{{end}}' 2>/dev/null || echo "Could not retrieve frontend environment"
- name: Wait for containers to initialize
continue-on-error: true
run: |
echo "Waiting 60 seconds for containers to initialize..."
sleep 60
echo ""
echo "=== Container Status (after wait) ==="
docker ps -a || true
echo ""
echo "=== Backend Container Logs (last 100 lines) ==="
docker logs --tail 100 rentalmanager-backend-ci 2>&1 || echo "Could not retrieve backend logs"
echo ""
echo "=== Backend Container Exit Code (after wait) ==="
docker inspect rentalmanager-backend-ci --format='Exit Code: {{.State.ExitCode}}, Status: {{.State.Status}}' 2>/dev/null || echo "Container not found"
echo ""
echo "=== Frontend Container Status (after wait) ==="
docker inspect rentalmanager-frontend-ci --format='Status: {{.State.Status}}, Exit Code: {{.State.ExitCode}}' 2>/dev/null || echo "Frontend container not found"
echo ""
echo "=== Frontend Container Logs (after wait) ==="
docker logs --tail 50 rentalmanager-frontend-ci 2>&1 || echo "Could not retrieve frontend logs"
- name: Wait for services to be healthy
run: |
echo "Checking backend health..."
for i in {1..30}; do
if curl -f --max-time 5 --connect-timeout 3 http://localhost:5111/health 2>/dev/null; then
echo "✅ Backend is healthy!"
break
fi
echo "Attempt $i/30: Backend not ready yet..."
sleep 3
done
echo "Checking frontend..."
for i in {1..30}; do
if curl -f --max-time 5 --connect-timeout 3 http://localhost:3001 2>/dev/null; then
echo "✅ Frontend is healthy!"
break
fi
echo "Attempt $i/30: Frontend not ready yet..."
sleep 3
done
echo "✅ All services are ready!"
- name: Show backend logs if health check fails
if: failure()
run: |
echo "=== Full Backend Container Logs ==="
docker logs rentalmanager-backend-ci || true
echo ""
echo "=== Backend Container Inspect (complete) ==="
docker inspect rentalmanager-backend-ci || true
echo ""
echo "=== Backend Container Exit Code ==="
docker inspect rentalmanager-backend-ci --format='Exit Code: {{.State.ExitCode}}, Status: {{.State.Status}}, Error: {{.State.Error}}' || true
echo ""
echo "=== Docker Compose Logs ==="
docker compose -f docker-compose.ci.yml logs backend || true
- name: Install E2E test dependencies
working-directory: tests/RentalManager.E2ETests
run: |
npm ci
npx playwright install chromium --with-deps
- name: Run E2E tests
working-directory: tests/RentalManager.E2ETests
timeout-minutes: 20
run: |
echo "Starting Playwright E2E tests..."
echo "Test timeout: 20 minutes"
echo "Per-test timeout: 60 seconds"
npm test -- --reporter=line
env:
CI: true
BASE_URL: http://localhost:3001
- name: Show test results if failed
if: failure()
working-directory: tests/RentalManager.E2ETests
run: |
echo "=== Test Results Summary ==="
if [ -f "test-results/results.json" ]; then
cat test-results/results.json | head -100
fi
echo "=== Container Logs ==="
docker logs --tail 100 rentalmanager-backend-ci || true
- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v5
with:
name: playwright-report
path: tests/RentalManager.E2ETests/playwright-report/
retention-days: 30
- name: Upload test results
if: failure()
uses: actions/upload-artifact@v5
with:
name: e2e-test-results
path: tests/RentalManager.E2ETests/test-results/
retention-days: 7
- name: Stop Docker services
if: always()
run: docker compose -f docker-compose.ci.yml down -v
# Code Quality Analysis
code-quality:
name: Code Quality
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v5
with:
fetch-depth: 0 # Shallow clones should be disabled for better analysis
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Restore dependencies
run: dotnet restore src/backend/RentalManager.sln
- name: Build for analysis
run: dotnet build src/backend/RentalManager.sln --configuration Release --no-restore
# Optional: Add SonarCloud or similar analysis here
# - name: SonarCloud Scan
# uses: SonarSource/sonarcloud-github-action@master
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
# Docker Build
docker-build:
name: Docker Build
runs-on: ubuntu-latest
needs: [backend, frontend]
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build backend image
uses: docker/build-push-action@v6
with:
context: src/backend
file: src/backend/Dockerfile
push: false
tags: rentalmanager-backend:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Build frontend image
uses: docker/build-push-action@v6
with:
context: src/frontend
file: src/frontend/Dockerfile
push: false
tags: rentalmanager-frontend:latest
cache-from: type=gha
cache-to: type=gha,mode=max
# Security Scanning
security:
name: Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: 'trivy-results.sarif'
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: ${{ env.DOTNET_VERSION }}
- name: Restore .NET dependencies
run: dotnet restore src/backend/RentalManager.sln
- name: Check for .NET vulnerabilities
continue-on-error: true
run: |
dotnet list src/backend/RentalManager.API/RentalManager.API.csproj package --vulnerable --include-transitive
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
cache-dependency-path: src/frontend/package-lock.json
- name: Install npm dependencies
working-directory: src/frontend
run: npm ci
- name: Check for npm vulnerabilities
working-directory: src/frontend
run: npm audit --audit-level=moderate
# Deployment Status
deployment-status:
name: Deployment Status
runs-on: ubuntu-latest
needs: [backend, frontend, e2e, code-quality, docker-build, security]
if: github.ref == 'refs/heads/main'
steps:
- name: Report deployment readiness
run: |
echo "✅ All checks passed!"
echo "🚀 Ready for deployment to staging/production"
echo "📊 Test Results: All tests passed"
echo "🔒 Security: No critical vulnerabilities found"
echo "🐳 Docker: Images built successfully"