nushell-plugins/scripts/install_from_manifest.nu
Jesús Pérez d9ef2f0d5b
Some checks failed
Build and Test / Validate Setup (push) Has been cancelled
Build and Test / Build (darwin-amd64) (push) Has been cancelled
Build and Test / Build (darwin-arm64) (push) Has been cancelled
Build and Test / Build (linux-amd64) (push) Has been cancelled
Build and Test / Build (windows-amd64) (push) Has been cancelled
Build and Test / Build (linux-arm64) (push) Has been cancelled
Build and Test / Security Audit (push) Has been cancelled
Build and Test / Package Results (push) Has been cancelled
Build and Test / Quality Gate (push) Has been cancelled
Nightly Build / Check for Changes (push) Has been cancelled
Nightly Build / Validate Setup (push) Has been cancelled
Nightly Build / Nightly Build (darwin-amd64) (push) Has been cancelled
Nightly Build / Nightly Build (darwin-arm64) (push) Has been cancelled
Nightly Build / Nightly Build (linux-amd64) (push) Has been cancelled
Nightly Build / Nightly Build (windows-amd64) (push) Has been cancelled
Nightly Build / Nightly Build (linux-arm64) (push) Has been cancelled
Nightly Build / Create Nightly Pre-release (push) Has been cancelled
Nightly Build / Notify Build Status (push) Has been cancelled
Nightly Build / Nightly Maintenance (push) Has been cancelled
chore: update all plugins to Nushell 0.111.0
- Bump all 18 plugins from 0.110.0 to 0.111.0
  - Update rust-toolchain.toml channel to 1.93.1 (nu 0.111.0 requires ≥1.91.1)

  Fixes:
  - interprocess pin =2.2.x → ^2.3.1 in nu_plugin_mcp, nu_plugin_nats, nu_plugin_typedialog
    (required by nu-plugin-core 0.111.0)
  - nu_plugin_typedialog: BackendType::Web initializer — add open_browser: false field
  - nu_plugin_auth: implement missing user_info_to_value helper referenced in tests

  Scripts:
  - update_all_plugins.nu: fix [package].version update on minor bumps; add [dev-dependencies]
    pass; add nu-plugin-test-support to managed crates
  - download_nushell.nu: rustup override unset before rm -rf on nushell dir replace;
    fix unclosed ) in string interpolation
2026-03-11 03:22:42 +00:00

