nushell-plugins/scripts/update_all_plugins.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

492 lines
14 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.

#!/usr/bin/env nu
# Update All Plugins - Bulk Plugin Updater
# Updates all nu_plugin_* Cargo.toml dependencies to a new Nushell version
#
# Usage:
# update_all_plugins.nu 0.108.0 # Update dependencies to version
# update_all_plugins.nu 0.108.0 --auto-approve # Skip confirmation
# update_all_plugins.nu --list # List current versions
# update_all_plugins.nu replace-version 0.109.1 0.110.0 # Replace [package] version
# update_all_plugins.nu replace-version 0.109.1 0.110.0 --dry-run # Preview changes
use lib/common_lib.nu *
# Main entry point
def main [
target_version?: string # Target Nushell version (e.g., "0.108.0")
--auto-approve # Skip confirmation prompts
--dry-run # Show what would be updated without changing
--list # List current plugin versions
--plugin: string # Update only specific plugin
] {
if $list {
list_plugin_versions
return
}
if ($target_version | is-empty) {
log_error "Please specify a target version"
show_usage
exit 1
}
log_info $"🔄 Updating all plugins to Nushell ($target_version)"
# Get all plugin directories
let plugins = if ($plugin | is-not-empty) {
[{ name: $plugin, path: $plugin }]
} else {
get_plugin_directories
}
if ($plugins | length) == 0 {
log_error "No plugin directories found"
exit 1
}
log_info $"Found ($plugins | length) plugins to update"
# Show current versions
log_info "\n📋 Current Versions:"
for p in $plugins {
let current = get_plugin_version $p.path
print $" ($p.name): ($current)"
}
# Confirm update
if not $auto_approve and not $dry_run {
print ""
let response = input $"Update all plugins to ($target_version)? \(yes/no\): "
if $response != "yes" {
log_info "Update cancelled"
exit 0
}
}
# Update each plugin
mut updated = 0
mut failed = []
print ""
for p in $plugins {
if $dry_run {
log_info $"\(DRY RUN\) Would update ($p.name)"
$updated = $updated + 1
} else {
let result = update_plugin $p.path $target_version
if $result {
log_success $"✓ Updated ($p.name)"
$updated = $updated + 1
} else {
log_error $"✗ Failed to update ($p.name)"
$failed = ($failed | append $p.name)
}
}
}
# Summary
print ""
if ($failed | length) == 0 {
log_success $"✅ Successfully updated ($updated) plugins to ($target_version)"
} else {
log_warn $"⚠️ Updated ($updated) plugins, ($failed | length) failed:"
for f in $failed {
log_error $" • ($f)"
}
exit 1
}
if not $dry_run {
log_info "\n📝 Next steps:"
log_info " 1. Build plugins: just build"
log_info " 2. Test plugins: just test"
log_info " 3. Create distribution: just pack-full"
}
}
# Show usage
def show_usage [] {
print "Usage:"
print " update_all_plugins.nu <version> # Update to version"
print " update_all_plugins.nu <version> --auto-approve"
print " update_all_plugins.nu --list # List current versions"
print ""
print "Examples:"
print " update_all_plugins.nu 0.108.0"
print " update_all_plugins.nu 0.108.0 --dry-run"
print " update_all_plugins.nu 0.108.0 --plugin nu_plugin_image"
}
# Get plugin directories
def get_plugin_directories []: nothing -> list<record> {
ls nu_plugin_*
| where type == dir
| each {|row|
{
name: (get_plugin_name $row.name)
path: $row.name
}
}
}
# Get plugin name from directory
def get_plugin_name [dir: string]: nothing -> string {
$dir | path basename
}
# Get current plugin version
def get_plugin_version [plugin_dir: string]: nothing -> string {
let cargo_toml = $"($plugin_dir)/Cargo.toml"
if not ($cargo_toml | path exists) {
return "N/A"
}
try {
let cargo_data = open $cargo_toml
let deps = $cargo_data | get dependencies
# Try to get nu-plugin version
if "nu-plugin" in ($deps | columns) {
let nu_plugin_spec = $deps | get nu-plugin
if ($nu_plugin_spec | describe) == "record" {
return ($nu_plugin_spec | get version)
} else {
return $nu_plugin_spec
}
}
return "unknown"
} catch {
return "error"
}
}
# Update single plugin
def update_plugin [
plugin_dir: string
target_version: string
]: nothing -> bool {
let cargo_toml = $"($plugin_dir)/Cargo.toml"
if not ($cargo_toml | path exists) {
log_error $"Cargo.toml not found in ($plugin_dir)"
return false
}
try {
# Read current Cargo.toml
let content = open $cargo_toml
# Update [dependencies] nu-* crates
let updated_deps = update_nu_dependencies ($content | get dependencies) $target_version
let updated_content = $content | update dependencies $updated_deps
# Update [dev-dependencies] nu-* crates if section exists
let updated_content = if "dev-dependencies" in ($updated_content | columns) {
let updated_dev_deps = update_nu_dependencies ($updated_content | get dev-dependencies) $target_version
$updated_content | update dev-dependencies $updated_dev_deps
} else {
$updated_content
}
# Update [package] version — these plugins always track the nushell release cycle
let final_content = if "package" in ($updated_content | columns) {
$updated_content | update package.version $target_version
} else {
$updated_content
}
# Only save if content actually changed (avoid unnecessary file timestamp updates)
let original_toml = $content | to toml
let new_toml = $final_content | to toml
if $original_toml != $new_toml {
# Content changed - save the file
$final_content | to toml | save -f $cargo_toml
return true
} else {
# No changes needed - don't touch the file
return true
}
} catch {|err|
log_error $"Error updating ($plugin_dir): ($err.msg)"
return false
}
}
# Update nu-* dependencies in dependencies table
def update_nu_dependencies [
deps: record
target_version: string
]: nothing -> record {
mut updated_deps = $deps
# List of nu-* crates to update (covers both [dependencies] and [dev-dependencies])
let nu_crates = [
"nu-plugin"
"nu-protocol"
"nu-engine"
"nu-parser"
"nu-cmd-base"
"nu-color-config"
"nu-utils"
"nu-path"
"nu-glob"
"nu-json"
"nu-pretty-hex"
"nu-system"
"nu-table"
"nu-term-grid"
"nu-plugin-test-support"
]
for crate in $nu_crates {
if $crate in ($deps | columns) {
let spec = $deps | get $crate
# Update version based on spec type
if ($spec | describe) == "record" {
# It's a detailed spec with version, path, features, etc.
let updated_spec = $spec | update version $target_version
$updated_deps = ($updated_deps | update $crate $updated_spec)
} else {
# It's just a version string
$updated_deps = ($updated_deps | update $crate $target_version)
}
}
}
$updated_deps
}
# List all plugin versions
def list_plugin_versions [] {
log_info "📋 Current Plugin Versions\n"
let plugins = get_plugin_directories
# Create table of versions
let versions = $plugins | each {|p|
{
plugin: $p.name
nu_plugin_version: (get_plugin_version $p.path)
}
}
$versions | table
print ""
log_info $"Total plugins: ($plugins | length)"
}
# Check for version mismatches
def "main check" [] {
log_info "🔍 Checking for version mismatches\n"
let plugins = get_plugin_directories
# Get all unique versions
let versions = $plugins
| each {|p| get_plugin_version $p.path}
| uniq
if ($versions | length) == 1 {
log_success $"✅ All plugins use consistent version: ($versions | first)"
} else {
log_warn $"⚠️ Version mismatch detected! Found ($versions | length) different versions:"
for v in $versions {
let count = $plugins | each {|p| get_plugin_version $p.path} | where {|ver| $ver == $v} | length
log_info $" ($v): ($count) plugins"
}
# Show which plugins have which versions
print "\nDetailed breakdown:"
for p in $plugins {
let version = get_plugin_version $p.path
print $" ($p.name): ($version)"
}
}
}
# Update to match nushell submodule version
def "main sync" [] {
log_info "🔄 Syncing plugin versions with nushell submodule\n"
# Get version from nushell submodule
let nushell_cargo = "./nushell/Cargo.toml"
if not ($nushell_cargo | path exists) {
log_error "Nushell submodule not found at ./nushell/"
log_info "Download it first with: ./scripts/download_nushell.nu"
exit 1
}
let nushell_version = try {
open $nushell_cargo | get package.version
} catch {
log_error "Failed to read nushell version"
exit 1
}
log_info $"Nushell submodule version: ($nushell_version)"
log_info "Updating all plugins to match...\n"
# Run main update
main $nushell_version --auto-approve
}
# Replace package version (from -> to)
# Only updates plugins with exact match of from_version
def "main replace-version" [
from_version: string # Source version to replace (e.g., "0.109.1")
to_version: string # Target version (e.g., "0.110.0")
--dry-run # Show what would be updated without changing
] {
log_info $"🔄 Replacing [package] version from ($from_version) to ($to_version)"
# Get all plugin directories
let all_plugins = get_plugin_directories
if ($all_plugins | is-empty) {
log_error "No plugin directories found"
exit 1
}
log_info $"Found ($all_plugins | length) plugin directories"
# Find plugins with matching version
let matching = $all_plugins | where {|plugin|
(get_package_version $plugin.path) == $from_version
}
let non_matching = $all_plugins | where {|plugin|
(get_package_version $plugin.path) != $from_version
}
# Show results
print ""
log_info "📋 Analysis Results:"
log_success $" ✓ Matching ($from_version): ($matching | length) plugins"
log_info $" • Other versions: ($non_matching | length) plugins"
if ($matching | is-empty) {
log_warn $"\nNo plugins found with [package] version ($from_version)"
log_info "Nothing to update."
exit 0
}
# Show which plugins will be updated
print "\n🎯 Plugins to update:"
$matching | each {|m| print $" ($m.name)"}
if ($non_matching | is-not-empty) {
print "\n⏭ Skipping (different versions):"
$non_matching | each {|nm|
let ver = get_package_version $nm.path
print $" ($nm.name) \(($ver)\)"
}
}
# Confirm update
if not $dry_run {
print ""
let response = input $"Update ($matching | length) plugins from ($from_version) to ($to_version)? \(yes/no\): "
if $response != "yes" {
log_info "Update cancelled"
exit 0
}
}
# Update each matching plugin
let results = $matching | each {|m|
if $dry_run {
log_info $"\(DRY RUN\) Would update ($m.name)"
{plugin: $m.name, success: true}
} else {
let success = replace_package_version $m.path $to_version
if $success {
log_success $"✓ Updated ($m.name)"
} else {
log_error $"✗ Failed to update ($m.name)"
}
{plugin: $m.name, success: $success}
}
}
let updated = $results | where success | length
let failed = $results | where {|r| not $r.success}
# Summary
print ""
if ($failed | is-empty) {
log_success $"✅ Successfully updated ($updated) plugins to ($to_version)"
} else {
log_warn $"⚠️ Updated ($updated) plugins, ($failed | length) failed:"
$failed | each {|f| log_error $" • ($f.plugin)"}
exit 1
}
if not $dry_run {
log_info "\n📝 Next steps:"
log_info " 1. Verify changes: git diff"
log_info " 2. Build plugins: just build"
log_info " 3. Test plugins: just test"
}
}
# Get package version (not dependency version)
def get_package_version [plugin_dir: string]: nothing -> string {
let cargo_toml = $"($plugin_dir)/Cargo.toml"
if not ($cargo_toml | path exists) {
return "N/A"
}
let cargo_data = open $cargo_toml
if "package" not-in ($cargo_data | columns) {
return "N/A"
}
$cargo_data.package.version
}
# Replace package version in Cargo.toml
def replace_package_version [
plugin_dir: string
new_version: string
]: nothing -> bool {
let cargo_toml = $"($plugin_dir)/Cargo.toml"
if not ($cargo_toml | path exists) {
log_error $"Cargo.toml not found in ($plugin_dir)"
return false
}
let content = open $cargo_toml
if "package" not-in ($content | columns) {
log_warn $"No [package] section found in ($plugin_dir)"
return false
}
# Update package version
let updated_content = $content | update package.version $new_version
# Only save if content actually changed
let original_toml = $content | to toml
let new_toml = $updated_content | to toml
if $original_toml == $new_toml {
return true
}
# Save the file
$updated_content | to toml | save -f $cargo_toml
true
}