name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
env:
NODE_VERSION: '18'
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
- name: Run linter
run: bun run lint
- name: Run formatter check
run: bun run format:check
- name: Run type check
run: bun run typecheck
- name: Run tests
run: bun test
build-server:
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Build MCP Server
run: bun build
- name: Upload MCP Server artifact
uses: actions/upload-artifact@v4
with:
name: mcp-server
path: dist/
retention-days: 7
build-web:
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
working-directory: ./web
run: bun install --frozen-lockfile
- name: Build Web UI
working-directory: ./web
run: bun run build
- name: Upload Web UI artifact
uses: actions/upload-artifact@v4
with:
name: web-ui
path: web/dist/
retention-days: 7
security-scan:
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run security scan
uses: aquasecurity/trivy-action@master
with:
scan-ref: ${{ github.ref_name }}
scan-type: 'fs'
scan-ref: ${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload security results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
deploy-staging:
runs-on: ubuntu-latest
needs: [build-server, build-web]
if: github.ref == 'refs/heads/develop'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push MCP Server image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: socialguess/mcp:staging
- name: Build and push Web UI image
uses: docker/build-push-action@v5
with:
context: ./web
file: ./web/Dockerfile
target: production
push: true
tags: socialguess/web:staging
deploy-production:
runs-on: ubuntu-latest
needs: [build-server, build-web, security-scan]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
environment:
name: production
url: https://socialguess.example.com
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push MCP Server image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: |
socialguess/mcp:latest
socialguess/mcp:${{ github.sha }}
- name: Build and push Web UI image
uses: docker/build-push-action@v5
with:
context: ./web
file: ./web/Dockerfile
target: production
push: true
tags: |
socialguess/web:latest
socialguess/web:${{ github.sha }}
- name: Deploy to production
run: |
echo "Deploying to production server..."
# Add deployment commands here (e.g., SSH to server and docker-compose pull)
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
- name: Notify deployment
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
text: 'Production deployment completed'
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
if: always()