# === CI/CD PIPELINE PRODUCTION === name: Production Deployment on: push: branches: [main] tags: ['v*'] pull_request: branches: [main] env: REGISTRY: ghcr.io IMAGE_NAME: veza/stream-server jobs: # === TESTS === test: name: Tests & Quality runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Rust uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy - name: Cache dependencies uses: actions/cache@v4 with: path: | ~/.cargo/registry ~/.cargo/git target key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Run tests run: | cargo test --verbose --all-features cargo test --release --verbose - name: Lint code run: | cargo fmt --all -- --check cargo clippy --all-targets --all-features -- -D warnings - name: Security audit run: | cargo install cargo-audit cargo audit - name: Check performance benchmarks run: | cargo bench --no-run # === BUILD & PUSH IMAGE === build: name: Build & Push Image runs-on: ubuntu-latest needs: test if: github.event_name == 'push' outputs: image-digest: ${{ steps.build.outputs.digest }} image-url: ${{ steps.build.outputs.image-url }} 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 }} tags: | type=ref,event=branch type=ref,event=pr type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=raw,value=latest,enable={{is_default_branch}} - name: Build and push image id: build uses: docker/build-push-action@v5 with: context: . file: ./Dockerfile.production platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max # === SECURITY SCAN === security-scan: name: Security Scan runs-on: ubuntu-latest needs: build if: github.event_name == 'push' steps: - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: image-ref: ${{ needs.build.outputs.image-url }} format: 'sarif' output: 'trivy-results.sarif' - name: Upload Trivy scan results uses: github/codeql-action/upload-sarif@v3 with: sarif_file: 'trivy-results.sarif' # === DEPLOY TO STAGING === deploy-staging: name: Deploy to Staging runs-on: ubuntu-latest needs: [build, security-scan] if: github.ref == 'refs/heads/main' environment: staging steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup kubectl uses: azure/setup-kubectl@v3 with: version: 'v1.28.0' - name: Configure kubectl run: | echo "${{ secrets.KUBECONFIG_STAGING }}" | base64 -d > kubeconfig export KUBECONFIG=kubeconfig - name: Deploy to staging run: | envsubst < k8s/staging/stream-server-deployment.yaml | kubectl apply -f - kubectl rollout status deployment/veza-stream-server -n veza-staging - name: Run integration tests run: | ./scripts/test_integration_staging.sh # === DEPLOY TO PRODUCTION === deploy-production: name: Deploy to Production runs-on: ubuntu-latest needs: [deploy-staging] if: startsWith(github.ref, 'refs/tags/v') environment: production steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup kubectl uses: azure/setup-kubectl@v3 with: version: 'v1.28.0' - name: Configure kubectl run: | echo "${{ secrets.KUBECONFIG_PRODUCTION }}" | base64 -d > kubeconfig export KUBECONFIG=kubeconfig - name: Pre-deployment checks run: | kubectl get pods -n veza-production kubectl top nodes - name: Deploy to production run: | envsubst < k8s/production/stream-server-deployment.yaml | kubectl apply -f - kubectl rollout status deployment/veza-stream-server -n veza-production --timeout=600s - name: Verify deployment run: | ./scripts/test_production_health.sh kubectl get pods -n veza-production -l app=veza-stream-server - name: Slack notification uses: 8398a7/action-slack@v3 with: status: ${{ job.status }} text: "🚀 Veza Stream Server v${{ github.ref_name }} deployed to production!" env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} # === PERFORMANCE TESTING === load-test: name: Load Testing runs-on: ubuntu-latest needs: deploy-staging if: github.ref == 'refs/heads/main' steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup K6 run: | sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69 echo "deb https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list sudo apt-get update sudo apt-get install k6 - name: Run load tests run: | k6 run --out json=load-test-results.json tests/load/stream-test.js k6 run --out json=websocket-test-results.json tests/load/websocket-test.js - name: Upload test results uses: actions/upload-artifact@v4 with: name: load-test-results path: "*-test-results.json" - name: Performance regression check run: | ./scripts/check_performance_regression.sh