Skip to content

Commit 71d7233

Browse files
ci(python): build platform wheels and publish phy assets on release
Wheels bundle libluos_engine.* via the package data; phy dylibs and a per-platform sha256 manifest are attached to the GitHub Release. A post-publish job installs the wheel and runs the network blinker, proving the phy download path end-to-end. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 584183d commit 71d7233

3 files changed

Lines changed: 127 additions & 0 deletions

File tree

.github/workflows/pio_release.yml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,88 @@ jobs:
184184
pio package pack
185185
pio package publish --owner luos --non-interactive
186186
cd ../..
187+
188+
build_wheels:
189+
needs: check_valid_tag
190+
runs-on: ${{ matrix.os }}
191+
strategy:
192+
matrix:
193+
os: [ubuntu-22.04, macos-latest, windows-latest]
194+
steps:
195+
- uses: actions/checkout@v4
196+
- name: Set up Python
197+
uses: actions/setup-python@v5
198+
with:
199+
python-version: "3.11"
200+
- name: Install build tooling
201+
run: |
202+
python -m pip install --upgrade pip
203+
pip install platformio cibuildwheel==2.* build
204+
- name: Build native engine + phy dylibs
205+
run: pio run -e native_lib
206+
- name: Stage core engine into the package and pin version
207+
shell: bash
208+
run: |
209+
cd bindings/python
210+
cp ../../.pio/build/native_lib/libluos_engine.* luos_engine/ || true
211+
printf 'ENGINE_VERSION = "%s"\n' "${GITHUB_REF_NAME}" > luos_engine/_version.py
212+
- name: Build wheel
213+
run: |
214+
cd bindings/python
215+
python -m build --wheel
216+
- uses: actions/upload-artifact@v4
217+
with:
218+
name: wheel-${{ matrix.os }}
219+
path: bindings/python/dist/*.whl
220+
221+
publish_phys:
222+
needs: check_valid_tag
223+
runs-on: ${{ matrix.os }}
224+
strategy:
225+
matrix:
226+
os: [ubuntu-22.04, macos-latest, windows-latest]
227+
steps:
228+
- uses: actions/checkout@v4
229+
- name: Set up Python
230+
uses: actions/setup-python@v5
231+
with:
232+
python-version: "3.11"
233+
- name: Install PlatformIO
234+
run: |
235+
python -m pip install --upgrade pip
236+
pip install platformio
237+
- name: Build native engine + phy dylibs
238+
run: pio run -e native_lib
239+
- name: Rename phys by platform key and build manifest
240+
shell: bash
241+
run: |
242+
python bindings/python/tools/stage_phy_assets.py \
243+
.pio/build/native_lib release_assets
244+
- name: Upload phy assets to the release
245+
uses: softprops/action-gh-release@v2
246+
with:
247+
tag_name: ${{ github.ref_name }}
248+
files: release_assets/*
249+
250+
smoke_test:
251+
needs: [build_wheels, publish_phys]
252+
runs-on: ${{ matrix.os }}
253+
strategy:
254+
matrix:
255+
os: [ubuntu-22.04, macos-latest, windows-latest]
256+
steps:
257+
- uses: actions/checkout@v4
258+
- uses: actions/setup-python@v5
259+
with:
260+
python-version: "3.11"
261+
- uses: actions/download-artifact@v4
262+
with:
263+
name: wheel-${{ matrix.os }}
264+
path: dist
265+
- name: Install the built wheel and run the network blinker
266+
shell: bash
267+
run: |
268+
python -m pip install --upgrade pip
269+
pip install dist/*.whl pyluos pytest
270+
# Phys are NOT bundled; this proves they download from the release.
271+
python -m pytest bindings/python/tests/test_network_blinker.py -v

bindings/python/pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@ test = ["pytest", "pyluos>=3.1"]
1414

1515
[tool.setuptools]
1616
packages = ["luos_engine"]
17+
18+
[tool.setuptools.package-data]
19+
luos_engine = ["libluos_engine.*", "*.so", "*.dylib", "*.dll"]
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"""Copy built phy dylibs into an output dir, renamed by platform key, and
2+
write a per-platform manifest of sha256 checksums. Run per-OS in CI; each
3+
run writes its own manifest-<key>.json so matrix jobs never clobber each
4+
other's manifest.
5+
6+
Usage: python stage_phy_assets.py <build_dir> <out_dir>
7+
"""
8+
import hashlib
9+
import json
10+
import sys
11+
from pathlib import Path
12+
13+
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
14+
from luos_engine._platform import dylib_ext, platform_key # noqa: E402
15+
16+
17+
def main(build_dir: str, out_dir: str) -> None:
18+
build = Path(build_dir)
19+
out = Path(out_dir)
20+
out.mkdir(parents=True, exist_ok=True)
21+
key = platform_key()
22+
ext = dylib_ext()
23+
24+
manifest = {}
25+
for src in build.glob(f"lib*_network{ext}"):
26+
basename = src.name[: -len(ext)] # libws_network
27+
asset = f"{basename}-{key}{ext}"
28+
data = src.read_bytes()
29+
(out / asset).write_bytes(data)
30+
manifest[asset] = hashlib.sha256(data).hexdigest()
31+
print(f"staged {asset}")
32+
33+
(out / f"manifest-{key}.json").write_text(
34+
json.dumps(manifest, indent=2, sort_keys=True)
35+
)
36+
37+
38+
if __name__ == "__main__":
39+
main(sys.argv[1], sys.argv[2])

0 commit comments

Comments
 (0)