#!/usr/bin/env nu # detect-provctl.nu - Detect provctl availability and capabilities # Usage: nu scripts/provisioning/detect-provctl.nu [--verbose] # # Returns JSON with provctl information or empty record if not available # Example output: # { # available: true, # path: "/Users/user/Development/provctl", # version: "0.1.0", # commands: ["start", "stop", "restart", "status", "logs", "deploy"], # backends: ["systemd", "launchd", "pidfile"] # } def main [--verbose] { let result = detect_provctl if $verbose { if ($result.available) { print $"✓ provctl detected at: ($result.path)" print $" Version: ($result.version)" print $" Commands: ($result.commands | str join ', ')" print $" Backends: ($result.backends | str join ', ')" } else { print "✗ provctl not found" print " Install from: https://github.com/Akasha/provctl" } } $result } # Main detection logic def detect_provctl []: nothing -> record { # Check common provctl locations in order let locations = [ # Check if provctl is available in PATH (which provctl 2>/dev/null | get path), # Check development location (if user is developer) "/Users/Akasha/Development/provctl", # Check cargo bin (($env.HOME? + "/.cargo/bin/provctl")), # Check /usr/local/bin "/usr/local/bin/provctl", # Check /opt/provctl "/opt/provctl", ] let found = ( $locations | where { |loc| ($loc != null) and ($loc != "") and (($loc | path exists) or (try { which $loc 2>/dev/null | get path } catch { null }) != null) } | first ) if ($found == null) { return { available: false, path: null, version: null, commands: [], backends: [], reason: "provctl not found in PATH" } } # Try to get version let version = ( try { (^$found --version 2>/dev/null | str trim) } catch { "unknown" } ) # Try to get help to detect commands let help_output = ( try { (^$found --help 2>/dev/null) } catch { "" } ) # Extract available commands from help text let commands = ( try { if ($help_output | str contains "Commands:") { let lines = ($help_output | split row "\n") let cmd_section = false let cmds = [] for line in $lines { if ($line | str contains "Commands:") { let cmd_section = true continue } if ($cmd_section and ($line | str starts-with " ")) { let cmd = ($line | str trim | split row " " | first) if ($cmd != "") { $cmds | append $cmd } } else if ($cmd_section and ($line | str trim == "")) { break } } $cmds } else { [] } } catch { [] } ) # Detect available backends (platform-specific) let backends = (detect_available_backends) { available: true, path: $found, version: $version, commands: $commands, backends: $backends, help_available: ($help_output != "") } } # Detect which backends are available on this system def detect_available_backends []: nothing -> list { mut backends = [] # Check for systemd (Linux) if ((try { which systemctl 2>/dev/null } catch { null }) != null) { $backends = ($backends | append "systemd") } # Check for launchd (macOS) if ((try { which launchctl 2>/dev/null } catch { null }) != null) { $backends = ($backends | append "launchd") } # Check for Docker if ((try { which docker 2>/dev/null } catch { null }) != null) { $backends = ($backends | append "docker") } # Check for Kubernetes if ((try { which kubectl 2>/dev/null } catch { null }) != null) { $backends = ($backends | append "kubernetes") } # PID files are always available $backends = ($backends | append "pidfile") $backends } # Helper to check if a command exists def command_exists [cmd: string]: nothing -> bool { (try { which $cmd 2>/dev/null } catch { null }) != null } # Run main if executed directly # Note: Nushell 0.109+ removed $nu.invocation-dir # Scripts are executed via `nu script.nu` so we can just call main main