Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ jobs:
~/.espressif
~/esp/esp-idf
# Bump the suffix when changing the IDF version to invalidate.
key: esp-idf-release-v6.1-${{ runner.os }}-v1
key: esp-idf-v6.1-beta1-${{ runner.os }}-v1

# The release-channel tag burned into the binary as MM_RELEASE (shown by
# SystemModule alongside the semver). Same resolution as the release
Expand Down Expand Up @@ -166,15 +166,16 @@ jobs:
- name: Build firmware
uses: espressif/esp-idf-ci-action@v1
with:
# Match the local development IDF (release/v6.1, v6.1-dev-5215-g0d928780081).
# Match the local development IDF (v6.1-beta1, commit b1d13e9f).
# The project uses v6-era APIs — `esp_eth_phy_new_generic`, the new
# mDNS component manager, `int clock_gpio` in the EMAC config (v5.x
# had a strongly-typed enum). v5.4 fails to compile platform_esp32.cpp.
# `release-v6.1` is the espressif/idf Docker tag built from the same
# `release/v6.1` branch the local pin lives on — the earliest IDF line
# that carries the esp32s31 preview target, and more stable than the
# rolling `v6.1-dev` tag.
esp_idf_version: release-v6.1
# `v6.1-beta1` is the espressif/idf Docker tag pinned to the same
# tagged beta the local pin uses — a fixed, signed pre-release (not the
# rolling `release-v6.1` branch tag), so CI and local build the exact
# same tree. This tracks the v6.1 line toward GA; re-pin to the `v6.1`
# tag once it ships (a deliberate re-test pass, see docs/building.md).
esp_idf_version: v6.1-beta1
# The IDF target follows the firmware-key prefix: esp32s31* → esp32s31
# (checked BEFORE esp32s3 — esp32s31 also startsWith 'esp32s3'),
# esp32s3* → esp32s3, esp32p4* → esp32p4 (the only target that pulls
Expand Down
12 changes: 6 additions & 6 deletions docs/building.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Every host needs [uv](https://docs.astral.sh/uv/), CMake 3.20+, and a C++20 comp

The ESP32 target uses ESP-IDF directly, not the Arduino framework.

**Tested IDF version:** **release/v6.1** (internal `v6.1-dev-5215-g0d928780081`). CI builds against this branch (the `release-v6.1` Docker tag) and local builds should match (clone command below). The why, the alternatives, and how to check for a newer one are in [ESP-IDF version](#esp-idf-version) below.
**Tested IDF version:** **v6.1-beta1** (commit `b1d13e9f`). CI builds against the `v6.1-beta1` Docker tag and local builds should match (clone command below). The why, the alternatives, and how to check for a newer one are in [ESP-IDF version](#esp-idf-version) below.

### Prerequisites

Expand All @@ -91,16 +91,16 @@ You need [uv](https://docs.astral.sh/uv/) (Python launcher), CMake 3.20+, and a
**macOS / Linux:**

```sh
git clone --depth 1 --branch release/v6.1 https://github.com/espressif/esp-idf.git ~/esp/esp-idf
git clone --depth 1 --branch v6.1-beta1 https://github.com/espressif/esp-idf.git ~/esp/esp-idf
```

**Windows** (PowerShell — run once with admin to enable long paths if you haven't already):

```powershell
# IDF and its tooling have deeply nested paths; without longpaths the clone
# trips MAX_PATH (260 chars) inside the release/v6.1 tree.
# trips MAX_PATH (260 chars) inside the v6.1-beta1 tree.
git config --global core.longpaths true
git clone --depth 1 --branch release/v6.1 https://github.com/espressif/esp-idf.git "$env:USERPROFILE\esp\esp-idf"
git clone --depth 1 --branch v6.1-beta1 https://github.com/espressif/esp-idf.git "$env:USERPROFILE\esp\esp-idf"
```

Then run the one-time Python environment setup — either open MoonDeck (`uv run moondeck/moondeck.py`), go to the ESP32 tab, and click **Setup ESP-IDF**, or run it directly:
Expand Down Expand Up @@ -130,9 +130,9 @@ The ESP32 tab in MoonDeck wraps the same steps as cards (Setup → Firmware →

### ESP-IDF version

**Pinned to `v6.1-dev-5215-g0d928780081`** (a specific commit on the `release/v6.1` branch). `setup_esp_idf.py` holds the exact commit in `PINNED_IDF_VERSION`, warns loudly when the installed tree differs, and by default offers to check the pin out so a stray `git pull` or a fresh shallow clone landing on a newer commit converges back rather than silently building against the wrong tree (`--no-checkout` keeps it warn-only). Minimum is ESP-IDF v5.1 (C++20 needs GCC 12+); the project uses v6.x APIs (`esp_eth_phy_new_generic`, the component manager for mDNS, the modern RMT/parlio/LCD drivers) so v5.x would need adjustments.
**Pinned to `v6.1-beta1`** (commit `b1d13e9f`, a signed pre-release tag). `setup_esp_idf.py` holds the exact commit in `PINNED_IDF_VERSION`, warns loudly when the installed tree differs, and by default offers to check the pin out so a stray `git pull` or a fresh shallow clone landing on a newer commit converges back rather than silently building against the wrong tree (`--no-checkout` keeps it warn-only). Minimum is ESP-IDF v5.1 (C++20 needs GCC 12+); the project uses v6.x APIs (`esp_eth_phy_new_generic`, the component manager for mDNS, the modern RMT/parlio/LCD drivers) so v5.x would need adjustments.

**Why `release/v6.1` and not a stable tag.** As of June 2026 the v6.x line is: **v6.0 is the current stable** (GA 2026-02-27); **v6.1 is still pre-release** (beta1 2026-06-11, RC1 2026-07-23, GA 2026-07-31). We pin a commit on the `release/v6.1` *branch* (the stabilising line, not `master`) because it carries driver fixes we want on the newer SoCs (P4 parlio, RMT v2 on every chip) **and is the earliest IDF line that carries the `esp32s31` preview target** — and because v6.0 vs v6.1 is a small delta. The trade-off is honest: a pre-release branch gets **no support guarantee** and moves under you, which is exactly why the pin is a fixed commit, not a floating branch. The clean inflection point is **v6.1 GA (2026-07-31)**: re-pin to the `v6.1` tag then, which starts the 30-month support clock (see below). That move is a deliberate re-test pass, not a routine pull. Tracked in [backlog](backlog/README.md).
**Why a v6.1 pre-release and not a stable tag.** The v6.x line is: **v6.0 is the current stable** (GA 2026-02-27); **v6.1 is pre-release** (beta1 2026-06-24, RC1 and GA targeted late July 2026). We pin the `v6.1-beta1` *tag* (a fixed, signed pre-release, not the rolling `release/v6.1` branch) because it carries driver fixes for the newer SoCs (P4 parlio, RMT v2 on every chip) **and is on the earliest IDF line that carries the `esp32s31` preview target** — and because v6.0 vs v6.1 is a small delta. Riding the betas toward GA means breakage from the v6.1 delta surfaces incrementally, not all at once at the GA re-pin. The trade-off is honest: a pre-release gets **no support guarantee**, which is why the pin is a fixed tag, not a floating branch. The clean inflection point is **v6.1 GA**: re-pin to the `v6.1` tag then, which starts the 30-month support clock (see below). Each pin move (beta1 → RC → GA) is a deliberate re-test pass, not a routine pull. Tracked in [backlog](backlog/README.md).

**v6.0 is the floor — don't depend on anything newer than it.** Because **v6.0 stable is our fallback** if the v6.1 line proves troublesome, the firmware and build tooling must stay buildable on v6.0. The rule is generic: **use no IDF API, component, Kconfig symbol, or tool that isn't present in v6.0.** A feature that exists only on the v6.1-dev branch (or arrives in a later minor) is off-limits until v6.0 is no longer the fallback. When adopting anything new from the IDF, confirm it shipped in v6.0 first (check the v6.0 docs / release notes, not `latest`); if it's v6.1-only, it waits.

Expand Down
10 changes: 5 additions & 5 deletions moondeck/build/setup_esp_idf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
INSTALL_SCRIPT_NAME = "install.bat" if sys.platform == "win32" else "install.sh"

# The ESP-IDF commit every target (classic ESP32, S3, P4, S31) has been
# validated against — a commit on the `release/v6.1` branch, the earliest IDF
# line that carries the esp32s31 preview target. The script can't *clone* the
# validated against — the `v6.1-beta1` tag, on the earliest IDF line that
# carries the esp32s31 preview target. The script can't *clone* the
# IDF for you (the dev does the initial clone per docs/building.md), but when the
# installed checkout drifts from this pin it offers to move it (git checkout +
# submodule sync) so a fresh shallow clone landing on a newer dev-branch commit
# — exactly what turns a green build red with no code change — converges back to
# the validated commit. Pass --no-checkout to keep the warn-only behaviour (a
# dev deliberately migrating off this snapshot to a newer release re-tests, not
# auto-reverts).
PINNED_IDF_COMMIT = "0d9287800812c95662921c2c5e812023939e3d58"
PINNED_IDF_VERSION = "v6.1-dev-5215-g0d928780081"
PINNED_IDF_COMMIT = "b1d13e9fe441c4f75e240c98a26fd631b7b3232f"
PINNED_IDF_VERSION = "v6.1-beta1"


def _installed_idf_commit(idf_path: Path) -> str:
Expand All @@ -49,7 +49,7 @@ def _checkout_pinned(idf_path: Path) -> bool:
co = subprocess.run(["git", "checkout", PINNED_IDF_COMMIT], cwd=str(idf_path))
if co.returncode != 0:
print(f" Checkout failed — the pinned commit may not be fetched yet. "
f"In {idf_path}: git fetch origin release/v6.1, then re-run.")
f"In {idf_path}: git fetch origin tag v6.1-beta1, then re-run.")
return False
# The new commit points its submodules at different SHAs; sync them so the
# build sees the matching component sources.
Expand Down
Loading