@tehreet/conduit
Version:
LLM API gateway with intelligent routing, robust process management, and health monitoring
699 lines (569 loc) • 18.3 kB
Markdown
# CI/CD Strategy for Conduit
## Table of Contents
- [Overview](#overview)
- [CI/CD Goals](#cicd-goals)
- [Technology Stack](#technology-stack)
- [Pipeline Architecture](#pipeline-architecture)
- [Branch Strategy](#branch-strategy)
- [Continuous Integration](#continuous-integration)
- [Continuous Deployment](#continuous-deployment)
- [NPM Publishing Strategy](#npm-publishing-strategy)
- [Docker Registry](#docker-registry)
- [Security & Compliance](#security--compliance)
- [Monitoring & Alerts](#monitoring--alerts)
- [Implementation Roadmap](#implementation-roadmap)
## Overview
This document outlines the comprehensive CI/CD strategy for Conduit, an intelligent LLM API gateway. Our CI/CD pipeline ensures code quality, automates testing, manages releases, and handles deployment across multiple environments.
## CI/CD Goals
1. **Automated Quality Assurance**: Ensure every commit meets quality standards
2. **Rapid Feedback**: Provide developers with quick feedback on code changes
3. **Automated Releases**: Streamline the release process with semantic versioning
4. **Zero-Downtime Deployments**: Deploy updates without service interruption
5. **Security First**: Integrate security scanning throughout the pipeline
6. **Reproducible Builds**: Ensure consistent builds across environments
## Technology Stack
- **CI/CD Platform**: GitHub Actions (primary), with GitLab CI/CD as backup
- **Container Registry**: GitHub Container Registry (GHCR) and Docker Hub
- **NPM Registry**: npmjs.com for public package distribution
- **Testing Frameworks**: Jest (unit), Playwright (E2E), Artillery (load testing)
- **Code Quality**: ESLint, Prettier, TypeScript compiler, SonarCloud
- **Security Scanning**: Snyk, GitHub Dependabot, OWASP Dependency Check
- **Monitoring**: Datadog, Prometheus, Grafana
## Pipeline Architecture
```mermaid
graph LR
A[Code Push] --> B[CI Pipeline]
B --> C{Branch?}
C -->|main| D[Production Pipeline]
C -->|develop| E[Staging Pipeline]
C -->|feature/*| F[Feature Pipeline]
D --> G[NPM Publish]
D --> H[Docker Build]
D --> I[Deploy Prod]
E --> J[Deploy Staging]
F --> K[PR Checks]
```
## Branch Strategy
We follow a modified GitFlow strategy:
- **main**: Production-ready code, protected branch
- **develop**: Integration branch for features
- **feature/***: Feature development branches
- **release/***: Release preparation branches
- **hotfix/***: Emergency fixes for production
### Branch Protection Rules
**Main Branch**:
- Require PR reviews (minimum 2 approvers)
- Require status checks to pass
- Require branches to be up to date
- Include administrators in restrictions
- Restrict force pushes and deletions
## Continuous Integration
### GitHub Actions Workflow: `.github/workflows/ci.yml`
```yaml
name: CI Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
env:
NODE_VERSION: '20.x'
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
# Code Quality Checks
quality:
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: Lint code
run: npm run lint
- name: Format check
run: npm run format:check
- name: Type check
run: npm run typecheck
- name: License check
run: npx license-checker --production --onlyAllow 'MIT;Apache-2.0;BSD-3-Clause;BSD-2-Clause;ISC'
# Security Scanning
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Snyk Security Scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high
- name: Upload Snyk results
uses: github/codeql-action/upload-sarif@v2
if: always()
with:
sarif_file: snyk.sarif
# Unit Tests
test-unit:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x, 22.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: Run unit tests
run: npm run test:unit -- --coverage
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
flags: unit
# Integration Tests
test-integration:
runs-on: ubuntu-latest
services:
redis:
image: redis:7-alpine
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
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:
REDIS_URL: redis://localhost:6379
# Build Artifacts
build:
needs: [quality, security, test-unit]
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: Build
run: npm run build
- name: Package artifacts
run: |
tar -czf conduit-${{ github.sha }}.tar.gz dist package.json package-lock.json
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: build-artifacts
path: conduit-${{ github.sha }}.tar.gz
retention-days: 7
# SonarCloud Analysis
sonarcloud:
needs: [test-unit]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
```
### Pull Request Workflow: `.github/workflows/pr.yml`
```yaml
name: PR Validation
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
# PR Title Validation
pr-title:
runs-on: ubuntu-latest
steps:
- name: Check PR title
uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
types: |
feat
fix
docs
style
refactor
perf
test
build
ci
chore
revert
# Size Check
size-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check bundle size
uses: andresz1/size-limit-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
skip_step: install
script: npm run size
# Preview Deployment
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy Preview
uses: amondnet/vercel-action@v20
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
github-token: ${{ secrets.GITHUB_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
```
## Continuous Deployment
### Release Workflow: `.github/workflows/release.yml`
```yaml
name: Release Pipeline
on:
push:
branches: [main]
workflow_dispatch:
inputs:
release-type:
description: 'Release type'
required: true
default: 'patch'
type: choice
options:
- patch
- minor
- major
permissions:
contents: write
packages: write
id-token: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Determine version
id: version
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
npm version ${{ github.event.inputs.release-type }} --no-git-tag-version
else
npm run semantic-release --dry-run
fi
echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
- name: Create Release
uses: semantic-release/semantic-release@v21
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
docker:
needs: release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
${{ secrets.DOCKERHUB_USERNAME }}/conduit
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
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
deploy-production:
needs: [release, docker]
runs-on: ubuntu-latest
environment: production
steps:
- name: Deploy to Production
run: |
# Deployment logic here
echo "Deploying version ${{ needs.release.outputs.version }} to production"
```
## NPM Publishing Strategy
### Automated NPM Publishing
1. **Version Management**:
- Use [semantic-release](https://github.com/semantic-release/semantic-release) for automated versioning
- Follow [Conventional Commits](https://www.conventionalcommits.org/) specification
- Automatic CHANGELOG generation
2. **Publishing Configuration**: `.releaserc.json`
```json
{
"branches": ["main"],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"@semantic-release/npm",
[
"@semantic-release/git",
{
"assets": ["package.json", "package-lock.json", "CHANGELOG.md"],
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
"@semantic-release/github"
]
}
```
3. **NPM Configuration**: `.npmrc`
```ini
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
@tehreet:registry=https://registry.npmjs.org/
access=public
save-exact=true
engine-strict=true
```
4. **Pre-publish Checklist**:
- Run full test suite
- Verify no security vulnerabilities
- Check bundle size limits
- Validate package contents with `npm pack --dry-run`
- Ensure LICENSE file is included
### Beta and Canary Releases
```yaml
# .github/workflows/canary.yml
name: Canary Release
on:
push:
branches: [develop]
jobs:
canary:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
registry-url: 'https://registry.npmjs.org'
- name: Install and Build
run: |
npm ci
npm run build
- name: Publish Canary
run: |
npm version prerelease --preid=canary.$(git rev-parse --short HEAD) --no-git-tag-version
npm publish --tag canary
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
```
## Docker Registry
### Multi-Registry Strategy
1. **GitHub Container Registry (GHCR)**:
- Primary registry for development/staging
- Integrated with GitHub permissions
- Free for public repositories
2. **Docker Hub**:
- Public distribution
- Better global CDN
- Community visibility
3. **Image Tagging Strategy**:
- `latest`: Latest stable release
- `v1.2.3`: Specific version
- `v1.2`: Minor version (auto-updates patch)
- `v1`: Major version (auto-updates minor/patch)
- `canary`: Latest development build
- `sha-abc1234`: Commit-specific builds
## Security & Compliance
### Security Scanning Pipeline
```yaml
# .github/workflows/security.yml
name: Security Audit
on:
schedule:
- cron: '0 0 * * *' # Daily at midnight
push:
branches: [main, develop]
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run npm audit
run: npm audit --production
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
dependency-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/dependency-review-action@v3
with:
fail-on-severity: moderate
```
### Secrets Management
1. **GitHub Secrets Required**:
- `NPM_TOKEN`: NPM authentication token
- `DOCKERHUB_USERNAME`: Docker Hub username
- `DOCKERHUB_TOKEN`: Docker Hub access token
- `SNYK_TOKEN`: Snyk authentication token
- `SONAR_TOKEN`: SonarCloud token
- `CODECOV_TOKEN`: Codecov token
- `VERCEL_TOKEN`: Vercel deployment token
2. **Secret Rotation**:
- Rotate all tokens every 90 days
- Use GitHub's secret scanning
- Implement least privilege principle
## Monitoring & Alerts
### CI/CD Metrics
1. **Key Metrics to Track**:
- Build success rate
- Average build time
- Test pass rate
- Deployment frequency
- Mean time to recovery (MTTR)
- Change failure rate
2. **Alerting Rules**:
- Failed builds on main branch
- Security vulnerabilities (high/critical)
- Performance regression >10%
- Bundle size increase >5%
- Test coverage drop >2%
3. **Dashboard Configuration**:
```yaml
# datadog-dashboard.yaml
widgets:
- title: "CI/CD Pipeline Health"
type: "timeseries"
requests:
- q: "avg:github.actions.workflow.run.duration{workflow:ci-pipeline}"
- title: "Deployment Success Rate"
type: "query_value"
requests:
- q: "sum:deployments.success{env:production}.as_rate()"
- title: "NPM Downloads"
type: "timeseries"
requests:
- q: "sum:npm.downloads{package:@tehreet/conduit}"
```
## Implementation Roadmap
### Phase 1: Foundation (Week 1-2)
- [ ] Set up GitHub Actions workflows
- [ ] Configure branch protection rules
- [ ] Implement basic CI pipeline (lint, test, build)
- [ ] Set up Codecov and SonarCloud
### Phase 2: Security & Quality (Week 3-4)
- [ ] Integrate Snyk security scanning
- [ ] Add dependency vulnerability checks
- [ ] Implement bundle size monitoring
- [ ] Set up license compliance checks
### Phase 3: Automated Releases (Week 5-6)
- [ ] Configure semantic-release
- [ ] Set up NPM publishing automation
- [ ] Implement Docker multi-arch builds
- [ ] Create canary release pipeline
### Phase 4: Advanced Features (Week 7-8)
- [ ] Add E2E testing with Playwright
- [ ] Implement load testing with Artillery
- [ ] Set up preview deployments
- [ ] Create rollback mechanisms
### Phase 5: Monitoring & Optimization (Week 9-10)
- [ ] Configure Datadog monitoring
- [ ] Create CI/CD dashboards
- [ ] Implement performance budgets
- [ ] Optimize pipeline performance
## Best Practices
1. **Keep Pipelines Fast**:
- Parallelize independent jobs
- Use caching effectively
- Optimize Docker layer caching
- Run only affected tests
2. **Maintain High Visibility**:
- Use status badges in README
- Send notifications to Slack/Discord
- Create detailed deployment logs
- Maintain audit trails
3. **Ensure Reproducibility**:
- Pin all dependency versions
- Use deterministic builds
- Archive all artifacts
- Tag all Docker images
4. **Practice Continuous Improvement**:
- Regular pipeline reviews
- Monitor and optimize costs
- Update dependencies monthly
- Conduct security audits quarterly
## Conclusion
This CI/CD strategy provides a robust foundation for Conduit's development and deployment processes. By implementing these pipelines, we ensure code quality, automate repetitive tasks, and maintain a secure and reliable release process. Regular reviews and updates of this strategy will help us adapt to changing requirements and emerging best practices.