Expand documentation/ #5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: ChainSync CI/CD Pipeline | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| release: | |
| types: [ published ] | |
| env: | |
| NODE_VERSION: '18' | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| # ============================================================================ | |
| # Code Quality & Testing | |
| # ============================================================================ | |
| lint-and-typecheck: | |
| name: Lint & Type 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: ${{ env.NODE_VERSION }} | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run linting | |
| run: npm run lint | |
| - name: Run type checking | |
| run: npm run typecheck | |
| - name: Check formatting | |
| run: npm run format:check | |
| unit-tests: | |
| name: Unit Tests | |
| 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 unit tests | |
| run: npm run test:unit | |
| env: | |
| CI: true | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v3 | |
| if: always() | |
| with: | |
| name: unit-test-results | |
| path: | | |
| test-results/ | |
| coverage/ | |
| integration-tests: | |
| name: Integration Tests | |
| runs-on: ubuntu-latest | |
| services: | |
| mongodb: | |
| image: mongo:7.0 | |
| env: | |
| MONGO_INITDB_ROOT_USERNAME: test | |
| MONGO_INITDB_ROOT_PASSWORD: test | |
| ports: | |
| - 27017:27017 | |
| redis: | |
| image: redis:7.2-alpine | |
| ports: | |
| - 6379:6379 | |
| 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 services | |
| run: npm run build:services | |
| - name: Run integration tests | |
| run: npm run test:integration | |
| env: | |
| CI: true | |
| TEST_DATABASE_URL: mongodb://test:test@localhost:27017/chainsync-test | |
| TEST_REDIS_URL: redis://localhost:6379 | |
| SKIP_STRIPE_TESTS: true | |
| - name: Upload integration test results | |
| uses: actions/upload-artifact@v3 | |
| if: always() | |
| with: | |
| name: integration-test-results | |
| path: test-results/ | |
| security-scan: | |
| name: Security Scan | |
| 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 security 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 | |
| # ============================================================================ | |
| # Build & Package | |
| # ============================================================================ | |
| build: | |
| name: Build Services | |
| runs-on: ubuntu-latest | |
| needs: [lint-and-typecheck, unit-tests] | |
| strategy: | |
| matrix: | |
| service: [api, billing, oracle-service] | |
| 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 service | |
| run: npm run build:${{ matrix.service }} | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v3 | |
| with: | |
| name: ${{ matrix.service }}-build | |
| path: | | |
| packages/services/${{ matrix.service }}/dist/ | |
| packages/services/${{ matrix.service }}/package.json | |
| docker-build: | |
| name: Build Docker Images | |
| runs-on: ubuntu-latest | |
| needs: [build, security-scan] | |
| if: github.event_name == 'push' || github.event_name == 'release' | |
| permissions: | |
| contents: read | |
| packages: write | |
| strategy: | |
| matrix: | |
| service: [api, billing, oracle-service] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Setup Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/${{ matrix.service }} | |
| tags: | | |
| type=ref,event=branch | |
| type=ref,event=pr | |
| type=sha,prefix={{branch}}- | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: packages/services/${{ matrix.service }}/Dockerfile | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| platforms: linux/amd64,linux/arm64 | |
| # ============================================================================ | |
| # End-to-End Testing | |
| # ============================================================================ | |
| e2e-tests: | |
| name: End-to-End Tests | |
| runs-on: ubuntu-latest | |
| needs: [docker-build, integration-tests] | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| 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: Start services with Docker Compose | |
| run: | | |
| cp .env.example .env | |
| docker-compose up -d | |
| sleep 60 # Wait for services to start | |
| - name: Wait for services to be healthy | |
| run: | | |
| timeout 300 bash -c 'until curl -f http://localhost:3000/health; do sleep 5; done' | |
| timeout 300 bash -c 'until curl -f http://localhost:3001/health; do sleep 5; done' | |
| - name: Run E2E tests | |
| run: npm run test:e2e | |
| env: | |
| CI: true | |
| API_BASE_URL: http://localhost:3000 | |
| BILLING_BASE_URL: http://localhost:3001 | |
| SKIP_STRIPE_TESTS: true | |
| - name: Upload E2E test results | |
| uses: actions/upload-artifact@v3 | |
| if: always() | |
| with: | |
| name: e2e-test-results | |
| path: test-results/ | |
| - name: Cleanup | |
| if: always() | |
| run: docker-compose down -v | |
| # ============================================================================ | |
| # Performance Testing | |
| # ============================================================================ | |
| performance-tests: | |
| name: Performance Tests | |
| runs-on: ubuntu-latest | |
| needs: [docker-build] | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| 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: Start services | |
| run: | | |
| cp .env.example .env | |
| docker-compose up -d api-service billing-service | |
| sleep 45 | |
| - name: Run performance tests | |
| run: npm run test:performance | |
| env: | |
| CI: true | |
| LOAD_TEST_USERS: 20 | |
| LOAD_TEST_REQUESTS: 100 | |
| LOAD_TEST_DURATION: 60000 | |
| - name: Upload performance results | |
| uses: actions/upload-artifact@v3 | |
| if: always() | |
| with: | |
| name: performance-test-results | |
| path: test-results/ | |
| - name: Cleanup | |
| if: always() | |
| run: docker-compose down | |
| # ============================================================================ | |
| # Deployment | |
| # ============================================================================ | |
| deploy-staging: | |
| name: Deploy to Staging | |
| runs-on: ubuntu-latest | |
| needs: [e2e-tests, performance-tests] | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/develop' | |
| environment: | |
| name: staging | |
| url: https://staging.chainsync.dev | |
| steps: | |
| - name: Deploy to staging | |
| uses: appleboy/ssh-action@v1.0.0 | |
| with: | |
| host: ${{ secrets.STAGING_HOST }} | |
| username: ${{ secrets.STAGING_USER }} | |
| key: ${{ secrets.STAGING_SSH_KEY }} | |
| script: | | |
| cd /opt/chainsync | |
| git pull origin develop | |
| docker-compose -f docker-compose.staging.yml pull | |
| docker-compose -f docker-compose.staging.yml up -d | |
| docker system prune -f | |
| deploy-production: | |
| name: Deploy to Production | |
| runs-on: ubuntu-latest | |
| needs: [e2e-tests, performance-tests] | |
| if: github.event_name == 'release' && github.event.action == 'published' | |
| environment: | |
| name: production | |
| url: https://chainsync.dev | |
| steps: | |
| - name: Deploy to production | |
| uses: appleboy/ssh-action@v1.0.0 | |
| with: | |
| host: ${{ secrets.PRODUCTION_HOST }} | |
| username: ${{ secrets.PRODUCTION_USER }} | |
| key: ${{ secrets.PRODUCTION_SSH_KEY }} | |
| script: | | |
| cd /opt/chainsync | |
| git pull origin main | |
| docker-compose pull | |
| docker-compose up -d | |
| docker system prune -f | |
| - name: Health check | |
| run: | | |
| sleep 60 | |
| curl -f https://chainsync.dev/health || exit 1 | |
| curl -f https://api.chainsync.dev/health || exit 1 | |
| - name: Notify deployment | |
| uses: 8398a7/action-slack@v3 | |
| if: always() | |
| with: | |
| status: ${{ job.status }} | |
| text: "ChainSync ${{ github.event.release.tag_name }} deployed to production" | |
| env: | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} | |
| # ============================================================================ | |
| # Monitoring & Notifications | |
| # ============================================================================ | |
| notify-failure: | |
| name: Notify on Failure | |
| runs-on: ubuntu-latest | |
| needs: [lint-and-typecheck, unit-tests, integration-tests, security-scan, build, docker-build] | |
| if: failure() | |
| steps: | |
| - name: Notify team of failure | |
| uses: 8398a7/action-slack@v3 | |
| with: | |
| status: failure | |
| text: "ChainSync CI/CD pipeline failed on ${{ github.ref_name }}" | |
| webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }} |