fix(arduino-cli): pin ATTinyCore to 1.4.1 (azduino.com micronucleus host unreachable)

ATTinyCore >=1.5.0 declares ATTinyCore:micronucleus@2.5-azd1b as a tool
dependency, hosted at https://azduino.com/bin/micronucleus/. That host
has been unreachable (connection refused) for extended periods, causing
every ATtiny85 compile to fail at the core-install step with:

  Download failed: performing HEAD request: ... dial tcp ...: connection refused
  Failed to install required core: ATTinyCore:avr

micronucleus is only used for USB upload — never for compilation — but
arduino-cli refuses to install a core whose tool deps cannot fetch.

Pin to 1.4.1, the last release whose micronucleus binary is hosted on
github.com (digistump release, reachable). The FQBN clock options we
ship (clock=16pll on attinyx5, etc.) are unchanged across 1.4.x.

  - backend/app/services/arduino_cli.py: new CORE_INSTALL_VERSIONS map
    consulted by ensure_core_for_board so the runtime auto-install
    passes "ATTinyCore:avr@1.4.1" instead of unversioned latest.
  - backend/Dockerfile and docker/entrypoint.sh: same pin so a fresh
    image bakes 1.4.1 in and never hits the runtime fallback path.

Existing regression tests in test/backend/unit/test_arduino_cli_attinycore.py
still pass (they assert presence, not version).
This commit is contained in:
David Montero 2026-05-22 15:15:53 +02:00
parent 0dcb504c1b
commit 2dbc023df4
3 changed files with 25 additions and 8 deletions

View File

@ -22,15 +22,19 @@ ENV WASI_SDK=/opt/wasi-sdk
# Initialize arduino-cli and install cores.
# - arduino:avr → Uno / Nano / Mega / etc. (built-in core, always needed)
# - ATTinyCore:avr → ATtiny85 (Spence Konde's third-party core, drazzy.com index)
# Without this the FQBN ATTinyCore:avr:attinyx5:chip=85,clock=internal16mhz
# fails with "Platform 'ATTinyCore:avr' not found: platform not installed".
# - ATTinyCore:avr@1.4.1 → ATtiny85 (Spence Konde's third-party core,
# drazzy.com index). Pinned to 1.4.1 because >=1.5.0 depends on
# micronucleus hosted at azduino.com (frequently unreachable). 1.4.1's
# micronucleus tool comes from github.com/digistump and still supports
# the FQBN clock options we ship (clock=16pll, etc.). We never invoke
# micronucleus — it is only required for USB upload, not compilation —
# but arduino-cli will not install a core whose tool deps cannot fetch.
RUN arduino-cli config init \
&& arduino-cli config add board_manager.additional_urls \
http://drazzy.com/package_drazzy.com_index.json \
&& arduino-cli core update-index \
&& arduino-cli core install arduino:avr \
&& arduino-cli core install ATTinyCore:avr
&& arduino-cli core install ATTinyCore:avr@1.4.1
WORKDIR /app

View File

@ -30,6 +30,17 @@ class ArduinoCLIService:
"esp32": "esp32:esp32",
}
# Version pins for `arduino-cli core install`. Keyed by core ID; if a core
# is in this map we pass `<core>@<version>` instead of just `<core>`.
# ATTinyCore: >=1.5.0 depends on micronucleus hosted at azduino.com, which
# has been unreachable for extended periods. 1.4.1 is the last release
# whose micronucleus tool is on github.com (digistump release) AND still
# supports the FQBN options we use (clock=16pll, etc.). Compile-only —
# micronucleus itself is never invoked here.
CORE_INSTALL_VERSIONS: dict[str, str] = {
"ATTinyCore:avr": "1.4.1",
}
def __init__(self, cli_path: str = "arduino-cli"):
self.cli_path = cli_path
self._ensure_board_urls()
@ -147,12 +158,14 @@ class ArduinoCLIService:
if self._is_core_installed(core_id):
return {"needed": False, "installed": True, "core_id": core_id, "log": ""}
# Install the core
print(f"[arduino-cli] Auto-installing core {core_id} for board {fqbn}...")
# Install the core (optionally pinned to a specific version)
version = self.CORE_INSTALL_VERSIONS.get(core_id)
install_spec = f"{core_id}@{version}" if version else core_id
print(f"[arduino-cli] Auto-installing core {install_spec} for board {fqbn}...")
def _install():
return subprocess.run(
[self.cli_path, "core", "install", core_id],
[self.cli_path, "core", "install", install_spec],
capture_output=True, text=True
)

View File

@ -35,7 +35,7 @@ fi
arduino-cli core update-index 2>/dev/null || true
arduino-cli core install arduino:avr 2>/dev/null || true
arduino-cli core install rp2040:rp2040 2>/dev/null || true
arduino-cli core install ATTinyCore:avr 2>/dev/null || true
arduino-cli core install ATTinyCore:avr@1.4.1 2>/dev/null || true
# ESP32 compilation now uses ESP-IDF instead of arduino-cli.
# arduino-cli ESP32 core is no longer needed for QEMU-compatible builds.