Platform restructured into crates/, added AI service and detector,
migrated control-center-ui to Leptos 0.8
413 lines
13 KiB
YAML
413 lines
13 KiB
YAML
name: CI/CD Pipeline - RAG Service
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
- develop
|
|
paths:
|
|
- 'provisioning/platform/rag/**'
|
|
- '.github/workflows/ci-cd.yml'
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
paths:
|
|
- 'provisioning/platform/rag/**'
|
|
|
|
env:
|
|
REGISTRY: ghcr.io
|
|
IMAGE_NAME: ${{ github.repository }}/provisioning-rag
|
|
RUST_VERSION: 1.80.1
|
|
|
|
jobs:
|
|
# ============================================================================
|
|
# LINTING AND FORMATTING
|
|
# ============================================================================
|
|
lint:
|
|
name: Lint and Format Check
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install Rust
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
toolchain: ${{ env.RUST_VERSION }}
|
|
components: rustfmt, clippy
|
|
|
|
- name: Cache Rust dependencies
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
workspaces: provisioning/platform/rag
|
|
|
|
- name: Run Clippy
|
|
run: |
|
|
cd provisioning/platform/rag
|
|
cargo clippy --all-targets --all-features -- -D warnings
|
|
|
|
- name: Check formatting
|
|
run: |
|
|
cd provisioning/platform/rag
|
|
cargo fmt -- --check
|
|
|
|
# ============================================================================
|
|
# UNIT TESTS
|
|
# ============================================================================
|
|
test:
|
|
name: Unit Tests
|
|
runs-on: ubuntu-latest
|
|
needs: lint
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install Rust
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
toolchain: ${{ env.RUST_VERSION }}
|
|
|
|
- name: Cache Rust dependencies
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
workspaces: provisioning/platform/rag
|
|
|
|
- name: Run tests
|
|
run: |
|
|
cd provisioning/platform/rag
|
|
cargo test --lib --doc
|
|
|
|
- name: Run integration tests
|
|
run: |
|
|
cd provisioning/platform/rag
|
|
cargo test --test integration_tests
|
|
|
|
- name: Upload test results
|
|
if: always()
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: test-results
|
|
path: provisioning/platform/rag/target/debug/deps/
|
|
|
|
# ============================================================================
|
|
# BENCHMARKING
|
|
# ============================================================================
|
|
benchmark:
|
|
name: Performance Benchmarks
|
|
runs-on: ubuntu-latest
|
|
needs: test
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install Rust
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
toolchain: ${{ env.RUST_VERSION }}
|
|
|
|
- name: Cache Rust dependencies
|
|
uses: Swatinem/rust-cache@v2
|
|
with:
|
|
workspaces: provisioning/platform/rag
|
|
|
|
- name: Run benchmarks
|
|
run: |
|
|
cd provisioning/platform/rag
|
|
cargo bench --no-run
|
|
cargo bench -- --output-format bencher | tee output.txt
|
|
|
|
- name: Store benchmark results
|
|
uses: benchmark-action/github-action-benchmark@v1
|
|
with:
|
|
name: Provisioning RAG Benchmarks
|
|
tool: 'cargo'
|
|
output-file-path: provisioning/platform/rag/output.txt
|
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
auto-push: true
|
|
|
|
- name: Upload benchmark results
|
|
if: always()
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: benchmark-results
|
|
path: provisioning/platform/rag/target/criterion/
|
|
|
|
# ============================================================================
|
|
# SECURITY SCANNING
|
|
# ============================================================================
|
|
security:
|
|
name: Security Scanning
|
|
runs-on: ubuntu-latest
|
|
needs: lint
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install Rust
|
|
uses: dtolnay/rust-toolchain@stable
|
|
with:
|
|
toolchain: ${{ env.RUST_VERSION }}
|
|
|
|
- name: Install cargo-audit
|
|
run: cargo install cargo-audit
|
|
|
|
- name: Audit dependencies
|
|
run: |
|
|
cd provisioning/platform/rag
|
|
cargo audit
|
|
|
|
- name: Run cargo-deny
|
|
uses: EmbarkStudios/cargo-deny-action@v1
|
|
with:
|
|
log-level: warn
|
|
command: check advisories
|
|
|
|
# ============================================================================
|
|
# BUILD DOCKER IMAGE
|
|
# ============================================================================
|
|
build:
|
|
name: Build Docker Image
|
|
runs-on: ubuntu-latest
|
|
needs: [test, benchmark, security]
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
outputs:
|
|
image-tag: ${{ steps.meta.outputs.tags }}
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v2
|
|
|
|
- name: Log in to Container Registry
|
|
uses: docker/login-action@v2
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Extract metadata
|
|
id: meta
|
|
uses: docker/metadata-action@v4
|
|
with:
|
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
tags: |
|
|
type=ref,event=branch
|
|
type=semver,pattern={{version}}
|
|
type=semver,pattern={{major}}.{{minor}}
|
|
type=sha,prefix={{branch}}-
|
|
type=raw,value=latest,enable={{is_default_branch}}
|
|
|
|
- name: Build and push Docker image
|
|
uses: docker/build-push-action@v4
|
|
with:
|
|
context: .
|
|
file: provisioning/platform/rag/docker/Dockerfile
|
|
push: true
|
|
tags: ${{ steps.meta.outputs.tags }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
|
|
# ============================================================================
|
|
# DEPLOY TO STAGING
|
|
# ============================================================================
|
|
deploy-staging:
|
|
name: Deploy to Staging
|
|
runs-on: ubuntu-latest
|
|
needs: build
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
environment:
|
|
name: staging
|
|
url: https://rag-staging.example.com
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up kubectl
|
|
uses: azure/setup-kubectl@v3
|
|
with:
|
|
version: v1.27.0
|
|
|
|
- name: Configure kubectl
|
|
run: |
|
|
mkdir -p $HOME/.kube
|
|
echo "${{ secrets.KUBECONFIG_STAGING }}" | base64 -d > $HOME/.kube/config
|
|
chmod 600 $HOME/.kube/config
|
|
|
|
- name: Deploy to Kubernetes
|
|
run: |
|
|
cd provisioning/platform/rag/k8s
|
|
kubectl apply -f 00-namespace.yaml
|
|
kubectl apply -f 01-configmap.yaml
|
|
kubectl apply -f 02-secrets.yaml
|
|
kubectl apply -f 03-storage.yaml
|
|
kubectl apply -f 04-deployment.yaml
|
|
kubectl apply -f 05-service.yaml
|
|
kubectl apply -f 06-hpa-ingress.yaml
|
|
kubectl apply -f 07-rbac.yaml
|
|
kubectl rollout status deployment/provisioning-rag -n provisioning-rag --timeout=5m
|
|
|
|
- name: Verify deployment health
|
|
run: |
|
|
for i in {1..30}; do
|
|
if curl -f https://rag-staging.example.com/health; then
|
|
echo "✓ Deployment healthy"
|
|
exit 0
|
|
fi
|
|
echo "Waiting for service to be healthy... ($i/30)"
|
|
sleep 10
|
|
done
|
|
echo "✗ Service failed to become healthy"
|
|
exit 1
|
|
|
|
- name: Run smoke tests
|
|
run: |
|
|
cd provisioning/platform/rag
|
|
curl -f https://rag-staging.example.com/health
|
|
curl -f https://rag-staging.example.com/tasks
|
|
echo "✓ Smoke tests passed"
|
|
|
|
# ============================================================================
|
|
# DEPLOY TO PRODUCTION
|
|
# ============================================================================
|
|
deploy-production:
|
|
name: Deploy to Production
|
|
runs-on: ubuntu-latest
|
|
needs: deploy-staging
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
environment:
|
|
name: production
|
|
url: https://rag.example.com
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up kubectl
|
|
uses: azure/setup-kubectl@v3
|
|
with:
|
|
version: v1.27.0
|
|
|
|
- name: Configure kubectl
|
|
run: |
|
|
mkdir -p $HOME/.kube
|
|
echo "${{ secrets.KUBECONFIG_PRODUCTION }}" | base64 -d > $HOME/.kube/config
|
|
chmod 600 $HOME/.kube/config
|
|
|
|
- name: Create backup of current state
|
|
run: |
|
|
cd provisioning/platform/rag/k8s
|
|
kubectl get deployment provisioning-rag -n provisioning-rag -o yaml > /tmp/deployment-backup.yaml
|
|
echo "Backup saved for rollback if needed"
|
|
|
|
- name: Deploy to Kubernetes
|
|
run: |
|
|
cd provisioning/platform/rag/k8s
|
|
kubectl apply -f 00-namespace.yaml
|
|
kubectl apply -f 01-configmap.yaml
|
|
kubectl apply -f 02-secrets.yaml
|
|
kubectl apply -f 03-storage.yaml
|
|
kubectl apply -f 04-deployment.yaml
|
|
kubectl apply -f 05-service.yaml
|
|
kubectl apply -f 06-hpa-ingress.yaml
|
|
kubectl apply -f 07-rbac.yaml
|
|
kubectl rollout status deployment/provisioning-rag -n provisioning-rag --timeout=10m
|
|
|
|
- name: Verify production health
|
|
run: |
|
|
for i in {1..30}; do
|
|
if curl -f https://rag.example.com/health; then
|
|
echo "✓ Production deployment healthy"
|
|
exit 0
|
|
fi
|
|
echo "Waiting for service to be healthy... ($i/30)"
|
|
sleep 10
|
|
done
|
|
echo "✗ Service failed to become healthy"
|
|
exit 1
|
|
|
|
- name: Run comprehensive tests
|
|
run: |
|
|
cd provisioning/platform/rag
|
|
curl -f https://rag.example.com/health
|
|
curl -f https://rag.example.com/tasks
|
|
curl -f https://rag.example.com/metrics
|
|
echo "✓ Comprehensive tests passed"
|
|
|
|
- name: Notify deployment
|
|
if: success()
|
|
run: |
|
|
echo "✓ Production deployment successful"
|
|
echo "Service URL: https://rag.example.com"
|
|
echo "Metrics: https://rag.example.com/metrics"
|
|
|
|
# ============================================================================
|
|
# ROLLBACK (Manual trigger)
|
|
# ============================================================================
|
|
rollback:
|
|
name: Rollback Production
|
|
runs-on: ubuntu-latest
|
|
if: failure() && github.event_name == 'workflow_dispatch'
|
|
environment:
|
|
name: production
|
|
steps:
|
|
- name: Set up kubectl
|
|
uses: azure/setup-kubectl@v3
|
|
|
|
- name: Configure kubectl
|
|
run: |
|
|
mkdir -p $HOME/.kube
|
|
echo "${{ secrets.KUBECONFIG_PRODUCTION }}" | base64 -d > $HOME/.kube/config
|
|
chmod 600 $HOME/.kube/config
|
|
|
|
- name: Rollback to previous version
|
|
run: |
|
|
kubectl rollout undo deployment/provisioning-rag -n provisioning-rag
|
|
kubectl rollout status deployment/provisioning-rag -n provisioning-rag --timeout=5m
|
|
|
|
- name: Verify rollback
|
|
run: |
|
|
curl -f https://rag.example.com/health
|
|
echo "✓ Rollback successful"
|
|
|
|
# ============================================================================
|
|
# NOTIFICATION
|
|
# ============================================================================
|
|
notify:
|
|
name: Notification
|
|
runs-on: ubuntu-latest
|
|
if: always()
|
|
needs: [lint, test, benchmark, security, build, deploy-staging, deploy-production]
|
|
steps:
|
|
- name: Determine status
|
|
id: status
|
|
run: |
|
|
if [ "${{ job.status }}" == "success" ]; then
|
|
echo "status=✓ Success" >> $GITHUB_OUTPUT
|
|
echo "color=0x28a745" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "status=✗ Failed" >> $GITHUB_OUTPUT
|
|
echo "color=0xdc3545" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Slack Notification
|
|
uses: slackapi/slack-github-action@v1
|
|
with:
|
|
webhook-url: ${{ secrets.SLACK_WEBHOOK }}
|
|
payload: |
|
|
{
|
|
"text": "RAG Service CI/CD Pipeline ${{ steps.status.outputs.status }}",
|
|
"blocks": [
|
|
{
|
|
"type": "section",
|
|
"text": {
|
|
"type": "mrkdwn",
|
|
"text": "RAG Service CI/CD Pipeline\n*Status:* ${{ steps.status.outputs.status }}\n*Commit:* ${{ github.sha }}\n*Branch:* ${{ github.ref_name }}"
|
|
}
|
|
}
|
|
]
|
|
}
|