Skip to content

Commit e770011

Browse files
authored
Merge pull request #15 from Sentience-Robotics/release/v0.1.1
Release v0.1.1 -> Master
2 parents f15a932 + 71d7ec4 commit e770011

19 files changed

Lines changed: 1645 additions & 296 deletions

.github/workflows/install-and-launch.yml

Lines changed: 117 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,95 @@ jobs:
9898
- name: Launch smoke test (headless, no TTY)
9999
run: ./launch_lucy.sh --headless ros2 doctor --report
100100

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
129+
with:
130+
python-version: '3.x'
131+
132+
- name: Generate releases manifest
133+
run: python windows/generate_releases.py
134+
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
148+
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
162+
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 }
180+
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+
101190
build-and-release-windows-exe:
102191
name: Build and Release Windows Executable
103192
# Only run this job when a new tag is pushed
@@ -115,15 +204,37 @@ jobs:
115204
with:
116205
python-version: '3.x'
117206

207+
- name: Generate releases manifest
208+
run: python windows/generate_releases.py
209+
118210
- name: Install PyInstaller
119-
run: pip install pyinstaller
211+
run: python -m pip install pyinstaller
120212

121-
- name: Build the executable
122-
run: pyinstaller --onefile --name Lucy windows/Lucy.py
213+
- name: Build Lucy.exe
214+
shell: pwsh
215+
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
228+
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
123233
124-
- name: Create Release and Upload Asset
234+
- name: Create Release and Upload Assets
125235
uses: softprops/action-gh-release@v2
126236
with:
127-
files: dist/Lucy.exe
128-
# This creates a draft release. Remove `draft: true` to publish it automatically.
237+
files: |
238+
dist/Lucy.exe
239+
dist/Lucy-Setup-*.exe
129240
draft: true

.github/workflows/release.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: Trigger Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Version number'
8+
required: true
9+
type: string
10+
11+
jobs:
12+
create-release:
13+
uses: Sentience-Robotics/.github/.github/workflows/release.yaml@master
14+
with:
15+
version: ${{ inputs.version }}
16+

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,10 @@ __pycache__/
3232

3333
# Local repo override (forks/branches; takes precedence over config/repos.json)
3434
config/repos.json.local
35+
36+
# End-user install profile (written by installer / Lucy.exe)
37+
config/install.profile.json
38+
39+
# Windows executable files
40+
dist/
41+
*.spec

Lucy.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ def set_dev_mode(is_enabled):
3636

3737
def run_command(command, interactive=False):
3838
"""Runs a command.
39-
39+
4040
If interactive is True, runs natively in the terminal.
4141
"""
4242
print(f"--- Running: {' '.join(command)} ---")
4343
try:
4444
if interactive:
45-
# Inherit standard IO to maintain terminal size and TTY functionality
45+
# Inherit standard IO to maintain terminal size and TTY functionality
4646
return subprocess.run(command).returncode
4747
else:
4848
# Popen is fine for non-interactive scripts like install/build
@@ -91,7 +91,7 @@ def main_tui(stdscr):
9191
continue
9292

9393
prefix = "> " if current_idx == i else " "
94-
94+
9595
if option == "Developer Mode":
9696
checkbox = "[x]" if is_dev_mode else "[ ]"
9797
stdscr.addstr(2 + i, 4, f"{prefix}{checkbox} {option}")
@@ -167,7 +167,7 @@ def check_initial_size():
167167
if task.get("interactive", False):
168168
print(f"--- Session finished with exit code {rc} ---")
169169
break
170-
170+
171171
task_name = task.get("name")
172172
if task_name in ["Install", "Rebuild"] and rc == 0:
173173
print(f"\n--- Task '{task_name}' finished successfully. ---")

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Workspace bringup for the Lucy / InMoov humanoid. Everything (ROS 2 Humble, Gaze
1010

1111
<sub>Linux GUI forwarding uses `xhost` (preinstalled). On Wayland run `xhost +local:docker` if windows don't open — see [GUI](#gui-rviz-and-gazebo).</sub>
1212

13-
> **Windows users:** see the [Windows README](windows/README.md) for step-by-step install instructions (including the Docker Desktop "uncheck WSL 2" note) and the native `windows/Lucy.py` manager.
13+
> **Windows users:** see the [Windows README](windows/README.md) **`Lucy-Setup.exe`** to install/update, **`Lucy.exe`** to launch.
1414
1515
## Get the repository
1616

@@ -48,13 +48,16 @@ python3 Lucy.py
4848
4949
### Windows
5050

51+
**Installer (recommended):** download `Lucy-Setup.exe` from [GitHub Releases](https://github.com/Sentience-Robotics/lucy_ws/releases), then see the [Windows README](windows/README.md).
52+
53+
**From source (developers):**
54+
5155
```bash
52-
python windows/Lucy.py
56+
python windows/Lucy.py --cli install # first time
57+
python windows/Lucy.py # launch
5358
```
5459

55-
> **Windows** additionally needs a third-party X Server — see the [Windows README](windows/README.md).
56-
57-
> **First run:** in the TUI, choose **`Install / Update`** before anything else. It clones the sub-repositories, builds the Docker image and the workspace (this can take a while). Only once it finishes should you use **`Launch`**.
60+
> **Windows** additionally needs a third-party X Server for RViz/Gazebo — see the [Windows README](windows/README.md). End users should use **`Lucy-Setup.exe`** instead of manual install.
5861
5962
### Opening the Control Panel
6063

config/launcher_config.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@
130130
"dependencies": ["core"],
131131
"conflicts": [],
132132
"command": "ros2 run lucy_cli tui",
133+
"readiness_check": "test -f /tmp/lucy_cli.ready",
134+
"nav_hint": "Ctrl-B W",
133135
"default_on": false
134136
},
135137
{

docs/developer_lucy_packages.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ Use the same structure as `repos.json` — list only the repos you want to overr
6565

6666
Delete the file to fall back to the tracked `repos.json`.
6767

68+
### Windows install profile (`config/install.profile.json`)
69+
70+
On Windows, **`Lucy-Setup.exe`** (or `Lucy.exe --cli …`) writes **`config/install.profile.json`** (gitignored) to record install choices: `lucy_ws` version, `repos_branch` (default `master`), `fetch_method` (`git` or `zip`), and whether **developer install** was selected. The file is created automatically on first install.
71+
72+
| Windows | Linux/macOS equivalent |
73+
|---------|------------------------|
74+
| `Lucy-Setup.exe` → Fresh install | `./install.sh` |
75+
| `Lucy-Setup.exe` → Update | `./install.sh` / `./install.sh --update` |
76+
| `Lucy-Setup.exe` → Repair | `./install.sh --repair` |
77+
| `Lucy.exe` (no args) | `./launch_lucy.sh` / **Launch** in `Lucy.py` |
78+
| `Lucy.exe --cli build-only` | `./install.sh --build-only` |
79+
6880
## `launch_lucy.sh`
6981

7082
Builds the Docker image if needed, mounts the workspace at `/workspace`, sources the built ROS overlay, then:

0 commit comments

Comments
 (0)