nushell-plugins/justfiles/version_update.just
Jesús Pérez 2b3e574e3d # Summary
fix: help system integration, build process optimization, and plugin rebuild efficiency

## Detailed Description

This commit addresses critical issues in the help system discoverability, build process robustness, and plugin rebuild efficiency.

### 1. Help System Integration (New Feature)

**Issue**: Version-update module recipes were not discoverable
- Not shown in `just help modules`
- Not referenced in `just help`
- Not included in help navigation system
- Users had to manually run `just --list` to find update commands

**Solution**:
- Added version-update module to all help outputs
- Updated `justfiles/help.just` to document all 30+ version-update recipes
- Created new `just commands` recipe as discoverable alias for `just --list`
- Integrated version-update into help-all workflow

**Impact**:
- Version-update commands now fully discoverable via help system
- Users can find update commands with: `just help modules`, `just help`, `just commands`
- Improved overall help system navigation

**Files Modified**:
- `justfiles/help.just` (+23 lines)
  - Added version-update module to help sections
  - Added to modules list
  - Added to help-all workflow
  - New `commands` recipe showing all recipes by group

### 2. Build Process Fixes (Phase 3: Bin Archives)

#### 2a. Plugin Archive Collection Bug

**Issue**: "No plugins found to package" warning in Phase 3
- Collected 26 plugin binaries but reported 0
- Archive creation skipped because count was wrong

**Root Cause**: `each` command returns null, so `| length` returned 0
```nushell
#  OLD - each returns null
let plugin_count = (ls nu_plugin_*/target/release/nu_plugin_* | each {|p|
    cp $p.name $"($temp_dir)/"
} | length)  # Returns 0!
```

**Solution**: Separated counting from copying with proper filtering
```nushell
#  NEW - count before operations
let plugins_to_copy = (ls nu_plugin_*/target/release/nu_plugin_* | where type == "file")
let plugin_count = ($plugins_to_copy | length)
```

**Impact**:
- Now correctly collects and reports 26 plugins
- Filters out .d dependency files automatically
- Warning eliminated

#### 2b. Tar Archive Path Handling

**Issue**: Tar command failing silently with relative paths in subshell
- `cd $temp_dir` changes context unpredictably
- Relative path `../$archive_name` fails in subshell
- Archive file not created despite exit code 0

**Root Cause**: Shell context and relative path issues in Nushell `do` block

**Solution**: Used `tar -C` with absolute paths instead of `cd`
```nushell
#  OLD - unreliable context switching
do {
    cd $temp_dir
    tar -czf ../$archive_name .
}

#  NEW - absolute paths, no context switching
tar -C $temp_dir -czf $archive_path .
```

**Additional Improvements**:
- Absolute path construction using `pwd | path join`
- Better error diagnostics with exit code and stderr output
- File verification after creation

**Impact**:
- Tar archives now created successfully
- Robust path handling across platforms
- Clear error messages for debugging

#### 2c. File Size Calculation Type Error

**Issue**: Runtime error when calculating archive size
```
Error: The '/' operator does not work on values of type 'list<filesize>'
```

**Root Cause**: `ls` returns list of records, so `.size` was a list
```nushell
#  OLD - returns list<filesize>
(ls $archive_path).size / 1024 / 1024

#  NEW - returns filesize
(ls $archive_path | get 0.size) / 1024 / 1024
```

**Impact**:
- Proper file size calculation in MB
- No more type errors

**Files Modified**:
- `scripts/create_full_distribution.nu` (+58 lines, refactored plugin collection)
  - Fixed plugin counting logic
  - Improved path handling with absolute paths
  - Enhanced error diagnostics

### 3. Plugin Rebuild Optimization

**Issue**: All plugins marked for rebuild even when dependencies unchanged
- Step 4 (`update_all_plugins.nu`) touched all Cargo.toml files at 01:00:32
- Step 5 saw all files as "newer" than binaries
- Marked ALL plugins for rebuild, though cargo only rebuilt changed ones

**Root Cause**: Script always saved files, even when no changes made
```nushell
#  OLD - always saves, touching file timestamp
$updated_content | to toml | save -f $cargo_toml
```

**Solution**: Only save if content actually changed
```nushell
#  NEW - compare before writing
let original_toml = $content | to toml
let new_toml = $updated_content | to toml

if $original_toml != $new_toml {
    $updated_content | to toml | save -f $cargo_toml
}
```

