Compare commits

...

5 Commits

Author SHA1 Message Date
Xuwznln
e0da1c7217 Fix one-key installation build
Install conda-pack before pack command

Add conda-pack to base when building one-key installer

Fix param error when using mamba run

Try fix one-key build on linux
2025-10-13 03:33:00 +08:00
hh.(SII)
51d3e61723 fix: rename schema field to resource_schema with serialization and validation aliases (#104)
Co-authored-by: ZiWei <131428629+ZiWei09@users.noreply.github.com>
2025-10-13 03:24:20 +08:00
Xuwznln
6b5765bbf3 Complete all one key installation 2025-10-13 03:24:19 +08:00
Xuwznln
eb1f3fbe1c Try fix one-key build on linux 2025-10-13 02:10:05 +08:00
Xuwznln
fb93b1cd94 fix startup env check.
add auto install during one-key installation
2025-10-13 01:59:53 +08:00
4 changed files with 63 additions and 86 deletions

View File

@@ -42,7 +42,7 @@ jobs:
defaults: defaults:
run: run:
# Windows uses cmd for better conda/mamba compatibility, Unix uses bash # Windows uses cmd for better conda/mamba compatibility, Unix uses bash
shell: ${{ matrix.platform == 'win-64' && 'cmd /C CALL {0}' || 'bash -el {0}' }} shell: ${{ matrix.platform == 'win-64' && 'cmd' || 'bash' }}
steps: steps:
- name: Check if platform should be built - name: Check if platform should be built
@@ -73,7 +73,6 @@ jobs:
channels: conda-forge,robostack-staging,uni-lab,defaults channels: conda-forge,robostack-staging,uni-lab,defaults
channel-priority: flexible channel-priority: flexible
activate-environment: unilab activate-environment: unilab
auto-activate-base: true
auto-update-conda: false auto-update-conda: false
show-channel-urls: true show-channel-urls: true
@@ -82,7 +81,7 @@ jobs:
run: | run: |
echo Installing unilabos and dependencies to unilab environment... echo Installing unilabos and dependencies to unilab environment...
echo Using mamba for faster and more reliable dependency resolution... 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 mamba install -n unilab uni-lab::unilabos conda-pack -c uni-lab -c robostack-staging -c conda-forge -y
- name: Install conda-pack, unilabos and dependencies (Unix) - name: Install conda-pack, unilabos and dependencies (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
@@ -90,15 +89,15 @@ jobs:
run: | run: |
echo "Installing unilabos and dependencies to unilab environment..." echo "Installing unilabos and dependencies to unilab environment..."
echo "Using mamba for faster and more reliable dependency resolution..." 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 mamba install -n unilab uni-lab::unilabos conda-pack -c uni-lab -c robostack-staging -c conda-forge -y
- name: Get latest ros-humble-unilabos-msgs version (Windows) - name: Get latest ros-humble-unilabos-msgs version (Windows)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
id: msgs_version_win id: msgs_version_win
run: | run: |
echo Checking installed ros-humble-unilabos-msgs version... echo Checking installed ros-humble-unilabos-msgs version...
conda list ros-humble-unilabos-msgs conda list -n unilab 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 for /f "tokens=2" %%i in ('conda list -n unilab 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_version=%VERSION% >> %GITHUB_OUTPUT%
echo Installed ros-humble-unilabos-msgs version: %VERSION% echo Installed ros-humble-unilabos-msgs version: %VERSION%
@@ -108,7 +107,7 @@ jobs:
shell: bash shell: bash
run: | run: |
echo "Checking installed ros-humble-unilabos-msgs version..." 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')") VERSION=$(conda list -n unilab 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_version=$VERSION" >> $GITHUB_OUTPUT
echo "Installed ros-humble-unilabos-msgs version: $VERSION" echo "Installed ros-humble-unilabos-msgs version: $VERSION"
@@ -119,7 +118,7 @@ jobs:
mamba search ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge || echo Search completed mamba search ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge || echo Search completed
echo. echo.
echo Updating ros-humble-unilabos-msgs to latest version... 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 mamba update -n unilab 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) - name: Check for newer ros-humble-unilabos-msgs (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
@@ -129,65 +128,65 @@ jobs:
mamba search ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge || echo "Search completed" mamba search ros-humble-unilabos-msgs -c uni-lab -c robostack-staging -c conda-forge || echo "Search completed"
echo "" echo ""
echo "Updating ros-humble-unilabos-msgs to latest version..." 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" mamba update -n unilab 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) - name: Install latest unilabos from source (Windows)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: | run: |
echo Uninstalling existing unilabos... echo Uninstalling existing unilabos...
pip uninstall unilabos -y || echo unilabos not installed via pip mamba run -n unilab pip uninstall unilabos -y || echo unilabos not installed via pip
echo Installing unilabos from source (branch: ${{ github.event.inputs.branch }})... echo Installing unilabos from source (branch: ${{ github.event.inputs.branch }})...
pip install . mamba run -n unilab pip install .
echo Verifying installation... echo Verifying installation...
pip show unilabos mamba run -n unilab pip show unilabos
- name: Install latest unilabos from source (Unix) - name: Install latest unilabos from source (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
shell: bash shell: bash
run: | run: |
echo "Uninstalling existing unilabos..." echo "Uninstalling existing unilabos..."
pip uninstall unilabos -y || echo "unilabos not installed via pip" mamba run -n unilab pip uninstall unilabos -y || echo "unilabos not installed via pip"
echo "Installing unilabos from source (branch: ${{ github.event.inputs.branch }})..." echo "Installing unilabos from source (branch: ${{ github.event.inputs.branch }})..."
pip install . mamba run -n unilab pip install .
echo "Verifying installation..." echo "Verifying installation..."
pip show unilabos mamba run -n unilab pip show unilabos
- name: Display environment info (Windows) - name: Display environment info (Windows)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: | run: |
echo === Environment Information === echo === Environment Information ===
conda env list mamba env list
echo. echo.
echo === Installed Packages === echo === Installed Packages ===
conda list | findstr /C:"unilabos" /C:"ros-humble-unilabos-msgs" || conda list mamba list -n unilab | findstr /C:"unilabos" /C:"ros-humble-unilabos-msgs" || mamba list -n unilab
echo. echo.
echo === Python Packages === echo === Python Packages ===
pip list | findstr unilabos || pip list mamba run -n unilab pip list | findstr unilabos || mamba run -n unilab pip list
- name: Display environment info (Unix) - name: Display environment info (Unix)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform != 'win-64'
shell: bash shell: bash
run: | run: |
echo "=== Environment Information ===" echo "=== Environment Information ==="
conda env list mamba env list
echo "" echo ""
echo "=== Installed Packages ===" echo "=== Installed Packages ==="
conda list | grep -E "(unilabos|ros-humble-unilabos-msgs)" || conda list mamba list -n unilab | grep -E "(unilabos|ros-humble-unilabos-msgs)" || mamba list -n unilab
echo "" echo ""
echo "=== Python Packages ===" echo "=== Python Packages ==="
pip list | grep unilabos || pip list mamba run -n unilab pip list | grep unilabos || mamba run -n unilab pip list
- name: Verify environment integrity (Windows) - name: Verify environment integrity (Windows)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: | run: |
echo Verifying Python version... echo Verifying Python version...
python -c "import sys; print(f'Python version: {sys.version}')" mamba run -n unilab python -c "import sys; print(f'Python version: {sys.version}')"
echo Verifying unilabos import... echo Verifying unilabos import...
python -c "import unilabos; print(f'UniLabOS version: {unilabos.__version__}')" || echo Warning: Could not import unilabos mamba run -n unilab python -c "import unilabos; print(f'UniLabOS version: {unilabos.__version__}')" || echo Warning: Could not import unilabos
echo Checking critical packages... echo Checking critical packages...
python -c "import rclpy; print('ROS2 rclpy: OK')" mamba run -n unilab python -c "import rclpy; print('ROS2 rclpy: OK')"
echo Running comprehensive verification script... echo Running comprehensive verification script...
python scripts\verify_installation.py || echo Warning: Verification script reported issues mamba run -n unilab python scripts\verify_installation.py --auto-install || echo Warning: Verification script reported issues
echo Environment verification complete! echo Environment verification complete!
- name: Verify environment integrity (Unix) - name: Verify environment integrity (Unix)
@@ -195,19 +194,20 @@ jobs:
shell: bash shell: bash
run: | run: |
echo "Verifying Python version..." echo "Verifying Python version..."
python -c "import sys; print(f'Python version: {sys.version}')" mamba run -n unilab python -c "import sys; print(f'Python version: {sys.version}')"
echo "Verifying unilabos import..." echo "Verifying unilabos import..."
python -c "import unilabos; print(f'UniLabOS version: {unilabos.__version__}')" || echo "Warning: Could not import unilabos" mamba run -n unilab python -c "import unilabos; print(f'UniLabOS version: {unilabos.__version__}')" || echo "Warning: Could not import unilabos"
echo "Checking critical packages..." echo "Checking critical packages..."
python -c "import rclpy; print('ROS2 rclpy: OK')" mamba run -n unilab python -c "import rclpy; print('ROS2 rclpy: OK')"
echo "Running comprehensive verification script..." echo "Running comprehensive verification script..."
python scripts/verify_installation.py || echo "Warning: Verification script reported issues" mamba run -n unilab python scripts/verify_installation.py --auto-install || echo "Warning: Verification script reported issues"
echo "Environment verification complete!" echo "Environment verification complete!"
- name: Pack conda environment (Windows) - name: Pack conda environment (Windows)
if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64' if: steps.should_build.outputs.should_build == 'true' && matrix.platform == 'win-64'
run: | run: |
echo Packing unilab environment with conda-pack... echo Packing unilab environment with conda-pack...
mamba install conda-pack -c conda-forge -y
conda pack -n unilab -o unilab-env-${{ matrix.platform }}.tar.gz --ignore-missing-files conda pack -n unilab -o unilab-env-${{ matrix.platform }}.tar.gz --ignore-missing-files
echo Pack file created: echo Pack file created:
dir unilab-env-${{ matrix.platform }}.tar.gz dir unilab-env-${{ matrix.platform }}.tar.gz
@@ -217,6 +217,7 @@ jobs:
shell: bash shell: bash
run: | run: |
echo "Packing unilab environment with conda-pack..." echo "Packing unilab environment with conda-pack..."
mamba install conda-pack -c conda-forge -y
conda pack -n unilab -o unilab-env-${{ matrix.platform }}.tar.gz --ignore-missing-files conda pack -n unilab -o unilab-env-${{ matrix.platform }}.tar.gz --ignore-missing-files
echo "Pack file created:" echo "Pack file created:"
ls -lh unilab-env-${{ matrix.platform }}.tar.gz ls -lh unilab-env-${{ matrix.platform }}.tar.gz
@@ -283,46 +284,6 @@ jobs:
ls -lh dist-package/ ls -lh dist-package/
echo "" 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 - name: Upload distribution package
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -365,12 +326,8 @@ jobs:
echo "Distribution package contents:" echo "Distribution package contents:"
ls -lh dist-package/ ls -lh dist-package/
echo "" 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 "Artifact name: unilab-pack-${{ matrix.platform }}-${{ github.event.inputs.branch }}"
echo "" echo ""
echo "After download:" echo "After download:"
echo " - Windows/macOS: Extract ZIP, then: tar -xzf unilab-pack-${{ matrix.platform }}.tar.gz" echo " install_unilab.sh"
echo " - Linux: Extract ZIP (or download tar.gz directly), run install_unilab.sh"
echo "==========================================" echo "=========================================="

View File

@@ -8,7 +8,10 @@ This script verifies that UniLabOS and its dependencies are correctly installed.
Run this script after installing the conda-pack environment to ensure everything works. Run this script after installing the conda-pack environment to ensure everything works.
Usage: Usage:
python verify_installation.py python verify_installation.py [--auto-install]
Options:
--auto-install Automatically install missing packages
Or in the conda environment: Or in the conda environment:
conda activate unilab conda activate unilab
@@ -17,14 +20,15 @@ Usage:
import sys import sys
import os import os
import argparse
# IMPORTANT: Set UTF-8 encoding BEFORE any other imports # IMPORTANT: Set UTF-8 encoding BEFORE any other imports
# This ensures all subsequent imports (including unilabos) can output UTF-8 characters # This ensures all subsequent imports (including unilabos) can output UTF-8 characters
if sys.platform == "win32": if sys.platform == "win32":
# Method 1: Reconfigure stdout/stderr to use UTF-8 with error handling # Method 1: Reconfigure stdout/stderr to use UTF-8 with error handling
try: try:
sys.stdout.reconfigure(encoding="utf-8", errors="replace") sys.stdout.reconfigure(encoding="utf-8", errors="replace") # type: ignore
sys.stderr.reconfigure(encoding="utf-8", errors="replace") sys.stderr.reconfigure(encoding="utf-8", errors="replace") # type: ignore
except (AttributeError, OSError): except (AttributeError, OSError):
pass pass
@@ -49,7 +53,7 @@ CHECK_MARK = "[OK]"
CROSS_MARK = "[FAIL]" CROSS_MARK = "[FAIL]"
def check_package(package_name: str, display_name: str = None) -> bool: def check_package(package_name: str, display_name: str | None = None) -> bool:
""" """
Check if a package can be imported. Check if a package can be imported.
@@ -87,9 +91,25 @@ def check_python_version() -> bool:
def main(): def main():
"""Run all verification checks.""" """Run all verification checks."""
# Parse command line arguments
parser = argparse.ArgumentParser(
description="Verify UniLabOS installation",
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument(
"--auto-install",
action="store_true",
help="Automatically install missing packages",
)
args = parser.parse_args()
print("=" * 60) print("=" * 60)
print("UniLabOS Installation Verification") print("UniLabOS Installation Verification")
print("=" * 60) print("=" * 60)
if args.auto_install:
print("Mode: Auto-install missing packages")
else:
print("Mode: Verification only")
print() print()
all_passed = True all_passed = True
@@ -113,14 +133,16 @@ def main():
print(f" {CHECK_MARK} UniLabOS installed") print(f" {CHECK_MARK} UniLabOS installed")
# Check environment without auto-install (verification only) # Check environment with optional auto-install
# Set show_details=False to suppress detailed Chinese output that may cause encoding issues # Set show_details=False to suppress detailed Chinese output that may cause encoding issues
env_check_passed = check_environment(auto_install=False, show_details=False) env_check_passed = check_environment(auto_install=args.auto_install, show_details=False)
if env_check_passed: if env_check_passed:
print(f" {CHECK_MARK} All required packages available") print(f" {CHECK_MARK} All required packages available")
else: else:
print(f" {CROSS_MARK} Some optional packages are missing") print(f" {CROSS_MARK} Some optional packages are missing")
if not args.auto_install:
print(" Hint: Run with --auto-install to automatically install missing packages")
except ImportError: except ImportError:
print(f" {CROSS_MARK} UniLabOS not installed") print(f" {CROSS_MARK} UniLabOS not installed")
all_passed = False all_passed = False

View File

@@ -11,18 +11,14 @@ from typing import Dict, Any, List
import networkx as nx import networkx as nx
import yaml import yaml
from unilabos.ros.nodes.resource_tracker import ResourceTreeSet, ResourceDict
# 首先添加项目根目录到路径 # 首先添加项目根目录到路径
current_dir = os.path.dirname(os.path.abspath(__file__)) current_dir = os.path.dirname(os.path.abspath(__file__))
unilabos_dir = os.path.dirname(os.path.dirname(current_dir)) unilabos_dir = os.path.dirname(os.path.dirname(current_dir))
if unilabos_dir not in sys.path: if unilabos_dir not in sys.path:
sys.path.append(unilabos_dir) sys.path.append(unilabos_dir)
from unilabos.config.config import load_config, BasicConfig, HTTPConfig
from unilabos.utils.banner_print import print_status, print_unilab_banner from unilabos.utils.banner_print import print_status, print_unilab_banner
from unilabos.resources.graphio import modify_to_backend_format from unilabos.config.config import load_config, BasicConfig, HTTPConfig
def load_config_from_file(config_path): def load_config_from_file(config_path):
if config_path is None: if config_path is None:
@@ -268,6 +264,8 @@ def main():
from unilabos.app.web import http_client from unilabos.app.web import http_client
from unilabos.app.web import start_server from unilabos.app.web import start_server
from unilabos.app.register import register_devices_and_resources from unilabos.app.register import register_devices_and_resources
from unilabos.resources.graphio import modify_to_backend_format
from unilabos.ros.nodes.resource_tracker import ResourceTreeSet, ResourceDict
# 显示启动横幅 # 显示启动横幅
print_unilab_banner(args_dict) print_unilab_banner(args_dict)

View File

@@ -49,7 +49,7 @@ class ResourceDict(BaseModel):
uuid: str = Field(description="Resource UUID") uuid: str = Field(description="Resource UUID")
name: str = Field(description="Resource name") name: str = Field(description="Resource name")
description: str = Field(description="Resource description", default="") description: str = Field(description="Resource description", default="")
schema: Dict[str, Any] = Field(description="Resource schema", default_factory=dict) resource_schema: Dict[str, Any] = Field(description="Resource schema", default_factory=dict, serialization_alias="schema", validation_alias="schema")
model: Dict[str, Any] = Field(description="Resource model", default_factory=dict) model: Dict[str, Any] = Field(description="Resource model", default_factory=dict)
icon: str = Field(description="Resource icon", default="") icon: str = Field(description="Resource icon", default="")
parent_uuid: Optional["str"] = Field(description="Parent resource uuid", default=None) # 先设定parent_uuid parent_uuid: Optional["str"] = Field(description="Parent resource uuid", default=None) # 先设定parent_uuid