Skip to content

Commit 529a536

Browse files
authored
Merge pull request #66 from Sentience-Robotics/release/v0.2.0
Release v0.2.0 -> Master
2 parents 2927857 + 3b42c9e commit 529a536

81 files changed

Lines changed: 99484 additions & 3903 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
PORT_ROSBRIDGE=9090
2-
PORT_CONTROL_PANEL=5000
2+
PORT_CONTROL_PANEL=4004
3+
4+
# DDS discovery (scripts/dds_env.sh). macOS defaults to localhost-only unicast
5+
# because multicast needs a Local Network permission tmux never gets.
6+
# LUCY_DDS_LOCALHOST=0
7+
# LUCY_DDS_INTERFACE=192.168.1.5
8+
# LUCY_DDS_PEERS=hostA,hostB

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.sh text eol=lf
2+
*.bash text eol=lf
Lines changed: 68 additions & 201 deletions
Original file line numberDiff line numberDiff line change
@@ -1,240 +1,107 @@
1-
# Full workspace install (clone + Docker image + rosdep + colcon + yarn) plus a
2-
# non-interactive launch smoke test, on both x86_64 and ARM64 GitHub-hosted runners.
3-
#
4-
# - DEV=false -> install.sh uses `url_https` from config/repos.json (sub-repos are public).
5-
# - CI=true -> install.sh skips the host `xhost` check (no GUI on runners).
6-
# - variant=arm runs on `ubuntu-24.04-arm` with `./install.sh --arm`; the built image
7-
# is then verified to be linux/arm64 (linux/amd64 for the default variant).
8-
# - Runner OS (22.04 or 24.04) is only the CI host. ROS Humble always runs inside
9-
# Jammy-based images (`osrf/ros:humble-desktop` / `ros:humble-ros-base-jammy`).
10-
# - `ubuntu-24.04-arm` is GitHub's hosted ARM64 runner label; there is no 22.04-arm
11-
# standard runner. The container OS stays Jammy regardless.
12-
# - The launch smoke test uses `./launch_lucy.sh --headless <command>`, which runs a
13-
# single command inside the container (no control panel, no auto Gazebo/RViz).
14-
15-
name: Install, Launch & Release
1+
# - DEV=false -> install.py uses url_https from config/repos.json.
2+
# - python3 install.py --skip-build clones sub-repos; colcon build runs via pixi run build.
3+
4+
name: Install, Build & Test
165

176
on:
187
workflow_dispatch:
198
push:
209
branches: [master, dev]
2110
tags:
22-
- 'v*' # Run on version tags like v1.0, v2.3.4
11+
- 'v*'
2312
pull_request:
2413
branches: [master, dev]
2514

2615
permissions:
2716
contents: read
2817

2918
jobs:
30-
install-and-launch:
19+
pixi-install-build-test:
20+
name: Pixi install & build (${{ matrix.runner }})
3121
concurrency:
32-
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.variant }}
22+
group: ${{ github.workflow }}-${{ github.ref }}-${{ matrix.runner }}
3323
cancel-in-progress: true
3424
runs-on: ${{ matrix.runner }}
3525
timeout-minutes: 120
3626
strategy:
3727
fail-fast: false
3828
matrix:
3929
include:
40-
- variant: default
41-
runner: ubuntu-latest
42-
use_arm_install: false
43-
expected_arch: linux/amd64
44-
- variant: arm
45-
runner: ubuntu-24.04-arm
46-
use_arm_install: true
47-
expected_arch: linux/arm64
30+
- runner: ubuntu-latest
31+
pixi_platform: linux-64
32+
- runner: ubuntu-24.04-arm
33+
pixi_platform: linux-aarch64
34+
- runner: macos-latest
35+
pixi_platform: osx-arm64
36+
- runner: windows-latest
37+
pixi_platform: win-64
4838
env:
4939
DEV: "false"
5040
CI: "true"
5141
steps:
52-
- uses: actions/checkout@v4
53-
54-
# Make sure no committed/local .env can flip DEV back to true at install time.
55-
- name: Drop workspace .env if present
56-
run: rm -f .env .env.local || true
57-
58-
# Docker Hub metadata/pull flakes (i/o timeout) fail `docker build` before
59-
# any Dockerfile layer runs. Pre-pull with retries so the build reuses cache.
60-
- name: Pre-pull base images (retry on Hub flakes)
61-
run: |
62-
pull_with_retry() {
63-
image="$1"
64-
for attempt in 1 2 3 4 5; do
65-
if docker pull "$image"; then
66-
return 0
67-
fi
68-
echo "docker pull ${image} failed (attempt ${attempt}/5), retrying..."
69-
sleep $((attempt * 15))
70-
done
71-
return 1
72-
}
73-
if [ "${{ matrix.use_arm_install }}" = true ]; then
74-
pull_with_retry ros:humble-ros-base-jammy
75-
else
76-
pull_with_retry osrf/ros:humble-desktop
77-
fi
78-
79-
- name: Install (clone + Docker image + rosdep + colcon + yarn)
80-
run: |
81-
chmod +x install.sh launch_lucy.sh
82-
if [ "${{ matrix.use_arm_install }}" = true ]; then
83-
./install.sh --arm
84-
else
85-
./install.sh
86-
fi
87-
88-
- name: Verify Lucy image architecture
89-
run: |
90-
osarch=$(docker image inspect lucy_ros2:humble --format '{{.Os}}/{{.Architecture}}')
91-
echo "lucy_ros2:humble -> ${osarch}"
92-
if [ "${osarch}" != "${{ matrix.expected_arch }}" ]; then
93-
echo "::error::Expected ${{ matrix.expected_arch }} after ./install.sh on ${{ matrix.runner }}, got ${osarch}"
94-
exit 1
95-
fi
42+
- uses: actions/checkout@v5
9643