316 lines
8.7 KiB
Plaintext
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
# Distribution Plugin Installer - Install & Register from Manifest
#
# Reads a distribution manifest (JSON) and installs/registers selected plugins.
# Plugins are copied to ~/.local/bin/ and registered with Nushell.
#
# Usage:
# install_from_manifest.nu # Uses DISTRIBUTION_MANIFEST.json
# install_from_manifest.nu --manifest manifest.json
# install_from_manifest.nu --list # List available plugins
# install_from_manifest.nu --all # Install all plugins
# install_from_manifest.nu --preset essential # Install preset
# install_from_manifest.nu --select auth kms # Install specific plugins
# install_from_manifest.nu --check # Dry-run
def main [
--manifest: string = "DISTRIBUTION_MANIFEST.json" # Path to manifest file
--list # List available plugins only
--all # Install all plugins
--preset: string # Use preset: essential, development, full
--select: list<string> # Select specific plugins
--check (-c) # Dry-run, don't make changes
--install-only # Only install, don't register
--register-only # Only register, skip install
] {
log_info "📦 Nushell Distribution Plugin Installer"
log_info "=================================================================="
# Step 1: Load manifest
log_info $"\n📋 Step 1: Loading manifest ($manifest)..."
let manifest_data = load_manifest $manifest
if $manifest_data == null {
return
}
let plugins = $manifest_data.plugins
if ($plugins | length) == 0 {
log_error "No plugins in manifest!"
return
}
log_success $"Loaded ($plugins | length) available plugin\(s\)"
# List mode?
if $list {
display_plugin_list $plugins
return
}
# Step 2: Select plugins
log_info "\n🎯 Step 2: Selecting plugins..."
let selected = if ($preset | is-not-empty) {
get_preset_plugins $plugins $preset
} else if ($select | length) > 0 {
filter_by_name $plugins $select
} else if $all {
$plugins
} else {
interactive_select $plugins
}
if ($selected | length) == 0 {
log_warn "No plugins selected"
return
}
# Step 3: Show selection
log_info ""
log_success $"Selected: ($selected | length) plugin\(s\)"
for plugin in $selected {
log_info $" • ($plugin.name) - ($plugin.purpose)"
}
# Step 4: Dry-run?
if $check {
log_info "\n✅ DRY RUN - No changes made"
return
}
# Step 5: Confirm
print ""
let response = try {
input "Proceed with installation? (yes/no): "
} catch {
"yes"
}
if $response != "yes" {
log_info "Cancelled"
return
}
# Step 6: Install
if not $register_only {
log_info "\n📦 Step 3: Installing plugins..."
install_plugins $selected $manifest_data.source_directory
}
# Step 7: Register
if not $install_only {
log_info "\n🔌 Step 4: Registering with Nushell..."
register_plugins $selected
}
# Summary
log_info "\n=================================================================="
log_success "✅ Complete!"
log_info ""
log_info "Next steps:"
log_info " 1. Restart Nushell: exit && nu"
log_info " 2. Verify: nu -c 'plugin list'"
}
# Load manifest from JSON file
def load_manifest [path: string]: nothing -> record {
if not ($path | path exists) {
log_error $"Manifest not found: ($path)"
return null
}
try {
let content = open $path
return $content
} catch {|err|
log_error $"Failed to load manifest: ($err.msg)"
return null
}
}
# Display plugin list
def display_plugin_list [plugins: list<record>] {
print ""
log_success $"Available plugins: ($plugins | length)"
print ""
for plugin in $plugins {
print $" ✓ ($plugin.name)"
print $" ($plugin.purpose)"
print ""
}
}
# Get preset plugins
def get_preset_plugins [plugins: list<record>, preset: string]: nothing -> list<record> {
match $preset {
"essential" => {
$plugins | where {|p|
$p.name in ["nu_plugin_auth", "nu_plugin_kms", "nu_plugin_orchestrator", "nu_plugin_kcl", "nu_plugin_tera"]
}
}
"development" => {
$plugins | where {|p|
$p.name in ["nu_plugin_auth", "nu_plugin_kms", "nu_plugin_orchestrator", "nu_plugin_kcl", "nu_plugin_tera", "nu_plugin_highlight", "nu_plugin_image", "nu_plugin_clipboard"]
}
}
"full" => {
$plugins
}
_ => {
log_error $"Unknown preset: ($preset)"
log_info "Available: essential, development, full"
[]
}
}
}
# Filter by name
def filter_by_name [plugins: list<record>, names: list<string>]: nothing -> list<record> {
$plugins | where {|p|
if $p.name in $names {
true
} else {
($p.name | str replace "^nu_plugin_" "") in $names
}
}
}
# Interactive select
def interactive_select [plugins: list<record>]: nothing -> list<record> {
print ""
log_info "Available presets:"
log_info " 1. Essential (5 core plugins)"
log_info " 2. Development (8 plugins)"
log_info " 3. All ($($plugins | length) plugins)"
print ""
let choice = try {
input "Select (1-3): "
} catch {
"1"
}
match $choice {
"1" => { get_preset_plugins $plugins "essential" }
"2" => { get_preset_plugins $plugins "development" }
"3" => { $plugins }
_ => { [] }
}
}
# Install plugins to ~/.local/bin/
def install_plugins [selected: list<record>, source_dir: string] {
let install_dir = $"($env.HOME)/.local/bin"
# Ensure directory exists
if not ($install_dir | path exists) {
log_info $"Creating directory: ($install_dir)"
mkdir $install_dir
}
for plugin in $selected {
log_info $"Installing: ($plugin.name)"
try {
let source_path = $"($source_dir)/($plugin.name)"
let target_path = $"($install_dir)/($plugin.name)"
if not ($source_path | path exists) {
log_error $" ✗ Source not found: ($source_path)"
continue
}
cp $source_path $target_path
chmod +x $target_path
# Fix macOS code signing issues
fix_macos_binary $target_path
log_success $" ✓ Installed to ($target_path)"
} catch {|err|
log_error $" ✗ Failed: ($err.msg)"
}
}
}
# Fix macOS code signing (remove quarantine, ad-hoc sign)
def fix_macos_binary [binary_path: string] {
let os_type = $nu.os-info.name
if $os_type == "macos" {
# Remove quarantine attribute
try {
^xattr -d com.apple.quarantine $binary_path out+err>| null
} catch {
# Silently ignore if attribute doesn't exist
}
# Ad-hoc sign the binary
try {
^codesign -s - $binary_path out+err>| null
} catch {
# Silently ignore if codesign fails
}
}
}
# Register plugins with Nushell
def register_plugins [selected: list<record>] {
let install_dir = $"($env.HOME)/.local/bin"
let nu_cmd = $"($install_dir)/nu"
# Fix code signing on nu binary if it exists locally
if ($nu_cmd | path exists) {
fix_macos_binary $nu_cmd
}
for plugin in $selected {
let basename = $plugin.name | str replace "^nu_plugin_" ""
let plugin_path = $"($install_dir)/($plugin.name)"
log_info $"Registering: ($plugin.name)"
try {
# Remove old registration if exists
try {
if ($nu_cmd | path exists) {
^$nu_cmd -c $"plugin rm ($basename)" out+err>| null
} else {
nu -c $"plugin rm ($basename)" out+err>| null
}
} catch {}
# Register new - use local nu if available, otherwise system nu
if ($nu_cmd | path exists) {
^$nu_cmd -c $"plugin add ($plugin_path)"
} else {
nu -c $"plugin add ($plugin_path)"
}
log_success $" ✓ Registered"
} catch {|err|
log_error $" ✗ Failed: ($err.msg)"
}
}
}
# Logging
def log_info [msg: string] {
print $" ($msg)"
}
def log_success [msg: string] {
print $"✅ ($msg)"
}
def log_error [msg: string] {
print $"❌ ($msg)"
}
def log_warn [msg: string] {
print $"⚠️ ($msg)"
}
main