Vapora/provisioning/scripts/ci-pipeline.nu
Jesús Pérez a395bd972f
Some checks failed
Rust CI / Security Audit (push) Has been cancelled
Rust CI / Check + Test + Lint (nightly) (push) Has been cancelled
Rust CI / Check + Test + Lint (stable) (push) Has been cancelled
mdBook Build & Deploy / Build mdBook (push) Has been cancelled
Nickel Type Check / Nickel Type Checking (push) Has been cancelled
mdBook Build & Deploy / Documentation Quality Check (push) Has been cancelled
mdBook Build & Deploy / Deploy to GitHub Pages (push) Has been cancelled
mdBook Build & Deploy / Notification (push) Has been cancelled
chore: add cd/ci ops
2026-01-12 03:36:55 +00:00

376 lines
10 KiB
Plaintext
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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