97-
# Single command in the container -> bypasses the control-panel / Gazebo / RViz auto-launch.
98-
- name: Launch smoke test (headless, no TTY)
99-
run: ./launch_lucy.sh --headless ros2 doctor --report
100-
101-
# Windows-specific CI. NOTE: GitHub-hosted Windows runners cannot run Linux
102-
# containers (no Hyper-V/nested virtualization, no WSL2), so the heavy install
103-
# step (docker build of the ROS image + colcon) CANNOT run here — that is
104-
# covered for both amd64/arm64 by the Linux `install-and-launch` job above.
105-
# This job verifies the Windows-only pieces on real x64 AND arm64 hardware:
106-
# - host CPU -> Docker platform detection (install_ops.host_container_platform)
107-
# - Lucy.exe builds (PyInstaller) and its bundled --cli imports work
108-
# - the NSIS installer compiles
109-
windows-build-test:
110-
name: Windows build & installer test (${{ matrix.arch }})
111-
strategy:
112-
fail-fast: false
113-
matrix:
114-
include:
115-
- arch: x64
116-
runner: windows-latest
117-
expected_platform: linux/amd64
118-
- arch: arm64
119-
runner: windows-11-arm
120-
expected_platform: linux/arm64
121-
runs-on: ${{ matrix.runner }}
122-
timeout-minutes: 30
123-
steps:
124-
- name: Check out repository
125-
uses: actions/checkout@v4
126-
127-
- name: Set up Python
128-
uses: actions/setup-python@v5
44+
- uses: prefix-dev/setup-pixi@v0.10.0
12945
with:
130-
python-version: '3.x'
46+
pixi-version: latest
47+
cache: ${{ matrix.pixi_platform != 'win-64' }}
48+
post-cleanup: false
13149

132-
- name: Generate releases manifest
133-
run: python windows/generate_releases.py
50+
- name: Workspace unit tests
51+
shell: bash
52+
run: pixi run workspace-test
13453

135-
- name: Verify host architecture detection
136-
shell: pwsh
137-
run: |
138-
$expected = "${{ matrix.expected_platform }}"
139-
$got = (python -c "import sys; sys.path.insert(0,'windows'); import install_ops; print(install_ops.host_container_platform())").Trim()
140-
Write-Host "host_container_platform() -> $got (expected $expected)"
141-
if ($got -ne $expected) {
142-
Write-Error "Arch detection mismatch: got '$got', expected '$expected'"
143-
exit 1
144-
}
145-
146-
- name: Install PyInstaller
147-
run: python -m pip install pyinstaller
54+
- name: Drop workspace .env if present
55+
shell: bash
56+
run: rm -f .env .env.local || true
14857

