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

132 lines
5.6 KiB
Text
Raw Permalink Normal View History

# Workspace path/root/state resolution — extracted from cli/components.nu (ADR-026 slice 2a-ii).
use platform/user/config.nu [get-active-workspace-details list-workspaces]
# Resolve the first server hostname present in the state file for a workspace.
# Used by --live to find which host to SSH into when the DAG server is unknown.
export def comp-state-server [workspace_path: string]: nothing -> string {
let st = (state-read $workspace_path)
$st.servers
| transpose hostname srv
| where {|row| ($row.srv.taskservs? | default {} | is-not-empty) }
| get 0?
| get -o hostname
| default ""
}
# ─── SSH + k0s kubectl live check infrastructure ─────────────────────────────
# Resolve workspace root path (exported for use by component.nu dispatcher).
export def comp-ws-path [workspace: string]: nothing -> string {
comp-resolve-ws-path $workspace
}
# Auto-detect infra name from workspace root (exported for use by component.nu dispatcher).
export def comp-ws-infra [ws_root: string]: nothing -> string {
ls ($ws_root | path join "infra")
| where type == dir
| get name
| each {|p| $p | path basename }
| where {|n| ($ws_root | path join "infra" $n "settings.ncl" | path exists) }
| get 0?
| default ""
}
# Resolve workspace name: explicit --workspace flag or active workspace.
# A path counts as a workspace ONLY if it has real workspace content — not just
# any directory that happens to be called "infra/". Otherwise $HOME/infra/
# (or similar incidental dirs) hijack the walk-up and shadow the active workspace.
def is-workspace-root [path: string]: nothing -> bool {
if (($path | path join ".ontology") | path exists) { return true }
if (($path | path join "config" "provisioning.ncl") | path exists) { return true }
let infra_dir = ($path | path join "infra")
if not ($infra_dir | path exists) { return false }
# Require at least one infra/*/settings.ncl to treat this as a workspace root.
(ls $infra_dir | where type == dir | get name
| any { |p| ($p | path join "settings.ncl" | path exists) })
}
def find-workspace-root-up [path: string]: nothing -> string {
if ($path | is-empty) or $path == "/" { return "" }
if (is-workspace-root $path) { return $path }
let parent = ($path | path dirname)
if $parent == $path { return "" }
find-workspace-root-up $parent
}
# Walk up from $path looking for a sibling `workspaces/<name>/` that qualifies as
# a workspace root. Returns the full path to the workspace, or "" if not found.
def find-named-workspace-up [path: string, name: string]: nothing -> string {
if ($path | is-empty) or $path == "/" { return "" }
let candidate = ($path | path join "workspaces" $name)
if ($candidate | path exists) and (is-workspace-root $candidate) {
return $candidate
}
let parent = ($path | path dirname)
if $parent == $path { return "" }
find-named-workspace-up $parent $name
}
# Derive the project root from $env.PROVISIONING (typically
# `<project-root>/provisioning`). Returns "" if PROVISIONING is unset.
def project-root-from-prov []: nothing -> string {
let prov = ($env.PROVISIONING? | default "")
if ($prov | is-empty) { return "" }
$prov | path dirname
}
# Returns the workspace ROOT PATH (not name) — works for both registered and unregistered workspaces.
export def comp-resolve-ws-path [workspace: string]: nothing -> string {
# 1. Explicit --workspace → resolve to a path.
if ($workspace | is-not-empty) {
# 1a. Absolute or CWD-relative path that is itself a workspace root.
let as_path = ($workspace | path expand)
if ($as_path | path exists) and (is-workspace-root $as_path) {
return $as_path
}
# 1b. Registered in the user config.
let registered = (
list-workspaces
| where { |ws| $ws.name == $workspace }
| get -o 0
)
if ($registered | is-not-empty) {
return $registered.path
}
# 1c. Walk up from CWD looking for a sibling `workspaces/<name>/`.
let from_cwd = (find-named-workspace-up $env.PWD $workspace)
if ($from_cwd | is-not-empty) { return $from_cwd }
# 1d. Derive from $env.PROVISIONING — the canonical project-root anchor.
let project_root = (project-root-from-prov)
if ($project_root | is-not-empty) {
let from_prov = ($project_root | path join "workspaces" $workspace)
if ($from_prov | path exists) and (is-workspace-root $from_prov) {
return $from_prov
}
}
error make {msg: $"Workspace '($workspace)' not found in registry, CWD ancestors, or under ($project_root)/workspaces/"}
}
# 2. Detect from CWD: registered workspace whose path is prefix of CWD
let pwd = $env.PWD
let from_registry = (
list-workspaces
| where { |ws| ($ws.path | is-not-empty) and ($pwd | str starts-with $ws.path) }
| sort-by { |ws| ($ws.path | str length) }
| last # longest match wins
)
if not ($from_registry | is-empty) {
return $from_registry.path
}
# 3. Unregistered: walk up CWD until workspace markers found
let ws_root = (find-workspace-root-up $pwd)
if ($ws_root | is-not-empty) {
return $ws_root
}
# 4. Fall back to active workspace
let details = (get-active-workspace-details)
if ($details == null) or ($details.path? | default "" | is-empty) {
error make {msg: "No active workspace — pass --workspace or activate one first"}
}
$details.path
}