#!/usr/bin/env nu # provctl - Provisioning orchestrator # # Coordinates pack, unpack, install, and deploy operations # # Usage: # nu scripts/provisioning/provctl.nu build-bundle --target x86_64-linux # nu scripts/provisioning/provctl.nu install-bundle bundle.tar.gz # nu scripts/provisioning/provctl.nu status # def show-help [] { print " provctl - syntaxis Provisioning Orchestrator USAGE: nu scripts/provisioning/provctl.nu [OPTIONS] ACTIONS: build-bundle Create a distribution bundle install-bundle Extract and install a bundle deploy-bundle Deploy configs from extracted bundle full-install Extract, install, and deploy (complete setup) status Show installation status list-targets List available build targets verify-bundle Verify bundle integrity clean Clean staging directories help Show this help message OPTIONS (build-bundle): --target Target triple (e.g., x86_64-unknown-linux-gnu) --format Package format (tar.gz, zip, deb, rpm) --output Output directory --verify Verify bundle after creation OPTIONS (install-bundle): --bundle Bundle file path --dest Extraction destination --prefix Installation prefix --force Force overwrite OPTIONS (deploy-bundle): --source Source bundle directory --config-dir Target config directory --backup Backup existing configs OPTIONS (full-install): --bundle Bundle file --prefix Installation prefix --config-dir Config directory --verify Verify throughout EXAMPLES: # Build bundle for current platform provctl build-bundle # Build bundle for Linux provctl build-bundle --target x86_64-unknown-linux-gnu --output dist/ # Show available targets provctl list-targets # Extract bundle provctl install-bundle --bundle ./bundle.tar.gz --prefix ~/.local # Complete installation from bundle provctl full-install --bundle ./bundle.tar.gz --verify # Check installation status provctl status " } def action-build-bundle [--target: string = "", --format: string = "tar.gz", --output: path = "dist/", --verify = false] { print "๐Ÿ”จ Building distribution bundle..." print "" let args = [ "scripts/provisioning/pack.nu" (if ($target != "") { ["--target", $target] } else { [] }) (if ($format != "tar.gz") { ["--format", $format] } else { [] }) (if ($output != "dist/") { ["--output", ($output | into string)] } else { [] }) (if $verify { ["--verify"] } else { [] }) ] | flatten try { nu ...$args } catch { error make {msg: "Failed to build bundle"} } } def action-install-bundle [--bundle: path = "", --dest: path = ".", --prefix: path = "", --force = false] { if ($bundle == "") { error make {msg: "Bundle file must be specified with --bundle"} } if (not (($bundle | path exists))) { let msg = "Bundle file not found: " + ($bundle | into string) error make {msg: $msg} } print "๐Ÿ“ฆ Installing bundle..." print "" let args = [ "scripts/provisioning/unpack.nu" ($bundle | into string) "--dest" ($dest | into string) ] | flatten try { nu ...$args } catch { error make {msg: "Failed to extract bundle"} } # Find extracted bundle and install print "" print "๐Ÿ“‚ Installing binaries..." let bundle_dirs = ( glob ($dest | path join "*") | where {|d| (($d | path type) == "dir")} ) if ($bundle_dirs | is-empty) { error make {msg: "No bundle directory found after extraction"} } let bundle_root = $bundle_dirs.0 let prefix_arg = if ($prefix == "") { [] } else { ["--prefix", ($prefix | into string)] } let install_args = [ "scripts/provisioning/install.nu" "--source" ($bundle_root | path join "bin" | into string) ...$prefix_arg (if $force { ["--force"] } else { [] }) ] | flatten try { nu ...$install_args } catch { error make {msg: "Failed to install binaries"} } } def action-deploy-bundle [--source: path = "", --config-dir: path = "", --backup = false] { if ($source == "") { error make {msg: "Source directory must be specified with --source"} } if (not (($source | path exists))) { let msg = "Source directory not found: " + ($source | into string) error make {msg: $msg} } print "โš™๏ธ Deploying configuration files..." print "" let config_arg = if ($config_dir == "") { [] } else { ["--config-dir", ($config_dir | into string)] } let args = [ "scripts/provisioning/deploy.nu" "--source" ($source | into string) ...$config_arg (if $backup { ["--backup"] } else { [] }) ] | flatten try { nu ...$args } catch { error make {msg: "Failed to deploy configs"} } } def action-full-install [--bundle: path = "", --prefix: path = "", --config-dir: path = "", --verify = false] { if ($bundle == "") { error make {msg: "Bundle file must be specified with --bundle"} } if (not (($bundle | path exists))) { let msg = "Bundle file not found: " + ($bundle | into string) error make {msg: $msg} } print "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" print "๐Ÿš€ syntaxis Full Installation" print "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" print "" # Step 1: Extract print "๐Ÿ“ฆ Step 1: Extracting bundle..." let temp_dir = ( "/tmp" | path join "syntaxis-install" (date now | format date "%s") ) ^mkdir -p $temp_dir try { action-install-bundle --bundle $bundle --dest $temp_dir --prefix $prefix --force true } catch { ^rm -rf $temp_dir error make {msg: "Installation failed during extraction"} } # Find extracted bundle let bundle_dirs = ( glob ($temp_dir | path join "*") | where {|d| (($d | path type) == "dir")} ) if ($bundle_dirs | is-empty) { ^rm -rf $temp_dir error make {msg: "No bundle directory found"} } let bundle_root = $bundle_dirs.0 # Step 2: Deploy configs print "" print "โš™๏ธ Step 2: Deploying configuration files..." try { action-deploy-bundle --source $bundle_root --config-dir $config_dir --backup true } catch { ^rm -rf $temp_dir error make {msg: "Installation failed during config deployment"} } # Cleanup ^rm -rf $temp_dir print "" print "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" print "โœ… Installation complete!" print "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" } def action-status [] { print "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" print "๐Ÿ“Š Installation Status" print "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" print "" # Check manifest let manifest_dir = ($env.HOME | path join ".syntaxis") let manifest_file = ($manifest_dir | path join "manifest.toml") if (not (($manifest_file | path exists))) { print "โš ๏ธ No installation manifest found" print " Run: provctl full-install --bundle " return } try { let manifest = (open --raw $manifest_file | from toml) print "Installation Details:" print (" Timestamp: " + ($manifest.installation.installed_at | into string)) print (" Prefix: " + ($manifest.installation.prefix | into string)) print "" print ("Installed Binaries: " + (($manifest.installation.binaries | length) | into string)) $manifest.installation.binaries | each {|binary_name| print (" โœ“ " + ($binary_name | into string)) } } catch { print "โš ๏ธ Could not read installation manifest" } # Check deployment manifest let deploy_manifest = ($manifest_dir | path join "deployment.toml") if (($deploy_manifest | path exists)) { try { let manifest = (open --raw $deploy_manifest | from toml) print "" print ("Deployed Configs: " + (($manifest.deployment.configs | length) | into string)) $manifest.deployment.configs | each {|config| print (" โœ“ " + ($config | into string)) } } catch { } } print "" } def action-list-targets [] { print "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" print "๐ŸŽฏ Available Build Targets" print "โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”" print "" try { nu scripts/provisioning/pack.nu --list-targets } catch { error make {msg: "Failed to list targets"} } } def action-verify-bundle [--bundle: path = ""] { if ($bundle == "") { let msg = "Bundle file must be specified with --bundle" error make {msg: $msg} } if (not (($bundle | path exists))) { let msg = "Bundle not found: " + ($bundle | into string) error make {msg: $msg} } print "๐Ÿ” Verifying bundle..." print "" # Validate structure let ext = ($bundle | path parse | get extension) let valid_format = (($ext == "gz") or ($ext == "zip")) if $valid_format { print ("โœ… Bundle format valid: " + ($ext | into string)) } else { error make {msg: "Invalid bundle format (expected .tar.gz or .zip)"} } # Check size let size_mb = (((ls $bundle | get size.0) | into int) / (1024 * 1024) | math round --precision 2) print ("โœ… Bundle size: " + ($size_mb | into string) + " MB") # Check checksums file let bundle_name = ($bundle | path parse | get stem) let checksums_file = ( ($bundle | path dirname) | path join ($bundle_name + ".checksums.toml") ) if (($checksums_file | path exists)) { print "โœ… Checksums file found" } else { print "โš ๏ธ Checksums file not found" } print "" print "โœ… Bundle verification complete" } def action-clean [] { print "๐Ÿงน Cleaning staging directories..." let staging_dirs = [ ".provisioning-staging" "/tmp/syntaxis-install" ] $staging_dirs | each {|dir| if (($dir | path exists)) { ^rm -rf $dir print (" โœ“ Removed: " + ($dir | into string)) } } print "โœ… Cleanup complete" } def main [action: string = "", ...args: string] { match $action { "build-bundle" => { action-build-bundle } "install-bundle" => { action-install-bundle } "deploy-bundle" => { action-deploy-bundle --source "." } "full-install" => { action-full-install } "status" => { action-status } "list-targets" => { action-list-targets } "verify-bundle" => { action-verify-bundle } "clean" => { action-clean } "help" | "--help" | "-h" => { show-help } "" => { show-help } _ => { print ("Unknown action: " + ($action | into string)) print "" show-help } } } # Parse args and execute let action = if (($in | length) > 0) { $in.0 } else { "" }