Skip to content

CI/CD — 自动化部署

GitHub Actions 工作流

yaml
# .github/workflows/deploy.yml
name: Deploy LLM API

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.11'
    
    - name: Install dependencies
      run: pip install -r requirements.txt
    
    - name: Run tests
      run: pytest tests/ -v
      env:
        DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}

  build-and-push:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Build Docker image
      run: docker build -t your-registry/llm-api:${{ github.sha }} .
    
    - name: Push to registry
      run: |
        echo ${{ secrets.REGISTRY_PASSWORD }} | docker login -u ${{ secrets.REGISTRY_USERNAME }} --password-stdin
        docker push your-registry/llm-api:${{ github.sha }}
        docker tag your-registry/llm-api:${{ github.sha }} your-registry/llm-api:latest
        docker push your-registry/llm-api:latest

  deploy:
    needs: build-and-push
    runs-on: ubuntu-latest
    
    steps:
    - name: Deploy to Kubernetes
      run: |
        kubectl set image deployment/llm-api \
          llm-api=your-registry/llm-api:${{ github.sha }} \
          -n finance-ai
        kubectl rollout status deployment/llm-api -n finance-ai

测试策略

python
# tests/test_api.py
import pytest
from fastapi.testclient import TestClient
from unittest.mock import patch, MagicMock
from main import app

client = TestClient(app)

@pytest.fixture
def mock_llm():
    with patch("main.client.chat.completions.create") as mock:
        mock.return_value = MagicMock(
            choices=[MagicMock(message=MagicMock(content="测试回复"))],
            usage=MagicMock(total_tokens=100)
        )
        yield mock

def test_chat_endpoint(mock_llm):
    response = client.post("/chat", json={"message": "测试问题"})
    assert response.status_code == 200
    assert "answer" in response.json()

def test_health_endpoint():
    response = client.get("/health")
    assert response.status_code == 200

环境管理

bash
# .env.production
DASHSCOPE_API_KEY=sk-prod-xxx
REDIS_URL=redis://prod-redis:6379
DATABASE_URL=mysql+pymysql://user:pass@prod-db:3306/finance
LOG_LEVEL=WARNING

# .env.staging
DASHSCOPE_API_KEY=sk-staging-xxx
REDIS_URL=redis://staging-redis:6379
LOG_LEVEL=INFO

本站内容由 褚成志 整理编写,仅供学习参考