Skip to content

Commit 6317627

Browse files
authored
Merge pull request #16 from AndrewDemsDS/devops/tier1-hardening
DevOps hardening + ESP32 softwareVersion fix
2 parents 55f2d93 + f9b402e commit 6317627

23 files changed

Lines changed: 532 additions & 42 deletions

.github/dependabot.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
version: 2
2+
# Automated dependency-update PRs. GitHub Actions are SHA-pinned in the workflows
3+
# (supply-chain safety); Dependabot proposes the bumps as reviewable PRs so the pins
4+
# stay current without hand-resolving SHAs. Python ecosystems track the pinned
5+
# requirements files added for the OTA + reverse-engineering tooling.
6+
updates:
7+
- package-ecosystem: github-actions
8+
directory: /
9+
schedule:
10+
interval: weekly
11+
commit-message:
12+
prefix: ci
13+
groups:
14+
actions:
15+
patterns: ["*"]
16+
17+
- package-ecosystem: pip
18+
directory: /firmware/scripts
19+
schedule:
20+
interval: weekly
21+
commit-message:
22+
prefix: build
23+
24+
- package-ecosystem: pip
25+
directory: /reverse-engineering/tools
26+
schedule:
27+
interval: weekly
28+
commit-message:
29+
prefix: build

.github/workflows/amebaz2-release.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
build:
1717
runs-on: [self-hosted, sdk-builder]
1818
steps:
19-
- uses: actions/checkout@v4
19+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
2020

2121
- name: Provision build env from the runner host
2222
run: |
@@ -43,8 +43,9 @@ jobs:
4343
sha256sum "flash_rac-integrated-v$V.bin" "rac-v$V.ota" "rac-v$V.json" > "SHA256SUMS-v$V.txt"
4444
4545
- name: Attach to the GitHub Release
46-
uses: softprops/action-gh-release@v2
46+
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
4747
with:
48+
generate_release_notes: true # auto "What's Changed" from commits/PRs since the last tag
4849
files: |
4950
firmware/built-images/flash_rac-integrated-v${{ env.V }}.bin
5051
firmware/built-images/rac-v${{ env.V }}.ota

.github/workflows/esp32-release.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
run:
2222
shell: bash # ESP-IDF export.sh + esp-matter export.sh are bash
2323
steps:
24-
- uses: actions/checkout@v4
24+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
2525

2626
- name: Tag must match CMake PROJECT_VER
2727
run: |
@@ -48,8 +48,9 @@ jobs:
4848
partition_table/partition-table.bin ota_data_initial.bin flasher_args.json > SHA256SUMS.txt
4949
5050
- name: Attach to the GitHub Release
51-
uses: softprops/action-gh-release@v2
51+
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
5252
with:
53+
generate_release_notes: true # auto "What's Changed" from commits/PRs since the last tag
5354
files: |
5455
firmware/esp32-matter/build/hisense_ac_matter.bin
5556
firmware/esp32-matter/build/bootloader/bootloader.bin

.github/workflows/qa.yaml

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,26 @@ jobs:
1717
host-qa:
1818
runs-on: ubuntu-latest
1919
steps:
20-
- uses: actions/checkout@v4
20+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
2121
with:
2222
fetch-depth: 0 # PR version-diff needs base history
2323

