2025-10-07 10:59:52 +01:00

416 lines
13 KiB
Plaintext

#!/usr/bin/env nu
# Main Deployment Script for Provisioning Platform Installer
#
# Provides three deployment modes:
# 1. Interactive: TUI-based deployment with user prompts
# 2. Headless: CLI-based deployment with command-line args
# 3. Unattended: Fully automated deployment from config files
use helpers.nu *
use platforms.nu *
use integration.nu *
# Deploy provisioning platform interactively
#
# Uses the Rust TUI installer for interactive configuration
# and deployment. This is the recommended method for first-time
# users and development environments.
#
# @returns: Deployment result record
export def deploy-interactive []: nothing -> record {
print "🚀 Starting interactive deployment..."
# Check prerequisites
let prereqs = check-prerequisites
if not $prereqs.success {
error make {
msg: "Prerequisites check failed"
label: {text: $prereqs.error}
}
}
# Launch Rust TUI installer
let installer_path = get-installer-path
try {
^$installer_path
{
success: true
mode: "interactive"
message: "Interactive deployment completed"
timestamp: (date now)
}
} catch {|err|
error make {
msg: "Interactive deployment failed"
label: {text: $err.msg}
help: "Check installer logs for details"
}
}
}
# Deploy provisioning platform in headless mode
#
# Uses command-line arguments to configure and deploy without
# interactive prompts. Suitable for scripted deployments and
# environments where TUI is not available.
#
# @param platform: Target platform (docker, podman, kubernetes, orbstack)
# @param mode: Deployment mode (solo, multi-user, cicd, enterprise)
# @param domain: Domain/hostname for services (default: localhost)
# @param services: Comma-separated list of services to enable
# @param auto_confirm: Skip confirmation prompts if true
# @returns: Deployment result record
export def deploy-headless [
platform: string # Target platform
mode: string # Deployment mode
--domain: string = "localhost" # Domain/hostname
--services: string = "" # Services to enable
--auto-confirm # Skip confirmations
--config-only # Generate config only
]: nothing -> record {
print $"🚀 Starting headless deployment: ($mode) on ($platform)"
# Validate inputs
let validation = validate-deployment-params $platform $mode
if not $validation.success {
error make {
msg: "Invalid deployment parameters"
label: {text: $validation.error}
}
}
# Check prerequisites
let prereqs = check-prerequisites
if not $prereqs.success {
error make {
msg: "Prerequisites check failed"
label: {text: $prereqs.error}
}
}
# Build config
let config = build-deployment-config {
platform: $platform
mode: $mode
domain: $domain
services: ($services | split row "," | where {|s| $s != ""})
auto_generate_secrets: true
}
# Save config
let config_path = save-deployment-config $config
print $"📝 Configuration saved to: ($config_path)"
# Stop if config-only mode
if $config_only {
return {
success: true
mode: "headless"
config_path: $config_path
message: "Configuration generated successfully"
timestamp: (date now)
}
}
# Confirm deployment unless auto-confirmed
if not $auto_confirm {
let confirmed = confirm-deployment $config
if not $confirmed {
return {
success: false
mode: "headless"
message: "Deployment cancelled by user"
timestamp: (date now)
}
}
}
# Execute deployment
let result = match $platform {
"docker" => { deploy-docker $config }
"podman" => { deploy-podman $config }
"kubernetes" => { deploy-kubernetes $config }
"orbstack" => { deploy-orbstack $config }
_ => {
error make {msg: $"Unsupported platform: ($platform)"}
}
}
# Run health checks
if $result.success {
print "🔍 Running health checks..."
let health = check-deployment-health $config
if not $health.success {
print "⚠️ Health checks failed - attempting rollback..."
rollback-deployment $config
return {
success: false
mode: "headless"
error: $health.error
message: "Deployment rolled back due to health check failures"
timestamp: (date now)
}
}
}
$result
}
# Deploy provisioning platform in unattended mode
#
# Fully automated deployment using pre-configured settings from
# a TOML config file, MCP server, or API. No user interaction
# required. Includes strict validation, progress tracking, and
# automated rollback on failure.
#
# @param config_source: Configuration source (file, mcp, api)
# @param source_path: Path/URL to config source
# @param webhook_url: Optional webhook for notifications
# @returns: Deployment result record
export def deploy-unattended [
config_source: string # Config source type (file, mcp, api)
source_path: string # Path/URL to config
--webhook-url: string = "" # Notification webhook
--strict # Strict validation mode
]: nothing -> record {
print $"🚀 Starting unattended deployment from ($config_source)..."
# Notify start if webhook configured
if $webhook_url != "" {
notify-webhook $webhook_url {
event: "deployment_started"
source: $config_source
timestamp: (date now)
}
}
# Load configuration from source
let config = match $config_source {
"file" => { load-config-from-file $source_path }
"mcp" => { load-config-from-mcp $source_path }
"api" => { load-config-from-api $source_path }
_ => {
error make {msg: $"Invalid config source: ($config_source)"}
}
}
# Strict validation in unattended mode
let validation = if $strict {
validate-deployment-config $config --strict
} else {
validate-deployment-config $config
}
if not $validation.success {
let error_result = {
success: false
mode: "unattended"
error: $validation.error
message: "Config validation failed"
timestamp: (date now)
}
if $webhook_url != "" {
notify-webhook $webhook_url ($error_result | merge {event: "deployment_failed"})
}
return $error_result
}
# Check prerequisites
let prereqs = check-prerequisites
if not $prereqs.success {
let error_result = {
success: false
mode: "unattended"
error: $prereqs.error
message: "Prerequisites check failed"
timestamp: (date now)
}
if $webhook_url != "" {
notify-webhook $webhook_url ($error_result | merge {event: "deployment_failed"})
}
return $error_result
}
# Execute deployment steps with progress tracking
try {
# Step 1: Validate configuration
print "[1/7] Validating configuration"
if $webhook_url != "" {
notify-webhook $webhook_url {event: "deployment_progress", step: "Validating configuration", progress: 14.3, timestamp: (date now)}
}
let _ = validate-deployment-config $config
# Step 2: Check platform availability
print "[2/7] Checking platform availability"
if $webhook_url != "" {
notify-webhook $webhook_url {event: "deployment_progress", step: "Checking platform availability", progress: 28.6, timestamp: (date now)}
}
let platform_check = check-platform-availability $config.platform
if not $platform_check.available {
error make {msg: $"Platform ($config.platform) not available"}
}
# Step 3: Generate secrets
print "[3/7] Generating secrets"
if $webhook_url != "" {
notify-webhook $webhook_url {event: "deployment_progress", step: "Generating secrets", progress: 42.9, timestamp: (date now)}
}
let secrets = generate-secrets $config
# Step 4: Create deployment manifests
print "[4/7] Creating deployment manifests"
if $webhook_url != "" {
notify-webhook $webhook_url {event: "deployment_progress", step: "Creating deployment manifests", progress: 57.2, timestamp: (date now)}
}
let manifests = create-deployment-manifests $config $secrets
# Step 5: Deploy services
print "[5/7] Deploying services"
if $webhook_url != "" {
notify-webhook $webhook_url {event: "deployment_progress", step: "Deploying services", progress: 71.5, timestamp: (date now)}
}
let deploy_result = match $config.platform {
"docker" => { deploy-docker $config }
"podman" => { deploy-podman $config }
"kubernetes" => { deploy-kubernetes $config }
"orbstack" => { deploy-orbstack $config }
_ => {
error make {msg: $"Unsupported platform: ($config.platform)"}
}
}
if not $deploy_result.success {
error make {msg: $"Deployment failed: ($deploy_result.error)"}
}
# Step 6: Run health checks
print "[6/7] Running health checks"
if $webhook_url != "" {
notify-webhook $webhook_url {event: "deployment_progress", step: "Running health checks", progress: 85.8, timestamp: (date now)}
}
let health = check-deployment-health $config
if not $health.success {
error make {msg: $"Health checks failed: ($health.error)"}
}
# Step 7: Finalize
print "[7/7] Finalizing deployment"
if $webhook_url != "" {
notify-webhook $webhook_url {event: "deployment_progress", step: "Finalizing deployment", progress: 100.0, timestamp: (date now)}
}
let success_result = {
success: true
mode: "unattended"
platform: $config.platform
deployment_mode: $config.mode
services: ($config.services | get name)
message: "Deployment completed successfully"
timestamp: (date now)
}
if $webhook_url != "" {
notify-webhook $webhook_url ($success_result | merge {event: "deployment_completed"})
}
print "✅ Deployment completed successfully!"
$success_result
} catch {|err|
print $"❌ Deployment failed: ($err.msg)"
# Attempt rollback
print "🔄 Attempting rollback..."
try {
rollback-deployment $config
print "✅ Rollback completed successfully"
} catch {|rb_err|
print $"❌ Rollback failed: ($rb_err.msg)"
}
let error_result = {
success: false
mode: "unattended"
error: $err.msg
message: "Deployment failed and rolled back"
timestamp: (date now)
}
if $webhook_url != "" {
notify-webhook $webhook_url ($error_result | merge {event: "deployment_failed"})
}
error make {
msg: "Unattended deployment failed"
label: {text: $err.msg}
}
}
}
# Show deployment modes and usage examples
export def "deploy help" [] {
print "
🚀 Provisioning Platform Deployment Modes
INTERACTIVE MODE (Recommended for first-time users)
nu deploy.nu deploy-interactive
- TUI-based configuration
- Step-by-step guidance
- Visual platform detection
- Service selection UI
HEADLESS MODE (For scripted deployments)
nu deploy.nu deploy-headless docker solo
nu deploy.nu deploy-headless kubernetes enterprise --domain prod.example.com
nu deploy.nu deploy-headless podman cicd --services orchestrator,gitea,postgres
Platforms: docker, podman, kubernetes, orbstack
Modes: solo, multi-user, cicd, enterprise
Options:
--domain <hostname> Domain/hostname (default: localhost)
--services <list> Comma-separated service list
--auto-confirm Skip confirmation prompts
--config-only Generate config only, don't deploy
UNATTENDED MODE (For CI/CD and automation)
nu deploy.nu deploy-unattended file ./deploy-config.toml
nu deploy.nu deploy-unattended mcp http://mcp-server:8084/config
nu deploy.nu deploy-unattended api http://api.example.com/deployment/config
Sources: file, mcp, api
Options:
--webhook-url <url> Send progress notifications to webhook
--strict Enable strict validation (default: true)
EXAMPLES:
# Solo development deployment
nu deploy.nu deploy-headless docker solo --auto-confirm
# Enterprise deployment with custom domain
nu deploy.nu deploy-headless kubernetes enterprise --domain prod.acme.com
# Unattended CI/CD deployment
nu deploy.nu deploy-unattended file ./configs/cicd-deploy.toml --webhook-url http://hooks.slack.com/...
# Config generation only
nu deploy.nu deploy-headless docker solo --config-only
For more information, see README.md
"
}