UNPKG

backend-mcp

Version:

Generador automΓ‘tico de backends con Node.js, Express, Prisma y mΓ³dulos configurables. Servidor MCP compatible con npx para agentes IA. Soporta PostgreSQL, MySQL, MongoDB y SQLite.

1,262 lines (1,078 loc) β€’ 32.8 kB
// modules/ci/init.js const fs = require('fs'); const path = require('path'); class CIModule { constructor(config = {}) { this.config = { platform: config.platform || 'github', // github, gitlab, jenkins environments: config.environments || ['development', 'staging', 'production'], testing: config.testing !== false, security: config.security !== false, docker: config.docker || false, notifications: config.notifications || {}, deployment: config.deployment || {}, qualityGates: config.qualityGates || {}, ...config }; this.projectRoot = config.projectRoot || process.cwd(); } async init() { console.log('πŸš€ Initializing CI/CD Module...'); try { await this.setupDirectories(); await this.generateWorkflows(); await this.generateScripts(); await this.generateConfigs(); await this.updatePackageJson(); console.log('βœ… CI/CD Module initialized successfully!'); console.log('πŸ“ Generated files:', this.getGeneratedFiles()); return { success: true, message: 'CI/CD module initialized successfully', files: this.getGeneratedFiles() }; } catch (error) { console.error('❌ Error initializing CI/CD module:', error); throw error; } } async setupDirectories() { const dirs = [ '.github/workflows', 'scripts/ci', 'scripts/deployment', 'config/ci' ]; for (const dir of dirs) { const dirPath = path.join(this.projectRoot, dir); if (!fs.existsSync(dirPath)) { fs.mkdirSync(dirPath, { recursive: true }); console.log(`πŸ“ Created directory: ${dir}`); } } } async generateWorkflows() { if (this.config.platform === 'github') { await this.generateGitHubActions(); } else if (this.config.platform === 'gitlab') { await this.generateGitLabCI(); } else if (this.config.platform === 'jenkins') { await this.generateJenkinsfile(); } } async generateGitHubActions() { // CI Workflow const ciWorkflow = `name: CI on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] env: NODE_VERSION: '18' REGISTRY: ghcr.io IMAGE_NAME: \${{ github.repository }} jobs: lint: runs-on: ubuntu-latest steps: - name: Checkout code 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 linter run: npm run lint - name: Check formatting run: npm run format:check test: runs-on: ubuntu-latest strategy: matrix: node-version: [16, 18, 20] steps: - name: Checkout code 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: Run tests run: npm run test:coverage - name: Upload coverage to Codecov uses: codecov/codecov-action@v3 with: token: \${{ secrets.CODECOV_TOKEN }} file: ./coverage/lcov.info security: runs-on: ubuntu-latest if: \${{ github.event_name == 'push' || github.event_name == 'pull_request' }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Run security audit run: npm audit --audit-level=high - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: javascript - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 build: runs-on: ubuntu-latest needs: [lint, test, security] steps: - name: Checkout code 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: Build application run: npm run build - name: Upload build artifacts uses: actions/upload-artifact@v3 with: name: build-artifacts path: dist/ retention-days: 30 ${this.config.docker ? ` - name: Build Docker image run: docker build -t \${{ env.REGISTRY }}/\${{ env.IMAGE_NAME }}:\${{ github.sha }} . - name: Log in to Container Registry uses: docker/login-action@v2 with: registry: \${{ env.REGISTRY }} username: \${{ github.actor }} password: \${{ secrets.GITHUB_TOKEN }} - name: Push Docker image run: docker push \${{ env.REGISTRY }}/\${{ env.IMAGE_NAME }}:\${{ github.sha }}` : ''} quality-gate: runs-on: ubuntu-latest needs: [build] steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: SonarQube Scan uses: sonarqube-quality-gate-action@master env: SONAR_TOKEN: \${{ secrets.SONAR_TOKEN }} - name: Quality Gate check id: sonarqube-quality-gate-check uses: sonarqube-quality-gate-action@master timeout-minutes: 5 env: SONAR_TOKEN: \${{ secrets.SONAR_TOKEN }} notify: runs-on: ubuntu-latest needs: [quality-gate] if: always() steps: - name: Notify Slack if: \${{ contains(fromJSON('["success", "failure"]'), job.status) }} uses: 8398a7/action-slack@v3 with: status: \${{ job.status }} channel: '#ci-cd' webhook_url: \${{ secrets.SLACK_WEBHOOK }} `; // CD Workflow const cdWorkflow = `name: CD on: push: branches: [ main ] workflow_dispatch: inputs: environment: description: 'Environment to deploy' required: true default: 'staging' type: choice options: - staging - production env: NODE_VERSION: '18' REGISTRY: ghcr.io IMAGE_NAME: \${{ github.repository }} jobs: deploy-staging: runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' || github.event.inputs.environment == 'staging' environment: name: staging url: https://staging.example.com steps: - name: Checkout code uses: actions/checkout@v4 - name: Download build artifacts uses: actions/download-artifact@v3 with: name: build-artifacts path: dist/ - name: Deploy to staging run: | echo "Deploying to staging environment..." # Add your deployment commands here ./scripts/deployment/deploy.sh staging - name: Run health check run: ./scripts/ci/health-check.sh staging - name: Notify deployment uses: 8398a7/action-slack@v3 with: status: 'success' text: 'πŸš€ Successfully deployed to staging' webhook_url: \${{ secrets.SLACK_WEBHOOK }} deploy-production: runs-on: ubuntu-latest if: github.event.inputs.environment == 'production' environment: name: production url: https://example.com needs: [deploy-staging] steps: - name: Checkout code uses: actions/checkout@v4 - name: Download build artifacts uses: actions/download-artifact@v3 with: name: build-artifacts path: dist/ - name: Deploy to production run: | echo "Deploying to production environment..." ./scripts/deployment/deploy.sh production - name: Run health check run: ./scripts/ci/health-check.sh production - name: Notify deployment uses: 8398a7/action-slack@v3 with: status: 'success' text: 'πŸŽ‰ Successfully deployed to production' webhook_url: \${{ secrets.SLACK_WEBHOOK }} rollback: runs-on: ubuntu-latest if: failure() environment: production steps: - name: Checkout code uses: actions/checkout@v4 - name: Rollback deployment run: ./scripts/deployment/rollback.sh - name: Notify rollback uses: 8398a7/action-slack@v3 with: status: 'warning' text: '⚠️ Rollback executed due to deployment failure' webhook_url: \${{ secrets.SLACK_WEBHOOK }} `; // Security Workflow const securityWorkflow = `name: Security on: schedule: - cron: '0 2 * * 1' # Weekly on Monday at 2 AM workflow_dispatch: jobs: dependency-check: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' cache: 'npm' - name: Install dependencies run: npm ci - name: Run dependency audit run: npm audit --audit-level=moderate - name: Check for outdated packages run: npm outdated container-security: runs-on: ubuntu-latest if: \${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Build Docker image run: docker build -t security-scan . - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: image-ref: 'security-scan' format: 'sarif' output: 'trivy-results.sarif' - name: Upload Trivy scan results uses: github/codeql-action/upload-sarif@v2 with: sarif_file: 'trivy-results.sarif' secrets-scan: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Run GitLeaks uses: gitleaks/gitleaks-action@v2 env: GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }} `; // Write workflow files fs.writeFileSync(path.join(this.projectRoot, '.github/workflows/ci.yml'), ciWorkflow); fs.writeFileSync(path.join(this.projectRoot, '.github/workflows/cd.yml'), cdWorkflow); fs.writeFileSync(path.join(this.projectRoot, '.github/workflows/security.yml'), securityWorkflow); // Dependabot configuration const dependabot = `version: 2 updates: - package-ecosystem: "npm" directory: "/" schedule: interval: "weekly" open-pull-requests-limit: 10 reviewers: - "@team-leads" assignees: - "@maintainers" commit-message: prefix: "chore" include: "scope" - package-ecosystem: "docker" directory: "/" schedule: interval: "weekly" reviewers: - "@devops-team" `; fs.writeFileSync(path.join(this.projectRoot, '.github/dependabot.yml'), dependabot); console.log('βœ… Generated GitHub Actions workflows'); } async generateGitLabCI() { const gitlabCI = `# .gitlab-ci.yml stages: - validate - test - security - build - deploy variables: NODE_VERSION: "18" DOCKER_DRIVER: overlay2 DOCKER_TLS_CERTDIR: "/certs" default: image: node:\$NODE_VERSION cache: paths: - node_modules/ - .npm/ before_script: - npm ci --cache .npm --prefer-offline # Validation Stage lint: stage: validate script: - npm run lint - npm run format:check rules: - if: \$CI_PIPELINE_SOURCE == "merge_request_event" - if: \$CI_COMMIT_BRANCH == \$CI_DEFAULT_BRANCH # Testing Stage unit-tests: stage: test script: - npm run test:coverage coverage: '/Lines\s*:\s*(\d+\.?\d*)%/' artifacts: reports: coverage_report: coverage_format: cobertura path: coverage/cobertura-coverage.xml paths: - coverage/ expire_in: 30 days rules: - if: \$CI_PIPELINE_SOURCE == "merge_request_event" - if: \$CI_COMMIT_BRANCH == \$CI_DEFAULT_BRANCH integration-tests: stage: test services: - postgres:13 - redis:6 variables: POSTGRES_DB: test_db POSTGRES_USER: test_user POSTGRES_PASSWORD: test_password DATABASE_URL: "postgresql://test_user:test_password@postgres:5432/test_db" REDIS_URL: "redis://redis:6379" script: - npm run test:integration rules: - if: \$CI_PIPELINE_SOURCE == "merge_request_event" - if: \$CI_COMMIT_BRANCH == \$CI_DEFAULT_BRANCH # Security Stage security-audit: stage: security script: - npm audit --audit-level=high allow_failure: true rules: - if: \$CI_PIPELINE_SOURCE == "merge_request_event" - if: \$CI_COMMIT_BRANCH == \$CI_DEFAULT_BRANCH sast: stage: security include: - template: Security/SAST.gitlab-ci.yml rules: - if: \$CI_COMMIT_BRANCH == \$CI_DEFAULT_BRANCH dependency-scanning: stage: security include: - template: Security/Dependency-Scanning.gitlab-ci.yml rules: - if: \$CI_COMMIT_BRANCH == \$CI_DEFAULT_BRANCH # Build Stage build: stage: build script: - npm run build artifacts: paths: - dist/ expire_in: 1 week rules: - if: \$CI_COMMIT_BRANCH == \$CI_DEFAULT_BRANCH - if: \$CI_PIPELINE_SOURCE == "merge_request_event" docker-build: stage: build image: docker:20.10.16 services: - docker:20.10.16-dind variables: DOCKER_IMAGE_TAG: \$CI_REGISTRY_IMAGE:\$CI_COMMIT_SHA script: - docker login -u \$CI_REGISTRY_USER -p \$CI_REGISTRY_PASSWORD \$CI_REGISTRY - docker build -t \$DOCKER_IMAGE_TAG . - docker push \$DOCKER_IMAGE_TAG rules: - if: \$CI_COMMIT_BRANCH == \$CI_DEFAULT_BRANCH # Deploy Stage deploy-staging: stage: deploy environment: name: staging url: https://staging.example.com script: - ./scripts/deployment/deploy.sh staging - ./scripts/ci/health-check.sh staging rules: - if: \$CI_COMMIT_BRANCH == \$CI_DEFAULT_BRANCH deploy-production: stage: deploy environment: name: production url: https://example.com script: - ./scripts/deployment/deploy.sh production - ./scripts/ci/health-check.sh production when: manual rules: - if: \$CI_COMMIT_BRANCH == \$CI_DEFAULT_BRANCH `; fs.writeFileSync(path.join(this.projectRoot, '.gitlab-ci.yml'), gitlabCI); console.log('βœ… Generated GitLab CI configuration'); } async generateJenkinsfile() { const jenkinsfile = `pipeline { agent any environment { NODE_VERSION = '18' DOCKER_REGISTRY = 'your-registry.com' IMAGE_NAME = 'your-app' } stages { stage('Checkout') { steps { checkout scm } } stage('Setup') { steps { sh 'nvm use \$NODE_VERSION' sh 'npm ci' } } stage('Lint') { steps { sh 'npm run lint' sh 'npm run format:check' } } stage('Test') { parallel { stage('Unit Tests') { steps { sh 'npm run test:coverage' } post { always { publishHTML([ allowMissing: false, alwaysLinkToLastBuild: true, keepAll: true, reportDir: 'coverage', reportFiles: 'index.html', reportName: 'Coverage Report' ]) } } } stage('Integration Tests') { steps { sh 'npm run test:integration' } } } } stage('Security') { parallel { stage('Audit') { steps { sh 'npm audit --audit-level=high' } } stage('SAST') { steps { sh 'npm run security:scan' } } } } stage('Build') { steps { sh 'npm run build' archiveArtifacts artifacts: 'dist/**', fingerprint: true } } stage('Docker Build') { when { branch 'main' } steps { script { def image = docker.build("\${DOCKER_REGISTRY}/\${IMAGE_NAME}:\${BUILD_NUMBER}") docker.withRegistry('https://\${DOCKER_REGISTRY}', 'docker-registry-credentials') { image.push() image.push('latest') } } } } stage('Deploy to Staging') { when { branch 'main' } steps { sh './scripts/deployment/deploy.sh staging' sh './scripts/ci/health-check.sh staging' } } stage('Deploy to Production') { when { branch 'main' } steps { input message: 'Deploy to production?', ok: 'Deploy' sh './scripts/deployment/deploy.sh production' sh './scripts/ci/health-check.sh production' } } } post { always { cleanWs() } success { slackSend( channel: '#ci-cd', color: 'good', message: "βœ… Pipeline succeeded for \${env.JOB_NAME} - \${env.BUILD_NUMBER}" ) } failure { slackSend( channel: '#ci-cd', color: 'danger', message: "❌ Pipeline failed for \${env.JOB_NAME} - \${env.BUILD_NUMBER}" ) } } }`; fs.writeFileSync(path.join(this.projectRoot, 'Jenkinsfile'), jenkinsfile); console.log('βœ… Generated Jenkinsfile'); } async generateScripts() { // Deploy script const deployScript = `#!/bin/bash # scripts/deployment/deploy.sh set -e ENVIRONMENT=\$1 if [ -z "\$ENVIRONMENT" ]; then echo "Usage: \$0 <environment>" exit 1 fi echo "πŸš€ Deploying to \$ENVIRONMENT environment..." # Load environment-specific configuration case \$ENVIRONMENT in "development") SERVER="dev.example.com" PORT="3000" ;; "staging") SERVER="staging.example.com" PORT="3000" ;; "production") SERVER="example.com" PORT="3000" ;; *) echo "❌ Unknown environment: \$ENVIRONMENT" exit 1 ;; esac # Backup current deployment echo "πŸ“¦ Creating backup..." ssh deploy@\$SERVER "mkdir -p /var/backups/app/\$(date +%Y%m%d_%H%M%S)" ssh deploy@\$SERVER "cp -r /var/www/app/* /var/backups/app/\$(date +%Y%m%d_%H%M%S)/" # Upload new build echo "πŸ“€ Uploading new build..." rsync -avz --delete dist/ deploy@\$SERVER:/var/www/app/ # Install dependencies echo "πŸ“¦ Installing dependencies..." ssh deploy@\$SERVER "cd /var/www/app && npm ci --production" # Run database migrations echo "πŸ—„οΈ Running database migrations..." ssh deploy@\$SERVER "cd /var/www/app && npm run db:migrate" # Restart application echo "πŸ”„ Restarting application..." ssh deploy@\$SERVER "pm2 restart app-\$ENVIRONMENT" # Wait for application to start echo "⏳ Waiting for application to start..." sleep 10 echo "βœ… Deployment to \$ENVIRONMENT completed successfully!" `; // Rollback script const rollbackScript = `#!/bin/bash # scripts/deployment/rollback.sh set -e ENVIRONMENT=\$1 BACKUP_VERSION=\$2 if [ -z "\$ENVIRONMENT" ]; then echo "Usage: \$0 <environment> [backup_version]" exit 1 fi echo "πŸ”„ Rolling back \$ENVIRONMENT environment..." # Load environment-specific configuration case \$ENVIRONMENT in "staging") SERVER="staging.example.com" ;; "production") SERVER="example.com" ;; *) echo "❌ Unknown environment: \$ENVIRONMENT" exit 1 ;; esac # Get latest backup if version not specified if [ -z "\$BACKUP_VERSION" ]; then BACKUP_VERSION=\$(ssh deploy@\$SERVER "ls -1t /var/backups/app/ | head -1") fi echo "πŸ“¦ Rolling back to version: \$BACKUP_VERSION" # Stop application echo "πŸ›‘ Stopping application..." ssh deploy@\$SERVER "pm2 stop app-\$ENVIRONMENT" # Restore backup echo "πŸ“₯ Restoring backup..." ssh deploy@\$SERVER "rm -rf /var/www/app/*" ssh deploy@\$SERVER "cp -r /var/backups/app/\$BACKUP_VERSION/* /var/www/app/" # Restart application echo "πŸ”„ Restarting application..." ssh deploy@\$SERVER "pm2 start app-\$ENVIRONMENT" # Wait for application to start echo "⏳ Waiting for application to start..." sleep 10 echo "βœ… Rollback to \$BACKUP_VERSION completed successfully!" `; // Health check script const healthCheckScript = `#!/bin/bash # scripts/ci/health-check.sh set -e ENVIRONMENT=\$1 MAX_RETRIES=30 RETRY_INTERVAL=10 if [ -z "\$ENVIRONMENT" ]; then echo "Usage: \$0 <environment>" exit 1 fi # Set environment-specific URL case \$ENVIRONMENT in "development") URL="http://localhost:3000" ;; "staging") URL="https://staging.example.com" ;; "production") URL="https://example.com" ;; *) echo "❌ Unknown environment: \$ENVIRONMENT" exit 1 ;; esac echo "πŸ₯ Running health check for \$ENVIRONMENT environment..." echo "πŸ”— Checking URL: \$URL" # Health check function check_health() { local response=\$(curl -s -o /dev/null -w "%{http_code}" "\$URL/health" || echo "000") if [ "\$response" = "200" ]; then return 0 else return 1 fi } # Retry logic for i in \$(seq 1 \$MAX_RETRIES); do echo "πŸ” Attempt \$i/\$MAX_RETRIES..." if check_health; then echo "βœ… Health check passed! Application is healthy." # Additional checks echo "πŸ” Running additional checks..." # Check database connectivity DB_RESPONSE=\$(curl -s -o /dev/null -w "%{http_code}" "\$URL/health/db" || echo "000") if [ "\$DB_RESPONSE" = "200" ]; then echo "βœ… Database connectivity: OK" else echo "⚠️ Database connectivity: FAILED (\$DB_RESPONSE)" fi # Check Redis connectivity REDIS_RESPONSE=\$(curl -s -o /dev/null -w "%{http_code}" "\$URL/health/redis" || echo "000") if [ "\$REDIS_RESPONSE" = "200" ]; then echo "βœ… Redis connectivity: OK" else echo "⚠️ Redis connectivity: FAILED (\$REDIS_RESPONSE)" fi # Check API endpoints API_RESPONSE=\$(curl -s -o /dev/null -w "%{http_code}" "\$URL/api/health" || echo "000") if [ "\$API_RESPONSE" = "200" ]; then echo "βœ… API endpoints: OK" else echo "⚠️ API endpoints: FAILED (\$API_RESPONSE)" fi echo "πŸŽ‰ All health checks completed successfully!" exit 0 else echo "❌ Health check failed. Retrying in \$RETRY_INTERVAL seconds..." sleep \$RETRY_INTERVAL fi done echo "πŸ’₯ Health check failed after \$MAX_RETRIES attempts!" exit 1 `; // Setup CI script const setupCIScript = `#!/bin/bash # scripts/ci/setup-ci.sh set -e echo "πŸ”§ Setting up CI/CD configuration..." # Create necessary directories mkdir -p .github/workflows mkdir -p scripts/ci mkdir -p scripts/deployment mkdir -p config/ci # Make scripts executable chmod +x scripts/deployment/*.sh chmod +x scripts/ci/*.sh # Install CI dependencies echo "πŸ“¦ Installing CI dependencies..." npm install --save-dev \ jest \ @types/jest \ supertest \ @types/supertest \ eslint \ prettier \ husky \ lint-staged # Setup Git hooks echo "πŸͺ Setting up Git hooks..." npx husky install npx husky add .husky/pre-commit "npx lint-staged" npx husky add .husky/commit-msg "npx commitlint --edit \$1" # Create lint-staged configuration cat > .lintstagedrc.json << EOF { "*.{js,ts,jsx,tsx}": [ "eslint --fix", "prettier --write" ], "*.{json,md,yml,yaml}": [ "prettier --write" ] } EOF echo "βœ… CI/CD setup completed successfully!" echo "πŸ“ Don't forget to:" echo " 1. Configure secrets in your repository settings" echo " 2. Update deployment URLs in scripts" echo " 3. Configure notification webhooks" echo " 4. Set up environment-specific configurations" `; // Write scripts fs.writeFileSync(path.join(this.projectRoot, 'scripts/deployment/deploy.sh'), deployScript); fs.writeFileSync(path.join(this.projectRoot, 'scripts/deployment/rollback.sh'), rollbackScript); fs.writeFileSync(path.join(this.projectRoot, 'scripts/ci/health-check.sh'), healthCheckScript); fs.writeFileSync(path.join(this.projectRoot, 'scripts/ci/setup-ci.sh'), setupCIScript); // Make scripts executable (Unix systems) if (process.platform !== 'win32') { const scripts = [ 'scripts/deployment/deploy.sh', 'scripts/deployment/rollback.sh', 'scripts/ci/health-check.sh', 'scripts/ci/setup-ci.sh' ]; scripts.forEach(script => { try { fs.chmodSync(path.join(this.projectRoot, script), '755'); } catch (error) { console.warn(`⚠️ Could not make ${script} executable:`, error.message); } }); } console.log('βœ… Generated CI/CD scripts'); } async generateConfigs() { // SonarQube configuration const sonarConfig = `# sonar-project.properties sonar.projectKey=your-project-key sonar.projectName=Your Project Name sonar.projectVersion=1.0.0 # Source code sonar.sources=src sonar.exclusions=**/*.test.ts,**/*.spec.ts,**/node_modules/**,**/dist/**,**/coverage/** # Test coverage sonar.typescript.lcov.reportPaths=coverage/lcov.info sonar.testExecutionReportPaths=test-results/sonar-report.xml # Language sonar.language=ts sonar.sourceEncoding=UTF-8 # Quality gates sonar.qualitygate.wait=true # Code analysis sonar.typescript.node=node sonar.typescript.exclusions=**/*.d.ts `; // ESLint configuration for CI const eslintConfig = `// .eslintrc.ci.js module.exports = { extends: ['.eslintrc.js'], rules: { // Stricter rules for CI 'no-console': 'error', 'no-debugger': 'error', 'no-unused-vars': 'error', '@typescript-eslint/no-unused-vars': 'error', 'prefer-const': 'error', 'no-var': 'error' }, env: { node: true, jest: true } }; `; // Prettier configuration const prettierConfig = `{ "semi": true, "trailingComma": "es5", "singleQuote": true, "printWidth": 80, "tabWidth": 2, "useTabs": false, "bracketSpacing": true, "arrowParens": "avoid", "endOfLine": "lf" } `; // Commitlint configuration const commitlintConfig = `// commitlint.config.js module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'type-enum': [ 2, 'always', [ 'feat', 'fix', 'docs', 'style', 'refactor', 'perf', 'test', 'chore', 'ci', 'build', 'revert' ] ], 'subject-max-length': [2, 'always', 100], 'subject-case': [2, 'always', 'lower-case'], 'header-max-length': [2, 'always', 100] } }; `; // Write configuration files fs.writeFileSync(path.join(this.projectRoot, 'sonar-project.properties'), sonarConfig); fs.writeFileSync(path.join(this.projectRoot, '.eslintrc.ci.js'), eslintConfig); fs.writeFileSync(path.join(this.projectRoot, '.prettierrc'), prettierConfig); fs.writeFileSync(path.join(this.projectRoot, 'commitlint.config.js'), commitlintConfig); console.log('βœ… Generated CI/CD configuration files'); } async updatePackageJson() { const packageJsonPath = path.join(this.projectRoot, 'package.json'); let packageJson = {}; if (fs.existsSync(packageJsonPath)) { packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); } // Add CI/CD scripts packageJson.scripts = { ...packageJson.scripts, // Linting and formatting "lint": "eslint src --ext .ts,.js", "lint:fix": "eslint src --ext .ts,.js --fix", "lint:ci": "eslint src --ext .ts,.js --config .eslintrc.ci.js", "format": "prettier --write \"src/**/*.{ts,js,json,md}\"", "format:check": "prettier --check \"src/**/*.{ts,js,json,md}\"", // Testing "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage", "test:ci": "jest --ci --coverage --watchAll=false", "test:integration": "jest --config jest.integration.config.js", "test:e2e": "jest --config jest.e2e.config.js", // Security "security:audit": "npm audit", "security:scan": "npm audit --audit-level=high", "security:fix": "npm audit fix", // Build and deployment "build": "tsc && npm run build:assets", "build:assets": "echo 'Building assets...'", "build:docker": "docker build -t app .", // CI/CD utilities "ci:setup": "./scripts/ci/setup-ci.sh", "ci:validate": "npm run lint:ci && npm run test:ci", "deploy:staging": "./scripts/deployment/deploy.sh staging", "deploy:production": "./scripts/deployment/deploy.sh production", "rollback": "./scripts/deployment/rollback.sh", "health-check": "./scripts/ci/health-check.sh", // Quality gates "quality:check": "npm run lint:ci && npm run test:coverage && npm run security:scan", "quality:report": "npm run test:coverage && npm run lint:ci -- --format json --output-file reports/eslint-report.json", // Git hooks "prepare": "husky install", "pre-commit": "lint-staged", "commit-msg": "commitlint --edit $1" }; // Add development dependencies packageJson.devDependencies = { ...packageJson.devDependencies, "@commitlint/cli": "^17.0.0", "@commitlint/config-conventional": "^17.0.0", "@types/jest": "^29.0.0", "@types/supertest": "^2.0.12", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", "eslint": "^8.0.0", "eslint-config-prettier": "^8.0.0", "eslint-plugin-prettier": "^4.0.0", "husky": "^8.0.0", "jest": "^29.0.0", "lint-staged": "^13.0.0", "prettier": "^2.0.0", "supertest": "^6.0.0", "ts-jest": "^29.0.0" }; // Add Jest configuration packageJson.jest = { preset: 'ts-jest', testEnvironment: 'node', roots: ['<rootDir>/src'], testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'], transform: { '^.+\\.ts$': 'ts-jest' }, collectCoverageFrom: [ 'src/**/*.ts', '!src/**/*.d.ts', '!src/**/*.test.ts', '!src/**/*.spec.ts' ], coverageDirectory: 'coverage', coverageReporters: ['text', 'lcov', 'html', 'cobertura'], coverageThreshold: { global: { branches: 80, functions: 80, lines: 80, statements: 80 } } }; // Add lint-staged configuration packageJson['lint-staged'] = { '*.{ts,js}': ['eslint --fix', 'prettier --write'], '*.{json,md,yml,yaml}': ['prettier --write'] }; fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); console.log('βœ… Updated package.json with CI/CD scripts and dependencies'); } getGeneratedFiles() { const files = [ '.github/workflows/ci.yml', '.github/workflows/cd.yml', '.github/workflows/security.yml', '.github/dependabot.yml', 'scripts/deployment/deploy.sh', 'scripts/deployment/rollback.sh', 'scripts/ci/health-check.sh', 'scripts/ci/setup-ci.sh', 'sonar-project.properties', '.eslintrc.ci.js', '.prettierrc', 'commitlint.config.js' ]; if (this.config.platform === 'gitlab') { files.push('.gitlab-ci.yml'); } if (this.config.platform === 'jenkins') { files.push('Jenkinsfile'); } return files; } } module.exports = CIModule;