provisioning-core/nulib/domain/version/taskserv.nu

278 lines
9.2 KiB
Text
Raw Permalink Normal View History

#!/usr/bin/env nu
# Taskserv version extraction and management utilities
# Handles Nickel taskserv files and version configuration
# Selective imports (ADR-025 Phase 3 Layer 2).
# version/core.nu and version/loader.nu star-imports were dead — dropped.
use primitives/io/interface.nu [_print]
use platform/config/accessor/functions.nu [get-taskservs-path]
# Extract version field from Nickel taskserv files
export def extract-nickel-version [
file_path: string
] {
if not ($file_path | path exists) { return "" }
let content = (open $file_path --raw)
# Look for version assignment in taskserv configuration files
let version_matches = ($content | lines | each { |line|
let trimmed_line = ($line | str trim)
# Match "version = " pattern (but not major_version, cni_version, etc.)
if ($trimmed_line | str starts-with "version") and ($trimmed_line | str contains "=") {
# Split on equals and take the right side
let parts = ($trimmed_line | split row "=")
if ($parts | length) >= 2 {
let version_value = ($parts | get 1 | str trim)
if ($version_value | str starts-with '"') {
# Remove quotes and get the value
($version_value | parse -r '"([^"]*)"' | get 0? | default {} | get capture0? | default "")
} else if ($version_value | str starts-with "'") {
# Handle single quotes
($version_value | parse -r "'([^']*)'" | get 0? | default {} | get capture0? | default "")
} else {
# Handle unquoted values (remove any trailing comments)
($version_value | str replace "\\s*#.*$" "" | str trim)
}
} else {
""
}
} else if ($trimmed_line | str starts-with "version:") and not ($trimmed_line | str contains "str") {
# Handle schema-style "version: value" (not type declarations)
let version_part = ($trimmed_line | str replace "version:\\s*" "")
if ($version_part | str starts-with '"') {
($version_part | parse -r '"([^"]*)"' | get 0? | default {} | get capture0? | default "")
} else if ($version_part | str starts-with "'") {
($version_part | parse -r "'([^']*)'" | get 0? | default {} | get capture0? | default "")
} else {
($version_part | str replace "\\s*#.*$" "" | str trim)
}
} else {
""
}
} | where { |v| $v != "" })
if ($version_matches | length) > 0 {
$version_matches | get 0
} else {
""
}
}
# Discover all taskserv Nickel files and their versions
export def discover-taskserv-configurations [
--base-path: string = ""
] {
let taskservs_path = if ($base_path | is-not-empty) {
$base_path
} else {
(get-taskservs-path)
}
if not ($taskservs_path | path exists) {
_print $"⚠️ Taskservs path not found: ($taskservs_path)"
return []
}
# Find all .ncl files recursively in the taskservs directory
let all_k_files = (glob $"($taskservs_path)/**/*.ncl")
let nickel_configs = ($all_k_files | each { |decl_file|
let version = (extract-nickel-version $decl_file)
if ($version | is-not-empty) {
let relative_path = ($decl_file | str replace $"($taskservs_path)/" "")
let path_parts = ($relative_path | split row "/" | where { |p| $p != "" })
# Determine ID from the path structure
let id = if ($path_parts | length) >= 2 {
# If it's a server-specific file like "wuji-strg-1/kubernetes.ncl"
let filename = ($decl_file | path basename | str replace ".ncl" "")
$"($path_parts.0)::($filename)"
} else {
# If it's a general file like "proxy.ncl"
($decl_file | path basename | str replace ".ncl" "")
}
{
id: $id
type: "taskserv"
nickel_file: $decl_file
version: $version
metadata: {
source_file: $decl_file
category: "taskserv"
path_structure: $path_parts
}
}
} else {
null
}
} | where { |item| $item != null })
$nickel_configs
}
# Update version in Nickel file
export def update-nickel-version [
file_path: string
new_version: string
] {
if not ($file_path | path exists) {
_print $"❌ File not found: ($file_path)"
return
}
let content = (open $file_path --raw)
# Replace version field while preserving formatting
let updated_content = ($content | lines | each { |line|
if ($line | str trim | str starts-with "version:") {
# Preserve indentation and update version
let indent = ($line | str replace "^(\\s*).*" '$1')
let line_trimmed = ($line | str trim)
if ($line_trimmed | str contains '"') {
$"($indent)version: \"($new_version)\""
} else if ($line_trimmed | str contains "'") {
$"($indent)version: '($new_version)'"
} else {
$"($indent)version: str = \"($new_version)\""
}
} else {
$line
}
} | str join "\n")
$updated_content | save -f $file_path
_print $"✅ Updated version in ($file_path) to ($new_version)"
}
# Check taskserv versions against available versions
export def check-taskserv-versions [
--fetch-latest = false
] {
let configs = (discover-taskserv-configurations)
if ($configs | is-empty) {
_print "No taskserv configurations found"
return []
}
$configs | each { |config|
# For now, return basic info - can be extended with version checking logic
{
id: $config.id
type: $config.type
configured: $config.version
nickel_file: $config.nickel_file
status: "configured"
}
}
}
# Update taskserv version in Nickel file
export def update-taskserv-version [
taskserv_id: string
new_version: string
--dry-run = false
] {
let configs = (discover-taskserv-configurations)
let config = ($configs | where id == $taskserv_id | first | default null)
if ($config | is-empty) {
_print $"❌ Taskserv '($taskserv_id)' not found"
return
}
if $dry_run {
_print $"🔍 Would update ($taskserv_id) from ($config.version) to ($new_version) in ($config.nickel_file)"
return
}
update-nickel-version $config.nickel_file $new_version
}
# Bulk update multiple taskservs
export def bulk-update-taskservs [
updates: list # List of {id: string, version: string}
--dry-run = false
] {
if ($updates | is-empty) {
_print "No updates provided"
return
}
_print $"Updating ($updates | length) taskservs..."
for update in $updates {
let taskserv_id = ($update | get id? | default "")
let new_version = ($update | get version? | default "")
if ($taskserv_id | is-empty) or ($new_version | is-empty) {
_print $"⚠️ Invalid update entry: ($update)"
continue
}
update-taskserv-version $taskserv_id $new_version --dry-run=$dry_run
}
if not $dry_run {
_print "✅ Bulk update completed"
}
}
# Sync taskserv versions with registry
export def taskserv-sync-versions [
--taskservs-path: string = ""
--component: string = "" # Specific component to sync
--dry-run = false
] {
let registry = (load-version-registry)
let comparisons = (compare-registry-with-taskservs --taskservs-path=$taskservs_path)
if ($comparisons | is-empty) {
_print "❌ No taskserv configurations found"
return
}
# Filter to out-of-sync components
mut out_of_sync = ($comparisons | where status == "out_of_sync")
if ($component | is-not-empty) {
let filtered = ($out_of_sync | where component == $component)
if ($filtered | is-empty) {
_print $"✅ Component '($component)' is already in sync or not found"
return
}
$out_of_sync = $filtered
}
if ($out_of_sync | is-empty) {
_print "✅ All taskservs are in sync with registry"
return
}
_print $"Found ($out_of_sync | length) components with version mismatches:"
for comp in $out_of_sync {
_print $"\n🔧 ($comp.component) [Registry: ($comp.registry_version)]"
# Find taskservs that need updating
let outdated_taskservs = ($comp.taskserv_configs | where not matches_registry)
for taskserv in $outdated_taskservs {
if $dry_run {
_print $"🔍 Would update ($taskserv.id): ($taskserv.version) -> ($comp.registry_version)"
} else {
_print $"🔄 Updating ($taskserv.id): ($taskserv.version) -> ($comp.registry_version)"
update-nickel-version $taskserv.file $comp.registry_version
}
}
}
if $dry_run {
_print "\n🔍 Dry run completed - no changes made"
} else {
_print "\n✅ Sync completed"
}
}