From 6a10d31f4568843b20154f54635d921c0b1474a0 Mon Sep 17 00:00:00 2001 From: Cryptotomte Date: Wed, 10 Jun 2026 10:22:26 +0200 Subject: [PATCH] chore: pin all dependencies and add CI build for frozen legacy firmware - platformio.ini: pin platform espressif32@6.12.0 and every library to the exact versions that built the April 2026 binary (from local .pio/libdeps metadata); document the AsyncTCP duplicate-install trap; comment out machine-specific COM ports - arduino-legacy.yml: CI build of firmware + littlefs image, all four flashable artifacts verified and uploaded (90-day retention) - CLAUDE.md: maintenance banner (frozen branch, never merged to main), corrected stale /update OTA claim (no OTA endpoint exists; deploys are cable/serial flash) Verified locally: clean build with pinned set, firmware.bin 963 KB (+2% vs April, explained by the June commit on this branch). Co-Authored-By: Claude Fable 5 --- .github/workflows/arduino-legacy.yml | 72 ++++++++++++++++++++++++++++ CLAUDE.md | 39 ++++++++++++--- platformio.ini | 36 ++++++++++---- 3 files changed, 130 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/arduino-legacy.yml diff --git a/.github/workflows/arduino-legacy.yml b/.github/workflows/arduino-legacy.yml new file mode 100644 index 0000000..62eda82 --- /dev/null +++ b/.github/workflows/arduino-legacy.yml @@ -0,0 +1,72 @@ +# CI build for the frozen legacy Arduino/PlatformIO firmware. +# Lives on the arduino-maintenance branch only — never merged to main. +# Guarantees the PRD success criterion: `git checkout arduino-final` always builds. +# +# Note: GitHub only surfaces workflow_dispatch in the UI/API for workflows on the +# default branch. Manual/scheduled reproducibility builds of this branch are +# provided by .github/workflows/arduino-legacy-cold.yml on main (added in the +# phase 0 PR); this file's push/PR triggers cover changes to the branch itself. +name: arduino-legacy-build + +on: + push: + branches: + - arduino-maintenance + pull_request: + branches: + - arduino-maintenance + workflow_dispatch: + +jobs: + build: + name: Build legacy firmware (pinned deps) + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Cache PlatformIO and pip + uses: actions/cache@v4 + with: + path: | + ~/.platformio/.cache + ~/.cache/pip + key: pio-legacy-${{ runner.os }}-${{ hashFiles('platformio.ini') }} + restore-keys: | + pio-legacy-${{ runner.os }}- + + - name: Install PlatformIO Core (pinned) + run: pip install platformio==6.1.19 + + - name: Build firmware + run: pio run -e wateringsystem + + - name: Build LittleFS filesystem image + run: pio run -e wateringsystem -t buildfs + + # if-no-files-found: error only fires when ZERO files match, so a partial + # match could silently upload an incomplete artifact set. Verify all four + # files exist before uploading. + - name: Verify all artifacts exist + run: | + test -f .pio/build/wateringsystem/firmware.bin + test -f .pio/build/wateringsystem/littlefs.bin + test -f .pio/build/wateringsystem/bootloader.bin + test -f .pio/build/wateringsystem/partitions.bin + + - name: Upload flashable artifacts + uses: actions/upload-artifact@v4 + with: + name: arduino-firmware + retention-days: 90 + if-no-files-found: error + path: | + .pio/build/wateringsystem/firmware.bin + .pio/build/wateringsystem/littlefs.bin + .pio/build/wateringsystem/bootloader.bin + .pio/build/wateringsystem/partitions.bin diff --git a/CLAUDE.md b/CLAUDE.md index 1f39b13..3d355b5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,5 +1,15 @@ # CLAUDE.md +> ⚠️ **MAINTENANCE BRANCH — FROZEN LEGACY FIRMWARE** +> This branch (`arduino-maintenance`) preserves the Arduino/PlatformIO firmware (v2.3.x) +> that runs the production greenhouse unit. It is NEVER merged into `main`. +> Active development happens on `main` under `firmware/` (ESP-IDF). +> All platform and library dependencies are pinned exactly in `platformio.ini` +> (do not relax the pins), and CI (`.github/workflows/arduino-legacy.yml`) is the +> canonical build. Patch flow: worktree → fix → CI build (pinned deps) → deploy to the +> production unit (serial flash — this firmware has no web-OTA endpoint) → +> tag `arduino-v2.3.x`. + This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview @@ -19,6 +29,12 @@ WateringSystem v2.3 is a production-ready embedded IoT system for automated gree ### Essential Build Commands +**CI is the canonical build:** every push to `arduino-maintenance` runs +`.github/workflows/arduino-legacy.yml`, which builds with exactly pinned +dependencies and uploads a fully flashable artifact set (`firmware.bin`, +`littlefs.bin`, `bootloader.bin`, `partitions.bin`). Local PlatformIO builds +are optional and only needed for flashing/monitoring over USB. + ```bash # Build the project platformio run --environment wateringsystem @@ -115,7 +131,7 @@ The codebase follows strict interface-based design with clean separation of conc ### Development Server - **Framework:** ESPAsyncWebServer with LittleFS file storage - **Features:** Real-time sensor monitoring, pump control, configuration management -- **OTA Updates:** Web-based firmware updates via /update endpoint +- **Firmware Updates:** No web-OTA endpoint exists in this firmware; updates are flashed over serial (use the CI artifacts: firmware.bin, littlefs.bin, bootloader.bin, partitions.bin) - **WiFi Configuration:** AP mode setup at 192.168.4.1 when unconfigured ### API Endpoints Structure @@ -178,15 +194,24 @@ The system includes comprehensive diagnostic commands accessible via Serial moni ## Key Dependencies +All dependencies are pinned to exact versions (the known-good set that built the +production binary). Never reintroduce `^`/`~` ranges or unpinned entries on this branch. + ```ini -lib_deps = - adafruit/Adafruit BME280 Library@^2.2.2 - adafruit/Adafruit Unified Sensor@^1.1.6 - bblanchon/ArduinoJson@^6.20.0 - me-no-dev/AsyncTCP - me-no-dev/ESPAsyncWebServer +platform = espressif32@6.12.0 +lib_deps = + adafruit/Adafruit BME280 Library@2.2.4 + adafruit/Adafruit Unified Sensor@1.1.15 + bblanchon/ArduinoJson@6.21.5 + me-no-dev/AsyncTCP@3.3.2 + me-no-dev/ESPAsyncWebServer@3.6.0 + adafruit/Adafruit BusIO@1.17.0 ; transitive pin (BME280 dep) ``` +Note: ESPAsyncWebServer also installs ESP32Async/AsyncTCP transitively, but only the +direct `me-no-dev/AsyncTCP@3.3.2` copy is linked (same as the production build). Do not +add the esp32async copy to `lib_deps` — it causes multiple-definition linker errors. + ## System Monitoring & Maintenance ### Status Indicators diff --git a/platformio.ini b/platformio.ini index 750886c..148f713 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,15 +7,23 @@ ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html +; +; FROZEN LEGACY CONFIGURATION (arduino-maintenance branch) +; All platform and library versions are pinned exactly to the known-good +; set that produced the April 2026 production binary. Do NOT relax these +; pins on this branch — reproducibility is the whole point. [env:wateringsystem] -platform = espressif32 +platform = espressif32@6.12.0 board = esp32dev framework = arduino -upload_port = COM4 -monitor_port = COM4 +; Builds are CI-only (see .github/workflows/arduino-legacy.yml); serial ports +; are machine-specific, so the upload/monitor ports are intentionally not set. +; Uncomment and adjust locally if you need to flash/monitor over USB. +; upload_port = COM4 +; monitor_port = COM4 monitor_speed = 115200 -build_flags = +build_flags = -D VERSION=0.1.0 -D DEBUG=1 ; Prevent conflict with ESP header HTTP method macros by undefining them before ESPAsyncWebServer includes @@ -34,11 +42,19 @@ build_flags = -UHTTP_PATCH -UHTTP_HEAD -UHTTP_OPTIONS -lib_deps = - adafruit/Adafruit BME280 Library@^2.2.2 - adafruit/Adafruit Unified Sensor@^1.1.6 - bblanchon/ArduinoJson@^6.20.0 - me-no-dev/AsyncTCP - me-no-dev/ESPAsyncWebServer +lib_deps = + adafruit/Adafruit BME280 Library@2.2.4 + adafruit/Adafruit Unified Sensor@1.1.15 + bblanchon/ArduinoJson@6.21.5 + me-no-dev/AsyncTCP@3.3.2 + me-no-dev/ESPAsyncWebServer@3.6.0 + ; Transitive dependency pinned explicitly (pulled in by Adafruit BME280): + adafruit/Adafruit BusIO@1.17.0 + ; NOTE: ESPAsyncWebServer 3.6.0 also declares ESP32Async/AsyncTCP@^3.3.2, + ; which gets *installed* alongside me-no-dev/AsyncTCP@3.3.2, but the LDF + ; links only the direct lib_deps copy (3.3.2) — verified identical to the + ; known-good April 2026 build. Do NOT add esp32async/AsyncTCP to lib_deps; + ; that promotes it to a linked dependency and causes multiple-definition + ; linker errors against the 3.3.2 copy. board_build.filesystem = littlefs board_build.partitions = default.csv