24+
# Static lint first (cheap, fails fast). Run these same two commands locally for parity.
25+
# shellcheck ships on the runner image; --severity=warning gates real bugs (quoting, unset
26+
# vars, logic) and skips the info/style nits the scripts intentionally use. ruff reads the
27+
# committed ruff.toml; it's pinned via pipx (bump with the local version + Dependabot).
28+
- name: Shell lint (shellcheck)
29+
run: |
30+
shellcheck --version
31+
shellcheck --severity=warning firmware/scripts/*.sh firmware/test/*.sh \
32+
firmware/.githooks/pre-commit firmware/.githooks/prepare-commit-msg
33+
34+
- name: Python lint (ruff)
35+
run: pipx run ruff==0.15.20 check .
36+
37+
- name: ESP32 version consistency
38+
run: bash firmware/scripts/esp32-lint.sh
39+
2440
- name: Host QA + lint
2541
run: bash firmware/scripts/ota-release.sh lint
2642

@@ -29,9 +45,12 @@ jobs:
2945
env:
3046
BASE: ${{ github.base_ref }}
3147
run: |
48+
# Scope to firmware/src (the shipped image is built from it + the .zap under sdk-edits).
49+
# firmware/test is host-only QA that never changes the image, so a test-tooling edit must
50+
# NOT force a softwareVersion bump.
3251
git fetch --no-tags --depth=1 origin "$BASE" || true
33-
if git diff --quiet FETCH_HEAD -- firmware/src firmware/test; then
34-
echo "no firmware/src|test change vs $BASE -- bump not required"; exit 0
52+
if git diff --quiet FETCH_HEAD -- firmware/src; then
53+
echo "no firmware/src change vs $BASE -- bump not required"; exit 0
3554
fi
3655
new=$(bash firmware/scripts/ota-release.sh verint "$(cat firmware/src/version.txt)")
3756
oldsem=$(git show "FETCH_HEAD:firmware/src/version.txt" 2>/dev/null | tr -d '[:space:]' || true)

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ First public cut. Everything below already ran privately; this release drops the
2121
covers codec, Matter↔A/C mapping, and virtual-A/C round-trip checks.
2222
- Reverse-engineering docs: RS-485 protocol, cloud/firewall, stock-FW init, hardware.
2323
- CI: a host lint gate on every push/PR, plus tagged-release builds that attach `.bin`/`.ota` to
24-
GitHub Releases (ESP32 on a hosted runner, AmebaZ2 on a self-hosted SDK runner).
24+
GitHub Releases (both the AmebaZ2 and ESP32 builds run on a self-hosted SDK runner).

firmware/.githooks/pre-commit

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@ if git diff --cached --name-only | grep -qE '^firmware/(src|test)/|room-air-cond
1010
echo "[pre-commit] LINT FAILED. Fix, or bypass with: git commit --no-verify"; exit 1; }
1111
fi
1212

13+
# ESP32 tree has no SDK-free build gate; esp32-lint.sh checks version consistency (host-only).
14+
if git diff --cached --name-only | grep -qE '^firmware/esp32-matter/'; then
15+
echo "[pre-commit] esp32 firmware changed -> esp32-lint.sh"
16+
bash "$REPO/firmware/scripts/esp32-lint.sh" || {
17+
echo "[pre-commit] ESP32 LINT FAILED. Fix, or bypass with: git commit --no-verify"; exit 1; }
18+
fi
19+
1320
# Prose slop gate: block em dashes in newly-added markdown (no-op when no .md is staged).
1421
bash "$REPO/firmware/scripts/stop-slop.sh" || exit 1
1522

firmware/esp32-matter/.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
# ESP-IDF / esp-matter build outputs (all regenerable from source + sdkconfig.defaults)
1+
# ESP-IDF / esp-matter build outputs (regenerable from source + sdkconfig.defaults).
2+
# NOTE: dependencies.lock is intentionally TRACKED (not ignored) -- it pins the exact
3+
# managed-component versions/hashes for reproducible builds, per ESP-IDF's own guidance.
24
build/
35
.cache/
46
managed_components/
5-
dependencies.lock
67
sdkconfig
78
sdkconfig.old

firmware/esp32-matter/CMakeLists.txt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# . ~/esp/esp-idf-v5.5.4/export.sh && . $ESP_MATTER_PATH/export.sh
33
# idf.py set-target esp32 && idf.py build flash monitor
44
cmake_minimum_required(VERSION 3.16)
5-
set(PROJECT_VER "1.0.7")
5+
set(PROJECT_VER "1.0.8")
66

77
# Unified versioning (issue #77): the Matter softwareVersion INT is DERIVED from PROJECT_VER --
88
# MAJOR*10000+MINOR*100+PATCH -> a readable, strictly-monotonic uint32. This keeps the human
@@ -15,6 +15,14 @@ list(GET _ver_parts 1 _ver_minor)
1515
list(GET _ver_parts 2 _ver_patch)
1616
math(EXPR PROJECT_VER_INT "${_ver_major}*10000 + ${_ver_minor}*100 + ${_ver_patch}")
1717

18+
# esp-matter's build reads PROJECT_VER_NUMBER (NOT our PROJECT_VER_INT) to set the GN arg
19+
# chip_config_software_version_number -> CHIP_CONFIG_SOFTWARE_VERSION_NUMBER, and that macro is what
20+
# ESP32 ConfigurationManagerImpl::GetSoftwareVersion() returns -- i.e. the BasicInformation
21+
# SoftwareVersion attribute (0/40/9) that HA + Matter OTA see. esp-matter/CMakeLists.txt defaults it
22+
# to 0 when PROJECT_VER_NUMBER is undefined, which is why the device reported softwareVersion 0
23+
# despite the correct semver string. Define the name esp-matter looks for. (issue #77)
24+
set(PROJECT_VER_NUMBER ${PROJECT_VER_INT})
25+
1826
if(NOT DEFINED ENV{ESP_MATTER_PATH})
1927
message(FATAL_ERROR "ESP_MATTER_PATH not set -- run: . <esp-matter>/export.sh")
2028
endif()
@@ -48,9 +56,9 @@ idf_build_set_property(COMPILE_OPTIONS "-Wno-format-nonliteral;-Wno-format-secur
4856
# keeps the literal path out of this tracked file; everything (IDF, esp-matter, project) sits under it.
4957
idf_build_set_property(COMPILE_OPTIONS "-ffile-prefix-map=$ENV{HOME}=/build" APPEND)
5058

51-
# Force the Matter softwareVersion int from PROJECT_VER (issue #77). Wins over sdkconfig's
52-
# CONFIG_DEVICE_SOFTWARE_VERSION_NUMBER because CHIPDeviceConfig.h guards the macro with #ifndef,
53-
# so the OTA int can never drift from the semver. (The string stays in sdkconfig.defaults, kept
54-
# equal to PROJECT_VER.)
59+
# Also pin CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION (a DIFFERENT macro from the
60+
# CHIP_CONFIG_SOFTWARE_VERSION_NUMBER above that GetSoftwareVersion actually returns) for the CHIP
61+
# code paths that read it (e.g. some OTA-requestor defaults). Belt-and-suspenders; the reported
62+
# softwareVersion attribute comes from PROJECT_VER_NUMBER -> chip_config_software_version_number.
5563
idf_build_set_property(COMPILE_DEFINITIONS "CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION=${PROJECT_VER_INT}" APPEND)
5664
message(STATUS "hisense: Matter softwareVersion ${PROJECT_VER_INT} (\"${PROJECT_VER}\") [issue #77]")
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
dependencies:
2+
espressif/cjson:
3+
component_hash: e788323270d90738662d66fffa910bfe1fba019bba087f01557e70c40485b469
4+
dependencies:
5+
- name: idf
6+
require: private
7+
version: '>=5.0'
8+
source:
9+
registry_url: https://components.espressif.com/
10+
type: service
11+
version: 1.7.19~2
12+
espressif/esp_delta_ota:
13+
component_hash: 147161b602ef51e9f6649eb6d90c4d4ac3c94228cb264fa0e68be7877180462d
14+
dependencies:
15+
- name: idf
16+
require: private
17+
version: '>=4.3'
18+
source:
19+
registry_url: https://components.espressif.com/
20+
type: service
21+
version: 1.1.4
22+
espressif/esp_encrypted_img:
23+
component_hash: a3d20984246263bf8f3fabb0cf5ced72e1499dcc0073fc7334646c0882fd1b3c
24+
dependencies:
25+
- name: espressif/esp_secure_cert_mgr
26+
registry_url: https://components.espressif.com
27+
require: private
28+
rules:
29+
- if: idf_version >= 5.3
30+
version: '>=2.5.1'
31+
- name: idf
32+
require: private
33+
version: '>=5.0'
34+
source:
35+
registry_url: https://components.espressif.com/
36+
type: service
37+
version: 2.7.0
38+
espressif/esp_secure_cert_mgr:
39+
component_hash: 40a986c1f45d91eb6d339ca51dcab90c4ecce2a6622c268edaaa05887852d464
40+
dependencies:
41+
- name: idf
42+
require: private
43+
version: '>=4.3'
44+
source:
45+
registry_url: https://components.espressif.com/
46+
type: service
47+
version: 2.9.2
48+
espressif/mdns:
49+
component_hash: e81ca7a7f53ea34e78274df054da692c272e1315572876b237b1748e267c013b
50+
dependencies:
51+
- name: idf
52+
require: private
53+
version: '>=5.0'
54+
source:
55+
registry_url: https://components.espressif.com/
56+
type: service
57+
version: 1.11.3
58+
idf:
59+
source:
60+
type: idf
61+
version: 5.5.4
62+
direct_dependencies:
63+
- espressif/cjson
64+
- espressif/esp_delta_ota
65+
- espressif/esp_encrypted_img
66+
- espressif/esp_secure_cert_mgr
67+
- espressif/mdns
68+
manifest_hash: 23158991195c91464282b0a6d37181b80b3866864ee8d0b7330ae1c3b40c7681
69+
target: esp32
70+
version: 2.0.0

firmware/esp32-matter/sdkconfig.defaults

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,12 @@ CONFIG_ENABLE_OTA_REQUESTOR=y
4242
CONFIG_CUSTOM_DEVICE_INFO_PROVIDER=y
4343
# Matter OTA software version. Unified scheme (issue #77): the int is DERIVED from PROJECT_VER
4444
# in CMakeLists.txt (MAJOR*10000+MINOR*100+PATCH) and injected as a compile definition that WINS
45-
# over this Kconfig value (CHIPDeviceConfig.h #ifndef guard). These are kept equal to PROJECT_VER
46-
# "1.0.3" (-> 10003) for clarity/fallback; edit PROJECT_VER, not this, and they stay in sync.
47-
CONFIG_DEVICE_SOFTWARE_VERSION_NUMBER=10005
48-
CONFIG_DEVICE_SOFTWARE_VERSION_STRING="1.0.5"
45+
# over this Kconfig NUMBER (CHIPDeviceConfig.h #ifndef guard). The STRING is NOT overridden by CMake,
46+
# so it (and the fallback NUMBER) MUST stay equal to PROJECT_VER or the device reports a stale
47+
# softwareVersionString. Edit PROJECT_VER in CMakeLists.txt, then update both lines below.
48+
# esp32-lint.sh enforces this equality (fails the commit/CI if they drift).
49+
CONFIG_DEVICE_SOFTWARE_VERSION_NUMBER=10008
50+
CONFIG_DEVICE_SOFTWARE_VERSION_STRING="1.0.8"
4951
# --- OTA hardening (faster + reliable on marginal Wi-Fi) ---
5052
# Delta OTA: ship a diff (tens of KB) instead of the full ~1.5MB image over BDX.
5153
CONFIG_ENABLE_DELTA_OTA=y

0 commit comments

Comments
 (0)