Skip to content

ci: build release targets from a shared matrix manifest#129

Open
g4bri3lDev wants to merge 1 commit into
mainfrom
ci/release-matrix
Open

ci: build release targets from a shared matrix manifest#129
g4bri3lDev wants to merge 1 commit into
mainfrom
ci/release-matrix

Conversation

@g4bri3lDev

Copy link
Copy Markdown
Member

Replaces the ten copy-pasted per-target build blocks in release.yml with a single matrix job driven by a new .github/firmware-targets.json, shared with main.yaml so CI and the release can no longer disagree about which targets exist or how they are packaged.

Why: the duplication had already drifted twice

esp32-c3-N4 merged images were built with the wrong chip. release.yml set pioenv=esp32-c3-N4 but ran esptool.py --chip esp32-c6 merge_bin. That is not just a mislabel — byte 0x3 of the ESP32 image header packs flash size and flash frequency, and the frequency encoding is chip-specific:

file before after
esp32-c3-N4_full.bin 0x20 (4MB, 40 MHz) 0x2f (4MB, 80 MHz)
esp32-c3-N16_full.bin 0x4f 0x4f (unchanged)

So C3-N4 boards flashed with _full.bin have been running their SPI flash at half speed. The correct value now matches the sibling esp32-c3-N16 target. Only the merged image was affected; the plain .bin comes straight from pio run.

esp32-N4 was never released. It is in platformio.ini and in main.yaml, but release.yml built only 10 of the 11 targets, so plain ESP32-N4 boards got no release binaries at all. It is not a copy-paste of the others either: it is a classic ESP32, whose bootloader sits at 0x1000 rather than the 0x0000 used by S3/C3/C6, so bootloader_offset had to become per-target data.

Also in here

  • Caching of ~/.platformio/.cache and ~/.cache/pip, matching main.yaml; release.yml had none.
  • Pinned toolchainplatformio==6.1.19, esptool==5.3.1, adafruit-nrfutil, intelhex, and uf2conv.py at a commit. Each is the version an unpinned install resolved to on the day 2.25.1 was built, so this preserves the current toolchain rather than moving it. main.yaml is pinned to the same Core so CI predicts the release.
  • permissions, timeout-minutes, actions/checkout@v6.
  • Asset upload is gated on every target succeeding, so a failed build can no longer leave a release with a partial asset set.

Verification

A/B tested on a fork: the old workflow and the new matrix were run against the same commit, in the same window, and their artifacts diffed.

  • Identical file sets apart from the new esp32-N4 pair; identical sizes throughout; NRF52840.hex and .uf2 byte-identical.
  • Every ESP32 binary differs in ~68 bytes of ~1.5 MB (0.004%), confined to three regions: the esp_app_desc_t time/date fields, a short string, and app_elf_sha256. That is ESP-IDF build-timestamp non-determinism, not this change. In each _full.bin those regions sit at the .bin offsets +0x10000, confirming merge_bin is a faithful concatenation.
  • esp32-c3-N4_full.bin is the sole file with extra differing regions — the header fix above.
  • esp32-N4_full.bin verified structurally: 0xFF padding through 0x0-0xFFF, bootloader magic 0xE9 at 0x1000.

Wall clock went from 11m25s (serial) to 3m45s (parallel), while building one more target.

Not changed, deliberately

Six envs set board_build.flash_mode=qio in platformio.ini, but the workflow has always passed --flash_mode dio. That is preserved as-is: changing it would alter bytes for six targets with no hardware validation. Worth a separate look.

esp32-N4 has never been flashed to hardware — its parameters are correct by documentation, but it deserves one test flash before a release ships it.

Replace the ten copy-pasted per-target build blocks in release.yml with a
single matrix job driven by .github/firmware-targets.json, shared with
main.yaml so CI and release cannot disagree about the target list.

The duplication had already drifted twice:
  - esp32-c3-N4 merged images were built with --chip esp32-c6
  - esp32-N4 was built in CI but never released

Also: cache pip/platformio, pin the toolchain (Core, esptool, nrfutil,
intelhex, uf2conv) so a tag rebuilds identically, add permissions and
timeouts, and gate asset upload on every target succeeding so a failed
build can no longer leave a release with a partial asset set.

Includes release-legacy.yml (arm A) for the A/B verification; temporary.
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