#!/usr/bin/env nu # Main distribution generator - orchestrates complete distribution creation # # Orchestrates: # - Core library preparation # - Platform service compilation # - Configuration bundling # - Documentation generation # - Installation package creation # - Multi-platform distribution assembly use std log def main [ --version: string = "" # Distribution version (auto-detected if empty) --platforms: string = "linux,macos,windows" # Target platforms --variants: string = "complete,minimal" # Distribution variants --output-dir: string = "dist" # Output directory for distributions --build-clean # Clean build before generation --include-sources # Include source code in distribution --compress # Compress final distributions --generate-docs # Generate documentation --parallel-builds # Build platforms in parallel --validate-output # Validate generated distributions --verbose # Enable verbose logging ]: nothing -> record { let repo_root = ($env.PWD | path dirname | path dirname | path dirname) # Detect version if not provided let target_version = if $version == "" { detect_project_version $repo_root } else { $version } let target_platforms = ($platforms | split row "," | each { str trim }) let target_variants = ($variants | split row "," | each { str trim }) let distribution_config = { version: $target_version platforms: $target_platforms variants: $target_variants output_dir: ($output_dir | path expand) build_clean: $build_clean include_sources: $include_sources compress: $compress generate_docs: $generate_docs parallel_builds: $parallel_builds validate_output: $validate_output verbose: $verbose repo_root: $repo_root } log info $"Starting distribution generation with config: ($distribution_config)" # Ensure output directory exists mkdir ($distribution_config.output_dir) let generation_results = [] try { # Phase 1: Preparation let preparation_result = prepare_distribution_environment $distribution_config let generation_results = ($generation_results | append { phase: "preparation", result: $preparation_result }) if $preparation_result.status != "success" { log error $"Distribution preparation failed: ($preparation_result.reason)" exit 1 } # Phase 2: Core Distribution let core_result = generate_core_distribution $distribution_config let generation_results = ($generation_results | append { phase: "core", result: $core_result }) if $core_result.status != "success" { log error $"Core distribution generation failed: ($core_result.reason)" exit 1 } # Phase 3: Platform Services let platform_result = generate_platform_distributions $distribution_config let generation_results = ($generation_results | append { phase: "platform", result: $platform_result }) if $platform_result.status != "success" { log error $"Platform distribution generation failed: ($platform_result.reason)" exit 1 } # Phase 4: Documentation let docs_result = if $distribution_config.generate_docs { generate_distribution_docs $distribution_config } else { { status: "skipped", reason: "documentation generation disabled" } } let generation_results = ($generation_results | append { phase: "documentation", result: $docs_result }) # Phase 5: Assembly let assembly_result = assemble_complete_distributions $distribution_config $generation_results let generation_results = ($generation_results | append { phase: "assembly", result: $assembly_result }) if $assembly_result.status != "success" { log error $"Distribution assembly failed: ($assembly_result.reason)" exit 1 } # Phase 6: Validation let validation_result = if $distribution_config.validate_output { validate_distributions $distribution_config $assembly_result } else { { status: "skipped", reason: "validation disabled" } } let generation_results = ($generation_results | append { phase: "validation", result: $validation_result }) let summary = { version: $distribution_config.version platforms: ($distribution_config.platforms | length) variants: ($distribution_config.variants | length) total_distributions: ($assembly_result.distributions | length) successful_phases: ($generation_results | where {|r| $r.result.status == "success"} | length) output_directory: $distribution_config.output_dir total_size: ($assembly_result.total_size) generation_config: $distribution_config phases: $generation_results } log info $"Distribution generation completed successfully - ($summary.total_distributions) distributions created" return $summary } catch {|err| log error $"Distribution generation failed: ($err.msg)" exit 1 } } # Detect project version from various sources def detect_project_version [repo_root: string]: nothing -> string { cd $repo_root # Try git tags first let git_version = try { let tag = (git describe --tags --exact-match HEAD 2>/dev/null | str trim) if $tag != "" { return ($tag | str replace "^v" "") } let latest = (git describe --tags --abbrev=0 2>/dev/null | str trim) if $latest != "" { return ($latest | str replace "^v" "") } "" } catch { "" } if $git_version != "" { return $git_version } # Try Cargo.toml let cargo_version = try { let cargo_files = (glob **/Cargo.toml --depth 2) if ($cargo_files | length) > 0 { let cargo_data = (open ($cargo_files | get 0)) return $cargo_data.package.version } "" } catch { "" } if $cargo_version != "" { return $cargo_version } # Fallback to date-based version return $"dev-(date now | format date '%Y%m%d')" } # Prepare distribution environment def prepare_distribution_environment [distribution_config: record]: nothing -> record { log info "Preparing distribution environment..." let start_time = (date now) try { # Clean build if requested if $distribution_config.build_clean { log info "Cleaning build environment..." let clean_result = (nu ($distribution_config.repo_root | path join "src" "tools" "build" "clean-build.nu") --scope all) if $distribution_config.verbose { log info $"Clean result: ($clean_result.total_size_cleaned) bytes cleaned" } } # Create distribution directory structure let dist_structure = [ "platform" "core" "config" "kcl" "extensions" "templates" "docs" "tmp" ] for dir in $dist_structure { mkdir ($distribution_config.output_dir | path join $dir) } # Validate dependencies let dependency_check = validate_distribution_dependencies $distribution_config if $dependency_check.missing_dependencies > 0 { return { status: "failed" reason: $"Missing dependencies: ($dependency_check.missing | str join ', ')" duration: ((date now) - $start_time) } } { status: "success" environment_ready: true directory_structure: $dist_structure dependency_check: $dependency_check duration: ((date now) - $start_time) } } catch {|err| { status: "failed" reason: $err.msg duration: ((date now) - $start_time) } } } # Validate distribution dependencies def validate_distribution_dependencies [distribution_config: record]: nothing -> record { let required_tools = [ { name: "nu", command: "nu --version", description: "Nushell shell" } { name: "git", command: "git --version", description: "Git version control" } { name: "cargo", command: "cargo --version", description: "Rust package manager" } { name: "rustc", command: "rustc --version", description: "Rust compiler" } ] let optional_tools = [ { name: "kcl", command: "kcl version", description: "KCL configuration language" } { name: "docker", command: "docker --version", description: "Docker containerization" } { name: "tar", command: "tar --version", description: "Archive creation" } { name: "zip", command: "zip -v", description: "Zip compression" } ] mut available = [] mut missing = [] # Check required tools for tool in $required_tools { let check_result = try { run-external $tool.command err> /dev/null | complete } catch { { exit_code: 1 } } if $check_result.exit_code == 0 { $available = ($available | append $tool.name) } else { $missing = ($missing | append $tool.name) } } # Check optional tools for tool in $optional_tools { let check_result = try { run-external $tool.command err> /dev/null | complete } catch { { exit_code: 1 } } if $check_result.exit_code == 0 { $available = ($available | append $tool.name) } } { required_available: (($required_tools | get name) | where {|name| $name in $available} | length) total_required: ($required_tools | length) optional_available: (($optional_tools | get name) | where {|name| $name in $available} | length) total_optional: ($optional_tools | length) missing_dependencies: ($missing | length) available: $available missing: $missing } } # Generate core distribution def generate_core_distribution [distribution_config: record]: nothing -> record { log info "Generating core distribution..." let start_time = (date now) try { # Use the build system to bundle core components let bundle_result = (nu ($distribution_config.repo_root | path join "src" "tools" "build" "bundle-core.nu") --output-dir ($distribution_config.output_dir | path join "core") --config-dir ($distribution_config.output_dir | path join "config") --validate --compress:$distribution_config.compress --exclude-dev --verbose:$distribution_config.verbose) if $bundle_result.failed > 0 { return { status: "failed" reason: $"Core bundling failed with ($bundle_result.failed) failures" bundle_result: $bundle_result duration: ((date now) - $start_time) } } # Validate KCL schemas let kcl_result = (nu ($distribution_config.repo_root | path join "src" "tools" "build" "validate-kcl.nu") --output-dir ($distribution_config.output_dir | path join "kcl") --format-code --verbose:$distribution_config.verbose) { status: "success" core_bundle: $bundle_result kcl_validation: $kcl_result components_bundled: $bundle_result.successful duration: ((date now) - $start_time) } } catch {|err| { status: "failed" reason: $err.msg duration: ((date now) - $start_time) } } } # Generate platform distributions def generate_platform_distributions [distribution_config: record]: nothing -> record { log info "Generating platform distributions..." let start_time = (date now) try { # Compile platform components for each target platform let platform_results = if $distribution_config.parallel_builds { compile_platforms_parallel $distribution_config } else { compile_platforms_sequential $distribution_config } let successful_platforms = ($platform_results | where status == "success" | length) let total_platforms = ($platform_results | length) if $successful_platforms == 0 { return { status: "failed" reason: "No platforms compiled successfully" platform_results: $platform_results duration: ((date now) - $start_time) } } { status: (if $successful_platforms == $total_platforms { "success" } else { "partial" }) platforms_compiled: $successful_platforms total_platforms: $total_platforms platform_results: $platform_results duration: ((date now) - $start_time) } } catch {|err| { status: "failed" reason: $err.msg duration: ((date now) - $start_time) } } } # Compile platforms in parallel def compile_platforms_parallel [distribution_config: record]: nothing -> list { # For simplicity, using sequential compilation for now # In a real implementation, you might use background processes compile_platforms_sequential $distribution_config } # Compile platforms sequentially def compile_platforms_sequential [distribution_config: record]: nothing -> list { $distribution_config.platforms | each {|platform| compile_single_platform $platform $distribution_config } } # Compile platform components for a single platform def compile_single_platform [platform: string, distribution_config: record]: nothing -> record { log info $"Compiling platform: ($platform)" let start_time = (date now) let target_triple = get_rust_target_triple $platform try { # Compile platform components let compile_result = (nu ($distribution_config.repo_root | path join "src" "tools" "build" "compile-platform.nu") --target $target_triple --release --output-dir ($distribution_config.output_dir | path join "platform") --verbose:$distribution_config.verbose --clean:$distribution_config.build_clean) { platform: $platform target: $target_triple status: (if $compile_result.failed > 0 { "failed" } else { "success" }) compiled_components: $compile_result.successful total_components: $compile_result.total compile_result: $compile_result duration: ((date now) - $start_time) } } catch {|err| { platform: $platform target: $target_triple status: "failed" reason: $err.msg duration: ((date now) - $start_time) } } } # Get Rust target triple for platform def get_rust_target_triple [platform: string]: nothing -> string { match $platform { "linux" => "x86_64-unknown-linux-gnu" "macos" => "x86_64-apple-darwin" "windows" => "x86_64-pc-windows-gnu" _ => $platform # Assume it's already a target triple } } # Generate distribution documentation def generate_distribution_docs [distribution_config: record]: nothing -> record { log info "Generating distribution documentation..." let start_time = (date now) try { let docs_dir = ($distribution_config.output_dir | path join "docs") mkdir $docs_dir # Generate README let readme_content = generate_distribution_readme $distribution_config $readme_content | save ($docs_dir | path join "README.md") # Generate installation guide let install_guide = generate_installation_guide $distribution_config $install_guide | save ($docs_dir | path join "INSTALLATION.md") # Generate changelog let changelog = generate_distribution_changelog $distribution_config $changelog | save ($docs_dir | path join "CHANGELOG.md") # Copy additional documentation copy_project_documentation $distribution_config $docs_dir { status: "success" docs_generated: ["README.md", "INSTALLATION.md", "CHANGELOG.md"] docs_directory: $docs_dir duration: ((date now) - $start_time) } } catch {|err| { status: "failed" reason: $err.msg duration: ((date now) - $start_time) } } } # Generate distribution README def generate_distribution_readme [distribution_config: record]: nothing -> string { $"# Provisioning System v($distribution_config.version) Cloud-native infrastructure provisioning and management system. ## Distribution Contents This distribution includes: - **Platform Binaries**: Core system executables for ($distribution_config.platforms | str join ', ') - **Core Libraries**: Nushell libraries and modules - **Configuration**: Default configuration templates - **KCL Schemas**: Infrastructure as Code definitions - **Documentation**: Installation and usage guides ## Quick Start ### Linux/macOS ```bash sudo ./install.sh ``` ### Windows ```cmd install.bat ``` ### Manual Installation 1. Extract the distribution archive 2. Copy binaries to your system PATH 3. Copy libraries to standard locations 4. Configure system settings ## Getting Started After installation: ```bash provisioning help provisioning version provisioning env ``` ## Documentation - **Installation Guide**: See INSTALLATION.md - **Changelog**: See CHANGELOG.md - **Online Documentation**: https://github.com/your-org/provisioning ## Support For support and issues: - GitHub: https://github.com/your-org/provisioning/issues - Documentation: https://docs.provisioning.example.com ## License This software is licensed under the MIT License. --- Generated on: (date now | format date '%Y-%m-%d %H:%M:%S') Distribution Version: ($distribution_config.version) " } # Generate installation guide def generate_installation_guide [distribution_config: record]: nothing -> string { $"# Installation Guide This guide covers installation of the Provisioning System v($distribution_config.version). ## System Requirements ### Minimum Requirements - Operating System: Linux, macOS, or Windows - Memory: 1GB RAM - Disk Space: 500MB free space - Network: Internet connection for downloads ### Supported Platforms - Linux (x86_64) - macOS (Intel) - Windows (x86_64) ## Installation Methods ### 1. Automated Installation (Recommended) #### Linux/macOS ```bash # Download and extract distribution tar -xzf provisioning-($distribution_config.version)-linux-complete.tar.gz cd provisioning-($distribution_config.version)-linux-complete # Run installer sudo ./install.sh ``` #### Windows ```cmd REM Extract distribution unzip provisioning-($distribution_config.version)-windows-complete.zip cd provisioning-($distribution_config.version)-windows-complete REM Run installer as Administrator install.bat ``` ### 2. Manual Installation #### Step 1: Extract Distribution Extract the distribution archive to a temporary location. #### Step 2: Install Binaries Copy the binaries from `platform/` to your system PATH: **Linux/macOS:** ```bash sudo cp platform/* /usr/local/bin/ sudo chmod +x /usr/local/bin/provisioning-* ``` **Windows:** ```cmd copy platform\\*.exe \"C:\\Program Files\\Provisioning\\bin\\\" ``` #### Step 3: Install Libraries Copy the core libraries: **Linux/macOS:** ```bash sudo mkdir -p /usr/local/lib/provisioning sudo cp -r core/* /usr/local/lib/provisioning/ ``` **Windows:** ```cmd mkdir \"C:\\Program Files\\Provisioning\\lib\" xcopy core\\* \"C:\\Program Files\\Provisioning\\lib\\\" /E /Y ``` #### Step 4: Install Configuration Copy default configuration files: **Linux/macOS:** ```bash sudo mkdir -p /etc/provisioning sudo cp config/* /etc/provisioning/ ``` **Windows:** ```cmd mkdir \"C:\\ProgramData\\Provisioning\" xcopy config\\* \"C:\\ProgramData\\Provisioning\\\" /E /Y ``` ## Verification After installation, verify the system is working: ```bash # Check version provisioning version # Check environment provisioning env # Test help system provisioning help ``` ## Configuration ### Environment Variables - `PROVISIONING_HOME`: Installation directory - `PROVISIONING_CONFIG`: Configuration file path - `PROVISIONING_ENV`: Environment (dev/test/prod) ### Configuration Files - `config.defaults.toml`: System defaults - `config.user.toml`: User-specific settings ## Troubleshooting ### Common Issues 1. **Command not found**: Ensure binaries are in your PATH 2. **Permission denied**: Check file permissions and user privileges 3. **Missing dependencies**: Install required system packages ### Getting Help - Run `provisioning help` for command help - Check logs in the system log directory - Visit https://github.com/your-org/provisioning/issues ## Uninstallation To remove the Provisioning System: **Linux/macOS:** ```bash # Remove binaries sudo rm /usr/local/bin/provisioning-* # Remove libraries sudo rm -rf /usr/local/lib/provisioning # Remove configuration sudo rm -rf /etc/provisioning ``` **Windows:** ```cmd REM Remove installation directory rmdir /S \"C:\\Program Files\\Provisioning\" rmdir /S \"C:\\ProgramData\\Provisioning\" ``` --- For more detailed information, visit the online documentation. " } # Generate distribution changelog def generate_distribution_changelog [distribution_config: record]: nothing -> string { # This would normally generate a changelog from git history $"# Changelog ## v($distribution_config.version) - (date now | format date '%Y-%m-%d') ### New Features - Complete distribution system with multi-platform support - Automated installation scripts for all platforms - Comprehensive configuration management ### Improvements - Enhanced build system with parallel compilation - Better error handling and validation - Improved documentation and examples ### Bug Fixes - Fixed platform-specific compatibility issues - Resolved configuration loading problems - Corrected installation script permissions --- For detailed commit history, see the project repository. " } # Copy project documentation def copy_project_documentation [distribution_config: record, docs_dir: string] { let source_docs = [ ($distribution_config.repo_root | path join "README.md") ($distribution_config.repo_root | path join "LICENSE") ($distribution_config.repo_root | path join "CONTRIBUTING.md") ] for doc_file in $source_docs { if ($doc_file | path exists) { let target_file = ($docs_dir | path join ($doc_file | path basename)) cp $doc_file $target_file } } } # Assemble complete distributions def assemble_complete_distributions [ distribution_config: record generation_results: list ]: nothing -> record { log info "Assembling complete distributions..." let start_time = (date now) try { mut assembled_distributions = [] mut total_size = 0 # Create distributions for each platform-variant combination for platform in $distribution_config.platforms { for variant in $distribution_config.variants { let dist_result = assemble_single_distribution $platform $variant $distribution_config if $dist_result.status == "success" { $assembled_distributions = ($assembled_distributions | append $dist_result) $total_size = $total_size + $dist_result.size } } } # Create source distribution if requested let source_dist = if $distribution_config.include_sources { create_source_distribution $distribution_config } else { { status: "skipped", reason: "source distribution not requested" } } { status: "success" distributions: $assembled_distributions source_distribution: $source_dist total_distributions: ($assembled_distributions | length) total_size: $total_size duration: ((date now) - $start_time) } } catch {|err| { status: "failed" reason: $err.msg duration: ((date now) - $start_time) } } } # Assemble single distribution def assemble_single_distribution [ platform: string variant: string distribution_config: record ]: nothing -> record { let dist_name = $"provisioning-($distribution_config.version)-($platform)-($variant)" let dist_dir = ($distribution_config.output_dir | path join "tmp" $dist_name) try { # Create distribution directory mkdir $dist_dir # Copy components based on variant match $variant { "complete" => { copy_complete_distribution $distribution_config $dist_dir $platform } "minimal" => { copy_minimal_distribution $distribution_config $dist_dir $platform } _ => { return { platform: $platform variant: $variant status: "failed" reason: $"unknown variant: ($variant)" } } } # Create installation scripts create_installation_scripts $dist_dir $platform $distribution_config # Create archive if compression is enabled let final_path = if $distribution_config.compress { create_distribution_archive $dist_dir $distribution_config.output_dir } else { # Move directory to final location let final_dir = ($distribution_config.output_dir | path join $dist_name) mv $dist_dir $final_dir $final_dir } let dist_size = get_directory_size $final_path { platform: $platform variant: $variant status: "success" name: $dist_name path: $final_path size: $dist_size compressed: $distribution_config.compress } } catch {|err| { platform: $platform variant: $variant status: "failed" reason: $err.msg } } } # Copy complete distribution components def copy_complete_distribution [distribution_config: record, dist_dir: string, platform: string] { # Copy all components let components = [ { source: "platform", target: "platform", filter_platform: true } { source: "core", target: "core", filter_platform: false } { source: "config", target: "config", filter_platform: false } { source: "kcl", target: "kcl", filter_platform: false } { source: "docs", target: "docs", filter_platform: false } ] for component in $components { let source_path = ($distribution_config.output_dir | path join $component.source) let target_path = ($dist_dir | path join $component.target) if ($source_path | path exists) { if $component.filter_platform and $component.source == "platform" { copy_platform_binaries $source_path $target_path $platform } else { cp -r $source_path $target_path } } } } # Copy minimal distribution components def copy_minimal_distribution [distribution_config: record, dist_dir: string, platform: string] { # Copy only essential components let essential_components = [ { source: "platform", target: "platform", filter_platform: true } { source: "core", target: "core", filter_platform: false } { source: "config", target: "config", filter_platform: false } ] for component in $essential_components { let source_path = ($distribution_config.output_dir | path join $component.source) let target_path = ($dist_dir | path join $component.target) if ($source_path | path exists) { if $component.filter_platform and $component.source == "platform" { copy_platform_binaries $source_path $target_path $platform } else { cp -r $source_path $target_path } } } } # Copy platform-specific binaries def copy_platform_binaries [source_path: string, target_path: string, platform: string] { mkdir $target_path let all_binaries = (ls $source_path | where type == file | get name) let target_suffix = get_rust_target_triple $platform for binary in $all_binaries { let binary_name = ($binary | path basename) # Check if binary matches the platform if ($binary_name | str contains $target_suffix) or not ($binary_name =~ "(linux|darwin|windows|gnu|msvc)") { let target_name = ($binary_name | str replace $"-($target_suffix)" "") cp $binary ($target_path | path join $target_name) } } } # Create installation scripts def create_installation_scripts [dist_dir: string, platform: string, distribution_config: record] { match $platform { "linux" | "macos" => { let install_script = create_unix_install_script $distribution_config $install_script | save ($dist_dir | path join "install.sh") chmod +x ($dist_dir | path join "install.sh") } "windows" => { let install_script = create_windows_install_script $distribution_config $install_script | save ($dist_dir | path join "install.bat") } _ => { log warning $"No installation script for platform: ($platform)" } } } # Create Unix install script def create_unix_install_script [distribution_config: record]: nothing -> string { $"#!/bin/bash # Provisioning System Installation Script # Version: ($distribution_config.version) set -e INSTALL_DIR=\"/usr/local\" CONFIG_DIR=\"/etc/provisioning\" LIB_DIR=\"$INSTALL_DIR/lib/provisioning\" echo \"Installing Provisioning System ($distribution_config.version)...\" # Check for root privileges if [[ $EUID -ne 0 ]]; then echo \"This script must be run as root (use sudo)\" exit 1 fi # Install binaries echo \"Installing binaries...\" mkdir -p \"$INSTALL_DIR/bin\" cp platform/* \"$INSTALL_DIR/bin/\" chmod +x \"$INSTALL_DIR/bin/\"* # Install libraries echo \"Installing libraries...\" mkdir -p \"$LIB_DIR\" cp -r core/* \"$LIB_DIR/\" # Install configuration echo \"Installing configuration...\" mkdir -p \"$CONFIG_DIR\" cp -r config/* \"$CONFIG_DIR/\" echo \"Installation complete!\" echo \"Run 'provisioning help' to get started.\" " } # Create Windows install script def create_windows_install_script [distribution_config: record]: nothing -> string { $"@echo off REM Provisioning System Installation Script REM Version: ($distribution_config.version) echo Installing Provisioning System ($distribution_config.version)... REM Create directories mkdir \"C:\\Program Files\\Provisioning\\bin\" 2>NUL mkdir \"C:\\Program Files\\Provisioning\\lib\" 2>NUL mkdir \"C:\\ProgramData\\Provisioning\" 2>NUL REM Install binaries echo Installing binaries... xcopy platform\\* \"C:\\Program Files\\Provisioning\\bin\\\" /Y /Q REM Install libraries echo Installing libraries... xcopy core\\* \"C:\\Program Files\\Provisioning\\lib\\\" /Y /Q /S REM Install configuration echo Installing configuration... xcopy config\\* \"C:\\ProgramData\\Provisioning\\\" /Y /Q /S echo Installation complete! echo Add \"C:\\Program Files\\Provisioning\\bin\" to your PATH echo Run 'provisioning-orchestrator --help' to get started. pause " } # Create distribution archive def create_distribution_archive [dist_dir: string, output_dir: string]: nothing -> string { let dist_name = ($dist_dir | path basename) let archive_name = $"($dist_name).tar.gz" let archive_path = ($output_dir | path join $archive_name) let parent_dir = ($dist_dir | path dirname) cd $parent_dir tar -czf $archive_path $dist_name # Clean up directory rm -rf $dist_dir return $archive_path } # Create source distribution def create_source_distribution [distribution_config: record]: nothing -> record { log info "Creating source distribution..." try { let source_name = $"provisioning-($distribution_config.version)-source" let source_dir = ($distribution_config.output_dir | path join "tmp" $source_name) # Create source distribution directory mkdir $source_dir # Copy source files (excluding build artifacts and temporary files) let exclude_patterns = [ "target/" "dist/" "*.tmp" ".git/" "node_modules/" "*.log" ] # This is a simplified copy - in practice, you'd use more sophisticated filtering cp -r ($distribution_config.repo_root | path join "src") ($source_dir | path join "src") cp ($distribution_config.repo_root | path join "README.md") ($source_dir | path join "README.md") cp ($distribution_config.repo_root | path join "LICENSE") ($source_dir | path join "LICENSE") # Create source archive let archive_path = create_distribution_archive $source_dir $distribution_config.output_dir { status: "success" name: $source_name path: $archive_path size: (get_directory_size $archive_path) } } catch {|err| { status: "failed" reason: $err.msg } } } # Validate distributions def validate_distributions [ distribution_config: record assembly_result: record ]: nothing -> record { log info "Validating generated distributions..." let start_time = (date now) try { let validation_results = $assembly_result.distributions | each {|dist| validate_single_distribution $dist $distribution_config } let successful_validations = ($validation_results | where status == "success" | length) let total_validations = ($validation_results | length) { status: (if $successful_validations == $total_validations { "success" } else { "partial" }) validated_distributions: $successful_validations total_distributions: $total_validations validation_results: $validation_results duration: ((date now) - $start_time) } } catch {|err| { status: "failed" reason: $err.msg duration: ((date now) - $start_time) } } } # Validate single distribution def validate_single_distribution [dist: record, distribution_config: record]: nothing -> record { # Use the package validation tool try { let validation_result = (nu ($distribution_config.repo_root | path join "src" "tools" "package" "validate-package.nu") $dist.path --validation-type quick --skip-execution --output-format json --cleanup) { distribution: $dist.name status: (if $validation_result.overall_status == "passed" { "success" } else { "failed" }) validation_result: $validation_result } } catch {|err| { distribution: $dist.name status: "failed" reason: $err.msg } } } # Get directory size def get_directory_size [path: string]: nothing -> int { if not ($path | path exists) { return 0 } let total_size = try { if ($path | path type) == "file" { ls $path | get 0.size } else { find $path -type f | each {|file| ls $file | get 0.size } | math sum } } catch { 0 } return ($total_size | if $in == null { 0 } else { $in }) } # Show distribution status def "main status" [] { let repo_root = ($env.PWD | path dirname | path dirname | path dirname) let version = (detect_project_version $repo_root) let dependency_check = validate_distribution_dependencies { repo_root: $repo_root } { project_version: $version repository: $repo_root supported_platforms: ["linux", "macos", "windows"] supported_variants: ["complete", "minimal"] dependencies: $dependency_check distribution_ready: ($dependency_check.missing_dependencies == 0) } } # Quick distribution generation def "main quick" [ --platform: string = "linux" # Single platform to build --variant: string = "complete" # Distribution variant ] { main --platforms $platform --variants $variant --parallel-builds:false }