414 lines
12 KiB
Plaintext
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"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|