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