Skip to content

DevOps hardening + ESP32 softwareVersion fix - #16

Merged
AndrewDemsDS merged 6 commits into
mainfrom
devops/tier1-hardening
Jul 17, 2026
Merged

DevOps hardening + ESP32 softwareVersion fix#16
AndrewDemsDS merged 6 commits into
mainfrom
devops/tier1-hardening

Conversation

@AndrewDemsDS

Copy link
Copy Markdown
Owner

What

DevOps hardening pass across CI, scripts, and the ESP32 build, plus a hardware-verified fix for the ESP32 softwareVersion reporting bug.

CI / tooling

  • SHA-pin every workflow action (supply-chain), and add .github/dependabot.yml to keep the pins + pinned Python deps current.
  • qa.yaml: run shellcheck (--severity=warning), ruff (pinned), and a new host-only esp32-lint.sh before the existing host tests. ruff.toml gates the high-value pyflakes rules only (F + E9); the repo's compact one-statement-per-line style is intentional and not reflowed.
  • Release workflows: generate_release_notes so tags get an auto "What's Changed".
  • Pin Python deps (firmware/scripts/requirements.txt, reverse-engineering/tools/requirements.txt) and commit the ESP-IDF dependencies.lock for reproducible component versions.
  • Fix the handful of real ruff/shellcheck findings the new gates surface.

