1. Тема дня

Учимся доказывать:

text
какая прошивка работает;
из какого commit она собрана;
каким toolchain;
с каким sdkconfig;
какой SHA-256 бинарника;
какой ELF нужен для coredump.

Главная мысль: version=1.8.0 недостаточно. Полная идентичность прошивки - это source, configuration, dependencies, toolchain и хеш конкретного артефакта.

2. Зачем это нужно

Для postmortem нельзя символизировать адрес только по версии:

text
version=1.8.0
PC=0x40091a42

Та же версия могла собираться с разными sdkconfig, stack sizes, patches, component versions. Нужны:

c
Git commit;
dirty state;
ESP-IDF version;
sdkconfig hash;
dependencies.lock hash;
ELF SHA-256;
firmware.bin SHA-256.

Для EC25 полная идентичность устройства также включает:

c
EC25 firmware;
MBN profile;
hardware revision;
config generation.

3. Теория

Version, build identity, reproducibility, authenticity

  • Version: 1.8.0 - удобно человеку.
  • Build identity: commit, config, dependencies, toolchain.
  • Reproducibility: две независимые сборки дают одинаковые байты.
  • Authenticity: release manifest подписан trusted key.

Git commit недостаточен

Если дерево dirty, commit не описывает бинарник. Release должен требовать:

text
git_dirty=false

ESP-IDF reproducible build

В sdkconfig.defaults:

text
CONFIG_APP_REPRODUCIBLE_BUILD=y

Не использовать:

text
__DATE__
__TIME__

Toolchain pinning

Плохо:

text
image: espressif/idf:latest

Лучше:

text
image: espressif/idf:v6.0.2@sha256:<digest>

esp_app_desc_t

ESP-IDF включает в образ esp_app_desc_t:

c
project name;
version;
ESP-IDF version;
secure version;
app_elf_sha256.

Runtime CLI version должен показывать эти поля.

Release manifest

Manifest связывает:

text
source -> environment -> configuration -> artifacts -> validation

Пример полей:

c
{
  "project": "traffic-controller",
  "version": "1.8.0",
  "git_commit": "9ac04be12f91",
  "dirty": false,
  "idf": "v6.0.2",
  "sdkconfig_sha256": "...",
  "app_bin_sha256": "...",
  "app_elf_sha256": "...",
  "hil_result": "passed"
}

Не пытайся встроить SHA-256 бинарника в него самого: это self-reference. Хеш итогового binary хранится во внешнем manifest.

STM32

Для STM32 сохраняй:

c
firmware.elf;
firmware.map;
firmware.hex/bin;
.ioc;
startup;
linker script;
HAL/LL/CMSIS versions;
STM32CubeMX version;
compiler version;
build flags.

Generated code лучше хранить в Git и в CI проверять повторную генерацию .ioc без diff.

4. Типичные ошибки

  • Версия содержит только 1.8.0.
  • Release собран из dirty tree.
  • Используется __DATE__/__TIME__.
  • CI использует latest.
  • Managed components не зафиксированы.
  • .bin сохранен, .elf удален.
  • ELF от другой сборки используется для coredump.
  • sdkconfig не сохраняется.
  • STM32 .ioc и CubeMX version не сохраняются.
  • Production пересобирает прошивку локально вместо CI artifact.

5. Практическое задание на 30-60 минут

Создай RELEASE_POLICY.md:

markdown
# Firmware release policy
1. Release builds are created only by CI.
2. Release source trees must be clean.
3. Every release has a semantic version and Git commit.
4. ESP-IDF and toolchain are pinned by container digest.
5. sdkconfig and dependency lock are archived.
6. Reproducible build mode is enabled.
7. Application ELF and BIN must reproduce bit-for-bit.
8. ELF, map, binaries and flash metadata are retained.
9. All artifacts have SHA-256 hashes.
10. Release manifest is signed.
11. Production flashes only immutable release artifacts.
12. Field diagnostics report firmware and modem identities.

Проверь две сборки в разных каталогах:

text
cmp /tmp/repro-a/build/traffic_controller.bin /tmp/repro-b/build/traffic_controller.bin
cmp /tmp/repro-a/build/traffic_controller.elf /tmp/repro-b/build/traffic_controller.elf

Собери release bundle:

text
.bin
.elf
.map
bootloader.bin
partition-table.bin
partition CSV
flasher_args.json
sdkconfig
dependencies.lock
version.txt
manifest
HIL report

6. Что почитать или попробовать дальше

  • ESP-IDF Reproducible Builds.
  • esp_app_desc_t и App Image Format.
  • IDF Component Manager dependencies.lock.
  • STM32CubeMX command-line generation и user code sections.
Два файла прошивки показывают version 1.8.0, но собраны с разными sdkconfig. Что можно заключить?

Критерии: Используйте полную build identity, а не только метку версии.

Задание

Проверьте release bundle, содержащий только firmware.bin и version.txt. Назовите недостающие evidence для воспроизводимости и postmortem, ничего не пересобирая.

Критерии самопроверки: Разделите сохранённые артефакты и доказанную воспроизводимость. Хеш binary должен оставаться внешним, чтобы избежать self-reference.

Показать ответ автора

Сохранить точный ELF, configuration/sdkconfig и dependency lock, source commit и чистоту дерева, pinned toolchain, соответствующие map/flash metadata, SHA-256 артефактов и внешний release manifest. Воспроизводимость проверяется независимыми сборками, а не выводится из version.txt.