**Impact**:
- Unchanged files preserve original timestamps
- Only plugins with actual dependency changes are rebuilt
- Efficient rebuild process with accurate file modification detection

**Files Modified**:
- `scripts/update_all_plugins.nu` (+12 lines, added content comparison)
  - Only touches files with real changes
  - Preserves timestamps for efficiency
  - Clearer logic and comments

### 4. Documentation

**Files Modified**:
- `CHANGELOG.md` (+56 lines)
  - Added comprehensive 2025-10-19 entry
  - Documented all fixes with root causes
  - Listed files modified and impact summary

## Technical Details

### Nushell Patterns Used

1. **Proper List Handling**:
   - `ls` returns list of records, access with `| get 0.size`
   - Filter with `where type == "file"` to exclude metadata

2. **Absolute Path Construction**:
   - `pwd | append "path" | path join` for cross-platform paths
   - Safer than string concatenation with `/`

3. **Content Comparison**:
   - Compare TOML string representation before saving
   - Preserves file timestamps for efficiency

4. **Error Diagnostics**:
   - Capture `stderr` from commands
   - Report exit codes and error messages separately

## Testing

- [x] Help system shows version-update module
- [x] `just commands` displays all recipes by group
- [x] Phase 3 bin archive creation works
- [x] Plugin collection reports correct count (26)
- [x] Tar archives created successfully
- [x] File size calculated correctly
- [x] Plugin rebuild only touches changed files
- [x] CHANGELOG updated with all changes

## Files Changed

```
38 files changed, 2721 insertions(+), 2548 deletions(-)

Core Changes:
- justfiles/help.just                  (+23)  Help system integration
- scripts/create_full_distribution.nu  (+58)  Build process fixes
- scripts/update_all_plugins.nu        (+12)  Rebuild optimization
- CHANGELOG.md                         (+56)  Documentation

Dependency Updates:
- All plugin Cargo.toml and Cargo.lock files (version consistency)
```

## Breaking Changes

None. These are bug fixes and optimizations that maintain backward compatibility.

## Migration Notes

No migration needed. Improvements are transparent to users.

## Related Issues

- Help system discoverability
- Build process Phase 3 failures
- Unnecessary plugin rebuilds
- Build process reliability

## Checklist

- [x] Changes follow Rust/Nushell idioms
- [x] Code is well-commented
- [x] Error handling is comprehensive
- [x] Documentation is updated
- [x] All changes tested
- [x] No breaking changes introduced
2025-10-19 01:17:13 +01:00

497 lines
18 KiB
Plaintext

