name: SourceFinder CI/CD Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] env: NODE_VERSION: '18.x' NODE_ENV: test jobs: # Étape 1: Linting et validation du code lint: name: Code Quality & Linting runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run ESLint run: npm run lint - name: Check for security vulnerabilities run: npm audit --audit-level=high # Étape 2: Tests unitaires unit-tests: name: Unit Tests runs-on: ubuntu-latest needs: lint steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run unit tests run: npm run test:unit env: NODE_ENV: test LOG_LEVEL: error - name: Upload unit test results uses: actions/upload-artifact@v4 if: always() with: name: unit-test-results path: coverage/ # Étape 3: Tests de sécurité security-tests: name: Security Tests runs-on: ubuntu-latest needs: lint steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run security tests run: npm run test:security env: NODE_ENV: test LOG_LEVEL: error - name: Upload security test results uses: actions/upload-artifact@v4 if: always() with: name: security-test-results path: coverage/ # Étape 4: Tests d'intégration integration-tests: name: Integration Tests runs-on: ubuntu-latest needs: [unit-tests, security-tests] services: redis: image: redis:7-alpine ports: - 6379:6379 options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run integration tests run: npm run test:integration env: NODE_ENV: test LOG_LEVEL: error REDIS_URL: redis://localhost:6379/15 OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY_TEST }} - name: Upload integration test results uses: actions/upload-artifact@v4 if: always() with: name: integration-test-results path: coverage/ # Étape 5: Tests de performance performance-tests: name: Performance Tests runs-on: ubuntu-latest needs: integration-tests steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run performance tests run: npm run test:performance env: NODE_ENV: test LOG_LEVEL: error - name: Upload performance test results uses: actions/upload-artifact@v4 if: always() with: name: performance-test-results path: coverage/ # Étape 6: Coverage consolidée coverage: name: Code Coverage Report runs-on: ubuntu-latest needs: [unit-tests, security-tests, integration-tests, performance-tests] steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run full test suite with coverage run: npm run test:coverage env: NODE_ENV: test LOG_LEVEL: error - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} file: ./coverage/lcov.info flags: unittests name: sourcefinder-coverage fail_ci_if_error: true - name: Upload coverage report uses: actions/upload-artifact@v4 with: name: coverage-report path: | coverage/ !coverage/tmp/ # Étape 7: Build et validation déploiement build: name: Build & Deployment Validation runs-on: ubuntu-latest needs: coverage strategy: matrix: node-version: ['16.x', '18.x', '20.x'] steps: - uses: actions/checkout@v4 - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'npm' - name: Install dependencies run: npm ci - name: Build application run: npm run build - name: Test application startup run: | timeout 30s npm start & sleep 5 curl --fail http://localhost:3000/health || exit 1 pkill -f "node server.js" env: NODE_ENV: production PORT: 3000 # Étape 8: Tests de régression (sur main seulement) regression-tests: name: Regression Tests runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' needs: build steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # Fetch full history for regression analysis - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run regression test suite run: | npm run test:ci npm run test:performance env: NODE_ENV: test LOG_LEVEL: error - name: Performance regression check run: | echo "Checking performance regression..." # Comparer les métriques avec le commit précédent # (implémentation spécifique selon les outils de monitoring) # Étape 9: Sécurité et vulnérabilités security-audit: name: Security Audit runs-on: ubuntu-latest needs: lint steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run npm audit run: npm audit --audit-level=moderate - name: Run Snyk security scan uses: snyk/actions/node@master continue-on-error: true env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: args: --severity-threshold=medium # Notification des résultats notify: name: Notify Results runs-on: ubuntu-latest needs: [coverage, build, regression-tests, security-audit] if: always() steps: - name: Notify success if: success() run: | echo "✅ All tests passed successfully!" echo "Coverage report available in artifacts" - name: Notify failure if: failure() run: | echo "❌ Some tests failed. Check the logs for details." exit 1 # Configuration des environnements de déploiement deploy-staging: name: Deploy to Staging runs-on: ubuntu-latest needs: [coverage, build] if: github.ref == 'refs/heads/develop' && github.event_name == 'push' environment: name: staging url: https://sourcefinder-staging.example.com steps: - uses: actions/checkout@v4 - name: Deploy to staging run: | echo "🚀 Deploying to staging environment..." # Commandes de déploiement staging - name: Run smoke tests run: | echo "🧪 Running smoke tests on staging..." curl --fail https://sourcefinder-staging.example.com/health deploy-production: name: Deploy to Production runs-on: ubuntu-latest needs: [regression-tests, security-audit] if: github.ref == 'refs/heads/main' && github.event_name == 'push' environment: name: production url: https://sourcefinder.example.com steps: - uses: actions/checkout@v4 - name: Deploy to production run: | echo "🚀 Deploying to production environment..." # Commandes de déploiement production - name: Run production health check run: | echo "🏥 Running production health check..." curl --fail https://sourcefinder.example.com/health