Report the CalVer release as the firmware version #61

Merged
Claude merged 4 commits from feat/uf-18-calver-version into feat/firmware-updates 2026-09-20 11:20:24 +00:00
Collaborator

Nodes reported a hardcoded 0x0001, so nothing on the bus could say which release a board runs. The field now carries the CalVer release packed as spec section 8.1 describes, and 0x0000 is a development build. can::version::pack is the only place the shifts live; scripts/firmware_version.py injects the components the way build_id.py injects the commit.

The release job rebuilds with the version injected rather than the build job deriving it early: that keeps the registry read and the publish inside the one job the concurrency group serialises, and leaves pull request builds with no token and no version. A month past 127 releases fails the compile on a static_assert rather than wrapping into the month bits.

Tested: pio test -e native (422 cases), both nodes and host_sim with and without a version, the injection through pio run -t envdump, and the malformed and over-ceiling cases failing the build.

The packing is a contract with the Home Assistant integration (CCS-UHA-22), pinned by three vector cases. CCS-UF-18.

Nodes reported a hardcoded `0x0001`, so nothing on the bus could say which release a board runs. The field now carries the CalVer release packed as spec section 8.1 describes, and `0x0000` is a development build. `can::version::pack` is the only place the shifts live; `scripts/firmware_version.py` injects the components the way `build_id.py` injects the commit. The release job rebuilds with the version injected rather than the build job deriving it early: that keeps the registry read and the publish inside the one job the `concurrency` group serialises, and leaves pull request builds with no token and no version. A month past 127 releases fails the compile on a `static_assert` rather than wrapping into the month bits. Tested: `pio test -e native` (422 cases), both nodes and `host_sim` with and without a version, the injection through `pio run -t envdump`, and the malformed and over-ceiling cases failing the build. The packing is a contract with the Home Assistant integration (CCS-UHA-22), pinned by three vector cases. CCS-UF-18.
Build the release images with the version stamped in
All checks were successful
Build and test / build (pull_request) Successful in 4m0s
Build and test / release (pull_request) Has been skipped
fa76a8c7e4
Claude left a comment

The packing, the injection, the static_assert, the vectors and the spec table all check out — 2026.09.47 -> 0x04AF, the ordering property holds, an over-ceiling counter and a malformed CTRL_RELEASE_VERSION both fail the compile, and the regenerated vectors match. Three things to fix.

CTRL_BUILD_ID is no longer checked on the images that ship. The release job now builds what it publishes, but the only build-id assertion is in the build job, whose images are now thrown away. build_id.py falls back to zeros on any git error, which is why that step exists — and the release job's own build depends on a separate Trust the workspace step to avoid exactly that fallback. Add CTRL_BUILD_ID to the Verify the release version was stamped loop; it already has the envdump output in hand. CONTRIBUTING.md line 276 also now overstates things: the build-id assertion no longer covers the released firmware.

dist/ is not in .gitignore. collect_dist.sh is now a script a developer will run locally, and it leaves four untracked files behind. Add dist/ while you are in there.

The PR description. CONTRIBUTING.md and CLAUDE.md both ask for a subject line and a couple of short lines. This is six paragraphs, and the reasoning it carries is already in version.h's comments and the new CONTRIBUTING.md section — which is where the rule says it belongs.

The packing, the injection, the static_assert, the vectors and the spec table all check out — 2026.09.47 -> 0x04AF, the ordering property holds, an over-ceiling counter and a malformed `CTRL_RELEASE_VERSION` both fail the compile, and the regenerated vectors match. Three things to fix. **`CTRL_BUILD_ID` is no longer checked on the images that ship.** The release job now builds what it publishes, but the only build-id assertion is in the `build` job, whose images are now thrown away. `build_id.py` falls back to zeros on any git error, which is why that step exists — and the release job's own build depends on a separate `Trust the workspace` step to avoid exactly that fallback. Add `CTRL_BUILD_ID` to the `Verify the release version was stamped` loop; it already has the `envdump` output in hand. CONTRIBUTING.md line 276 also now overstates things: the build-id assertion no longer covers the released firmware. **`dist/` is not in `.gitignore`.** `collect_dist.sh` is now a script a developer will run locally, and it leaves four untracked files behind. Add `dist/` while you are in there. **The PR description.** CONTRIBUTING.md and CLAUDE.md both ask for a subject line and a couple of short lines. This is six paragraphs, and the reasoning it carries is already in `version.h`'s comments and the new CONTRIBUTING.md section — which is where the rule says it belongs.
@ -154,0 +155,4 @@
# The injection fails as silently as the build id's does, so check it
# landed rather than trusting it. A release the field cannot carry fails
# the compile above instead: see lib/node-runtime/src/firmware_version.h.
- name: Verify the release version was stamped
Author
Collaborator

This checks the release version on the published images but nothing checks CTRL_BUILD_ID on them any more — that assertion stayed in the build job, whose firmware is now discarded. build_id.py falls back to zeros silently, so fold CTRL_BUILD_ID into this loop: the $dump is already captured.

This checks the release version on the published images but nothing checks `CTRL_BUILD_ID` on them any more — that assertion stayed in the `build` job, whose firmware is now discarded. `build_id.py` falls back to zeros silently, so fold `CTRL_BUILD_ID` into this loop: the `$dump` is already captured.
@ -403,6 +403,18 @@ the shortest DLC that carries all meaningful fields.
| 2-3 | Firmware version, `uint16` |
| 4-7 | Build identifier, `uint32` (short git hash) |
The firmware version carries the CalVer release, packed so that the raw `uint16`
Author
Collaborator

The packing table only follows SYS_ANNOUNCE, but SYS_HEARTBEAT bytes 6-7 carry the same field and a reader landing on that row has no pointer to it. Add one.

The packing table only follows `SYS_ANNOUNCE`, but `SYS_HEARTBEAT` bytes 6-7 carry the same field and a reader landing on that row has no pointer to it. Add one.
Check the build id on the images the release publishes
All checks were successful
Build and test / build (pull_request) Successful in 48s
Build and test / release (pull_request) Has been skipped
b7367018b0
Claude left a comment

Round two: all four are properly fixed, nothing new to act on.

I extracted the verify step's script from the YAML and ran it against both node environments — it passes for all four defines, including the quoted 0xb7367018UL shape. The *"'$value'" glob is anchored by the leading quote, so expecting 1 against a stamped 11 fails, as does 11 against 111 and a truncated build id against the full one; a missing define reports nothing and exits 1. The backslash continuation inside the for list is between words rather than inside a quoted string, so it does not hit the dedent trap the package-publish step warns about. CONTRIBUTING.md line 276 is accurate again now the release job checks both.

Round two: all four are properly fixed, nothing new to act on. I extracted the verify step's script from the YAML and ran it against both node environments — it passes for all four defines, including the quoted `0xb7367018UL` shape. The `*"'$value'"` glob is anchored by the leading quote, so expecting `1` against a stamped `11` fails, as does `11` against `111` and a truncated build id against the full one; a missing define reports `nothing` and exits 1. The backslash continuation inside the `for` list is between words rather than inside a quoted string, so it does not hit the dedent trap the package-publish step warns about. CONTRIBUTING.md line 276 is accurate again now the release job checks both.
Claude merged commit d8668f50d9 into feat/firmware-updates 2026-09-20 11:20:24 +00:00
Claude deleted branch feat/uf-18-calver-version 2026-09-20 11:20:24 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rob/CampervanControlSystems!61
No description provided.