ADR-014-v4: Deployment Pipeline - Part 2 (Technical)
Document Specification Block​
Document: ADR-014-v4-deployment-pipeline-part2-technical
Version: 1.0.0
Purpose: Constrain AI implementation with exact technical specifications for deployment pipeline
Audience: AI agents, developers implementing the system
Date Created: 2025-09-01
Date Modified: 2025-09-01
QA Review Date: Pending
Status: DRAFT
Table of Contents​
- Constraints
- Dependencies
- Component Architecture
- Data Models
- Implementation Patterns
- API Specifications
- Testing Requirements
- Performance Benchmarks
- Security Controls
- Logging and Error Handling
- References
- Approval Signatures
1. Constraints​
CONSTRAINT: Zero-Downtime Deployment​
All deployments MUST maintain 100% uptime. No service interruption allowed.
CONSTRAINT: Sub-4-Minute Builds​
Build and deployment pipeline MUST complete within 4 minutes for standard changes.
CONSTRAINT: Automatic Rollback​
Failed deployments MUST automatically rollback within 30 seconds of health check failure.
CONSTRAINT: Multi-Region Consistency​
Deployments MUST maintain consistency across all regions with <5 second lag.
CONSTRAINT: Audit Compliance​
Every deployment action MUST be logged with full traceability for SOC2 compliance.
2. Dependencies​
cargo.toml Dependencies​
[dependencies]
# Cloud SDK
google-cloud-sdk = { version = "0.25", features = ["storage", "build", "run"] }
# Container tools
bollard = "0.16" # Docker API
kaniko = "0.1" # Container builder
# Deployment orchestration
k8s-openapi = { version = "0.20", features = ["v1_28"] }
kube = { version = "0.87", features = ["runtime", "derive"] }
# Monitoring
prometheus = { version = "0.13", features = ["process"] }
opentelemetry = { version = "0.21", features = ["trace", "metrics"] }
# Core
tokio = { version = "1.35", features = ["full"] }
anyhow = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
uuid = { version = "1.6", features = ["v4", "serde"] }
chrono = { version = "0.4", features = ["serde"] }
3. Component Architecture​
// File: src/deployment/pipeline_service.rs
use std::sync::Arc;
use anyhow::Result;
pub struct DeploymentPipeline {
build_service: Arc<BuildService>,
deployment_service: Arc<DeploymentService>,
health_checker: Arc<HealthChecker>,
rollback_manager: Arc<RollbackManager>,
audit_logger: Arc<AuditLogger>,
}
// File: src/deployment/pipeline_service.rs
impl DeploymentPipeline {
pub async fn deploy(&self, request: DeploymentRequest) -> Result<DeploymentResult> {
// 1. Build stage
let build_result = self.build_service
.build_with_cache(&request.source)
.await?;
// 2. Security scan
self.security_scan(&build_result).await?;
// 3. Blue-green deployment
let deployment = self.deployment_service
.deploy_blue_green(&build_result, &request.target)
.await?;
// 4. Health validation
match self.health_checker.validate(&deployment).await {
Ok(_) => {
// 5. Traffic switch
self.deployment_service.switch_traffic(&deployment).await?;
self.audit_logger.log_success(&deployment).await?;
Ok(deployment.into())
}
Err(e) => {
// 6. Auto rollback
self.rollback_manager.execute(&deployment).await?;
self.audit_logger.log_rollback(&deployment, &e).await?;
Err(e)
}
}
}
}
4. Data Models​
Deployment Models​
// File: src/models/deployment.rs
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeploymentRequest {
pub id: Uuid,
pub source: SourceConfig,
pub target: TargetEnvironment,
pub strategy: DeploymentStrategy,
pub metadata: DeploymentMetadata,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SourceConfig {
pub repository: String,
pub branch: String,
pub commit: String,
pub dockerfile: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DeploymentStrategy {
BlueGreen { switch_delay_seconds: u32 },
Canary { stages: Vec<CanaryStage> },
Rolling { max_surge: u32, max_unavailable: u32 },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthCheck {
pub endpoint: String,
pub interval_seconds: u32,
pub timeout_seconds: u32,
pub success_threshold: u32,
pub failure_threshold: u32,
}
5. Implementation Patterns​
Build Optimization​
// File: src/deployment/build_service.rs
pub struct BuildService {
cache_bucket: String,
registry: String,
machine_type: String,
}
impl BuildService {
pub async fn build_with_cache(&self, source: &SourceConfig) -> Result<BuildResult> {
let config = CloudBuildConfig {
steps: vec![
// Step 1: Restore cache
BuildStep {
name: "gcr.io/cloud-builders/gsutil",
args: vec![
"cp",
&format!("gs://{}/cache.tar.gz", self.cache_bucket),
"cache.tar.gz"
],
},
// Step 2: Build with cargo-chef
BuildStep {
name: "gcr.io/kaniko-project/executor",
args: vec![
"--dockerfile=Dockerfile",
"--cache=true",
"--cache-ttl=168h",
&format!("--destination={}/api:$COMMIT_SHA", self.registry),
],
},
// Step 3: Save cache
BuildStep {
name: "gcr.io/cloud-builders/gsutil",
args: vec![
"cp",
"target/release/deps/*",
&format!("gs://{}/", self.cache_bucket),
],
},
],
options: BuildOptions {
machine_type: "E2_HIGHCPU_8".to_string(),
disk_size_gb: 100,
substitution_option: "ALLOW_LOOSE",
},
timeout: "600s",
};
self.execute_build(config).await
}
}
Blue-Green Deployment​
// File: src/deployment/deployment_service.rs
impl DeploymentService {
pub async fn deploy_blue_green(
&self,
build: &BuildResult,
target: &TargetEnvironment,
) -> Result<Deployment> {
// 1. Deploy to green environment
let green_revision = self.deploy_revision(
&build.image,
&format!("{}-green", target.service_name),
0, // No traffic initially
).await?;
// 2. Run smoke tests
self.run_smoke_tests(&green_revision).await?;
// 3. Prepare for switch
Ok(Deployment {
id: Uuid::new_v4(),
blue_revision: self.get_current_revision(&target.service_name).await?,
green_revision,
status: DeploymentStatus::AwaitingSwitch,
created_at: Utc::now(),
})
}
pub async fn switch_traffic(&self, deployment: &Deployment) -> Result<()> {
let traffic_config = TrafficConfig {
revisions: vec![
(deployment.green_revision.clone(), 100),
(deployment.blue_revision.clone(), 0),
],
};
self.update_traffic(traffic_config).await
}
}
6. API Specifications​
Deployment Endpoints​
// File: src/api/handlers/deployment.rs
use actix_web::{web, HttpResponse, Result};
#[post("/api/v1/deploy")]
pub async fn trigger_deployment(
web::Json(request): web::Json<DeploymentRequest>,
pipeline: web::Data<Arc<DeploymentPipeline>>,
claims: Claims,
) -> Result<HttpResponse> {
// Validate permissions
if !claims.has_permission("deployment:create") {
return Ok(HttpResponse::Forbidden().json(json!({
"error": "insufficient_permissions"
})));
}
match pipeline.deploy(request.into_inner()).await {
Ok(result) => Ok(HttpResponse::Ok().json(result)),
Err(e) => Ok(HttpResponse::InternalServerError().json(json!({
"error": "deployment_failed",
"message": e.to_string()
})))
}
}
#[post("/api/v1/rollback/{deployment_id}")]
pub async fn rollback_deployment(
path: web::Path<Uuid>,
rollback_manager: web::Data<Arc<RollbackManager>>,
claims: Claims,
) -> Result<HttpResponse> {
let result = rollback_manager
.rollback(path.into_inner(), claims.user_id)
.await?;
Ok(HttpResponse::Ok().json(result))
}
7. Testing Requirements​
Test Coverage Requirements​
- Unit Test Coverage: ≥95% of deployment logic
- Integration Test Coverage: ≥90% of pipeline flows
- E2E Test Coverage: All critical deployment paths
- Chaos Test Coverage: Network failures, partial deployments
Integration Tests​
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_blue_green_deployment() {
let pipeline = setup_test_pipeline().await;
let request = DeploymentRequest {
source: SourceConfig {
repository: "test-repo",
branch: "main",
commit: "abc123",
dockerfile: None,
},
target: TargetEnvironment {
service_name: "api",
region: "us-central1",
project_id: "test-project",
},
strategy: DeploymentStrategy::BlueGreen {
switch_delay_seconds: 30
},
metadata: Default::default(),
};
let result = pipeline.deploy(request).await.unwrap();
assert_eq!(result.status, DeploymentStatus::Success);
}
#[tokio::test]
async fn test_automatic_rollback() {
let pipeline = setup_test_pipeline().await;
let failing_request = create_failing_deployment_request();
let result = pipeline.deploy(failing_request).await;
assert!(result.is_err());
// Verify rollback occurred
let status = pipeline.get_deployment_status().await.unwrap();
assert_eq!(status.rollback_count, 1);
}
}
8. Performance Benchmarks​
Required Metrics​
const BUILD_TIME_TARGET_MS: u64 = 240_000; // 4 minutes
const ROLLBACK_TIME_TARGET_MS: u64 = 30_000; // 30 seconds
const HEALTH_CHECK_TIMEOUT_MS: u64 = 5_000;
pub struct PerformanceValidator {
pub fn validate_deployment_performance(&self, metrics: &DeploymentMetrics) -> ValidationResult {
let mut result = ValidationResult::default();
// Build time
result.build_time_ok = metrics.build_duration_ms <= BUILD_TIME_TARGET_MS;
// Rollback time
if let Some(rollback_ms) = metrics.rollback_duration_ms {
result.rollback_time_ok = rollback_ms <= ROLLBACK_TIME_TARGET_MS;
}
// Health check responsiveness
result.health_check_ok = metrics.health_check_duration_ms <= HEALTH_CHECK_TIMEOUT_MS;
result
}
}
9. Security Controls​
Deployment Security​
// File: src/deployment/security.rs
pub struct DeploymentSecurity {
scanner: Arc<ContainerScanner>,
policy_engine: Arc<PolicyEngine>,
}
impl DeploymentSecurity {
pub async fn validate_deployment(&self, build: &BuildResult) -> Result<()> {
// Container scanning
let scan_result = self.scanner.scan_image(&build.image).await?;
if scan_result.critical_vulnerabilities > 0 {
return Err(anyhow!("Critical vulnerabilities found"));
}
// Policy validation
self.policy_engine.validate_deployment_policy(build).await?;
// Sign image
self.sign_container_image(&build.image).await?;
Ok(())
}
}
10. Logging and Error Handling​
Deployment Logging​
// File: src/deployment/logging.rs
use tracing::{info, error, instrument};
#[instrument(skip(self))]
pub async fn log_deployment_event(&self, event: DeploymentEvent) {
let entry = json!({
"timestamp": Utc::now(),
"event_type": event.event_type,
"deployment_id": event.deployment_id,
"service": event.service_name,
"region": event.region,
"user": event.triggered_by,
"status": event.status,
"duration_ms": event.duration_ms,
});
info!(deployment_event = ?entry, "Deployment event");
}
Error Handling​
#[derive(thiserror::Error, Debug)]
pub enum DeploymentError {
#[error("Build failed: {0}")]
BuildFailed(String),
#[error("Health check failed after {attempts} attempts")]
HealthCheckFailed { attempts: u32 },
#[error("Rollback failed: {0}")]
RollbackFailed(String),
#[error("Security scan failed: {vulnerabilities} critical vulnerabilities")]
SecurityScanFailed { vulnerabilities: u32 },
}
11. References​
- ADR-001-v4: Container Execution
- ADR-008-v4: Monitoring & Observability
- ADR-010-v4: Disaster Recovery
- LOGGING-STANDARD-v4
Version Compatibility​
- Google Cloud SDK: 0.25+ for Cloud Build v2 API
- Kubernetes: 1.28+ for traffic management features
- Cloud Run: Latest for blue-green deployments
12. Approval Signatures​
Technical Sign-off​
| Component | Owner | Approved | Date |
|---|---|---|---|
| Architecture | Session5 | ✓ | 2025-09-01 |
| Implementation | Pending | - | - |
| Security Review | Pending | - | - |
| Performance Test | Pending | - | - |
Implementation Checklist​
- Pipeline service implemented
- Build optimization with caching
- Blue-green deployment logic
- Health check validation
- Automatic rollback mechanism
- Security scanning integration
- API endpoints tested
- Performance benchmarks met
- Monitoring configured