prvng_core/nulib/taskservs/status.nu
Jesús Pérez 894046ef5a
feat(core): three-layer DAG, unified component arch, commands-registry cache, Nushell 0.112.2 migration
- DAG architecture: `dag show/validate/export` (nulib/main_provisioning/dag.nu),
    config loader (lib_provisioning/config/loader/dag.nu), taskserv dag-executor.
    Backed by schemas/lib/dag/*.ncl; orchestrator emits NATS events via
    WorkspaceComposition::into_workflow. See ADR-020, ADR-021.
  - Unified Component Architecture: components/mod.nu, main_provisioning/
    {components,workflow,extensions,ontoref-queries}.nu. Full workflow engine with
    topological sort and NATS subject emission. Blocks A-H complete (libre-daoshi).
  - Commands-registry: nulib/commands-registry.ncl (Nickel source, 314 lines) +
    JSON cache at ~/.cache/provisioning/commands-registry.json rebuilt on source
    change. cli/provisioning fast-path alias expansion avoids cold Nu startup.
    ADDING_COMMANDS.md documents new-command workflow.
  - Platform service manager: service-manager.nu (+573), startup.nu (+611),
    service-check.nu (+255); autostart/bootstrap/health/target refactored.
  - Nushell 0.112.2 migration: removed all try/catch and bash redirections;
    external commands prefixed with ^; type signatures enforced. Driven by
    scripts/refactor-try-catch{,-simplified}.nu.
  - TTY stack: removed shlib/*-tty.sh; replaced by cli/tty-dispatch.sh,
    tty-filter.sh, tty-commands.conf.
  - New domain modules: images/ (golden image lifecycle), workspace/{state,sync}.nu,
    main_provisioning/{bootstrap,cluster-deploy,fip,state}.nu, commands/{state,
    build,integrations/auth,utilities/alias}.nu, platform.nu expanded (+874).
  - Config loader overhaul: loader/core.nu slimmed (-759), cache/core.nu
    refactored (-454), removed legacy loaders/file_loader.nu (-330).
  - Thirteen new provisioning-<domain>.nu top-level modules for bash dispatcher.
  - Tests: test_workspace_state.nu (+351); updates to test_oci_registry,
    test_services.
  - README + CHANGELOG updated.
2026-04-17 04:27:33 +01:00

127 lines
4.9 KiB
Text

use dag-executor.nu [load-dag]
use ../workspace/state.nu [state-read, state-node-get]
use ../lib_provisioning/config/accessor.nu *
use ../lib_provisioning/utils/settings.nu [find_get_settings, settings_with_env]
def state-icon [s: string]: nothing -> string {
match $s {
"completed" => $"(_ansi green)✅(_ansi reset)",
"running" => $"(_ansi yellow)🔄(_ansi reset)",
"failed" => $"(_ansi red)❌(_ansi reset)",
"blocked" => $"(_ansi red_dimmed)⊘(_ansi reset)",
_ => $"(_ansi default_dimmed)⏳(_ansi reset)",
}
}
def state-col [s: string]: nothing -> string {
match $s {
"completed" => (_ansi green),
"running" => (_ansi yellow),
"failed" => (_ansi red),
"blocked" => (_ansi red_dimmed),
_ => (_ansi default_dimmed),
}
}
def fmt-ts [ts: string]: nothing -> string {
if ($ts | is-empty) { "—" } else { $ts | str replace "T" " " | str replace "Z" "" }
}
# Show DAG formula execution progress — which taskservs completed, pending, failed
export def "main status" [
--infra (-i): string = ""
--settings (-s): string = ""
--server: string = ""
] {
let curr_settings = (settings_with_env (find_get_settings --infra $infra --settings $settings))
let workspace_path = ($curr_settings.src_path? | default $env.PWD)
let dag = (load-dag $curr_settings)
if not $dag.has_dag {
_print "No DAG found — no formula state to show."
return
}
let st = (state-read $workspace_path)
for formula in $dag.formulas {
if ($server | is-not-empty) and $formula.server != $server { continue }
let all_done = ($formula.nodes | all {|n|
let ns = (state-node-get $workspace_path $formula.server $n.taskserv.name)
$ns.state == "completed"
})
let tag = if $all_done {
$"(_ansi green)[complete](_ansi reset)"
} else {
$"(_ansi yellow)[in progress](_ansi reset)"
}
_print $"▶ (_ansi green_bold)($formula.id)(_ansi reset) on (_ansi cyan_bold)($formula.server)(_ansi reset) ($tag)"
for node in $formula.nodes {
let ns = (state-node-get $workspace_path $formula.server $node.taskserv.name)
let icon = (state-icon $ns.state)
let col = (state-col $ns.state)
let name_pad = ($node.taskserv.name | fill -a l -w 20)
let st_pad = ($ns.state | fill -a l -w 10)
let ts = if $ns.state == "completed" { fmt-ts $ns.ended_at } else { "" }
let extra = if ($ns.blocker? | default "" | is-not-empty) {
$" ← blocked by (_ansi red)($ns.blocker)(_ansi reset)"
} else { "" }
_print $" ($icon) ($col)($name_pad)(_ansi reset) ($col)($st_pad)(_ansi reset) ($ts)($extra)"
}
_print ""
}
}
# List all taskservs in the DAG with their state
export def "main list" [
--infra (-i): string = ""
--settings (-s): string = ""
--server: string = ""
--out: string = ""
] {
let curr_settings = (settings_with_env (find_get_settings --infra $infra --settings $settings))
let workspace_path = ($curr_settings.src_path? | default $env.PWD)
let dag = (load-dag $curr_settings)
if not $dag.has_dag {
_print "No DAG found."
return
}
let rows = ($dag.formulas | each {|formula|
if ($server | is-not-empty) and $formula.server != $server { [] } else {
$formula.nodes | each {|node|
let ns = (state-node-get $workspace_path $formula.server $node.taskserv.name)
{
taskserv: $node.taskserv.name,
server: $formula.server,
state: $ns.state,
profile: ($node.taskserv.profile? | default "default"),
depends_on: ($node.depends_on? | default [] | each {|d| $d.node_id } | str join ","),
ended: (fmt-ts $ns.ended_at),
actor: ($ns.actor?.identity? | default ""),
}
}
}
} | flatten)
if $out == "json" { $rows | to json; return }
if $out == "yaml" { $rows | to yaml; return }
_print $"(_ansi default_dimmed)TASKSERV SERVER STATE PROFILE DEPENDS-ON ENDED(_ansi reset)"
for row in $rows {
let col = (state-col $row.state)
let icon = (state-icon $row.state)
_print (
$"($icon) ($col)($row.taskserv | fill -a l -w 20)(_ansi reset)" +
$" (_ansi cyan)($row.server | fill -a l -w 17)(_ansi reset)" +
$" ($col)($row.state | fill -a l -w 10)(_ansi reset)" +
$" ($row.profile | fill -a l -w 10)" +
$" ($row.depends_on | fill -a l -w 20)" +
$" ($row.ended)"
)
}
}