ontoref/reflection/bin/check-prereqs.nu

169 lines
5.4 KiB
Plaintext
Raw Normal View History

2026-03-13 00:21:04 +00:00
#!/usr/bin/env nu
# Check environment prerequisites for ontoref operations.
#
# Usage:
# nu reflection/bin/check-prereqs.nu
# nu reflection/bin/check-prereqs.nu --context ci
# nu reflection/bin/check-prereqs.nu --context agent
# nu reflection/bin/check-prereqs.nu --form new_adr
# nu reflection/bin/check-prereqs.nu --context local_dev --severity Hard
def main [
--context: string = "local_dev",
--form: string = "",
--severity: string = "",
--json,
] {
let base_file = "reflection/requirements/base.ncl"
let contexts_file = "reflection/requirements/contexts.ncl"
# Inline daemon-export with subprocess fallback (standalone script, no module imports).
let export_base = do { ^nickel export $base_file } | complete
if $export_base.exit_code != 0 {
error make { msg: "Failed to load base.ncl — is nickel installed?" }
}
let all_tools = ($export_base.stdout | from json | get tools)
let export_ctx = do { ^nickel export $contexts_file } | complete
if $export_ctx.exit_code != 0 {
error make { msg: "Failed to load contexts.ncl" }
}
let ctx_candidates = ($export_ctx.stdout | from json | get contexts | where id == $context)
if ($ctx_candidates | is-empty) {
error make { msg: $"Unknown context '($context)'. Valid: local_dev | ci | agent | benchmark" }
}
let ctx_def = ($ctx_candidates | first)
let tools = if ($form | is-empty) {
$all_tools | where { |it| $it.contexts | any { |c| $c == $context } }
} else {
$all_tools | where { |it| $it.used_by_forms | any { |f| $f == $form } }
}
let tools = if ($severity | is-empty) {
$tools
} else {
$tools | where { |it| $it.severity == $severity }
}
let results = $tools | each { |tool|
let is_plugin = ($tool.plugin_name? | is-not-empty)
# Presence check: plugin registry or PATH binary
let present = if $is_plugin {
plugin list | where name == $tool.plugin_name | is-not-empty
} else {
(do { run-external "which" $tool.binary } | complete | get exit_code) == 0
}
# Version: run check_cmd via nu -c for both binary and plugin tools
let version = if $present and ($tool.check_cmd | is-not-empty) {
do { nu -c $"($tool.check_cmd) | str trim" } | complete
| if $in.exit_code == 0 { $in.stdout | str trim } else { "unknown" }
} else if $present {
"present"
} else {
"not installed"
}
let version_ok = if $present and $version != "unknown" and $version != "present" {
let min_parts = ($tool.version_min | split row "." | each { |p| $p | into int })
let act_result = (
$version
| parse --regex $tool.version_extract
| if ($in | is-empty) { null } else { $in | first | get capture0 }
)
if ($act_result | is-empty) {
true # Cannot parse version — assume ok (plugin compat versions)
} else {
let act_parts = ($act_result | split row "." | each { |p| $p | into int })
let major_ok = ($act_parts | get 0) >= ($min_parts | get 0)
let minor_ok = if ($act_parts | get 0) == ($min_parts | get 0) {
($act_parts | get 1) >= ($min_parts | get 1)
} else { true }
$major_ok and $minor_ok
}
} else if $present {
true
} else {
false
}
let config_ok = if $present and ($tool.config_check? | is-not-empty) {
do { nu -c $tool.config_check } | complete | get exit_code | $in == 0
} else {
true
}
let display_name = if $is_plugin { $"plugin:($tool.plugin_name)" } else { $tool.binary }
{
id: $tool.id,
binary: $display_name,
severity: $tool.severity,
present: $present,
version: $version,
version_min: $tool.version_min,
version_ok: $version_ok,
config_ok: $config_ok,
status: (if not $present {
"MISSING"
} else if not $version_ok {
"VERSION_LOW"
} else if not $config_ok {
"CONFIG_FAIL"
} else {
"OK"
}),
install_hint: $tool.install_hint,
config_hint: ($tool.config_hint? | default ""),
}
}
if $json {
$results | to json
return
}
print $"Environment check — context: ($context)"
print $"─────────────────────────────────────────────────────"
let fails = $results | where status != "OK"
for r in $results {
let icon = match $r.status {
"OK" => "✓",
"MISSING" => "✗",
"VERSION_LOW" => "↑",
"CONFIG_FAIL" => "⚠",
_ => "?",
}
let sev = if $r.severity == "Hard" { "[Hard]" } else { "[Soft]" }
print $"($icon) ($sev) ($r.binary) ($r.version) [min: ($r.version_min)]"
}
print ""
if ($fails | is-empty) {
print "All checks passed."
return
}
let hard_fails = $fails | where severity == "Hard"
for f in $fails {
print $"── ($f.binary) — ($f.status) ──"
match $f.status {
"MISSING" => { print $" Install: ($f.install_hint)" },
"VERSION_LOW" => { print $" Installed: ($f.version) Required: >= ($f.version_min)" ; print $" Update: ($f.install_hint)" },
"CONFIG_FAIL" => { print $" Config issue: ($f.config_hint)" },
}
print ""
}
if ($hard_fails | is-not-empty) {
let hard_ids = $hard_fails | get binary | str join ", "
error make { msg: $"Hard prerequisites not met: ($hard_ids)" }
}
}