Versioning & Compatibility¶
RaceLink is split across four source repositories, each of which has its own version stream:
racelink-host— Python wheel, version exposed asracelink.__version__and viaracelink-host-version.RaceLink_Gateway— ESP32-S3 firmware. Version reported in the device's identification string.RaceLink_WLED— WLED usermod + build profiles. Version stored inversion.json; firmware artefacts published per profile.RaceLink_RH_Plugin— RotorHazard plugin. Plugin version stored incustom_plugins/racelink_rh_plugin/manifest.json; the embedded host wheel is pinned per release.
Wire-protocol version¶
The wire format carries a separate, wire-only version pair in
racelink_proto.h:
Bump rules:
- Bump
MINORfor backward-compatible additions: a new opcode whose absence is harmless, a new optional flag bit, etc. - Bump
MAJORfor breaking changes: a struct reshape, an opcode reused with new semantics, etc.
tests/test_proto_header_drift.py in the host repository verifies
that the three byte-identical copies of racelink_proto.h (Host,
Gateway, WLED) agree. An intentional protocol change still requires
a coordinated commit across all three repositories.
Cross-component compatibility¶
The components do not share a version number — there is no
"RaceLink 1.0" stream. Compatibility is established at the wire-
protocol layer (a host targeting PROTO_VER_MAJOR=2 interoperates
with any gateway/WLED that also targets PROTO_VER_MAJOR=2).
A practical rule of thumb:
| Direction | Compatibility expectation |
|---|---|
| Host ↔ Gateway | Major-version-aligned. OPC_SYNC extends from 4 → 5 bytes; older gateways accept the 5 B form, but a node flashed with old firmware rejects the trailing flags byte. Synchronised rollout required for the 5-byte SYNC form. |
| Host ↔ WLED node | Major-version-aligned. Older nodes silently drop unknown opcodes; new opcodes on a host running an old node fleet are no-ops. |
| Gateway ↔ WLED node | Same. |
| Host ↔ RH plugin | Plugin imports racelink-host as a package; the plugin manifest pins an immutable host wheel. The plugin's own version moves independently. |
Release flows¶
- Host wheel.
.github/workflows/release.yml(Actions UI). Seehost/README.md§Release artifacts. Output:racelink_host-<version>-py3-none-any.whl,racelink-host-<version>.tar.gz,racelink-host-<version>-sha256.txt. - Gateway firmware. Built locally with PlatformIO; release flow
is currently undocumented in the source (gap noted in
AUDIT_RESPONSE.md). - WLED firmware.
.github/workflows/release.ymlinRaceLink_WLED. Resolves the latest official WLED release unless awled_refoverride is supplied; bakesversion.jsoninto the build artefacts. Seewled/README.md§"GitHub release workflow". - RH plugin.
.github/workflows/offline-release.yamlinRaceLink_RH_Plugin. Resolves the latest publishedRaceLink_Hostrelease (or an explicit override), bumps the manifest version, builds the offline ZIP. Seerh-plugin/docs/release-playbook.md.
Gateway / firmware version reporting¶
- The gateway identifies itself via
GW_CMD_IDENTIFY(a USB-only command); the reply carries an identity string with the device type (DEV_TYPE_STR="RaceLink_Gateway_v4"). - WLED nodes carry
WLED_RELEASE_NAMEbaked at build time. WLED's/json/infoendpoint returns it; the host's OTA workflow uses it to validate firmware compatibility (Gate 4 of the OTA acceptance check — seehost/docs/DEVELOPER_GUIDE.md§"WLED OTA gate matrix").
When to bump what¶
| Change | Bump |
|---|---|
| Add a new opcode (backward compatible) | PROTO_VER_MINOR + the patch version of the originator (host or firmware that introduces it); coordinated PR across the three repos |
| Reshape a struct or reuse an opcode value | PROTO_VER_MAJOR + matching synchronised release of all three repos |
| Add a host-only feature (no wire change) | host patch version |
| Fix a host-only bug | host patch version |
| WLED usermod-only change | RaceLink_WLED patch version |
| Gateway firmware-only change | gateway patch version |
| RH plugin glue change | plugin patch version (host wheel pin can stay the same) |