name: LabFusion CI/CD Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] env: REGISTRY: gitea.example.com IMAGE_PREFIX: labfusion jobs: # Java Spring Boot API Gateway api-gateway: runs-on: [self-hosted] env: RUNNER_TOOL_CACHE: /toolcache defaults: run: working-directory: ./services/api-gateway steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' cache: maven - name: Make Maven wrapper executable run: chmod +x ./mvnw - name: Cache Maven dependencies uses: actions/cache@v4 with: path: | ~/.m2/repository ~/.m2/wrapper key: maven-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} restore-keys: | maven-${{ runner.os }}- maven- fail-on-cache-miss: false - name: Run tests and send to SonarQube run: | echo "Running tests and sending results to SonarQube..." ./mvnw clean verify sonar:sonar \ -Dsonar.projectKey=labfusion-api-gateway \ -Dsonar.projectName='LabFusion API Gateway' \ -Dsonar.host.url=${{ secrets.SONAR_HOST_URL }} \ -Dsonar.token=${{ secrets.SONAR_TOKEN }} - name: Run code quality checks run: ./mvnw spotbugs:check checkstyle:check - name: Build application run: ./mvnw clean package -DskipTests - name: Build Docker image (test only) run: docker build -t api-gateway:test . # Python FastAPI Service Adapters service-adapters: runs-on: [self-hosted] env: RUNNER_TOOL_CACHE: /toolcache defaults: run: working-directory: ./services/service-adapters steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python 3.11 uses: actions/setup-python@v4 with: python-version: '3.11' - name: Cache pip dependencies uses: actions/cache@v4 with: path: | ~/.cache/pip ~/.local/lib/python*/site-packages key: pip-${{ runner.os }}-${{ hashFiles('**/requirements.txt') }} restore-keys: | pip-${{ runner.os }}- pip- fail-on-cache-miss: false - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install pytest pytest-cov flake8 black isort - name: Run code formatting check run: | black --check . isort --check-only --profile black . - name: Run linting run: flake8 . --count --max-complexity=10 --max-line-length=150 - name: Create test reports directory run: | mkdir -p tests/reports - name: Run tests run: | pytest --cov=. --cov-report=xml --cov-report=html --junitxml=tests/reports/junit.xml - name: Send results to SonarQube run: | echo "Sending Service Adapters results to SonarQube..." # Install pysonar for SonarQube analysis pip install pysonar # Run SonarQube analysis pysonar \ --sonar-host-url=${{ secrets.SONAR_HOST_URL }} \ --sonar-token=${{ secrets.SONAR_TOKEN }} \ --sonar-project-key=labfusion-service-adapters \ --sonar-project-name="LabFusion Service Adapters" - name: Build Docker image (test only) run: docker build -t service-adapters:test . # Node.js API Documentation Service api-docs: runs-on: [self-hosted] env: RUNNER_TOOL_CACHE: /toolcache defaults: run: working-directory: ./services/api-docs steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Node.js 18 uses: actions/setup-node@v4 with: node-version: '18' - name: Cache npm dependencies uses: actions/cache@v4 with: path: | ~/.npm node_modules ~/.cache/node-gyp key: npm-${{ runner.os }}-18-${{ hashFiles('services/api-docs/package-lock.json') }} restore-keys: | npm-${{ runner.os }}-18- npm-${{ runner.os }}- npm- fail-on-cache-miss: false - name: Install dependencies run: | if [ -f package-lock.json ]; then npm ci else npm install fi - name: Run linting run: npm run lint - name: Run tests run: npm test -- --coverage --coverageReporters=lcov --coverageReporters=text --coverageReporters=html - name: Send results to SonarQube run: | echo "Sending API Docs results to SonarQube..." # Install SonarQube Scanner for Node.js npm install -g @sonar/scan # Run SonarQube analysis sonar-scanner \ -Dsonar.host.url=${{ secrets.SONAR_HOST_URL }} \ -Dsonar.login=${{ secrets.SONAR_TOKEN }} \ -Dsonar.projectKey=labfusion-api-docs \ -Dsonar.projectName='LabFusion API Docs' - name: Build application run: npm run build - name: Build Docker image (test only) run: docker build -t api-docs:test . # React Frontend frontend: runs-on: [self-hosted] env: RUNNER_TOOL_CACHE: /toolcache defaults: run: working-directory: ./frontend steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Node.js 18 uses: actions/setup-node@v4 with: node-version: '18' - name: Cache npm dependencies uses: actions/cache@v4 with: path: | ~/.npm node_modules ~/.cache/node-gyp key: npm-${{ runner.os }}-18-${{ hashFiles('frontend/package-lock.json') }} restore-keys: | npm-${{ runner.os }}-18- npm-${{ runner.os }}- npm- fail-on-cache-miss: false - name: Install dependencies run: | if [ -f package-lock.json ]; then npm ci else npm install fi - name: Run linting run: npm run lint - name: Run tests run: npm test -- --coverage --watchAll=false --coverageReporters=lcov --coverageReporters=text --coverageReporters=html - name: Send results to SonarQube run: | echo "Sending Frontend results to SonarQube..." # Install SonarQube Scanner for Node.js npm install -g @sonar/scan # Run SonarQube analysis sonar-scanner \ -Dsonar.host.url=${{ secrets.SONAR_HOST_URL }} \ -Dsonar.login=${{ secrets.SONAR_TOKEN }} \ -Dsonar.projectKey=labfusion-frontend \ -Dsonar.projectName='LabFusion Frontend' - name: Build application run: npm run build - name: Build Docker image (test only) run: docker build -t frontend:test . # Integration Tests integration-tests: runs-on: [self-hosted] needs: [api-gateway, service-adapters, api-docs, frontend] steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Start services with Docker Compose run: | docker-compose -f docker-compose.dev.yml up -d sleep 30 # Wait for services to start - name: Run integration tests run: | # Test API Gateway health curl -f http://localhost:8080/actuator/health || exit 1 # Test Service Adapters health curl -f http://localhost:8000/health || exit 1 # Test API Docs health curl -f http://localhost:3000/health || exit 1 # Test Frontend build curl -f http://localhost:3001 || exit 1 - name: Stop services if: always() run: docker-compose -f docker-compose.dev.yml down