Rustelo/scripts/verify-prerequisites.nu
Jesús Pérez 7cab57b645
Some checks failed
CI/CD Pipeline / Test Suite (push) Has been cancelled
CI/CD Pipeline / Security Audit (push) Has been cancelled
CI/CD Pipeline / Build Docker Image (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Performance Benchmarks (push) Has been cancelled
CI/CD Pipeline / Cleanup (push) Has been cancelled
chore: update layout and files
2026-02-08 20:18:46 +00:00

651 lines
22 KiB
Plaintext
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env nu
# Rustelo Prerequisites Verification
# Verifies that all required tools are properly installed and working
def main [
--verbose (-v) # Show detailed version information
--fix-path # Attempt to fix PATH issues
--format (-f): string = "human" # Output format: human, json, yaml, toml
] {
# Validate format parameter
if $format not-in ["human", "json", "yaml", "toml"] {
print $"Error: Invalid format '($format)'. Supported formats: human, json, yaml, toml"
return
}
# Collect all system and prerequisite information
let system_info = if $verbose or $format != "human" {
collect_system_info
} else {
{}
}
let rust_status = collect_rust_info $verbose
let node_status = collect_node_info $verbose
let nushell_status = collect_nushell_info $verbose
let just_status = collect_just_info $verbose
let additional_tools = collect_additional_tools_info $verbose
# Compile results
let prerequisites = {
rust: $rust_status,
node: $node_status,
nushell: $nushell_status,
just: $just_status
}
let all_required_ok = (
$rust_status.installed and
$node_status.installed and
$nushell_status.installed and
$just_status.installed
)
let issues = (
[$rust_status, $node_status, $nushell_status, $just_status]
| where not installed
| get issue
| where $it != null
)
# Create comprehensive result object
let result = {
timestamp: (date now | format date '%Y-%m-%dT%H:%M:%S%.3fZ'),
system: $system_info,
prerequisites: $prerequisites,
additional_tools: $additional_tools,
summary: {
all_prerequisites_met: $all_required_ok,
total_issues: ($issues | length),
issues: $issues
}
}
# Output in requested format
match $format {
"human" => { output_human $result $verbose $fix_path },
"json" => { $result | to json },
"yaml" => { $result | to yaml },
"toml" => { $result | to toml }
}
}
# Data collection functions for structured output
def collect_system_info [] {
let os_name = try {
let uname_s = (^uname -s | str trim)
match $uname_s {
"Darwin" => "macOS",
"Linux" => "Linux",
"MINGW64_NT" => "Windows",
_ => $uname_s
}
} catch {
try { (sys host | get name) } catch { "unknown" }
}
let arch = try {
let uname_m = (^uname -m | str trim)
match $uname_m {
"arm64" => "Apple Silicon (ARM64)",
"x86_64" => "Intel x64",
"aarch64" => "ARM64",
_ => $uname_m
}
} catch {
try { (sys host | get cpu | first | get brand) } catch { "unknown" }
}
let kernel = try {
(^uname -r | str trim)
} catch {
try { (sys host | get kernel_version) } catch { "unknown" }
}
let detailed_os = if ($os_name == "macOS") {
let version = try { (^sw_vers -productVersion | str trim) } catch { "" }
let name = try { (^sw_vers -productName | str trim) } catch { "" }
if ($version != "" and $name != "") {
$"($name) ($version)"
} else {
$os_name
}
} else {
$os_name
}
{
os: $detailed_os,
arch: $arch,
kernel: $kernel,
shell: ($env.SHELL? | default 'unknown')
}
}
def collect_rust_info [verbose: bool] {
if (which rustc | is-not-empty) and (which cargo | is-not-empty) {
let rustc_version = try { (rustc --version | str trim) } catch { "unknown" }
let cargo_version = try { (cargo --version | str trim) } catch { "unknown" }
let toolchain = try { (rustup show active-toolchain | str trim) } catch { "unknown" }
{
installed: true,
rustc_version: $rustc_version,
cargo_version: $cargo_version,
toolchain: $toolchain,
issue: null
}
} else {
{
installed: false,
rustc_version: null,
cargo_version: null,
toolchain: null,
issue: "Rust compiler (rustc) and Cargo not found. Install from https://rustup.rs/"
}
}
}
def collect_node_info [verbose: bool] {
let node_ok = (which node | is-not-empty)
let pnpm_ok = (which pnpm | is-not-empty)
let npm_ok = (which npm | is-not-empty)
let node_version = if $node_ok { try { (node --version | str trim) } catch { null } } else { null }
let pnpm_version = if $pnpm_ok { try { (pnpm --version | str trim) } catch { null } } else { null }
let npm_version = if $npm_ok { try { (npm --version | str trim) } catch { null } } else { null }
if $node_ok and $pnpm_ok {
{
installed: true,
node_version: $node_version,
pnpm_version: $pnpm_version,
npm_version: $npm_version,
issue: null
}
} else if $node_ok and not $pnpm_ok {
{
installed: false,
node_version: $node_version,
pnpm_version: null,
npm_version: $npm_version,
issue: "pnpm package manager not found. Install with: npm install -g pnpm"
}
} else {
{
installed: false,
node_version: null,
pnpm_version: null,
npm_version: null,
issue: "Node.js and pnpm not found. Install Node.js from https://nodejs.org/ then run: npm install -g pnpm"
}
}
}
def collect_nushell_info [verbose: bool] {
if (which nu | is-not-empty) {
let version = try { (nu --version | lines | first | str trim) } catch { "unknown" }
let features = try { (nu -c "version | get features" | str join ", ") } catch { "unknown" }
{
installed: true,
version: $version,
features: $features,
current_shell: ($env.SHELL? | default "unknown"),
issue: null
}
} else {
{
installed: false,
version: null,
features: null,
current_shell: ($env.SHELL? | default "unknown"),
issue: "Nushell shell not found. Install from https://github.com/nushell/nushell/releases or via package manager"
}
}
}
def collect_just_info [verbose: bool] {
if (which just | is-not-empty) {
let version = try { (just --version | str trim) } catch { "unknown" }
let justfile_exists = ("justfile" | path exists) or ("Justfile" | path exists)
{
installed: true,
version: $version,
justfile_found: $justfile_exists,
issue: null
}
} else {
{
installed: false,
version: null,
justfile_found: false,
issue: "Just command runner not found. Install with: cargo install just"
}
}
}
def collect_additional_tools_info [verbose: bool] {
let tools = [
{
name: "git",
installed: (which git | is-not-empty),
version: (if (which git | is-not-empty) { try { (git --version | str replace "git version " "") } catch { "unknown" } } else { null })
},
{
name: "sqlite",
installed: (which sqlite3 | is-not-empty),
version: (if (which sqlite3 | is-not-empty) { try { (sqlite3 --version | split row " " | first) } catch { "unknown" } } else { null })
},
{
name: "docker",
installed: (which docker | is-not-empty),
version: (if (which docker | is-not-empty) { try { (docker --version | str replace "Docker version " "" | split row "," | first) } catch { "unknown" } } else { null })
},
{
name: "vscode",
installed: ((which code | is-not-empty) or ("/Applications/Visual Studio Code.app" | path exists)),
version: (if (which code | is-not-empty) {
try { (code --version | lines | first) } catch { "available" }
} else if ("/Applications/Visual Studio Code.app" | path exists) {
"installed (app bundle)"
} else {
null
})
},
{
name: "zed",
installed: ((which zed | is-not-empty) or ("/Applications/Zed.app" | path exists)),
version: (if (which zed | is-not-empty) {
try { (zed --version | str trim) } catch { "available" }
} else if ("/Applications/Zed.app" | path exists) {
"installed (app bundle)"
} else {
null
})
},
{
name: "claude-code",
installed: ((which claude-code | is-not-empty) or (which claude | is-not-empty) or ("/Applications/Claude.app" | path exists)),
version: (if (which claude-code | is-not-empty) {
try { (claude-code --version | str trim) } catch { "available" }
} else if (which claude | is-not-empty) {
try { (claude --version | str trim) } catch { "available" }
} else if ("/Applications/Claude.app" | path exists) {
"installed (app bundle)"
} else {
null
})
},
{
name: "neovim",
installed: (which nvim | is-not-empty),
version: (if (which nvim | is-not-empty) { try { (nvim --version | lines | first | str replace "NVIM " "") } catch { "available" } } else { null })
},
{
name: "gemini",
installed: ((which gemini | is-not-empty) or ("/Applications/Gemini 2- The Duplicate Finder.app" | path exists)),
version: (if (which gemini | is-not-empty) {
try { (gemini --version | str trim) } catch { "available" }
} else if ("/Applications/Gemini 2- The Duplicate Finder.app" | path exists) {
"installed (app bundle)"
} else { null })
},
{
name: "codex",
installed: (which codex | is-not-empty),
version: (if (which codex | is-not-empty) { try { (codex --version | str trim) } catch { "available" } } else { null })
}
]
$tools
}
def output_human [result: record, verbose: bool, fix_path: bool] {
print "🔍 Verifying Rustelo Prerequisites..."
print ""
# Show system information if verbose
if $verbose and ($result.system | is-not-empty) {
print ""
print "💻 System Information:"
print $" OS: ($result.system.os)"
print $" Arch: ($result.system.arch)"
print $" Kernel: ($result.system.kernel)"
print $" Shell: ($result.system.shell)"
print ""
}
# Show prerequisites
let prereqs = $result.prerequisites
if $prereqs.rust.installed {
print $"✅ Rust: ($prereqs.rust.rustc_version)"
if $verbose {
print $" Cargo: ($prereqs.rust.cargo_version)"
print $" Toolchain: ($prereqs.rust.toolchain)"
}
} else {
print "❌ Rust: Not found"
}
if $prereqs.node.installed {
print $"✅ Node.js: ($prereqs.node.node_version)"
print $"✅ pnpm: ($prereqs.node.pnpm_version)"
if $verbose and ($prereqs.node.npm_version != null) {
print $" npm: ($prereqs.node.npm_version)"
}
} else if ($prereqs.node.node_version != null) {
print $"✅ Node.js: ($prereqs.node.node_version)"
print "❌ pnpm: Not found"
} else {
print "❌ Node.js: Not found"
print "❌ pnpm: Not found"
}
if $prereqs.nushell.installed {
print $"✅ Nushell: ($prereqs.nushell.version)"
if $verbose {
print $" Current shell: ($prereqs.nushell.current_shell)"
print $" Features: ($prereqs.nushell.features)"
}
} else {
print "❌ Nushell: Not found"
}
if $prereqs.just.installed {
print $"✅ Just: ($prereqs.just.version)"
if $verbose and $prereqs.just.justfile_found {
print " ✅ justfile found in current directory"
} else if $verbose {
print " ⚠️ No justfile found in current directory"
}
} else {
print "❌ Just: Not found"
}
# Show additional tools
print ""
print "🔧 Additional Development Tools:"
for tool in $result.additional_tools {
if $tool.installed {
match $tool.name {
"vscode" => { print $"✅ VS Code: ($tool.version)" },
"zed" => { print $"✅ Zed Editor: ($tool.version)" },
"claude-code" => { print $"✅ Claude Code: ($tool.version)" },
"neovim" => { print $"✅ Neovim: ($tool.version)" },
"mvps" => { print $"✅ MVPS: ($tool.version)" },
_ => { print $"✅ ($tool.name | str title-case): ($tool.version)" }
}
} else {
match $tool.name {
"git" => { print "⚠️ Git: Not found (recommended for version control)" },
"sqlite" => { print "⚠️ SQLite: Not found (useful for local database development)" },
"docker" => { print " Docker: Not found (optional, for containerized deployment)" },
"vscode" => { print " VS Code: Not found (popular code editor)" },
"zed" => { print " Zed Editor: Not found (modern collaborative editor)" },
"claude-code" => { print " Claude Code: Not found (AI-powered coding assistant)" },
"neovim" => { print " Neovim: Not found (vim-based editor)" },
"mvps" => { print " MVPS: Not found (development tool)" }
}
}
}
print ""
if $result.summary.all_prerequisites_met {
print "✅ All prerequisites are properly installed!"
print ""
print "🚀 You're ready to create Rustelo projects:"
print " rustelo new my-website"
print " cd my-website"
print " just dev"
print ""
} else {
print "❌ Some prerequisites are missing or have issues:"
print ""
for issue in $result.summary.issues {
print $" • ($issue)"
}
print ""
print "🔧 To fix these issues:"
print " nu scripts/install-prerequisites.nu"
print ""
if $fix_path {
attempt_path_fix
}
}
}
def check_rust [verbose: bool] {
if (which rustc | is-not-empty) and (which cargo | is-not-empty) {
let rustc_version = (rustc --version | str trim)
let cargo_version = (cargo --version | str trim)
print $"✅ Rust: ($rustc_version)"
if $verbose {
print $" Cargo: ($cargo_version)"
print $" Toolchain: (rustup show active-toolchain | str trim)"
}
{ ok: true, issue: null }
} else {
print "❌ Rust: Not found"
{ ok: false, issue: "Rust compiler (rustc) and Cargo not found. Install from https://rustup.rs/" }
}
}
def check_node [verbose: bool] {
let node_ok = (which node | is-not-empty)
let pnpm_ok = (which pnpm | is-not-empty)
if $node_ok and $pnpm_ok {
let node_version = (node --version | str trim)
let pnpm_version = (pnpm --version | str trim)
print $"✅ Node.js: ($node_version)"
print $"✅ pnpm: ($pnpm_version)"
if $verbose {
let npm_version = if (which npm | is-not-empty) { (npm --version | str trim) } else { "not found" }
print $" npm: ($npm_version)"
}
{ ok: true, issue: null }
} else if $node_ok and not $pnpm_ok {
let node_version = (node --version | str trim)
print $"✅ Node.js: ($node_version)"
print "❌ pnpm: Not found"
{ ok: false, issue: "pnpm package manager not found. Install with: npm install -g pnpm" }
} else {
print "❌ Node.js: Not found"
print "❌ pnpm: Not found"
{ ok: false, issue: "Node.js and pnpm not found. Install Node.js from https://nodejs.org/ then run: npm install -g pnpm" }
}
}
def check_nushell [verbose: bool] {
if (which nu | is-not-empty) {
let version = (nu --version | lines | first | str trim)
print $"✅ Nushell: ($version)"
if $verbose {
# Check if current shell is nushell
let current_shell = ($env.SHELL? | default "unknown")
print $" Current shell: ($current_shell)"
# Check nushell features
try {
let features = (nu -c "version | get features" | str join ", ")
print $" Features: ($features)"
} catch {
print " Features: Could not determine"
}
}
{ ok: true, issue: null }
} else {
print "❌ Nushell: Not found"
{ ok: false, issue: "Nushell shell not found. Install from https://github.com/nushell/nushell/releases or via package manager" }
}
}
def check_just [verbose: bool] {
if (which just | is-not-empty) {
let version = (just --version | str trim)
print $"✅ Just: ($version)"
if $verbose {
# Check if justfile exists in current directory
if ("justfile" | path exists) {
print " ✅ justfile found in current directory"
} else if ("Justfile" | path exists) {
print " ✅ Justfile found in current directory"
} else {
print " ⚠️ No justfile found in current directory"
}
}
{ ok: true, issue: null }
} else {
print "❌ Just: Not found"
{ ok: false, issue: "Just command runner not found. Install with: cargo install just" }
}
}
def check_additional_tools [verbose: bool] {
print ""
print "🔧 Additional Development Tools:"
# Git
if (which git | is-not-empty) {
let version = (git --version | str replace "git version " "")
print $"✅ Git: ($version)"
} else {
print "⚠️ Git: Not found (recommended for version control)"
}
# SQLite (useful for local development)
if (which sqlite3 | is-not-empty) {
let version = (sqlite3 --version | split row " " | first)
print $"✅ SQLite: ($version)"
} else {
print "⚠️ SQLite: Not found (useful for local database development)"
}
# Docker (for containerized deployments)
if (which docker | is-not-empty) {
let version = (docker --version | str replace "Docker version " "" | split row "," | first)
print $"✅ Docker: ($version)"
} else {
print " Docker: Not found (optional, for containerized deployment)"
}
# VS Code or other editors with Rust support
if (which code | is-not-empty) {
print "✅ VS Code: Available"
} else if (which nvim | is-not-empty) {
print "✅ Neovim: Available"
} else if (which vim | is-not-empty) {
print "✅ Vim: Available"
} else {
print " Editor: Consider installing VS Code with rust-analyzer extension"
}
}
def attempt_path_fix [] {
print ""
print "🔧 Attempting to fix PATH issues..."
let home = $env.HOME
let cargo_bin = $"($home)/.cargo/bin"
let local_bin = "/usr/local/bin"
# Check if cargo bin is in PATH
if not ($env.PATH | split row ":" | any { |p| $p == $cargo_bin }) {
print $"Adding ($cargo_bin) to PATH..."
$env.PATH = ($env.PATH | split row ":" | append $cargo_bin | uniq)
}
# Check if local bin is in PATH
if not ($env.PATH | split row ":" | any { |p| $p == $local_bin }) {
print $"Adding ($local_bin) to PATH..."
$env.PATH = ($env.PATH | split row ":" | append $local_bin | uniq)
}
# Suggest shell configuration updates
print ""
print "💡 To make PATH changes permanent, add these lines to your shell config:"
print ""
let shell_config = match ($env.SHELL? | default "") {
$path if ($path | str ends-with "zsh") => "~/.zshrc",
$path if ($path | str ends-with "bash") => "~/.bashrc",
$path if ($path | str ends-with "fish") => "~/.config/fish/config.fish",
_ => "~/.bashrc"
}
print $" echo 'export PATH=\"$PATH:($cargo_bin):($local_bin)\"' >> ($shell_config)"
print " source ($shell_config)"
print ""
}
# Show system information if verbose
def show_system_info [] {
print ""
print "💻 System Information:"
# Get system info properly for different platforms
let os_name = try {
let uname_s = (^uname -s | str trim)
match $uname_s {
"Darwin" => "macOS",
"Linux" => "Linux",
"MINGW64_NT" => "Windows",
_ => $uname_s
}
} catch {
try { (sys host | get name) } catch { "unknown" }
}
let arch = try {
let uname_m = (^uname -m | str trim)
match $uname_m {
"arm64" => "Apple Silicon (ARM64)",
"x86_64" => "Intel x64",
"aarch64" => "ARM64",
_ => $uname_m
}
} catch {
try { (sys host | get cpu | first | get brand) } catch { "unknown" }
}
let kernel = try {
(^uname -r | str trim)
} catch {
try { (sys host | get kernel_version) } catch { "unknown" }
}
# Get more detailed OS info on macOS
let detailed_os = if ($os_name == "macOS") {
let version = try { (^sw_vers -productVersion | str trim) } catch { "" }
let name = try { (^sw_vers -productName | str trim) } catch { "" }
if ($version != "" and $name != "") {
$"($name) ($version)"
} else {
$os_name
}
} else {
$os_name
}
print $" OS: ($detailed_os)"
print $" Arch: ($arch)"
print $" Kernel: ($kernel)"
print $" Shell: ($env.SHELL? | default 'unknown')"
print ""
}