Merge _configs/ into config/ for single configuration directory. Update all path references. Changes: - Move _configs/* to config/ - Update .gitignore for new patterns - No code references to _configs/ found Impact: -1 root directory (layout_conventions.md compliance)
416 lines
12 KiB
Plaintext
416 lines
12 KiB
Plaintext
#!/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 <ACTION> [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> Target triple (e.g., x86_64-unknown-linux-gnu)
|
|
--format <FORMAT> Package format (tar.gz, zip, deb, rpm)
|
|
--output <DIR> Output directory
|
|
--verify Verify bundle after creation
|
|
|
|
OPTIONS (install-bundle):
|
|
--bundle <FILE> Bundle file path
|
|
--dest <DIR> Extraction destination
|
|
--prefix <PATH> Installation prefix
|
|
--force Force overwrite
|
|
|
|
OPTIONS (deploy-bundle):
|
|
--source <DIR> Source bundle directory
|
|
--config-dir <PATH> Target config directory
|
|
--backup Backup existing configs
|
|
|
|
OPTIONS (full-install):
|
|
--bundle <FILE> Bundle file
|
|
--prefix <PATH> Installation prefix
|
|
--config-dir <PATH> 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 <file>"
|
|
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 { "" }
|