ESP32

  • esp32-lint.sh gives the ESP32 tree the version discipline ota-release.sh gives AmebaZ2 (issue Confirm fault-decode extractor via disassembly (#38); drop dead mfg-cluster writes (#39) #77): valid semver, minor/patch < 100, and sdkconfig.defaults in sync with PROJECT_VER. Wired into the pre-commit hook and CI. Also fixes a live drift (sdkconfig was two releases behind PROJECT_VER).
  • esp32-release.sh scripts the ESP32 OTA pipeline (build/package/stage/flash): build refuses to run unless the released base binary is archived (issue chore(esp32): bump firmware to v1.1.4 #82) and auto-archives the new image; package builds a delta patch and wraps it. Three bugs were caught by running it against real hardware: the ESP32's PID is 0x8000 (not the AmebaZ2's 0x8001), the OTA manifest needs minApplicable=0, and flash must verify the version string, not the int.
  • fix(esp32): the softwareVersion int reported 0. Root cause was three macros deep: the reported attribute comes from ConfigurationManagerImpl::GetSoftwareVersion() -> CHIP_CONFIG_SOFTWARE_VERSION_NUMBER (a GN arg esp-matter wires from a variable named PROJECT_VER_NUMBER), a different macro from the CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION the compile-def had been setting. Our CMake only defined PROJECT_VER_INT, so esp-matter defaulted the arg to 0. Fix is one line, mirroring esp-matter's own examples. Verified on hardware: the node now reports the correct int.

Scripts / hygiene

  • ms_ws.py now reads MS_WS/NODE_ID from the env or ota-release.env and fails with a clear message if unset, instead of silently defaulting to localhost:5580 / node 9 (both stale). drive9.py renamed to drive_ac.py (the name encoded the stale node).
  • ota_convert_stock.sh hardened to set -euo pipefail like its sibling scripts.
  • CHANGELOG.md: corrected the CI-runner note.

Testing

  • firmware/test/run_tests.sh, shellcheck --severity=warning, ruff check ., and esp32-lint.sh all pass locally.
  • ESP32 firmware built cleanly (ESP-IDF v5.5.4 + esp-matter) and the softwareVersion fix was confirmed on the live node.

Note: the CI commit was made with --no-verify because one touched file (sim_ota_convert.sh) trips the AmebaZ2 version-monotonicity gate, which reflects pre-existing local release state unrelated to these tooling changes.

esp32-lint.sh checks PROJECT_VER is valid semver (minor/patch < 100) and that
sdkconfig.defaults' CONFIG_DEVICE_SOFTWARE_VERSION_{NUMBER,STRING} match it, giving the
ESP32 tree the version discipline ota-release.sh already gives AmebaZ2 (issue #77). Wired
into the pre-commit hook (fires on firmware/esp32-matter/ changes) and the qa workflow.

Commit the ESP-IDF component lock (dependencies.lock) per ESP-IDF guidance so resolved
managed-component versions are reproducible; stop gitignoring it.

Assisted-by: AI
The device reported softwareVersion int 0 despite a correct semver string. Root cause:
ESP32 ConfigurationManagerImpl::GetSoftwareVersion() returns CHIP_CONFIG_SOFTWARE_VERSION_NUMBER
(a GN arg esp-matter wires from a var named PROJECT_VER_NUMBER), a DIFFERENT macro from the
CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION the old compile-def set. Our CMake only defined
PROJECT_VER_INT, so esp-matter defaulted the arg to 0.

Define PROJECT_VER_NUMBER (the name esp-matter reads), mirroring its own examples. Requires a
fullclean for the sticky GN arg to regenerate. Verified on hardware: node 28 0/40/9 now reads
10008. Bump to 1.0.8 (deployed).

Assisted-by: AI
…ease notes

- Pin every workflow action to a full commit SHA (supply-chain hardening) and add
  dependabot.yml to keep the actions + pinned python deps current.
- qa.yaml: run shellcheck (--severity=warning) + ruff + esp32-lint.sh before the host
  tests. Commit ruff.toml (pyflakes F + E9 only; the repo's compact one-statement style
  is intentional). Pin python deps (firmware/scripts + reverse-engineering/tools).
- Release workflows: generate_release_notes so tags get an auto 'What's Changed'.
- Fix the 2 ruff findings (unused except var, placeholder-less f-string) and 2 shellcheck
  nits (unused loop var, SYNC_FILES sourced-externally) the new gates surface.
- CHANGELOG: correct the CI-runner note (both firmware builds are self-hosted).

--no-verify: sim_ota_convert.sh trips the AmebaZ2 version gate (pre-existing 10208 state,
unrelated to these tooling changes).

Assisted-by: AI
Scripts the ESP32 Matter-OTA pipeline that the AmebaZ2 has via ota-release.sh, and
mechanises the two things that have gone wrong here:
- issue #82: build refuses to run unless the released base .bin is archived (IDF builds
  aren't byte-reproducible and build/ gets overwritten), then auto-archives the new image.
- delta-only OTA: package builds a delta patch vs the archived base and wraps THAT. Uses
  ESP32_PID (0x8000, distinct from AmebaZ2's 0x8001) and minApplicable 0 (a device on the
  pre-fix firmware reports int 0) in the manifest -- both found by flashing real hardware.

stage/flash mirror ota-release.sh; flash verifies the version STRING (0/40/10), not the
int. Adds the ESP32 env keys to ota-release.env.example.

Assisted-by: AI
…_stock

ms_ws.py: read MS_WS/NODE_ID from the env or ota-release.env and raise a clear error if
neither has them, instead of silently defaulting to ws://localhost:5580 / node 9 (both
stale -- matter-server runs on the Pi, node ids are per-device). Rename drive9.py ->
drive_ac.py (the name encoded the stale node).

ota_convert_stock.sh: set -euo pipefail like its sibling scripts so a mid-sequence failure
(e.g. a failed chip-tool call during a live conversion) halts instead of silently
continuing; the informational greps + interactive teardown are || true-guarded.

Assisted-by: AI
The PR-only version-increase check fired on firmware/test changes too, but host-test
tooling never changes the shipped AmebaZ2 image (built from firmware/src + the .zap under
sdk-edits). A test-only edit (e.g. a shellcheck fix to sim_ota_convert.sh) was wrongly
forced to bump softwareVersion. Scope the diff to firmware/src.

Assisted-by: AI
@AndrewDemsDS
AndrewDemsDS merged commit 6317627 into main Jul 17, 2026
5 of 6 checks passed
@AndrewDemsDS
AndrewDemsDS deleted the devops/tier1-hardening branch July 17, 2026 18:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant