211 lines
8.3 KiB
Text
211 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)
|
||
|
|
}
|
||
|
|
}
|