#!/usr/bin/env nu # Version registry management for taskservs # Handles the central version registry and integrates with taskserv configurations # Selective imports (ADR-025 Phase 3 Layer 2). use domain/version/core.nu [fetch-versions] use domain/version/taskserv.nu [discover-taskserv-configurations] use primitives/io/interface.nu [_print] # Load the version registry export def load-version-registry [ --registry-file: string = "" ] { let registry_path = if ($registry_file | is-not-empty) { $registry_file } else { ($env.PROVISIONING | path join "core" | path join "taskservs-versions.yaml") } if not ($registry_path | path exists) { _print $"⚠️ Version registry not found: ($registry_path)" return {} } open $registry_path } # Update registry with latest version information export def update-registry-versions [ --components: list = [] # Specific components to update, empty for all --dry-run = false ] { let registry = (load-version-registry) if ($registry | is-empty) { _print "❌ Could not load version registry" return } let components_to_update = if ($components | is-empty) { $registry | transpose key value | get key } else { $components } _print $"Updating versions for ($components_to_update | length) components..." for component in $components_to_update { let component_config = if ($component in ($registry | columns)) { $registry | get $component } else { null } if ($component_config | is-empty) { _print $"⚠️ Component '($component)' not found in registry" continue } if ($component_config.fixed | default false) { _print $"🔒 Skipping pinned component: ($component)" continue } if ($component_config.source | is-empty) { _print $"⚠️ No source configured for: ($component)" continue } _print $"🔍 Checking latest version for: ($component)" let latest_versions = (fetch-versions $component_config.source --limit=5) if ($latest_versions | is-empty) { _print $"❌ Could not fetch versions for: ($component)" continue } let latest = ($latest_versions | get 0) let current = ($component_config.current_version | default "") if $latest != $current { _print $"📦 ($component): ($current) -> ($latest)" if not $dry_run { # Update registry with new version update-registry-component $component "current_version" $latest update-registry-component $component "latest_check" (date now | format date "%Y-%m-%d %H:%M:%S") } } else { _print $"✅ ($component): up to date at ($current)" } } if not $dry_run { _print "✅ Registry update completed" } else { _print "🔍 Dry run completed - no changes made" } } # Update a specific component field in the registry export def update-registry-component [ component_id: string field: string value: string ] { let registry_path = ($env.PROVISIONING | path join "core" | path join "taskservs-versions.yaml") if not ($registry_path | path exists) { _print $"❌ Registry file not found: ($registry_path)" return } let registry = (open $registry_path) let component_config = if ($component_id in ($registry | columns)) { $registry | get $component_id } else { null } if ($component_config | is-empty) { _print $"❌ Component '($component_id)' not found in registry" return } let updated_component = ($component_config | upsert $field $value) let updated_registry = ($registry | upsert $component_id $updated_component) $updated_registry | save -f $registry_path } # Compare registry versions with taskserv configurations export def compare-registry-with-taskservs [ --taskservs-path: string = "" ] { let registry = (load-version-registry) let taskserv_configs = (discover-taskserv-configurations --base-path=$taskservs_path) if ($registry | is-empty) or ($taskserv_configs | is-empty) { _print "❌ Could not load registry or taskserv configurations" return [] } # Group taskservs by component type let taskserv_by_component = ($taskserv_configs | group-by { |config| # Extract component name from ID (handle both "component" and "server::component" formats) if ($config.id | str contains "::") { ($config.id | split row "::" | get 1) } else { $config.id } }) let comparisons = ($registry | transpose component registry_config | each { |registry_item| let component = $registry_item.component let registry_version = ($registry_item.registry_config.current_version | default "") let taskservs = if ($component in ($taskserv_by_component | columns)) { $taskserv_by_component | get $component } else { [] } if ($taskservs | is-empty) { { component: $component registry_version: $registry_version taskserv_configs: [] status: "unused" summary: "Not used in any taskservs" } } else { let taskserv_versions = ($taskservs | each { |ts| { id: $ts.id version: $ts.version file: $ts.nickel_file matches_registry: ($ts.version == $registry_version) }}) let all_match = ($taskserv_versions | all { |ts| $ts.matches_registry }) let any_outdated = ($taskserv_versions | any { |ts| not $ts.matches_registry }) let status = if $all_match { "in_sync" } else if $any_outdated { "out_of_sync" } else { "mixed" } { component: $component registry_version: $registry_version taskserv_configs: $taskserv_versions status: $status summary: $"($taskserv_versions | length) taskservs, ($taskserv_versions | where matches_registry | length) in sync" } } }) $comparisons } # Show version status summary export def show-version-status [ --taskservs-path: string = "" --format: string = "table" # table, detail, json ] { let comparisons = (compare-registry-with-taskservs --taskservs-path=$taskservs_path) match $format { "table" => { _print "Taskserv Version Status:" _print ($comparisons | select component registry_version status summary | table) } "detail" => { for comparison in $comparisons { _print $"\n🔧 ($comparison.component) \\(Registry: ($comparison.registry_version)\\)" _print $" Status: ($comparison.status) - ($comparison.summary)" if ($comparison.taskserv_configs | length) > 0 { for config in $comparison.taskserv_configs { let status_icon = if $config.matches_registry { "✅" } else { "❌" } _print $" ($status_icon) ($config.id): ($config.version)" } } } } "json" => { print ($comparisons | to json -i 2) } _ => { _print $"❌ Unknown format: ($format). Use 'table', 'detail', or 'json'" } } } # Pin/unpin component in registry export def set-registry-fixed [ component_id: string fixed: bool ] { update-registry-component $component_id "fixed" ($fixed | into string) if $fixed { _print $"🔒 Pinned ($component_id) in registry" } else { _print $"🔓 Unpinned ($component_id) in registry" } }