Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2ba2d8a
feat(pixi): add RoboStack Jazzy workspace foundation
charlesmadjeri Aug 30, 2026
9c7453f
refactor(launcher): run install and launch through Pixi
charlesmadjeri Aug 30, 2026
7210ce3
chore(docker): remove Docker, add Pixi CI and tests
charlesmadjeri Aug 30, 2026
42f2b74
evol(windows,docs): update Windows support and documentation
charlesmadjeri Aug 30, 2026
a56f754
refactor(launcher): split into package and preserve services on core …
charlesmadjeri Aug 31, 2026
6a06bef
fix(windows): update launcher parsing
Mael-RABOT Aug 31, 2026
b0f7d80
Merge pull request #38 from Sentience-Robotics/cma/refactor-launcher-…
charlesmadjeri Aug 31, 2026
e425b07
Merge pull request #39 from Sentience-Robotics/cma/chore-docker-remov…
charlesmadjeri Aug 31, 2026
7b283b9
Merge pull request #40 from Sentience-Robotics/cma/evol-windows-docs
charlesmadjeri Aug 31, 2026
a979c35
Merge pull request #42 from Sentience-Robotics/cma/refactor-launcher-…
charlesmadjeri Aug 31, 2026
4f15232
fix(pixi): address PR review — docs, CI test, drop audio_common
charlesmadjeri Aug 31, 2026
b936f57
fix(docs): remvoe useless comments or docs
charlesmadjeri Aug 31, 2026
bc7d4ed
fix(pixi): enable Gazebo ogre2 rendering on Jetson via host GL env
Aug 31, 2026
cff7276
fix(pixi): centralize Jetson detection in launcher.platform
charlesmadjeri Aug 31, 2026
0151e7a
Merge pull request #43 from Sentience-Robotics/cma/fix-pixi-refacto
charlesmadjeri Sep 1, 2026
10f4eb6
Merge pull request #44 from Sentience-Robotics/cma/fix-pixi-jetson-gpu
charlesmadjeri Sep 1, 2026
8abc026
Merge pull request #37 from Sentience-Robotics/cma/feat-pixi-foundation
charlesmadjeri Sep 1, 2026
b4c5709
Fix Pixi - Windows & macOS (#46)
Arcod7 Sep 1, 2026
4db4c23
fix: dev branch for control panel
Arcod7 Sep 1, 2026
7fb1c99
Fix pixi regressions (#49)
Arcod7 Sep 2, 2026
f0587fd
fix: config repos.json
Arcod7 Sep 2, 2026
b1c9f87
fix: readme update (#52)
Arcod7 Sep 2, 2026
f04a618
Windows entry point, visualisation-only sim, and windows/ cleanup (#53)
Arcod7 Sep 2, 2026
622f659
fix(launcher): keep the TUI responsive while status probes run (#54)
Arcod7 Sep 2, 2026
9426f2a
fix: scope DDS discovery to the local host (#55)
Arcod7 Sep 2, 2026
85e6322
fix(tests): guard the POSIX-only status probe tests on Windows
Arcod7 Sep 2, 2026
b96aa06
fix(windows): scope DDS discovery on the Windows entry point (#57)
Arcod7 Sep 3, 2026
30e064b
feat(launcher): one Control Center per host, and recover a lost one (…
Arcod7 Sep 3, 2026
10a2cf2
feat(launcher): prune ros2 logs older than a week on exit (#60)
Arcod7 Sep 3, 2026
c487672
feat(ci): assert the core bringup produces a usable ROS graph (#56)
Arcod7 Sep 3, 2026
914f145
feat(launcher): show which readiness milestone core is waiting on (#58)
Arcod7 Sep 3, 2026
144a6c3
fix: formatting
Arcod7 Sep 3, 2026
b510259
hotfix(script): no interaction on install script
Mael-RABOT Sep 3, 2026
af2400c
Merge pull request #61 from Sentience-Robotics/mra/hotfix-install-prompt
Mael-RABOT Sep 3, 2026
9549a44
hotfix(ci): Skip windows TUI tests and run CI without gazebo (#62)
Arcod7 Sep 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
PORT_ROSBRIDGE=9090
PORT_CONTROL_PANEL=4004

# DDS discovery (scripts/dds_env.sh). macOS defaults to localhost-only unicast
# because multicast needs a Local Network permission tmux never gets.
# LUCY_DDS_LOCALHOST=0
# LUCY_DDS_INTERFACE=192.168.1.5
# LUCY_DDS_PEERS=hostA,hostB
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.sh text eol=lf
*.bash text eol=lf
265 changes: 68 additions & 197 deletions .github/workflows/install-and-launch.yml
Original file line number Diff line number Diff line change
@@ -1,236 +1,107 @@
# Full workspace install (clone + Docker image + rosdep + colcon + yarn) plus a
# non-interactive launch smoke test, on both x86_64 and ARM64 GitHub-hosted runners.
#
# - DEV=false -> install.sh uses `url_https` from config/repos.json (sub-repos are public).
# - CI=true -> install.sh skips the host `xhost` check (no GUI on runners).
# - variant=arm runs on `ubuntu-24.04-arm` with `./install.sh --arm`; the built image
# is then verified to be linux/arm64 (linux/amd64 for the default variant).
# - Runner OS (22.04 or 24.04) is only the CI host. ROS 2 Jazzy always runs inside
# Noble-based images (`ubuntu:24.04` + `ros-jazzy-*` packages; tagged `lucy_ros2:jazzy`).
# - `ubuntu-24.04-arm` is GitHub's hosted ARM64 runner label; there is no 22.04-arm
# standard runner. The container OS stays Noble (24.04) regardless.
# - The launch smoke test uses `./launch_lucy.sh --headless <command>`, which runs a
# single command inside the container (no control panel, no auto Gazebo/RViz).

name: Install, Launch & Release
# - DEV=false -> install.py uses url_https from config/repos.json.
# - python3 install.py --skip-build clones sub-repos; colcon build runs via pixi run build.

name: Install, Build & Test

on:
workflow_dispatch:
push:
branches: [master, dev]
tags:
- 'v*' # Run on version tags like v1.0, v2.3.4
- 'v*'
pull_request:
branches: [master, dev]

permissions:
contents: read

jobs:
install-and-launch:
pixi-install-build-test:
name: Pixi install & build (${{ matrix.runner }})
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.variant }}
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.runner }}
cancel-in-progress: true
runs-on: ${{ matrix.runner }}
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
include:
- variant: default
runner: ubuntu-latest
use_arm_install: false
expected_arch: linux/amd64
- variant: arm
runner: ubuntu-24.04-arm
use_arm_install: true
expected_arch: linux/arm64
- runner: ubuntu-latest
pixi_platform: linux-64
- runner: ubuntu-24.04-arm
pixi_platform: linux-aarch64
- runner: macos-latest
pixi_platform: osx-arm64
- runner: windows-latest
pixi_platform: win-64
env:
DEV: "false"
CI: "true"
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

# Make sure no committed/local .env can flip DEV back to true at install time.
- name: Drop workspace .env if present
run: rm -f .env .env.local || true

# Docker Hub metadata/pull flakes (i/o timeout) fail `docker build` before
# any Dockerfile layer runs. Pre-pull with retries so the build reuses cache.
- name: Pre-pull base images (retry on Hub flakes)
run: |
pull_with_retry() {
image="$1"
for attempt in 1 2 3 4 5; do
if docker pull "$image"; then
return 0
fi
echo "docker pull ${image} failed (attempt ${attempt}/5), retrying..."
sleep $((attempt * 15))
done
return 1
}
pull_with_retry ubuntu:24.04

- name: Install (clone + Docker image + rosdep + colcon + yarn)
run: |
chmod +x install.sh launch_lucy.sh
if [ "${{ matrix.use_arm_install }}" = true ]; then
./install.sh --arm
else
./install.sh
fi

- name: Verify Lucy image architecture
run: |
osarch=$(docker image inspect lucy_ros2:jazzy --format '{{.Os}}/{{.Architecture}}')
echo "lucy_ros2:jazzy -> ${osarch}"
if [ "${osarch}" != "${{ matrix.expected_arch }}" ]; then
echo "::error::Expected ${{ matrix.expected_arch }} after ./install.sh on ${{ matrix.runner }}, got ${osarch}"
exit 1
fi

# Single command in the container -> bypasses the control-panel / Gazebo / RViz auto-launch.
- name: Launch smoke test (headless, no TTY)
run: ./launch_lucy.sh --headless ros2 doctor --report

# Windows-specific CI. NOTE: GitHub-hosted Windows runners cannot run Linux
# containers (no Hyper-V/nested virtualization, no WSL2), so the heavy install
# step (docker build of the ROS image + colcon) CANNOT run here — that is
# covered for both amd64/arm64 by the Linux `install-and-launch` job above.
# This job verifies the Windows-only pieces on real x64 AND arm64 hardware:
# - host CPU -> Docker platform detection (install_ops.host_container_platform)
# - Lucy.exe builds (PyInstaller) and its bundled --cli imports work
# - the NSIS installer compiles
windows-build-test:
name: Windows build & installer test (${{ matrix.arch }})
strategy:
fail-fast: false
matrix:
include:
- arch: x64
runner: windows-latest
expected_platform: linux/amd64
- arch: arm64
runner: windows-11-arm
expected_platform: linux/arm64
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
steps:
- name: Check out repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
- uses: prefix-dev/setup-pixi@v0.10.0
with:
python-version: '3.x'
pixi-version: latest
cache: ${{ matrix.pixi_platform != 'win-64' }}
post-cleanup: false

- name: Generate releases manifest
run: python windows/generate_releases.py

- name: Verify host architecture detection
shell: pwsh
run: |
$expected = "${{ matrix.expected_platform }}"
$got = (python -c "import sys; sys.path.insert(0,'windows'); import install_ops; print(install_ops.host_container_platform())").Trim()
Write-Host "host_container_platform() -> $got (expected $expected)"
if ($got -ne $expected) {
Write-Error "Arch detection mismatch: got '$got', expected '$expected'"
exit 1
}
- name: Workspace unit tests
shell: bash
run: pixi run workspace-test

- name: Install PyInstaller
run: python -m pip install pyinstaller
- name: Drop workspace .env if present
shell: bash
run: rm -f .env .env.local || true

- name: Build Lucy.exe
shell: pwsh
run: |
python -m PyInstaller --noconfirm --onefile --name Lucy `
--icon windows/assets/lucy-icon.ico `
--hidden-import install_ops `
--hidden-import install_runner `
--paths windows `
windows/Lucy.py
if (-not (Test-Path "dist/Lucy.exe")) { Write-Error "Lucy.exe not produced"; exit 1 }

- name: Smoke-test Lucy.exe CLI (bundled imports + prereq report)
shell: pwsh
- name: Clone sub-repositories (skip colcon)
shell: bash
run: |
dist\Lucy.exe --cli check-prereqs
$code = $LASTEXITCODE
Write-Host "check-prereqs exit code: $code"
# 0 (all present) or 1 (a prereq missing, e.g. no Docker on CI) both mean
# the exe ran fine; >1 = crash. Reset the propagated exit code explicitly.
if ($code -gt 1) { Write-Error "Lucy.exe --cli check-prereqs crashed (exit $code)"; exit 1 }
exit 0

- name: Install NSIS
run: choco install nsis -y --no-progress

- name: Build Lucy-Setup.exe (NSIS)
shell: pwsh
run: |
$makensis = "${env:ProgramFiles(x86)}\NSIS\makensis.exe"
& $makensis "/DMyAppVersion=0.0.0-ci" windows/installer/Lucy.nsi
if (-not (Test-Path "dist/Lucy-Setup-0.0.0-ci.exe")) { Write-Error "Installer not produced"; exit 1 }
chmod +x launch_lucy.sh
python3 install.py --skip-build

- name: Upload Windows artifacts
uses: actions/upload-artifact@v4
with:
name: lucy-windows-${{ matrix.arch }}
path: |
dist/Lucy.exe
dist/Lucy-Setup-0.0.0-ci.exe
if-no-files-found: error

build-and-release-windows-exe:
name: Build and Release Windows Executable
# Only run this job when a new tag is pushed
if: startsWith(github.ref, 'refs/tags/')
runs-on: windows-latest
needs: install-and-launch
permissions:
contents: write # Required to create a release and upload assets
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Build workspace (colcon)
shell: bash
run: pixi run build

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install control panel (yarn)
shell: bash
run: pixi run panel-install

- name: Generate releases manifest
run: python windows/generate_releases.py
- name: Run colcon tests
shell: bash
run: pixi run test-only

- name: Install PyInstaller
run: python -m pip install pyinstaller
- name: ROS doctor
shell: bash
run: pixi run doctor

- name: Build Lucy.exe
shell: pwsh
- name: Launch smoke test (headless)
shell: bash
run: ./launch_lucy.sh --headless python scripts/ros_doctor.py

- name: Launcher tmux smoke (Linux)
if: matrix.pixi_platform == 'linux-64'
shell: bash
run: |
python -m PyInstaller --noconfirm --onefile --name Lucy `
--icon windows/assets/lucy-icon.ico `
--hidden-import install_ops `
--hidden-import install_runner `
--paths windows `
windows/Lucy.py

- name: Install NSIS
run: choco install nsis -y

- name: Build Lucy-Setup.exe
shell: pwsh
chmod +x scripts/ci_tmux_launcher_smoke.sh
LUCY_WS_ROOT="$PWD" ./scripts/ci_tmux_launcher_smoke.sh

# The smoke above answers "did the processes start". This asks whether the
# graph they formed is one the control panel and RViz can actually use.
- name: Core bringup graph checks (Linux)
if: matrix.pixi_platform == 'linux-64'
shell: bash
run: pixi run core-bringup-test

- name: Verify Pixi platform
shell: bash
run: |
$version = "${{ github.ref_name }}" -replace '^v',''
if (-not $version) { $version = "0.0.0" }
$makensis = "${env:ProgramFiles(x86)}\NSIS\makensis.exe"
& $makensis "/DMyAppVersion=$version" windows/installer/Lucy.nsi
got=$(pixi info --json | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('platform', ''))")
echo "pixi platform -> ${got} (expected ${{ matrix.pixi_platform }})"
if [ "${got}" != "${{ matrix.pixi_platform }}" ]; then
echo "::error::Pixi platform mismatch on ${{ matrix.runner }}"
exit 1
fi

- name: Create Release and Upload Assets
uses: softprops/action-gh-release@v2
with:
files: |
dist/Lucy.exe
dist/Lucy-Setup-*.exe
draft: true
20 changes: 13 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Workspace (filled by install.sh)
# Pixi
.pixi/

# Workspace (filled by install.py)
src/

# Colcon
Expand All @@ -24,23 +27,26 @@ __pycache__/
.env
.env.local

# Docker platform choice (./install.sh --arm)
.lucy-docker-platform

# Launcher remembered tick selection (persisted across container restarts)
# Launcher remembered tick selection (persisted across restarts)
.lucy_launcher_state.json

# Launcher runtime modifier state (which core modifiers were applied)
.lucy_launcher_modifiers.json
.lucy_launcher.pid

# Local repo override (forks/branches; takes precedence over config/repos.json)
config/repos.json.local

# Local launcher override (package list/toggles; takes precedence over config/launcher_config.json)
config/launcher_config.json.local

# End-user install profile (written by installer / Lucy.exe)
# End-user install profile (written by the Windows installer)
config/install.profile.json

# Windows executable files
dist/
*.spec

*.local
*.local
.local/

Loading