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

210 lines
8.3 KiB
Text

use std log
export def compare-versions [version1: string, version2: string] {
let v1_parts = ($version1 | split row "." | each { into int })
let v2_parts = ($version2 | split row "." | each { into int })
if ($v1_parts.0 > $v2_parts.0) { return "greater" }
if ($v1_parts.0 < $v2_parts.0) { return "less" }
if ($v1_parts.1 > $v2_parts.1) { return "greater" }
if ($v1_parts.1 < $v2_parts.1) { return "less" }
if ($v1_parts.2 > $v2_parts.2) { return "greater" }
if ($v1_parts.2 < $v2_parts.2) { return "less" }
"equal"
}
export def is-version-compatible [current: string, required: string] {
let comparison = (compare-versions $current $required)
$comparison == "equal" or $comparison == "greater"
}
export def get-system-version [] {
if ($env.PROVISIONING_VERS? | is-not-empty) { return $env.PROVISIONING_VERS }
let cli_path = ([$env.PROVISIONING "core" "cli" "provisioning"] | path join)
if ($cli_path | path exists) {
let version_line = (open $cli_path | lines | where $it =~ "^# Release:" | first)
if ($version_line | is-not-empty) {
return ($version_line | str replace "# Release: " "" | str trim)
}
}
"1.0.11"
}
export def get-workspace-metadata-path [workspace_path: string] {
$workspace_path | path join ".provisioning" | path join "metadata.yaml"
}
export def load-workspace-metadata [workspace_path: string] {
let metadata_path = (get-workspace-metadata-path $workspace_path)
if not ($metadata_path | path exists) {
return {
version: {provisioning: "unknown", schema: "unknown", workspace_format: "unknown"}
created: "unknown"
last_updated: "unknown"
migration_history: []
}
}
open $metadata_path
}
export def save-workspace-metadata [workspace_path: string, metadata: record] {
let metadata_path = (get-workspace-metadata-path $workspace_path)
let metadata_dir = ($metadata_path | path dirname)
if not ($metadata_dir | path exists) { mkdir $metadata_dir }
let updated_metadata = ($metadata | upsert last_updated (date now | format date "%Y-%m-%dT%H:%M:%SZ"))
$updated_metadata | to yaml | save -f $metadata_path
}
export def init-workspace-metadata [workspace_path: string, workspace_name: string] {
let system_version = (get-system-version)
let metadata = {
workspace: {name: $workspace_name, path: $workspace_path}
version: {provisioning: $system_version, schema: "1.0.0", workspace_format: "1.0.0"}
created: (date now | format date "%Y-%m-%dT%H:%M:%SZ")
last_updated: (date now | format date "%Y-%m-%dT%H:%M:%SZ")
migration_history: []
compatibility: {min_provisioning_version: "1.0.0", min_schema_version: "1.0.0"}
}
save-workspace-metadata $workspace_path $metadata
$metadata
}
export def check-workspace-compatibility [workspace_path: string] {
let metadata = (load-workspace-metadata $workspace_path)
let system_version = (get-system-version)
if ($metadata.version.provisioning == "unknown") {
return {
compatible: false, reason: "no_metadata"
message: "Workspace metadata not found or corrupted"
requires_migration: true, current_system: $system_version, workspace_version: "unknown"
}
}
let workspace_version = $metadata.version.provisioning
let min_required = ($metadata.compatibility?.min_provisioning_version? | default "2.0.0")
let system_compatible = (is-version-compatible $system_version $min_required)
if not $system_compatible {
return {
compatible: false, reason: "version_too_old"
message: $"Provisioning system version ($system_version) is older than required ($min_required)"
requires_migration: false, requires_upgrade: true
current_system: $system_version, workspace_version: $workspace_version, min_required: $min_required
}
}
let version_comparison = (compare-versions $system_version $workspace_version)
if ($version_comparison == "greater") {
return {
compatible: true, reason: "migration_available"
message: $"Workspace can be migrated from ($workspace_version) to ($system_version)"
requires_migration: true, migration_optional: true
current_system: $system_version, workspace_version: $workspace_version
}
}
if ($version_comparison == "less") {
return {
compatible: false, reason: "workspace_too_new"
message: $"Workspace version ($workspace_version) is newer than system ($system_version)"
requires_migration: false, requires_upgrade: true
current_system: $system_version, workspace_version: $workspace_version
}
}
{
compatible: true, reason: "version_match"
message: "Workspace and system versions match"
requires_migration: false
current_system: $system_version, workspace_version: $workspace_version
}
}
export def add-migration-record [
workspace_path: string
from_version: string
to_version: string
migration_type: string
success: bool
notes?: string
] {
let metadata = (load-workspace-metadata $workspace_path)
let migration_record = {
from_version: $from_version, to_version: $to_version, migration_type: $migration_type
timestamp: (date now | format date "%Y-%m-%dT%H:%M:%SZ")
success: $success, notes: ($notes | default "")
}
let updated_metadata = (
$metadata
| upsert migration_history ($metadata.migration_history | append $migration_record)
| upsert version.provisioning $to_version
)
save-workspace-metadata $workspace_path $updated_metadata
}
export def get-version-summary [workspace_path: string] {
let metadata = (load-workspace-metadata $workspace_path)
let system_version = (get-system-version)
let compatibility = (check-workspace-compatibility $workspace_path)
{
system: {version: $system_version}
workspace: {
name: ($metadata.workspace?.name? | default "unknown")
path: $workspace_path
version: ($metadata.version?.provisioning? | default "unknown")
schema_version: ($metadata.version?.schema? | default "unknown")
format_version: ($metadata.version?.workspace_format? | default "unknown")
created: ($metadata.created? | default "unknown")
last_updated: ($metadata.last_updated? | default "unknown")
}
compatibility: $compatibility
migrations: {
count: ($metadata.migration_history? | default [] | length)
last_migration: ($metadata.migration_history? | default [] | last | default null)
}
}
}
export def validate-workspace-structure [workspace_path: string] {
mut issues = []
for dir in ["config", "infra", ".provisioning"] {
let dir_path = ($workspace_path | path join $dir)
if not ($dir_path | path exists) {
$issues = ($issues | append {
type: "missing_directory", path: $dir, severity: "error"
message: $"Required directory missing: ($dir)"
})
}
}
let config_schema_path = ($workspace_path | path join "config" | path join "provisioning.ncl")
let config_yaml_path = ($workspace_path | path join "config" | path join "provisioning.yaml")
if (not ($config_schema_path | path exists) and not ($config_yaml_path | path exists)) {
$issues = ($issues | append {
type: "missing_file"
path: "config/provisioning.ncl or config/provisioning.yaml"
severity: "error"
message: "Main configuration file missing (provisioning.ncl or provisioning.yaml required)"
})
}
let metadata_path = (get-workspace-metadata-path $workspace_path)
if not ($metadata_path | path exists) {
$issues = ($issues | append {
type: "missing_metadata", path: ".provisioning/metadata.yaml", severity: "warning"
message: "Workspace metadata missing - run migration"
})
}
{
valid: (($issues | where severity == "error" | length) == 0)
issues: $issues
warnings: ($issues | where severity == "warning" | length)
errors: ($issues | where severity == "error" | length)
}
}