149-
- name: Build Lucy.exe
150-
shell: pwsh
151-
run: |
152-
python -m PyInstaller --noconfirm --onefile --name Lucy `
153-
--icon windows/assets/lucy-icon.ico `
154-
--hidden-import install_ops `
155-
--hidden-import install_runner `
156-
--paths windows `
157-
windows/Lucy.py
158-
if (-not (Test-Path "dist/Lucy.exe")) { Write-Error "Lucy.exe not produced"; exit 1 }
159-
160-
- name: Smoke-test Lucy.exe CLI (bundled imports + prereq report)
161-
shell: pwsh
58+
- name: Clone sub-repositories (skip colcon)
59+
shell: bash
16260
run: |
163-
dist\Lucy.exe --cli check-prereqs
164-
$code = $LASTEXITCODE
165-
Write-Host "check-prereqs exit code: $code"
166-
# 0 (all present) or 1 (a prereq missing, e.g. no Docker on CI) both mean
167-
# the exe ran fine; >1 = crash. Reset the propagated exit code explicitly.
168-
if ($code -gt 1) { Write-Error "Lucy.exe --cli check-prereqs crashed (exit $code)"; exit 1 }
169-
exit 0
170-
171-
- name: Install NSIS
172-
run: choco install nsis -y --no-progress
173-
174-
- name: Build Lucy-Setup.exe (NSIS)
175-
shell: pwsh
176-
run: |
177-
$makensis = "${env:ProgramFiles(x86)}\NSIS\makensis.exe"
178-
& $makensis "/DMyAppVersion=0.0.0-ci" windows/installer/Lucy.nsi
179-
if (-not (Test-Path "dist/Lucy-Setup-0.0.0-ci.exe")) { Write-Error "Installer not produced"; exit 1 }
61+
chmod +x launch_lucy.sh
62+
python3 install.py --skip-build
18063
181-
- name: Upload Windows artifacts
182-
uses: actions/upload-artifact@v4
183-
with:
184-
name: lucy-windows-${{ matrix.arch }}
185-
path: |
186-
dist/Lucy.exe
187-
dist/Lucy-Setup-0.0.0-ci.exe
188-
if-no-files-found: error
189-
190-
build-and-release-windows-exe:
191-
name: Build and Release Windows Executable
192-
# Only run this job when a new tag is pushed
193-
if: startsWith(github.ref, 'refs/tags/')
194-
runs-on: windows-latest
195-
needs: install-and-launch
196-
permissions:
197-
contents: write # Required to create a release and upload assets
198-
steps:
199-
- name: Check out repository
200-
uses: actions/checkout@v4
64+
- name: Build workspace (colcon)
65+
shell: bash
66+
run: pixi run build
20167

202-
- name: Set up Python
203-
uses: actions/setup-python@v5
204-
with:
205-
python-version: '3.x'
68+
- name: Install control panel (yarn)
69+
shell: bash
70+
run: pixi run panel-install
20671

207-
- name: Generate releases manifest
208-
run: python windows/generate_releases.py
72+
- name: Run colcon tests
73+
shell: bash
74+
run: pixi run test-only
20975

210-
- name: Install PyInstaller
211-
run: python -m pip install pyinstaller
76+
- name: ROS doctor
77+
shell: bash
78+
run: pixi run doctor
21279

213-
- name: Build Lucy.exe
214-
shell: pwsh
80+
- name: Launch smoke test (headless)
81+
shell: bash
82+
run: ./launch_lucy.sh --headless python scripts/ros_doctor.py
83+
84+
- name: Launcher tmux smoke (Linux)
85+
if: matrix.pixi_platform == 'linux-64'
86+
shell: bash
21587
run: |
216-
python -m PyInstaller --noconfirm --onefile --name Lucy `
217-
--icon windows/assets/lucy-icon.ico `
218-
--hidden-import install_ops `
219-
--hidden-import install_runner `
220-
--paths windows `
221-
windows/Lucy.py
222-
223-
- name: Install NSIS
224-
run: choco install nsis -y
225-
226-
- name: Build Lucy-Setup.exe
227-
shell: pwsh
88+
chmod +x scripts/ci_tmux_launcher_smoke.sh
89+
LUCY_WS_ROOT="$PWD" ./scripts/ci_tmux_launcher_smoke.sh
90+
91+
# The smoke above answers "did the processes start". This asks whether the
92+
# graph they formed is one the control panel and RViz can actually use.
93+
- name: Core bringup graph checks (Linux)
94+
if: matrix.pixi_platform == 'linux-64'
95+
shell: bash
96+
run: pixi run core-bringup-test
97+
98+
- name: Verify Pixi platform
99+
shell: bash
228100
run: |
229-
$version = "${{ github.ref_name }}" -replace '^v',''
230-
if (-not $version) { $version = "0.0.0" }
231-
$makensis = "${env:ProgramFiles(x86)}\NSIS\makensis.exe"
232-
& $makensis "/DMyAppVersion=$version" windows/installer/Lucy.nsi
101+
got=$(pixi info --json | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('platform', ''))")
102+
echo "pixi platform -> ${got} (expected ${{ matrix.pixi_platform }})"
103+
if [ "${got}" != "${{ matrix.pixi_platform }}" ]; then
104+
echo "::error::Pixi platform mismatch on ${{ matrix.runner }}"
105+
exit 1
106+
fi
233107
234-
- name: Create Release and Upload Assets
235-
uses: softprops/action-gh-release@v2
236-
with:
237-
files: |
238-
dist/Lucy.exe
239-
dist/Lucy-Setup-*.exe
240-
draft: true

.gitignore

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
# Workspace (filled by install.sh)
1+
# Pixi
2+
.pixi/
3+
4+
# Workspace (filled by install.py)
25
src/
36

47
# Colcon
@@ -24,18 +27,26 @@ __pycache__/
2427
.env
2528
.env.local
2629

27-
# Docker platform choice (./install.sh --arm)
28-
.lucy-docker-platform
29-
30-
# Launcher remembered tick selection (persisted across container restarts)
30+
# Launcher remembered tick selection (persisted across restarts)
3131
.lucy_launcher_state.json
3232

33+
# Launcher runtime modifier state (which core modifiers were applied)
34+
.lucy_launcher_modifiers.json
35+
.lucy_launcher.pid
36+
3337
# Local repo override (forks/branches; takes precedence over config/repos.json)
3438
config/repos.json.local
3539

36-
# End-user install profile (written by installer / Lucy.exe)
40+
# Local launcher override (package list/toggles; takes precedence over config/launcher_config.json)
41+
config/launcher_config.json.local
42+
43+
# End-user install profile (written by the Windows installer)
3744
config/install.profile.json
3845

3946
# Windows executable files
4047
dist/
41-
*.spec
48+
*.spec
49+
50+
*.local
51+
.local/
52+

0 commit comments

Comments
 (0)