name: Build Conda-Pack Environment on: workflow_dispatch: inputs: branch: description: '选择要构建的分支' required: true default: 'dev' type: string platforms: description: '选择构建平台 (逗号分隔): linux-64, osx-64, osx-arm64, win-64' required: false default: 'win-64' type: string jobs: build-conda-pack: strategy: fail-fast: false matrix: include: - os: ubuntu-latest platform: linux-64 env_file: unilabos-linux-64.yaml script_ext: sh - os: macos-13 # Intel platform: osx-64 env_file: unilabos-osx-64.yaml script_ext: sh - os: macos-latest # ARM64 platform: osx-arm64 env_file: unilabos-osx-arm64.yaml script_ext: sh - os: windows-latest platform: win-64 env_file: unilabos-win64.yaml script_ext: bat runs-on: ${{ matrix.os }} defaults: run: # Windows uses cmd for better conda/mamba compatibility, Unix uses bash shell: ${{ matrix.platform == 'win-64' && 'cmd /C CALL {0}' || '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 elif [[ "${{ github.event.inputs.platforms }}" == *"${{ matrix.platform }}"* ]]; then echo "should_build=true" >> $GITHUB_OUTPUT else echo "should_build=false" >> $GITHUB_OUTPUT fi - uses: actions/checkout@v4 if: steps.should_build.outputs.should_build == 'true' with: ref: ${{ github.event.inputs.branch }} fetch-depth: 0 - name: Setup Miniforge (with mamba) if: steps.should_build.outputs.should_build == 'true' uses: conda-incubator/setup-miniconda@v3 with: miniforge-version: latest use-mamba: true python-version: '3.11.11' channels: conda-forge,robostack-staging,uni-lab,defaults channel-priority: flexible activate-environment: unilab auto-activate-base: true auto-update-conda: false show-channel-urls: true - name: Install conda-pack, unilabos and dependencies (Windows) if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' run: | echo Installing unilabos and dependencies to unilab environment... echo Using mamba for faster and more reliable dependency resolution... mamba install uni-lab::unilabos conda-pack -c uni-lab -c robostack-staging -c conda-forge -y - name: Install conda-pack, unilabos and dependencies (Unix) if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' shell: bash run: | echo "Installing unilabos and dependencies to unilab environment..." echo "Using mamba for faster and more reliable dependency resolution..." mamba install uni-lab::unilabos conda-pack -c uni-lab -c robostack-staging -c conda-forge -y - name: Get latest ros-humble-unilabos-msgs version (Windows) if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' id: msgs_version_win run: | echo Checking installed ros-humble-unilabos-msgs version... conda list ros-humble-unilabos-msgs for /f "tokens=2" %%i in ('conda list ros-humble-unilabos-msgs --json ^| python -c "import sys, json; pkgs=json.load(sys.stdin); print(pkgs[0]['version'] if pkgs else 'not-found')"') do set VERSION=%%i echo installed_version=%VERSION% >> %GITHUB_OUTPUT% echo Installed ros-humble-unilabos-msgs version: %VERSION% - name: Get latest ros-humble-unilabos-msgs version (Unix) if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' id: msgs_version_unix shell: bash run: | echo "Checking installed ros-humble-unilabos-msgs version..." VERSION=$(conda list ros-humble-unilabos-msgs --json | python -c "import sys, json; pkgs=json.load(sys.stdin); print(pkgs[0]['version'] if pkgs else 'not-found')") echo "installed_version=$VERSION" >> $GITHUB_OUTPUT echo "Installed ros-humble-unilabos-msgs version: $VERSION" - name: Check for newer ros-humble-unilabos-msgs (Windows) if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' run: | echo Checking for available ros-humble-unilabos-msgs versions... mamba search ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge || echo Search completed echo. echo Updating ros-humble-unilabos-msgs to latest version... mamba update ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge -y || echo Already at latest version - name: Check for newer ros-humble-unilabos-msgs (Unix) if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' shell: bash run: | echo "Checking for available ros-humble-unilabos-msgs versions..." mamba search ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge || echo "Search completed" echo "" echo "Updating ros-humble-unilabos-msgs to latest version..." mamba update ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge -y || echo "Already at latest version" - name: Install latest unilabos from source (Windows) if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' run: | echo Uninstalling existing unilabos... pip uninstall unilabos -y || echo unilabos not installed via pip echo Installing unilabos from source (branch: ${{ github.event.inputs.branch }})... pip install . echo Verifying installation... pip show unilabos - name: Install latest unilabos from source (Unix) if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' shell: bash run: | echo "Uninstalling existing unilabos..." pip uninstall unilabos -y || echo "unilabos not installed via pip" echo "Installing unilabos from source (branch: ${{ github.event.inputs.branch }})..." pip install . echo "Verifying installation..." pip show unilabos - name: Display environment info (Windows) if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' run: | echo === Environment Information === conda env list echo. echo === Installed Packages === conda list | findstr /C:"unilabos" /C:"ros-humble-unilabos-msgs" || conda list echo. echo === Python Packages === pip list | findstr unilabos || pip list - name: Display environment info (Unix) if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' shell: bash run: | echo "=== Environment Information ===" conda env list echo "" echo "=== Installed Packages ===" conda list | grep -E "(unilabos|ros-humble-unilabos-msgs)" || conda list echo "" echo "=== Python Packages ===" pip list | grep unilabos || pip list - name: Verify environment integrity (Windows) if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' run: | echo Verifying Python version... python -c "import sys; print(f'Python version: {sys.version}')" echo Verifying unilabos import... python -c "import unilabos; print(f'UniLabOS version: {unilabos.__version__}')" || echo Warning: Could not import unilabos echo Checking critical packages... python -c "import rclpy; print('ROS2 rclpy: OK')" echo Running comprehensive verification script... python scripts\verify_installation.py || echo Warning: Verification script reported issues echo Environment verification complete! - name: Verify environment integrity (Unix) if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' shell: bash run: | echo "Verifying Python version..." python -c "import sys; print(f'Python version: {sys.version}')" echo "Verifying unilabos import..." python -c "import unilabos; print(f'UniLabOS version: {unilabos.__version__}')" || echo "Warning: Could not import unilabos" echo "Checking critical packages..." python -c "import rclpy; print('ROS2 rclpy: OK')" echo "Running comprehensive verification script..." python scripts/verify_installation.py || echo "Warning: Verification script reported issues" echo "Environment verification complete!" - name: Pack conda environment (Windows) if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' run: | echo Packing unilab environment with conda-pack... conda pack -n unilab -o unilab-env-${{ matrix.platform }}.tar.gz --ignore-missing-files echo Pack file created: dir unilab-env-${{ matrix.platform }}.tar.gz - name: Pack conda environment (Unix) if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' shell: bash run: | echo "Packing unilab environment with conda-pack..." conda pack -n unilab -o unilab-env-${{ matrix.platform }}.tar.gz --ignore-missing-files echo "Pack file created:" ls -lh unilab-env-${{ matrix.platform }}.tar.gz - name: Prepare Windows distribution package if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' run: | echo ========================================== echo Creating distribution package... echo Platform: ${{ matrix.platform }} echo ========================================== mkdir dist-package 2>nul || cd . rem Copy packed environment echo Adding: unilab-env-${{ matrix.platform }}.tar.gz copy unilab-env-${{ matrix.platform }}.tar.gz dist-package\ rem Copy installation script echo Adding: install_unilab.bat copy scripts\install_unilab.bat dist-package\ rem Copy verification script echo Adding: verify_installation.py copy scripts\verify_installation.py dist-package\ rem Create README using Python script echo Creating: README.txt python scripts\create_readme.py ${{ matrix.platform }} ${{ github.event.inputs.branch }} dist-package\README.txt echo. echo Distribution package contents: dir /b dist-package echo. - 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..." echo "Platform: ${{ matrix.platform }}" echo "==========================================" mkdir -p dist-package # Copy packed environment echo "Adding: unilab-env-${{ matrix.platform }}.tar.gz" cp unilab-env-${{ matrix.platform }}.tar.gz dist-package/ # 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 using Python script echo "Creating: README.txt" 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: Finalize Windows distribution package if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' run: | echo ========================================== echo Windows distribution package ready echo. echo Package will be uploaded as artifact echo GitHub Actions will automatically create ZIP echo. echo Contents: dir /b dist-package echo. echo Users will download a ZIP containing: echo - install_unilab.bat echo - unilab-env-${{ matrix.platform }}.tar.gz echo - verify_installation.py echo - README.txt echo ========================================== - name: Create Unix/Linux TAR.GZ archive if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' shell: bash run: | echo "==========================================" 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 "" 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 if: steps.should_build.outputs.should_build == 'true' uses: actions/upload-artifact@v4 with: name: unilab-pack-${{ matrix.platform }}-${{ github.event.inputs.branch }} path: dist-package/ retention-days: 90 if-no-files-found: error - name: Display package info (Windows) if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' run: | echo ========================================== echo Build Summary echo ========================================== echo Platform: ${{ matrix.platform }} echo Branch: ${{ github.event.inputs.branch }} echo Python version: 3.11.11 echo. echo Distribution package contents: dir dist-package echo. echo Artifact name: unilab-pack-${{ matrix.platform }}-${{ github.event.inputs.branch }} echo. echo After download, extract the ZIP and run: echo install_unilab.bat echo ========================================== - name: Display package info (Unix) if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' shell: bash run: | echo "==========================================" echo "Build Summary" echo "==========================================" echo "Platform: ${{ matrix.platform }}" echo "Branch: ${{ github.event.inputs.branch }}" echo "Python version: 3.11.11" echo "" echo "Distribution package contents:" ls -lh dist-package/ echo "" echo "Package size (tar.gz):" ls -lh unilab-pack-*.tar.gz echo "" echo "Artifact name: unilab-pack-${{ matrix.platform }}-${{ github.event.inputs.branch }}" echo "" echo "After download:" echo " - Windows/macOS: Extract ZIP, then: tar -xzf unilab-pack-${{ matrix.platform }}.tar.gz" echo " - Linux: Extract ZIP (or download tar.gz directly), run install_unilab.sh" echo "=========================================="