- Comprehensive CI/CD pipeline documentation (CI_CD_PIPELINE.md) - GitHub Actions workflows (test, build, deploy) - GitLab CI example (.gitlab-ci.yml) - Security scanning integration (Trivy, Cargo Audit, SAST) - Performance testing integration (Criterion benchmarks) - GitOps workflows (ArgoCD, Kustomize, Terraform) - Multi-environment deployment (dev, staging, production) - Automated rollback on failure - Health check validation - Kubernetes manifests and Helm charts Wave 125 Phase 3B - Deployment Excellence Agent 98 Mission: CI/CD Pipeline Documentation (P2 - MEDIUM) Duration: 1-2 hours
423 lines
12 KiB
YAML
423 lines
12 KiB
YAML
# GitLab CI/CD Pipeline for Foxhunt HFT Trading System
|
|
# This is an example configuration for teams using GitLab CI instead of GitHub Actions
|
|
|
|
stages:
|
|
- test
|
|
- security
|
|
- build
|
|
- deploy
|
|
|
|
variables:
|
|
CARGO_HOME: ${CI_PROJECT_DIR}/.cargo
|
|
RUST_BACKTRACE: "1"
|
|
SQLX_OFFLINE: "true"
|
|
REGISTRY: ${CI_REGISTRY}
|
|
IMAGE_PREFIX: ${CI_REGISTRY_IMAGE}
|
|
|
|
# Cache Cargo dependencies
|
|
.rust_cache:
|
|
cache:
|
|
key: ${CI_COMMIT_REF_SLUG}
|
|
paths:
|
|
- .cargo/
|
|
- target/
|
|
|
|
# Docker-in-Docker service for building images
|
|
.docker_service:
|
|
services:
|
|
- docker:24-dind
|
|
variables:
|
|
DOCKER_HOST: tcp://docker:2376
|
|
DOCKER_TLS_CERTDIR: "/certs"
|
|
DOCKER_TLS_VERIFY: 1
|
|
DOCKER_CERT_PATH: "$DOCKER_TLS_CERTDIR/client"
|
|
|
|
# ================================
|
|
# Test Stage
|
|
# ================================
|
|
|
|
test:unit:
|
|
stage: test
|
|
image: rust:1.75-slim
|
|
extends: .rust_cache
|
|
services:
|
|
- postgres:16-alpine
|
|
- redis:7-alpine
|
|
- vault:latest
|
|
variables:
|
|
POSTGRES_USER: foxhunt
|
|
POSTGRES_PASSWORD: foxhunt_dev_password
|
|
POSTGRES_DB: foxhunt
|
|
DATABASE_URL: postgresql://foxhunt:foxhunt_dev_password@postgres:5432/foxhunt
|
|
REDIS_URL: redis://redis:6379
|
|
VAULT_ADDR: http://vault:8200
|
|
VAULT_TOKEN: foxhunt-dev-root
|
|
VAULT_DEV_ROOT_TOKEN_ID: foxhunt-dev-root
|
|
JWT_SECRET: test_jwt_secret
|
|
RUST_LOG: info
|
|
before_script:
|
|
- apt-get update && apt-get install -y libssl-dev pkg-config postgresql-client
|
|
- cargo install sqlx-cli --no-default-features --features postgres
|
|
- cargo install cargo-llvm-cov
|
|
- cargo sqlx migrate run
|
|
script:
|
|
- cargo fmt --all -- --check
|
|
- cargo clippy --workspace --all-targets -- -D warnings
|
|
- cargo test --workspace --lib --bins
|
|
- cargo test --workspace --test '*' -- --test-threads=1
|
|
timeout: 30m
|
|
artifacts:
|
|
when: always
|
|
paths:
|
|
- target/nextest/
|
|
expire_in: 30 days
|
|
rules:
|
|
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
- if: '$CI_COMMIT_BRANCH == "develop"'
|
|
- if: '$CI_COMMIT_BRANCH =~ /^feature\/.*/'
|
|
|
|
test:coverage:
|
|
stage: test
|
|
image: rust:1.75-slim
|
|
extends: .rust_cache
|
|
services:
|
|
- postgres:16-alpine
|
|
- redis:7-alpine
|
|
- vault:latest
|
|
variables:
|
|
POSTGRES_USER: foxhunt
|
|
POSTGRES_PASSWORD: foxhunt_dev_password
|
|
POSTGRES_DB: foxhunt
|
|
DATABASE_URL: postgresql://foxhunt:foxhunt_dev_password@postgres:5432/foxhunt
|
|
REDIS_URL: redis://redis:6379
|
|
VAULT_ADDR: http://vault:8200
|
|
VAULT_TOKEN: foxhunt-dev-root
|
|
VAULT_DEV_ROOT_TOKEN_ID: foxhunt-dev-root
|
|
JWT_SECRET: test_jwt_secret
|
|
before_script:
|
|
- apt-get update && apt-get install -y libssl-dev pkg-config postgresql-client
|
|
- cargo install sqlx-cli --no-default-features --features postgres
|
|
- cargo install cargo-llvm-cov
|
|
- cargo sqlx migrate run
|
|
script:
|
|
- cargo llvm-cov --workspace --lcov --output-path lcov.info
|
|
- cargo llvm-cov --workspace --html --output-dir coverage_report
|
|
- |
|
|
COVERAGE=$(cargo llvm-cov --workspace --summary-only | grep -oP 'TOTAL.*\K[0-9.]+(?=%)')
|
|
echo "Coverage: $COVERAGE%"
|
|
if (( $(echo "$COVERAGE < 60.0" | bc -l) )); then
|
|
echo "❌ Coverage $COVERAGE% below threshold 60%"
|
|
exit 1
|
|
fi
|
|
echo "✅ Coverage $COVERAGE% meets threshold"
|
|
coverage: '/TOTAL.*\s+(\d+\.\d+)%/'
|
|
timeout: 30m
|
|
artifacts:
|
|
paths:
|
|
- lcov.info
|
|
- coverage_report/
|
|
expire_in: 30 days
|
|
reports:
|
|
coverage_report:
|
|
coverage_format: cobertura
|
|
path: lcov.info
|
|
rules:
|
|
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
- if: '$CI_COMMIT_BRANCH == "develop"'
|
|
|
|
# ================================
|
|
# Security Stage
|
|
# ================================
|
|
|
|
security:audit:
|
|
stage: security
|
|
image: rust:1.75-slim
|
|
extends: .rust_cache
|
|
before_script:
|
|
- cargo install cargo-audit
|
|
- cargo install cargo-geiger
|
|
script:
|
|
- cargo audit --deny warnings --ignore RUSTSEC-2020-0071
|
|
- cargo geiger --all-features --output-format Json > geiger-report.json
|
|
timeout: 10m
|
|
artifacts:
|
|
paths:
|
|
- geiger-report.json
|
|
expire_in: 30 days
|
|
rules:
|
|
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
- if: '$CI_COMMIT_BRANCH == "develop"'
|
|
|
|
security:sast:
|
|
stage: security
|
|
image: returntocorp/semgrep:latest
|
|
script:
|
|
- semgrep --config=auto --sarif --output=sast-report.sarif .
|
|
timeout: 10m
|
|
artifacts:
|
|
reports:
|
|
sast: sast-report.sarif
|
|
expire_in: 30 days
|
|
rules:
|
|
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
|
|
security:secrets:
|
|
stage: security
|
|
image: trufflesecurity/trufflehog:latest
|
|
script:
|
|
- trufflehog filesystem . --json --only-verified > secrets-scan.json
|
|
timeout: 10m
|
|
artifacts:
|
|
paths:
|
|
- secrets-scan.json
|
|
expire_in: 30 days
|
|
rules:
|
|
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
|
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
|
|
# ================================
|
|
# Build Stage
|
|
# ================================
|
|
|
|
.build_docker_image:
|
|
stage: build
|
|
extends: .docker_service
|
|
image: docker:24
|
|
before_script:
|
|
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
|
script:
|
|
- |
|
|
# Build multi-platform image
|
|
docker buildx create --use --name multiarch --driver docker-container
|
|
docker buildx build \
|
|
--platform linux/amd64,linux/arm64 \
|
|
--file services/${SERVICE}/Dockerfile \
|
|
--tag ${IMAGE_PREFIX}/${SERVICE}:${CI_COMMIT_SHA} \
|
|
--tag ${IMAGE_PREFIX}/${SERVICE}:${CI_COMMIT_REF_SLUG} \
|
|
--push \
|
|
--build-arg SERVICE_NAME=${SERVICE} \
|
|
--build-arg GIT_COMMIT=${CI_COMMIT_SHA} \
|
|
--build-arg GIT_BRANCH=${CI_COMMIT_REF_NAME} \
|
|
--build-arg BUILD_DATE=${CI_COMMIT_TIMESTAMP} \
|
|
.
|
|
- |
|
|
# Scan image for vulnerabilities
|
|
docker pull ${IMAGE_PREFIX}/${SERVICE}:${CI_COMMIT_SHA}
|
|
docker run --rm \
|
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
aquasec/trivy:latest \
|
|
image --severity CRITICAL,HIGH \
|
|
--exit-code 0 \
|
|
--format json \
|
|
--output trivy-${SERVICE}.json \
|
|
${IMAGE_PREFIX}/${SERVICE}:${CI_COMMIT_SHA}
|
|
timeout: 30m
|
|
artifacts:
|
|
paths:
|
|
- trivy-*.json
|
|
expire_in: 30 days
|
|
rules:
|
|
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
- if: '$CI_COMMIT_BRANCH == "develop"'
|
|
- if: '$CI_COMMIT_TAG'
|
|
|
|
build:api_gateway:
|
|
extends: .build_docker_image
|
|
variables:
|
|
SERVICE: api_gateway
|
|
|
|
build:trading_service:
|
|
extends: .build_docker_image
|
|
variables:
|
|
SERVICE: trading_service
|
|
|
|
build:backtesting_service:
|
|
extends: .build_docker_image
|
|
variables:
|
|
SERVICE: backtesting_service
|
|
|
|
build:ml_training_service:
|
|
extends: .build_docker_image
|
|
variables:
|
|
SERVICE: ml_training_service
|
|
|
|
build:tli:
|
|
stage: build
|
|
image: rust:1.75-slim
|
|
extends: .rust_cache
|
|
parallel:
|
|
matrix:
|
|
- TARGET: x86_64-unknown-linux-gnu
|
|
PLATFORM: linux-amd64
|
|
- TARGET: x86_64-apple-darwin
|
|
PLATFORM: macos-amd64
|
|
- TARGET: x86_64-pc-windows-msvc
|
|
PLATFORM: windows-amd64
|
|
before_script:
|
|
- apt-get update && apt-get install -y libssl-dev pkg-config
|
|
- rustup target add ${TARGET}
|
|
script:
|
|
- cargo build --release -p tli --target ${TARGET}
|
|
- |
|
|
if [ "${TARGET}" != "x86_64-pc-windows-msvc" ]; then
|
|
strip target/${TARGET}/release/tli
|
|
fi
|
|
timeout: 20m
|
|
artifacts:
|
|
name: "tli-${PLATFORM}"
|
|
paths:
|
|
- target/${TARGET}/release/tli*
|
|
expire_in: 30 days
|
|
rules:
|
|
- if: '$CI_COMMIT_TAG'
|
|
|
|
# ================================
|
|
# Deploy Stage
|
|
# ================================
|
|
|
|
.deploy:
|
|
stage: deploy
|
|
image: bitnami/kubectl:latest
|
|
before_script:
|
|
- kubectl config set-cluster k8s --server="${K8S_API_URL}"
|
|
- kubectl config set-credentials gitlab --token="${K8S_TOKEN}"
|
|
- kubectl config set-context default --cluster=k8s --user=gitlab --namespace=${NAMESPACE}
|
|
- kubectl config use-context default
|
|
script:
|
|
- |
|
|
# Update image tags
|
|
cd k8s/overlays/${ENVIRONMENT}
|
|
kubectl set image deployment/api-gateway api-gateway=${IMAGE_PREFIX}/api_gateway:${CI_COMMIT_SHA}
|
|
kubectl set image deployment/trading-service trading-service=${IMAGE_PREFIX}/trading_service:${CI_COMMIT_SHA}
|
|
kubectl set image deployment/backtesting-service backtesting-service=${IMAGE_PREFIX}/backtesting_service:${CI_COMMIT_SHA}
|
|
kubectl set image deployment/ml-training-service ml-training-service=${IMAGE_PREFIX}/ml_training_service:${CI_COMMIT_SHA}
|
|
|
|
# Wait for rollout
|
|
kubectl rollout status deployment/api-gateway --timeout=10m
|
|
kubectl rollout status deployment/trading-service --timeout=10m
|
|
kubectl rollout status deployment/backtesting-service --timeout=10m
|
|
kubectl rollout status deployment/ml-training-service --timeout=10m
|
|
|
|
# Health checks
|
|
for SERVICE in api-gateway trading-service backtesting-service ml-training-service; do
|
|
POD=$(kubectl get pod -l app=${SERVICE} -o jsonpath='{.items[0].metadata.name}')
|
|
kubectl exec ${POD} -- grpc_health_probe -addr=:50051
|
|
done
|
|
timeout: 30m
|
|
|
|
deploy:dev:
|
|
extends: .deploy
|
|
variables:
|
|
ENVIRONMENT: dev
|
|
NAMESPACE: foxhunt-dev
|
|
K8S_API_URL: ${DEV_K8S_API_URL}
|
|
K8S_TOKEN: ${DEV_K8S_TOKEN}
|
|
environment:
|
|
name: development
|
|
url: https://dev.foxhunt.io
|
|
on_stop: stop:dev
|
|
rules:
|
|
- if: '$CI_COMMIT_BRANCH == "develop"'
|
|
|
|
deploy:staging:
|
|
extends: .deploy
|
|
variables:
|
|
ENVIRONMENT: staging
|
|
NAMESPACE: foxhunt-staging
|
|
K8S_API_URL: ${STAGING_K8S_API_URL}
|
|
K8S_TOKEN: ${STAGING_K8S_TOKEN}
|
|
environment:
|
|
name: staging
|
|
url: https://staging.foxhunt.io
|
|
on_stop: stop:staging
|
|
rules:
|
|
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
when: manual
|
|
|
|
deploy:production:
|
|
extends: .deploy
|
|
variables:
|
|
ENVIRONMENT: production
|
|
NAMESPACE: foxhunt-prod
|
|
K8S_API_URL: ${PROD_K8S_API_URL}
|
|
K8S_TOKEN: ${PROD_K8S_TOKEN}
|
|
environment:
|
|
name: production
|
|
url: https://foxhunt.io
|
|
on_stop: stop:production
|
|
rules:
|
|
- if: '$CI_COMMIT_TAG'
|
|
when: manual
|
|
needs:
|
|
- build:api_gateway
|
|
- build:trading_service
|
|
- build:backtesting_service
|
|
- build:ml_training_service
|
|
- security:audit
|
|
|
|
# ================================
|
|
# Cleanup
|
|
# ================================
|
|
|
|
.stop_environment:
|
|
stage: deploy
|
|
image: bitnami/kubectl:latest
|
|
when: manual
|
|
script:
|
|
- kubectl scale deployment --all --replicas=0 -n ${NAMESPACE}
|
|
|
|
stop:dev:
|
|
extends: .stop_environment
|
|
variables:
|
|
NAMESPACE: foxhunt-dev
|
|
environment:
|
|
name: development
|
|
action: stop
|
|
|
|
stop:staging:
|
|
extends: .stop_environment
|
|
variables:
|
|
NAMESPACE: foxhunt-staging
|
|
environment:
|
|
name: staging
|
|
action: stop
|
|
|
|
stop:production:
|
|
extends: .stop_environment
|
|
variables:
|
|
NAMESPACE: foxhunt-prod
|
|
environment:
|
|
name: production
|
|
action: stop
|
|
|
|
# ================================
|
|
# Release
|
|
# ================================
|
|
|
|
release:
|
|
stage: deploy
|
|
image: registry.gitlab.com/gitlab-org/release-cli:latest
|
|
script:
|
|
- echo "Creating release for ${CI_COMMIT_TAG}"
|
|
release:
|
|
tag_name: ${CI_COMMIT_TAG}
|
|
name: 'Release ${CI_COMMIT_TAG}'
|
|
description: |
|
|
## Release ${CI_COMMIT_TAG}
|
|
|
|
Deployed to production at ${CI_COMMIT_TIMESTAMP}
|
|
|
|
### Services
|
|
- API Gateway: ${IMAGE_PREFIX}/api_gateway:${CI_COMMIT_TAG}
|
|
- Trading Service: ${IMAGE_PREFIX}/trading_service:${CI_COMMIT_TAG}
|
|
- Backtesting Service: ${IMAGE_PREFIX}/backtesting_service:${CI_COMMIT_TAG}
|
|
- ML Training Service: ${IMAGE_PREFIX}/ml_training_service:${CI_COMMIT_TAG}
|
|
rules:
|
|
- if: '$CI_COMMIT_TAG'
|
|
needs:
|
|
- deploy:production
|