Vapora/provisioning/scripts/ci-pipeline.nu

376 lines
10 KiB
Plaintext
Raw Permalink Normal View History

2026-01-12 03:36:55 +00:00
#!/usr/bin/env nu
# VAPORA CI/CD Pipeline Integration
# Validates, builds, and tests deployment artifacts
# Designed for GitHub Actions, GitLab CI, Jenkins integration
# Version: 1.0.0
def main [
--mode: string = "multiuser"
--artifact-dir: string = "artifacts"
--test-deploy: bool = false
] {
let start_time = (date now)
print "🔧 VAPORA CI/CD Pipeline"
print $"Mode: ($mode) | Artifact Dir: ($artifact_dir)"
print $"Timestamp: ($start_time | format date '%Y-%m-%d %H:%M:%S')"
print ""
# Step 1: Validate Nickel configurations
print "Step 1⃣ - Validating Nickel configurations..."
validate-nickel-configs
# Step 2: Generate configurations
print "Step 2⃣ - Generating configurations..."
generate-all-configs $artifact_dir
# Step 3: Validate all outputs
print "Step 3⃣ - Validating all outputs..."
validate-all-outputs $artifact_dir
# Step 4: Render templates
print "Step 4⃣ - Rendering templates..."
render-all-templates $artifact_dir
# Step 5: Test deployment artifacts
if $test_deploy {
print "Step 5⃣ - Testing deployment (dry-run)..."
test-deployment-artifacts $artifact_dir
}
# Step 6: Generate reports
print "Step 6⃣ - Generating reports..."
generate-reports $artifact_dir
let end_time = (date now)
let duration = ($end_time - $start_time)
print ""
print "✅ CI/CD Pipeline Complete"
print $"Duration: ($duration)"
print $"Artifacts: ($artifact_dir)"
}
def validate-nickel-configs: nothing {
print " 🔍 Checking Nickel configurations..."
let configs = [
"schemas/vapora/main.ncl"
"schemas/vapora/backend.ncl"
"schemas/vapora/agents.ncl"
"schemas/vapora/llm-router.ncl"
"schemas/platform/common/helpers.ncl"
"schemas/platform/schemas/common/server.ncl"
"schemas/platform/schemas/common/database.ncl"
"schemas/platform/schemas/common/monitoring.ncl"
"schemas/platform/schemas/common/security.ncl"
"schemas/platform/schemas/common/storage.ncl"
"schemas/platform/configs/vapora-solo.ncl"
"schemas/platform/configs/vapora-multiuser.ncl"
"schemas/platform/configs/vapora-enterprise.ncl"
]
$configs | each { |config|
print $" → ($config)"
let result = do {
nickel typecheck $config
} | complete
if $result.exit_code != 0 {
error make {msg: $"Typecheck failed: ($result.stderr)"}
}
print $" ✓ Valid"
}
print " ✓ All Nickel configurations valid"
}
def generate-all-configs [artifact_dir: string] {
print " 🔨 Generating configurations for all modes..."
let modes = ["solo", "multiuser", "enterprise"]
$modes | each { |mode|
print $" → ($mode) mode"
let result = do {
nickel export $"schemas/platform/configs/vapora-($mode).ncl"
} | complete
if $result.exit_code != 0 {
error make {msg: $"Export failed for ($mode): ($result.stderr)"}
}
let output_path = ($artifact_dir | path join $"config-($mode).json")
do {
$result.stdout | save -f $output_path
} | complete | if $in.exit_code != 0 {
error make {msg: $"Failed to save config-($mode).json"}
}
print $" ✓ Generated"
}
print " ✓ All configurations generated"
}
def validate-all-outputs [artifact_dir: string] {
print " ✅ Validating all JSON outputs..."
let json_files = [
"config-solo.json"
"config-multiuser.json"
"config-enterprise.json"
]
$json_files | each { |file|
let path = ($artifact_dir | path join $file)
if not ($path | path exists) {
error make {msg: $"Missing file: ($file)"}
}
let result = do {
open $path | to json
} | complete
if $result.exit_code != 0 {
error make {msg: $"Invalid JSON: ($file)"}
}
print $" ✓ ($file) valid"
}
print " ✓ All JSON outputs valid"
}
def render-all-templates [artifact_dir: string] {
print " 🎨 Rendering Jinja2 templates..."
let modes = ["solo", "multiuser", "enterprise"]
$modes | each { |mode|
let config_path = ($artifact_dir | path join $"config-($mode).json")
# TOML
print $" → ($mode): TOML"
let toml_result = do {
jinja2 schemas/platform/templates/configs/vapora.toml.j2 $config_path
} | complete
if $toml_result.exit_code != 0 {
error make {msg: $"TOML rendering failed: ($toml_result.stderr)"}
}
do {
$toml_result.stdout | save -f ($artifact_dir | path join $"vapora-($mode).toml")
} | complete | if $in.exit_code != 0 {
error make {msg: "Failed to save TOML"}
}
# YAML
print $" → ($mode): YAML"
let yaml_result = do {
jinja2 schemas/platform/templates/configs/vapora.yaml.j2 $config_path
} | complete
if $yaml_result.exit_code != 0 {
error make {msg: $"YAML rendering failed: ($yaml_result.stderr)"}
}
do {
$yaml_result.stdout | save -f ($artifact_dir | path join $"vapora-($mode).yaml")
} | complete | if $in.exit_code != 0 {
error make {msg: "Failed to save YAML"}
}
}
# Kubernetes templates (for all modes, they're the same ConfigMap/Deployment pattern)
print " → Kubernetes: ConfigMap"
let config_path = ($artifact_dir | path join "config-enterprise.json")
let cm_result = do {
jinja2 schemas/platform/templates/kubernetes/configmap.yaml.j2 $config_path
} | complete
if $cm_result.exit_code != 0 {
error make {msg: $"ConfigMap rendering failed: ($cm_result.stderr)"}
}
do {
$cm_result.stdout | save -f ($artifact_dir | path join "configmap.yaml")
} | complete | if $in.exit_code != 0 {
error make {msg: "Failed to save ConfigMap"}
}
print " → Kubernetes: Deployment"
let deploy_result = do {
jinja2 schemas/platform/templates/kubernetes/deployment.yaml.j2 $config_path
} | complete
if $deploy_result.exit_code != 0 {
error make {msg: $"Deployment rendering failed: ($deploy_result.stderr)"}
}
do {
$deploy_result.stdout | save -f ($artifact_dir | path join "deployment.yaml")
} | complete | if $in.exit_code != 0 {
error make {msg: "Failed to save Deployment"}
}
# Docker Compose
print " → Docker Compose"
let docker_path = ($artifact_dir | path join "config-solo.json")
let dc_result = do {
jinja2 schemas/platform/templates/docker-compose/docker-compose.yaml.j2 $docker_path
} | complete
if $dc_result.exit_code != 0 {
error make {msg: $"Docker Compose rendering failed: ($dc_result.stderr)"}
}
do {
$dc_result.stdout | save -f ($artifact_dir | path join "docker-compose.yml")
} | complete | if $in.exit_code != 0 {
error make {msg: "Failed to save Docker Compose"}
}
print " ✓ All templates rendered"
}
def test-deployment-artifacts [artifact_dir: string] {
print " 🧪 Testing deployment artifacts (dry-run)..."
# Validate YAML with yq
print " → Validating YAML syntax..."
let yaml_files = [
"vapora-solo.yaml"
"vapora-multiuser.yaml"
"vapora-enterprise.yaml"
"configmap.yaml"
"deployment.yaml"
"docker-compose.yml"
]
$yaml_files | each { |file|
let path = ($artifact_dir | path join $file)
if ($path | path exists) {
let result = do {
yq eval '.' $path
} | complete
if $result.exit_code != 0 {
error make {msg: $"Invalid YAML in ($file)"}
}
print $" ✓ ($file)"
}
}
# Test Kubernetes manifests with kubectl dry-run
print " → Testing Kubernetes manifests..."
let cm_path = ($artifact_dir | path join "configmap.yaml")
let deploy_path = ($artifact_dir | path join "deployment.yaml")
if ($cm_path | path exists) {
let result = do {
kubectl apply -f $cm_path --dry-run=client
} | complete
if $result.exit_code != 0 {
error make {msg: $"Invalid Kubernetes ConfigMap: ($result.stderr)"}
}
print " ✓ ConfigMap (dry-run passed)"
}
if ($deploy_path | path exists) {
let result = do {
kubectl apply -f $deploy_path --dry-run=client
} | complete
if $result.exit_code != 0 {
error make {msg: $"Invalid Kubernetes Deployment: ($result.stderr)"}
}
print " ✓ Deployment (dry-run passed)"
}
print " ✓ All tests passed"
}
def generate-reports [artifact_dir: string] {
print " 📋 Generating CI/CD reports..."
# Generate manifest
let manifest_path = ($artifact_dir | path join "MANIFEST.md")
let report = @"
# VAPORA Deployment Artifacts
Generated: (date now | format date '%Y-%m-%d %H:%M:%S')
## Files Generated
### Configurations
- config-solo.json
- config-multiuser.json
- config-enterprise.json
### TOML Outputs
- vapora-solo.toml
- vapora-multiuser.toml
- vapora-enterprise.toml
### YAML Outputs
- vapora-solo.yaml
- vapora-multiuser.yaml
- vapora-enterprise.yaml
### Kubernetes Manifests
- configmap.yaml
- deployment.yaml
### Docker Compose
- docker-compose.yml
## Deployment Modes
| Mode | Solo | Multiuser | Enterprise |
|------|------|-----------|------------|
| Host | 127.0.0.1 | 0.0.0.0 | 0.0.0.0 |
| Workers | 2 | 4 | 8 |
| NATS | disabled | enabled | enabled |
| Cost Tracking | disabled | enabled | enabled |
| Max Agents | 3 | 10 | 50 |
## Status
✅ All configurations generated
✅ All templates rendered
✅ All outputs validated
"@
do {
$report | save -f $manifest_path
} | complete | if $in.exit_code != 0 {
print " ⚠️ Failed to save manifest"
} else {
print $" ✓ Manifest: ($manifest_path)"
}
# List all artifacts
print " 📦 Artifacts summary:"
let artifacts = do {
ls $artifact_dir -la
} | complete
if $artifacts.exit_code == 0 {
$artifacts.stdout | lines | each { |line|
if ($line | str contains ".json") or ($line | str contains ".yaml") or ($line | str contains ".toml") or ($line | str contains ".yml") {
print $" • ($line)"
}
}
}
}
# Run main function
main