# Version Update Commands
# Semi-automated Nushell version update workflows
# 🔄 VERSION UPDATE WORKFLOWS
# Update to new Nushell version - ALL-IN-ONE (downloads, builds, updates plugins, creates distributions)
[no-cd]
[group('version-update')]
complete-update VERSION="":
#!/usr/bin/env bash
if [ -z "{{VERSION}}" ]; then
echo "❌ Error: VERSION parameter required"
echo "Usage: just complete-update 0.108.0"
echo " just complete-update 0.108.0 --auto-approve # Skip prompts"
echo " just complete-update 0.108.0 --fix # Auto-fix issues"
exit 1
fi
echo "🚀 Complete Nushell Update (ALL-IN-ONE) - RUNNER"
echo "Note: Using built nu 0.108.0 binary (system nu may be broken)"
echo ""
cd "{{justfile_directory()}}"
SCRIPT_DIR="{{justfile_directory()}}/scripts"
# Use newly built nu binary instead of broken system nu
NU_BIN="{{justfile_directory()}}/nushell/target/release/nu"
echo "Step 1/7: Downloading Nushell {{VERSION}}..."
echo " 📝 Command: $NU_BIN $SCRIPT_DIR/download_nushell.nu {{VERSION}}"
"$NU_BIN" "$SCRIPT_DIR/download_nushell.nu" "{{VERSION}}" || exit 1
echo ""
echo "Step 2/7: Analyzing features..."
echo " 📝 Command: $NU_BIN $SCRIPT_DIR/analyze_nushell_features.nu --validate"
$NU_BIN "$SCRIPT_DIR/analyze_nushell_features.nu" --validate || exit 1
echo ""
echo "Step 3/7: Building Nushell..."
# Check if binary already exists with correct version
if [ -f "nushell/target/release/nu" ]; then
BUILT_VERSION=$("nushell/target/release/nu" --version 2>/dev/null || echo "")
if [ "$BUILT_VERSION" = "{{VERSION}}" ]; then
echo "✅ Nushell {{VERSION}} already built - skipping build"
else
echo " 📝 Command: cd nushell && cargo build --release --workspace --features \"mcp,plugin,sqlite,trash-support,system-clipboard,rustls-tls\""
(cd nushell && cargo build --release --workspace --features "mcp,plugin,sqlite,trash-support,system-clipboard,rustls-tls") || exit 1
fi
else
echo " 📝 Command: cd nushell && cargo build --release --workspace --features \"mcp,plugin,sqlite,trash-support,system-clipboard,rustls-tls\""
(cd nushell && cargo build --release --workspace --features "mcp,plugin,sqlite,trash-support,system-clipboard,rustls-tls") || exit 1
fi
echo ""
echo "Step 4/7: Updating plugins..."
echo " 📝 Command: $NU_BIN $SCRIPT_DIR/update_all_plugins.nu {{VERSION}} --auto-approve"
$NU_BIN "$SCRIPT_DIR/update_all_plugins.nu" "{{VERSION}}" --auto-approve || exit 1
echo ""
echo "Step 5/7: Building plugins..."
# Check if plugins need rebuilding
PLUGINS_NEED_BUILD=false
for plugin in nu_plugin_*; do
if [ -d "$plugin" ]; then
# Check if binary exists
BINARY="$plugin/target/release/$plugin"
if [ ! -f "$BINARY" ]; then
PLUGINS_NEED_BUILD=true
break
fi
# Check if Cargo.toml is newer than binary
if [ "$plugin/Cargo.toml" -nt "$BINARY" ]; then
PLUGINS_NEED_BUILD=true
break
fi
fi
done
if [ "$PLUGINS_NEED_BUILD" = false ]; then
echo "✅ All plugins already built - skipping rebuild"
else
echo " 📝 Command: for each plugin dir: cd <plugin> && cargo build --release"
for plugin in nu_plugin_*; do
if [ -d "$plugin" ]; then
(cd "$plugin" && cargo build --release) || exit 1
fi
done
fi
echo ""
echo "Step 6/7: Creating distributions..."
echo " 📝 Command: $NU_BIN $SCRIPT_DIR/create_full_distribution.nu"
$NU_BIN "$SCRIPT_DIR/create_full_distribution.nu" || exit 1
echo ""
echo "Step 7/7: Validating..."
echo " 📝 Command: $NU_BIN $SCRIPT_DIR/update_all_plugins.nu check"
$NU_BIN "$SCRIPT_DIR/update_all_plugins.nu" check || exit 1
echo ""
echo "✅ Complete Nushell Update Finished!"
# Update to new Nushell version WITH prompts (ask before updating plugins)
[no-cd]
[group('version-update')]
complete-update-interactive VERSION="":
#!/usr/bin/env bash
if [ -z "{{VERSION}}" ]; then
echo "❌ Error: VERSION parameter required"
echo "Usage: just complete-update-interactive 0.108.0"
exit 1
fi
echo "🚀 Complete Nushell Update (INTERACTIVE MODE)"
echo "Note: Using built nu binary (system nu may be broken)"
echo ""
cd "{{justfile_directory()}}"
SCRIPT_DIR="{{justfile_directory()}}/scripts"
NU_BIN="{{justfile_directory()}}/nushell/target/release/nu"
echo "Step 1/7: Downloading Nushell {{VERSION}}..."
"$NU_BIN" "$SCRIPT_DIR/download_nushell.nu" "{{VERSION}}" || exit 1
echo ""
echo "Step 2/7: Analyzing features..."
$NU_BIN "$SCRIPT_DIR/analyze_nushell_features.nu" --validate || exit 1
echo ""
echo "Step 3/7: Building Nushell..."
if [ -f "nushell/target/release/nu" ]; then
BUILT_VERSION=$("nushell/target/release/nu" --version 2>/dev/null || echo "")
if [ "$BUILT_VERSION" = "{{VERSION}}" ]; then
echo "✅ Nushell {{VERSION}} already built - skipping build"
else
(cd nushell && cargo build --release --workspace --features "mcp,plugin,sqlite,trash-support,system-clipboard,rustls-tls") || exit 1
fi
else
(cd nushell && cargo build --release --workspace --features "mcp,plugin,sqlite,trash-support,system-clipboard,rustls-tls") || exit 1
fi
echo ""
echo "Step 4/7: Updating plugins..."
$NU_BIN "$SCRIPT_DIR/update_all_plugins.nu" "{{VERSION}}" || exit 1
echo ""
echo "Step 5/7: Building plugins..."
# Check if plugins need rebuilding
PLUGINS_NEED_BUILD=false
for plugin in nu_plugin_*; do
if [ -d "$plugin" ]; then
# Check if binary exists
BINARY="$plugin/target/release/$plugin"
if [ ! -f "$BINARY" ]; then
PLUGINS_NEED_BUILD=true
break
fi
# Check if Cargo.toml is newer than binary
if [ "$plugin/Cargo.toml" -nt "$BINARY" ]; then
PLUGINS_NEED_BUILD=true
break
fi
fi
done
if [ "$PLUGINS_NEED_BUILD" = false ]; then
echo "✅ All plugins already built - skipping rebuild"
else
echo " 📝 Command: for each plugin dir: cd <plugin> && cargo build --release"
for plugin in nu_plugin_*; do
if [ -d "$plugin" ]; then
(cd "$plugin" && cargo build --release) || exit 1
fi
done
fi
echo ""
echo "Step 6/7: Creating distributions..."
echo " 📝 Command: $NU_BIN $SCRIPT_DIR/create_full_distribution.nu"
$NU_BIN "$SCRIPT_DIR/create_full_distribution.nu" || exit 1
echo ""
echo "Step 7/7: Validating..."
echo " 📝 Command: $NU_BIN $SCRIPT_DIR/update_all_plugins.nu check"
$NU_BIN "$SCRIPT_DIR/update_all_plugins.nu" check || exit 1
echo ""
echo "✅ Complete Nushell Update Finished!"
# Update to latest Nushell version - ALL-IN-ONE
[no-cd]
[group('version-update')]
update-latest:
@echo "🚀 Updating to latest Nushell version"
@nu {{justfile_directory()}}/scripts/complete_update.nu --latest
# Download and build Nushell core only (downloads, builds, validates)
[no-cd]
[group('version-update')]
download-and-build VERSION="":
#!/usr/bin/env bash
if [ -z "{{VERSION}}" ]; then
echo "❌ Error: VERSION parameter required"
echo "Usage: just download-and-build 0.108.0"
exit 1
fi
echo "📥 Downloading and building Nushell {{VERSION}}"
nu {{justfile_directory()}}/scripts/update_nushell_version.nu {{VERSION}}
# Update all plugin dependencies to match Nushell version
[no-cd]
[group('version-update')]
update-plugins VERSION="":
#!/usr/bin/env bash
if [ -z "{{VERSION}}" ]; then
echo "❌ Error: VERSION parameter required"
echo "Usage: just update-plugins 0.108.0"
exit 1
fi
echo "📦 Updating all plugin dependencies to {{VERSION}}"
nu {{justfile_directory()}}/scripts/update_all_plugins.nu {{VERSION}}
# Update plugins to match nushell submodule version (auto-sync)
[no-cd]
[group('version-update')]
sync-plugins:
@echo "🔄 Syncing plugin versions with nushell submodule"
@nu {{justfile_directory()}}/scripts/update_all_plugins.nu sync
# Check plugin version consistency
[no-cd]
[group('version-update')]
check-versions:
@echo "🔍 Checking plugin version consistency"
@nu {{justfile_directory()}}/scripts/update_all_plugins.nu check
# List current plugin versions
[no-cd]
[group('version-update')]
list-versions:
@echo "📋 Plugin Version List"
@nu {{justfile_directory()}}/scripts/update_all_plugins.nu --list
# 📦 DISTRIBUTION CREATION
# Create complete distribution packages (nushell + all plugins)
[no-cd]
[group('version-update')]
create-distribution:
@echo "📦 Creating complete distribution packages"
@nu {{justfile_directory()}}/scripts/create_full_distribution.nu
# Create distributions for all platforms
[no-cd]
[group('version-update')]
create-distribution-all:
@echo "📦 Creating distributions for all platforms"
@nu {{justfile_directory()}}/scripts/create_full_distribution.nu --all-platforms --checksums
# Create plugin-only bin archives
[no-cd]
[group('version-update')]
create-bin-archives:
@echo "📦 Creating bin archives (plugins only)"
@nu {{justfile_directory()}}/scripts/create_full_distribution.nu --bin-only
# Rebuild everything and create fresh distributions
[no-cd]
[group('version-update')]
rebuild-all:
@echo "🔨 Rebuild all and create distributions"
@nu {{justfile_directory()}}/scripts/create_full_distribution.nu rebuild
# Show distribution status
[no-cd]
[group('version-update')]
dist-status:
@echo "📊 Distribution Status"
@nu {{justfile_directory()}}/scripts/create_full_distribution.nu status
# 🔍 FEATURE ANALYSIS
# Analyze available Nushell features
[no-cd]
[group('version-update')]
analyze-features:
@echo "🔍 Analyzing Nushell features"
@nu {{justfile_directory()}}/scripts/analyze_nushell_features.nu --validate
# Show all available features
[no-cd]
[group('version-update')]
show-features:
@echo "📋 All Available Features"
@nu {{justfile_directory()}}/scripts/analyze_nushell_features.nu --show-all
# Show feature dependency tree
[no-cd]
[group('version-update')]
feature-tree FEATURE="mcp":
@echo "🌲 Feature Dependency Tree for {{FEATURE}}"
@nu {{justfile_directory()}}/scripts/analyze_nushell_features.nu tree {{FEATURE}}
# Generate build command with desired features
[no-cd]
[group('version-update')]
build-cmd:
@echo "🔧 Generate Build Command"
@nu {{justfile_directory()}}/scripts/analyze_nushell_features.nu build-cmd
# 🔍 DEPENDENCY AUDITING
# Audit plugin dependencies for version mismatches (advanced analysis)
[no-cd]
[group('version-update')]
audit-versions:
@echo "🔍 Auditing plugin dependency versions"
@nu {{justfile_directory()}}/scripts/audit_crate_dependencies.nu --export
# Audit specific plugin dependency versions
[no-cd]
[group('version-update')]
audit-plugin-versions PLUGIN:
@echo "🔍 Auditing {{PLUGIN}} dependency versions"
@nu {{justfile_directory()}}/scripts/audit_crate_dependencies.nu --plugin {{PLUGIN}}
# Show dependency matrix (which plugins use which crates)
[no-cd]
[group('version-update')]
dependency-matrix:
@echo "📊 Dependency Matrix"
@nu {{justfile_directory()}}/scripts/audit_crate_dependencies.nu matrix
# 🚨 BREAKING CHANGE DETECTION
# Detect breaking changes for current version
[no-cd]
[group('version-update')]
detect-breaking:
@echo "🚨 Detecting breaking changes"
@nu {{justfile_directory()}}/scripts/detect_breaking_changes.nu --scan-plugins --export
# 📥 DOWNLOAD & BUILD
# Download Nushell source from GitHub tags
[no-cd]
[group('version-update')]
download-source VERSION="":
#!/usr/bin/env bash
if [ -z "{{VERSION}}" ]; then
echo "❌ Error: VERSION parameter required"
echo "Usage: just download-source 0.108.0"
exit 1
fi
echo "📥 Downloading Nushell source {{VERSION}}"
nu {{justfile_directory()}}/scripts/download_nushell.nu {{VERSION}}
# Download latest Nushell source
[no-cd]
[group('version-update')]
download-latest:
@echo "📥 Downloading latest Nushell"
@nu {{justfile_directory()}}/scripts/download_nushell.nu --latest
# Build Nushell with all features (MCP, plugin, sqlite, etc.)
[no-cd]
[group('version-update')]
build-nu:
@echo "🔨 Building Nushell with all features"
@nu {{justfile_directory()}}/scripts/build_nushell.nu
# 📊 STATUS & VALIDATION
# Check update system status
[no-cd]
[group('version-update')]
update-status:
@echo "📊 Update System Status"
@nu {{justfile_directory()}}/scripts/complete_update.nu status
# Validate code rules against binary
[no-cd]
[group('version-update')]
validate-code:
@echo "✅ Validating code rules"
@nu {{justfile_directory()}}/scripts/validate_code_rules.nu
# 🧹 CLEANUP
# Clean up temporary update files
[no-cd]
[group('version-update')]
clean-update:
@echo "🧹 Cleaning update temporary files"
@nu {{justfile_directory()}}/scripts/update_nushell_version.nu clean
# 📚 DOCUMENTATION & HELP
# Show version update documentation
[no-cd]
[group('version-update')]
update-docs:
@echo "📚 Version Update Documentation"
@echo ""
@echo "Complete Guide:"
@echo " guides/COMPLETE_VERSION_UPDATE_GUIDE.md"
@echo ""
@echo "Version-Specific Docs:"
@echo " updates/108/ (for each version)"
@echo ""
@echo " • NUSHELL_0.108_UPDATE_SUMMARY.md - Complete summary"
@echo " • MIGRATION_0.108.0.md - Migration guide"
@echo " • NUSHELL_UPDATE_AUTOMATION.md - Automation details"
@echo ""
@echo "Quick Reference:"
@echo " just complete-update 0.108.0 - Update everything"
@echo " just update-latest - Update to latest"
@echo " just update-plugins 0.108.0 - Update plugins only"
@echo " just create-distribution - Create packages"
# Quick reference for version update commands
[no-cd]
[group('version-update')]
update-help:
@echo "🔄 Version Update Quick Reference"
@echo ""
@echo "Complete Workflows:"
@echo " just complete-update 0.108.0 - All-in-one (automatic, no prompts)"
@echo " just complete-update-interactive 0.108.0 - All-in-one (with confirmation)"
@echo " just update-latest - Update to latest release"
@echo " just rebuild-all - Rebuild & redistribute"
@echo ""
@echo "Arguments & Flags:"
@echo " just show-arguments - Show all available commands and modes"
@echo ""
@echo "Step-by-Step:"
@echo " just download-source 0.108.0 - 1. Download source"
@echo " just build-nu - 2. Build nushell"
@echo " just update-plugins 0.108.0 - 3. Update plugins"
@echo " just create-distribution - 4. Create packages"
@echo ""
@echo "Analysis & Validation:"
@echo " just check-versions - Check version consistency"
@echo " just audit-versions - Audit dependency versions"
@echo " just detect-breaking - Find breaking changes"
@echo " just analyze-features - Show available features"
@echo ""
@echo "Status & Info:"
@echo " just update-status - Show update status"
@echo " just dist-status - Show distribution status"
@echo " just list-versions - List plugin versions"
@echo ""
@echo "Documentation:"
@echo " just update-docs - Show documentation paths"
@echo " cat guides/COMPLETE_VERSION_UPDATE_GUIDE.md"
# 📋 ARGUMENTS REFERENCE
# Available flags for version update commands
[no-cd]
[group('version-update')]
show-arguments:
@echo "📋 Version Update Commands - Arguments Reference"
@echo ""
@echo "🚀 AUTOMATIC MODE (Recommended - No Prompts)"
@echo "Usage: just complete-update VERSION"
@echo " Automatically skips all confirmation prompts"
@echo " Example: just complete-update 0.108.0"
@echo ""
@echo "🤔 INTERACTIVE MODE (Ask Before Updates)"
@echo "Usage: just complete-update-interactive VERSION"
@echo " Prompts for confirmation before updating plugins"
@echo " Example: just complete-update-interactive 0.108.0"
@echo ""
@echo "Parameters:"
@echo " VERSION Required. Nushell version to update to (e.g., 0.108.0)"
@echo ""
@echo "7 Steps in Both Modes:"
@echo " Step 1: Download Nushell source from GitHub"
@echo " (skipped if version already exists)"
@echo " Step 2: Analyze available features (MCP, plugin, sqlite, etc.)"
@echo " Step 3: Build Nushell with all features"
@echo " (skipped if already built and version matches)"
@echo " Step 4: Update all plugin dependencies to match version"
@echo " (automatic mode: skips prompt | interactive: asks)"
@echo " Step 5: Build all plugins for distribution"
@echo " Step 6: Create distribution packages"
@echo " Step 7: Validate installation and plugin registration"
@echo ""
@echo "Comparison:"
@echo " Automatic: just complete-update 0.108.0"
@echo " No prompts, ideal for CI/CD"
@echo ""
@echo " Interactive: just complete-update-interactive 0.108.0"
@echo " Asks before updating plugins"
# 🔧 HELPER FUNCTIONS (private recipes)
# Note: Parameter validation is done inline in each recipe that requires VERSION