From 43b992e3eb5a554dcb8d7c2abcf154ba30eb082e Mon Sep 17 00:00:00 2001 From: Xuwznln <18435084+Xuwznln@users.noreply.github.com> Date: Sun, 12 Oct 2025 20:47:06 +0800 Subject: [PATCH] Update conda-pack-build.yml --- .github/workflows/conda-pack-build.yml | 163 +++++++++++----------- scripts/create_readme.py | 185 +++++++++++++++++++++++++ scripts/get_package_version.py | 68 +++++++++ 3 files changed, 332 insertions(+), 84 deletions(-) create mode 100644 scripts/create_readme.py create mode 100644 scripts/get_package_version.py diff --git a/.github/workflows/conda-pack-build.yml b/.github/workflows/conda-pack-build.yml index f80d6df1..d7be2ef4 100644 --- a/.github/workflows/conda-pack-build.yml +++ b/.github/workflows/conda-pack-build.yml @@ -41,11 +41,13 @@ jobs: defaults: run: - shell: bash -l {0} + # Windows needs PowerShell for conda/mamba, Unix uses bash + shell: ${{ matrix.platform == 'win-64' && 'pwsh' || 'bash -el {0}' }} steps: - name: Check if platform should be built id: should_build + shell: bash run: | if [[ -z "${{ github.event.inputs.platforms }}" ]]; then echo "should_build=true" >> $GITHUB_OUTPUT @@ -86,9 +88,8 @@ jobs: if: steps.should_build.outputs.should_build == 'true' id: msgs_version run: | - INSTALLED_VERSION=$(conda list ros-humble-unilabos-msgs | grep ros-humble-unilabos-msgs | awk '{print $2}') - echo "installed_version=$INSTALLED_VERSION" >> $GITHUB_OUTPUT - echo "Installed ros-humble-unilabos-msgs version: $INSTALLED_VERSION" + echo "Checking installed ros-humble-unilabos-msgs version..." + python scripts/get_package_version.py ros-humble-unilabos-msgs - name: Check for newer ros-humble-unilabos-msgs if: steps.should_build.outputs.should_build == 'true' @@ -149,8 +150,39 @@ jobs: echo "Pack file created:" ls -lh unilab-env-${{ matrix.platform }}.tar.gz - - name: Prepare distribution package (scripts + environment) - if: steps.should_build.outputs.should_build == 'true' + - name: Prepare Windows distribution package + if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' + run: | + Write-Host "==========================================" + Write-Host "Creating distribution package..." + Write-Host "Platform: ${{ matrix.platform }}" + Write-Host "==========================================" + New-Item -ItemType Directory -Force -Path dist-package | Out-Null + + # Copy packed environment + Write-Host "Adding: unilab-env-${{ matrix.platform }}.tar.gz" + Copy-Item unilab-env-${{ matrix.platform }}.tar.gz dist-package/ + + # Copy installation script + Write-Host "Adding: install_unilab.bat" + Copy-Item scripts/install_unilab.bat dist-package/ + + # Copy verification script + Write-Host "Adding: verify_installation.py" + Copy-Item scripts/verify_installation.py dist-package/ + + # Create README using Python script + Write-Host "Creating: README.txt" + python scripts/create_readme.py ${{ matrix.platform }} ${{ github.event.inputs.branch }} dist-package/README.txt + + Write-Host "" + Write-Host "Distribution package contents:" + Get-ChildItem dist-package | Format-Table Name, Length + Write-Host "" + + - name: Prepare Unix/Linux distribution package + if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' + shell: bash run: | echo "==========================================" echo "Creating distribution package..." @@ -162,104 +194,67 @@ jobs: echo "Adding: unilab-env-${{ matrix.platform }}.tar.gz" cp unilab-env-${{ matrix.platform }}.tar.gz dist-package/ - # Copy installation script (platform specific) - if [ "${{ matrix.platform }}" == "win-64" ]; then - echo "Adding: install_unilab.bat" - cp scripts/install_unilab.bat dist-package/ - else - echo "Adding: install_unilab.sh" - cp scripts/install_unilab.sh dist-package/ - chmod +x dist-package/install_unilab.sh - fi + # Copy installation script + echo "Adding: install_unilab.sh" + cp scripts/install_unilab.sh dist-package/ + chmod +x dist-package/install_unilab.sh # Copy verification script echo "Adding: verify_installation.py" cp scripts/verify_installation.py dist-package/ - # Create README + # Create README using Python script echo "Creating: README.txt" - cat > dist-package/README.txt << 'EOFREADME' - UniLabOS Conda-Pack Environment - ================================ - - This package contains a pre-built UniLabOS environment. - - Installation Instructions: - -------------------------- - - Windows: - 1. Extract unilab-pack-win-64.zip - 2. Double-click install_unilab.bat (or run in cmd) - 3. Follow the prompts - - macOS/Linux: - 1. Extract unilab-pack-{platform}.tar.gz - 2. Run: bash install_unilab.sh - 3. Follow the prompts - - The installation script will: - - Automatically find your conda installation - - Extract the environment to conda's envs/unilab directory - - Run conda-unpack to finalize setup - - After installation: - conda activate unilab - python verify_installation.py - - Package Contents: - - install_unilab script (automatic installation) - - unilab-env-{platform}.tar.gz (packed environment) - - verify_installation.py (verification tool) - - README.txt (this file) - - Branch: ${{ github.event.inputs.branch }} - Platform: ${{ matrix.platform }} - Python: 3.11.11 - Build Date: $(date -u +"%Y-%m-%d %H:%M:%S UTC") - EOFREADME + python scripts/create_readme.py ${{ matrix.platform }} ${{ github.event.inputs.branch }} dist-package/README.txt echo "" echo "Distribution package contents:" ls -lh dist-package/ echo "" - - name: Create final distribution archive (ZIP/TAR.GZ) - if: steps.should_build.outputs.should_build == 'true' + - name: Create Windows ZIP archive + if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' + run: | + Write-Host "==========================================" + Write-Host "Creating Windows ZIP archive (ZIP64 support for large files)..." + Write-Host "Archive: unilab-pack-${{ matrix.platform }}.zip" + Write-Host "Contents: install_unilab.bat + unilab-env-${{ matrix.platform }}.tar.gz + extras" + Write-Host "" + + # Use Python script with ZIP64 support instead of PowerShell Compress-Archive + # PowerShell Compress-Archive has a 2GB limitation + python scripts/create_zip_archive.py dist-package unilab-pack-${{ matrix.platform }}.zip + + Write-Host "==========================================" + Write-Host "" + Write-Host "Final package created:" + Get-ChildItem unilab-pack-* | Format-Table Name, Length + Write-Host "" + Write-Host "Users can now:" + Write-Host " 1. Download unilab-pack-${{ matrix.platform }}.zip" + Write-Host " 2. Extract it" + Write-Host " 3. Run install_unilab.bat" + Write-Host "" + + - name: Create Unix/Linux TAR.GZ archive + if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' + shell: bash run: | echo "==========================================" - if [ "${{ matrix.platform }}" == "win-64" ]; then - echo "Creating Windows ZIP archive (ZIP64 support for large files)..." - echo "Archive: unilab-pack-win-64.zip" - echo "Contents: install_unilab.bat + unilab-env-win-64.tar.gz + extras" - echo "" - - # Use Python script with ZIP64 support instead of PowerShell Compress-Archive - # PowerShell Compress-Archive has a 2GB limitation - python scripts/create_zip_archive.py dist-package unilab-pack-${{ matrix.platform }}.zip - else - echo "Creating Unix/Linux TAR.GZ archive..." - echo "Archive: unilab-pack-${{ matrix.platform }}.tar.gz" - echo "Contents: install_unilab.sh + unilab-env-${{ matrix.platform }}.tar.gz + extras" - tar -czf unilab-pack-${{ matrix.platform }}.tar.gz -C dist-package . - fi + echo "Creating Unix/Linux TAR.GZ archive..." + echo "Archive: unilab-pack-${{ matrix.platform }}.tar.gz" + echo "Contents: install_unilab.sh + unilab-env-${{ matrix.platform }}.tar.gz + extras" + tar -czf unilab-pack-${{ matrix.platform }}.tar.gz -C dist-package . echo "==========================================" echo "" echo "Final package created:" ls -lh unilab-pack-* echo "" - - if [ "${{ matrix.platform }}" == "win-64" ]; then - echo "Users can now:" - echo " 1. Download unilab-pack-win-64.zip" - echo " 2. Extract it" - echo " 3. Run install_unilab.bat" - else - echo "Users can now:" - echo " 1. Download unilab-pack-${{ matrix.platform }}.tar.gz" - echo " 2. Extract it: tar -xzf unilab-pack-${{ matrix.platform }}.tar.gz" - echo " 3. Run: bash install_unilab.sh" - fi + echo "Users can now:" + echo " 1. Download unilab-pack-${{ matrix.platform }}.tar.gz" + echo " 2. Extract it: tar -xzf unilab-pack-${{ matrix.platform }}.tar.gz" + echo " 3. Run: bash install_unilab.sh" echo "" - name: Upload distribution package diff --git a/scripts/create_readme.py b/scripts/create_readme.py new file mode 100644 index 00000000..545b13b8 --- /dev/null +++ b/scripts/create_readme.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python3 +""" +Create Distribution Package README +=================================== + +Generate README.txt for conda-pack distribution packages. + +Usage: + python create_readme.py + +Arguments: + platform: Platform identifier (win-64, linux-64, osx-64, osx-arm64) + branch: Git branch name + output_file: Output file path (e.g., dist-package/README.txt) + +Example: + python create_readme.py win-64 dev dist-package/README.txt +""" + +import argparse +import sys +from datetime import datetime, timezone +from pathlib import Path + + +def get_readme_content(platform: str, branch: str) -> str: + """ + Generate README content for the specified platform. + + Args: + platform: Platform identifier + branch: Git branch name + + Returns: + str: README content + """ + # Get current UTC time + build_date = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC") + + # Determine platform-specific content + is_windows = platform == "win-64" + + if is_windows: + archive_ext = "zip" + install_script = "install_unilab.bat" + platform_instructions = """Windows: + 1. Extract unilab-pack-win-64.zip + 2. Double-click install_unilab.bat (or run in cmd) + 3. Follow the prompts""" + else: + archive_ext = "tar.gz" + install_script = "install_unilab.sh" + platform_name = {"linux-64": "linux-64", "osx-64": "osx-64", "osx-arm64": "osx-arm64"}.get(platform, platform) + platform_instructions = f"""macOS/Linux: + 1. Extract unilab-pack-{platform_name}.tar.gz + 2. Run: bash install_unilab.sh + 3. Follow the prompts""" + + # Generate README content + readme = f"""UniLabOS Conda-Pack Environment +================================ + +This package contains a pre-built UniLabOS environment. + +Installation Instructions: +-------------------------- + +{platform_instructions} + +The installation script will: + - Automatically find your conda installation + - Extract the environment to conda's envs/unilab directory + - Run conda-unpack to finalize setup + +After installation: + conda activate unilab + python verify_installation.py + +Verification: +------------- + +The verify_installation.py script will check: + - Python version (3.11.11) + - ROS2 rclpy installation + - UniLabOS installation and dependencies + +If all checks pass, you're ready to use UniLabOS! + +Package Contents: +----------------- + + - {install_script} (automatic installation script) + - unilab-env-{platform}.tar.gz (packed conda environment) + - verify_installation.py (environment verification tool) + - README.txt (this file) + +Build Information: +------------------ + + Branch: {branch} + Platform: {platform} + Python: 3.11.11 + Date: {build_date} + +Troubleshooting: +---------------- + +If installation fails: + + 1. Ensure conda or mamba is installed + Check: conda --version + + 2. Verify you have sufficient disk space + Required: ~5-10 GB after extraction + + 3. Check installation permissions + You need write access to conda's envs directory + + 4. For detailed logs, run the install script from terminal + +For more help: + - Documentation: docs/user_guide/installation.md + - Quick Start: QUICK_START_CONDA_PACK.md + - Issues: https://github.com/dptech-corp/Uni-Lab-OS/issues + +License: +-------- + +UniLabOS is licensed under GPL-3.0-only. +See LICENSE file for details. + +Repository: https://github.com/dptech-corp/Uni-Lab-OS +""" + + return readme + + +def main(): + """Main entry point.""" + parser = argparse.ArgumentParser( + description="Generate README.txt for conda-pack distribution", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + python create_readme.py win-64 dev dist-package/README.txt + python create_readme.py linux-64 main dist-package/README.txt + """, + ) + + parser.add_argument("platform", choices=["win-64", "linux-64", "osx-64", "osx-arm64"], help="Platform identifier") + + parser.add_argument("branch", help="Git branch name") + + parser.add_argument("output_file", help="Output file path") + + args = parser.parse_args() + + try: + # Generate README content + readme_content = get_readme_content(args.platform, args.branch) + + # Create output directory if needed + output_path = Path(args.output_file) + output_path.parent.mkdir(parents=True, exist_ok=True) + + # Write README file + with open(output_path, "w", encoding="utf-8") as f: + f.write(readme_content) + + print(f"✓ README.txt created: {output_path}") + print(f" Platform: {args.platform}") + print(f" Branch: {args.branch}") + + return 0 + + except Exception as e: + print(f"Error creating README: {e}", file=sys.stderr) + import traceback + + traceback.print_exc() + return 1 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/scripts/get_package_version.py b/scripts/get_package_version.py new file mode 100644 index 00000000..f8f68a70 --- /dev/null +++ b/scripts/get_package_version.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +""" +Get Conda Package Version +========================== + +Get the installed version of a conda package and output it for GitHub Actions. + +Usage: + python get_package_version.py + +Example: + python get_package_version.py ros-humble-unilabos-msgs +""" + +import json +import os +import subprocess +import sys + + +def get_package_version(package_name: str) -> str: + """ + Get the installed version of a conda package. + + Args: + package_name: Name of the package to check + + Returns: + str: Version string or 'not-found' + """ + try: + # Use conda list with JSON output for reliable parsing + result = subprocess.run(["conda", "list", package_name, "--json"], capture_output=True, text=True, check=True) + + packages = json.loads(result.stdout) + + if packages: + version = packages[0]["version"] + return version + else: + return "not-found" + + except (subprocess.CalledProcessError, json.JSONDecodeError, KeyError, IndexError) as e: + print(f"Error getting package version: {e}", file=sys.stderr) + return "error" + + +def main(): + """Main entry point.""" + if len(sys.argv) != 2: + print(f"Usage: {sys.argv[0]} ", file=sys.stderr) + sys.exit(1) + + package_name = sys.argv[1] + version = get_package_version(package_name) + + # Output for GitHub Actions + github_output = os.getenv("GITHUB_OUTPUT") + if github_output: + with open(github_output, "a") as f: + f.write(f"installed_version={version}\n") + + # Also print for logs + print(f"Installed {package_name} version: {version}") + + +if __name__ == "__main__": + main()