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
- 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
492 lines
14 KiB
Plaintext
Executable File
492 lines
14 KiB
Plaintext
Executable File
#!/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
|
||
}
|