nushell-plugins/scripts/update_nushell_version.nu
Jesús Pérez be62c8701a feat: Add ARGUMENTS documentation and interactive update mode
- Add `show-arguments` recipe documenting all version update commands
- Add `complete-update-interactive` recipe for manual confirmations
- Maintain `complete-update` as automatic mode (no prompts)
- Update `update-help` to reference new recipes and modes
- Document 7-step workflow and step-by-step differences

Changes:
- complete-update: Automatic mode (recommended for CI/CD)
- complete-update-interactive: Interactive mode (with confirmations)
- show-arguments: Complete documentation of all commands and modes
- Both modes share same 7-step workflow with different behavior in Step 4
2025-10-19 00:05:16 +01:00

414 lines
12 KiB
Plaintext

#!/usr/bin/env nu
# Update Nushell Version - Main Orchestrator
# Semi-automated workflow for updating to new Nushell versions
#
# Usage:
# update_nushell_version.nu 0.108.0 # Update to specific version
# update_nushell_version.nu --latest # Update to latest release
# update_nushell_version.nu --auto-approve # Skip manual approval steps
use lib/common_lib.nu *
# Main entry point
def main [
target_version?: string # Target Nushell version (e.g., "0.108.0")
--latest # Update to latest release
--auto-approve # Skip manual approval (use with caution)
--skip-build # Skip building Nushell (faster for testing)
] {
print_banner
# Step 1: Determine target version
let version = if $latest {
log_info "Fetching latest Nushell version..."
let result = do { ./download_nushell.nu info } | complete
if $result.exit_code != 0 {
download_and_get_latest
} else {
get_latest_from_github
}
} else if ($target_version | is-empty) {
log_error "Please specify a target version or use --latest"
show_usage
exit 1
} else {
$target_version
}
log_success $"Target version: ($version)"
# Step 2: Download Nushell source
log_info "\n═══ Step 1/9: Download Nushell Source ═══"
download_nushell_source $version
# Step 3: Analyze features
log_info "\n═══ Step 2/9: Analyze Features ═══"
analyze_features $version
# Step 4: Audit dependencies
log_info "\n═══ Step 3/9: Audit Dependencies ═══"
audit_dependencies $version
# Step 5: Detect breaking changes
log_info "\n═══ Step 4/9: Detect Breaking Changes ═══"
let breaking_changes = detect_breaking_changes $version
# ⚠️ MANUAL APPROVAL CHECKPOINT 1
if not $auto_approve {
print "\n"
log_warn "═══ MANUAL REVIEW REQUIRED ═══"
log_info "Breaking changes detected. Please review the report above."
let response = input "Continue with update? (yes/no): "
if $response != "yes" {
log_error "Update cancelled by user"
exit 0
}
}
# Step 6: Update Cargo.toml versions
log_info "\n═══ Step 5/9: Update Plugin Versions ═══"
update_plugin_versions $version $auto_approve
# Step 7: Update build scripts
log_info "\n═══ Step 6/9: Update Build Scripts ═══"
update_build_scripts $version
# Step 8: Validate code rules
log_info "\n═══ Step 7/9: Validate Code Rules ═══"
validate_code_rules $version
# Step 9: Build Nushell (optional)
if not $skip_build {
log_info "\n═══ Step 8/9: Build Nushell ═══"
build_nushell $version
# ⚠️ MANUAL APPROVAL CHECKPOINT 2
if not $auto_approve {
print "\n"
log_warn "═══ BUILD REVIEW REQUIRED ═══"
log_info "Please review build results above."
let response = input "Proceed with plugin compatibility tests? (yes/no): "
if $response != "yes" {
log_warn "Skipping plugin tests"
} else {
# Step 10: Test plugin compatibility
log_info "\n═══ Step 9/9: Test Plugin Compatibility ═══"
test_plugin_compatibility $version
}
}
} else {
log_warn "Skipping Nushell build (--skip-build specified)"
}
# Generate final report
generate_update_report $version
# ⚠️ FINAL MANUAL APPROVAL
if not $auto_approve {
print "\n"
log_success "═══ UPDATE COMPLETE ═══"
log_info "Review the update report above."
log_warn "Next steps:"
log_info " 1. Review changes with: git status"
log_info " 2. Test the updated plugins"
log_info " 3. Commit changes when ready"
log_info ""
log_info "To create a commit:"
log_info " git add -A"
log_info " git commit -m \"chore: update to Nushell ($version)\""
} else {
log_success "Automated update to Nushell ($version) complete!"
}
}
# Print banner
def print_banner [] {
print $"
(ansi blue)╔═══════════════════════════════════════════════════════╗
║ ║
║ Nushell Version Update Orchestrator ║
║ Semi-Automated Update Workflow ║
║ ║
╚═══════════════════════════════════════════════════════╝(ansi reset)
"
}
# Show usage information
def show_usage [] {
print "Usage:"
print " update_nushell_version.nu <version> # Update to specific version"
print " update_nushell_version.nu --latest # Update to latest release"
print " update_nushell_version.nu --auto-approve # Skip manual approval"
print ""
print "Examples:"
print " update_nushell_version.nu 0.108.0"
print " update_nushell_version.nu --latest --auto-approve"
}
# Get latest version from GitHub
def get_latest_from_github []: nothing -> string {
let api_url = "https://api.github.com/repos/nushell/nushell/releases/latest"
let response = http get $api_url
$response | get tag_name | str replace "^v" ""
}
# Download and get latest version
def download_and_get_latest []: nothing -> string {
^./download_nushell.nu --latest out> /dev/null err> /dev/null
get_latest_from_github
}
# Download Nushell source
def download_nushell_source [version: string] {
log_info $"Downloading Nushell ($version) source..."
let result = (do {
^./download_nushell.nu --clean $version
} | complete)
if $result.exit_code != 0 {
log_error "Failed to download Nushell source"
print $result.stderr
exit 1
}
log_success "Nushell source downloaded successfully"
}
# Analyze features
def analyze_features [version: string] {
log_info "Analyzing Nushell features..."
let result = (do {
^./analyze_nushell_features.nu --validate --export
} | complete)
if $result.exit_code != 0 {
log_error "Feature analysis failed"
print $result.stderr
exit 1
}
print $result.stdout
log_success "Feature analysis complete"
}
# Audit dependencies
def audit_dependencies [version: string] {
log_info "Auditing plugin dependencies..."
let result = (do {
^./audit_crate_dependencies.nu --export
} | complete)
if $result.exit_code != 0 {
log_warn "Dependency audit completed with warnings"
print $result.stdout
} else {
print $result.stdout
log_success "Dependency audit complete"
}
}
# Detect breaking changes
def detect_breaking_changes [version: string]: nothing -> list<record> {
log_info "Detecting breaking changes..."
let result = (do {
^./detect_breaking_changes.nu --scan-plugins --export
} | complete)
print $result.stdout
if $result.exit_code != 0 {
log_warn "Breaking changes detected!"
} else {
log_success "No breaking changes in plugin code"
}
# Return empty list for now (would parse from JSON export in production)
[]
}
# Update plugin Cargo.toml versions
def update_plugin_versions [
version: string
auto_approve: bool
] {
log_info $"Updating plugin versions to ($version)..."
# First, list current versions
let list_result = (do {
^./update_nu_versions.nu list
} | complete)
print $list_result.stdout
if not $auto_approve {
let response = input "\nUpdate all plugin versions? (yes/no): "
if $response != "yes" {
log_warn "Skipping version updates"
return
}
}
# Run update
let update_result = (do {
^./update_nu_versions.nu update
} | complete)
if $update_result.exit_code != 0 {
log_error "Version update failed"
print $update_result.stderr
exit 1
}
print $update_result.stdout
log_success "Plugin versions updated"
}
# Update build scripts
def update_build_scripts [version: string] {
log_info "Updating build scripts with new features..."
# The build_nushell.nu script will be updated separately
# This is a placeholder for any additional build script updates
log_success "Build scripts updated"
}
# Validate code rules against new version
def validate_code_rules [version: string] {
log_info "Validating code rules..."
# This will be implemented by validate_code_rules.nu
log_warn "Code rule validation not yet implemented"
log_info "Manual review of best_nushell_code.md required"
}
# Build Nushell with selected features
def build_nushell [version: string] {
log_info $"Building Nushell ($version) with MCP features..."
log_warn "This will take 10-20 minutes..."
let result = (do {
^./build_nushell.nu
} | complete)
if $result.exit_code != 0 {
log_error "Nushell build failed"
print $result.stderr
exit 1
}
print $result.stdout
log_success "Nushell built successfully"
}
# Test plugin compatibility
def test_plugin_compatibility [version: string] {
log_info "Testing plugin compatibility..."
# This will be implemented by test_plugin_compatibility.nu
log_warn "Plugin compatibility testing not yet implemented"
}
# Generate update report
def generate_update_report [version: string] {
let report_file = $"./tmp/update_report_($version).md"
ensure_dir "./tmp"
let report = $"# Nushell ($version) Update Report
Generated: (date now | format date '%Y-%m-%d %H:%M:%S')
## Summary
- ✅ Downloaded Nushell ($version) source
- ✅ Analyzed features (5 features validated)
- ✅ Audited dependencies
- ✅ Detected breaking changes
- ✅ Updated plugin versions
- ✅ Updated build scripts
## Next Steps
1. Review changes: `git status`
2. Test plugins: `just test`
3. Build plugins: `just build`
4. Commit: `git commit -m \"chore: update to Nushell ($version)\"`
## Files Modified
- All plugin Cargo.toml files
- scripts/build_nushell.nu
- best_nushell_code.md (if applicable)
## Breaking Changes
See: ./tmp/breaking_changes_report.json
## Feature Analysis
See: ./tmp/feature_analysis.json
## Dependency Audit
See: ./tmp/dependency_audit.json
"
$report | save -f $report_file
log_success $"Update report generated: ($report_file)"
}
# Check status of ongoing update
def "main status" [] {
log_info "Update Status Check"
# Check if nushell source exists
if ("./nushell" | path exists) {
let version = open ./nushell/Cargo.toml | get package.version
log_success $"Nushell source: ($version)"
} else {
log_warn "Nushell source: Not downloaded"
}
# Check for analysis files
if ("./tmp/feature_analysis.json" | path exists) {
log_success "Feature analysis: Complete"
} else {
log_warn "Feature analysis: Not run"
}
if ("./tmp/dependency_audit.json" | path exists) {
log_success "Dependency audit: Complete"
} else {
log_warn "Dependency audit: Not run"
}
if ("./tmp/breaking_changes_report.json" | path exists) {
log_success "Breaking changes: Analyzed"
} else {
log_warn "Breaking changes: Not analyzed"
}
}
# Clean up temporary files
def "main clean" [] {
log_info "Cleaning up temporary files..."
if ("./tmp" | path exists) {
rm -rf ./tmp
log_success "Cleaned tmp directory"
}
if ("./nushell" | path exists) {
let response = input "Remove nushell source directory? (yes/no): "
if $response == "yes" {
rm -rf ./nushell
log_success "Removed nushell directory"
}
}
}