Skip to content

Auto Update#366

Open
netmindz wants to merge 1 commit into
MoonModules:mdevfrom
netmindz:auto-ota-mm
Open

Auto Update#366
netmindz wants to merge 1 commit into
MoonModules:mdevfrom
netmindz:auto-ota-mm

Conversation

@netmindz
Copy link
Copy Markdown
Collaborator

@netmindz netmindz commented Jun 6, 2026

This pull request adds an automatic firmware update feature to the WLED update page, allowing users to update their device firmware directly from the web interface with a single click. The update process fetches the latest release from GitHub, downloads the appropriate firmware binary, and uploads it to the device, providing real-time status updates to the user.

New auto-update functionality:

  • Added a new autoUpdate() JavaScript function in update.htm that:

    • Fetches device info to determine the correct firmware repository.
    • Checks GitHub for the latest release and matches the appropriate firmware binary.
    • Downloads the firmware and automatically uploads it to the device, updating the user on progress and errors.
  • Introduced a new "Auto update" button and status display to the update page UI, enabling users to trigger the auto-update process and view progress or error messages.

Summary by CodeRabbit

  • New Features
    • Automatic firmware updates: Added an "Auto update" button in the update interface that automatically checks for and retrieves the latest firmware release available, downloads it, and installs it without requiring manual intervention. The feature displays status messages throughout the entire update process and notifies you with an error message if the update fails.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 6, 2026

Review Change Stack

Walkthrough

The update page adds an "Auto update" button that automatically retrieves the latest firmware from the configured GitHub repository, matches it to the device build configuration, downloads the binary, and submits it through the existing multipart form—eliminating the manual download step.

Changes

Auto-update Feature

Layer / File(s) Summary
Auto-update async function and GitHub integration
wled00/data/update.htm
The autoUpdate() async function fetches device metadata from /json/info, queries GitHub Releases API, derives the expected firmware asset name from build info, downloads the matching .bin file, injects it into the form input, and submits the form. Status updates and error handling occur throughout the workflow.
Auto-update UI button and status
wled00/data/update.htm
New button element (autoUpdBtn), status display span (autoUpdStatus), and separator are added to the form UI to trigger the auto-update workflow and display real-time progress and error feedback.

Sequence Diagram

sequenceDiagram
  participant User
  participant Device as Local Device
  participant GitHub as GitHub API
  participant Form as Update Form
  User->>Form: Click "Auto update" button
  Form->>Device: GET /json/info
  Device-->>Form: Device build metadata
  Form->>GitHub: GET latest release (configured repo)
  GitHub-->>Form: Release data with assets
  Form->>Form: Derive expected asset name
  Form->>GitHub: Download matching .bin asset
  GitHub-->>Form: Binary content
  Form->>Form: Inject binary into file input
  Form->>Form: Submit multipart form
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Auto Update' accurately summarizes the main change: adding an automatic firmware update feature with a new button and function to the WLED update page.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
wled00/data/update.htm (1)

10-54: ⚡ Quick win

Mark WLED-MM-specific additions with // WLEDMM comments.

Please annotate the new auto-update JS/UI additions with // WLEDMM comments to match project web UI conventions.

As per coding guidelines, “add // WLEDMM comments on WLED-MM specific additions.”

Also applies to: 68-70

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wled00/data/update.htm` around lines 10 - 54, The autoUpdate function
contains WLED-MM specific logic (GitHub lookup, asset selection, download
replacement of host, building File/DataTransfer and form submit) and needs
inline markers; add // WLEDMM comments on each WLED-MM-specific addition inside
autoUpdate—specifically annotate the GitHub fetch block (fetch to api.github.com
and parsing ghRelease), the assetSuffix/asset selection logic, the host-rewrite
line (fwUrl = ... replace...), the blob->File/DataTransfer handling and the form
submit/U() call—so each of those unique sections (autoUpdate,
infoResp/ghResp/ghRelease handling, asset selection, fwUrl replacement,
File/DataTransfer creation, and gId('uf').submit()) is followed or prefixed with
a // WLEDMM comment to match project UI conventions.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wled00/data/update.htm`:
- Around line 29-33: In autoUpdate(), guard use of ghRelease.tag_name,
ghRelease.assets and info.release before calling .replace, .find or .map: check
typeof ghRelease.tag_name === 'string' before computing releaseVer, ensure
Array.isArray(ghRelease.assets) before searching/mapping assets, and verify
info.release is present (non-empty string) before building assetSuffix; for each
missing/invalid condition set a clear status.textContent (e.g., "Missing release
tag", "No assets array in release", "Missing device info.release") and
early-return to avoid the generic error path.
- Around line 17-18: autoUpdate() currently performs three fetch() calls (info
fetch via getURL('/json/info'), GitHub latest release fetch, and firmware
download) with no timeout; add a small AbortController-based helper (e.g.,
fetchWithTimeout or timeoutFetch) that accepts a URL, options, and a timeout ms,
uses AbortController to cancel the request after the timeout, and throws on
timeout, then replace the direct fetch(...) calls inside autoUpdate() with this
helper; mark your additions with the required // WLEDMM comment(s) in the inline
<script> (place a // WLEDMM above the helper and another where you call the
helper in autoUpdate() so WLED-MM-specific changes are clearly identifiable).

---

Nitpick comments:
In `@wled00/data/update.htm`:
- Around line 10-54: The autoUpdate function contains WLED-MM specific logic
(GitHub lookup, asset selection, download replacement of host, building
File/DataTransfer and form submit) and needs inline markers; add // WLEDMM
comments on each WLED-MM-specific addition inside autoUpdate—specifically
annotate the GitHub fetch block (fetch to api.github.com and parsing ghRelease),
the assetSuffix/asset selection logic, the host-rewrite line (fwUrl = ...
replace...), the blob->File/DataTransfer handling and the form submit/U()
call—so each of those unique sections (autoUpdate, infoResp/ghResp/ghRelease
handling, asset selection, fwUrl replacement, File/DataTransfer creation, and
gId('uf').submit()) is followed or prefixed with a // WLEDMM comment to match
project UI conventions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a7a47339-1ddb-4377-b45f-bf93bea19513

📥 Commits

Reviewing files that changed from the base of the PR and between 49baa0a and 743e4ff.

📒 Files selected for processing (1)
  • wled00/data/update.htm

Comment thread wled00/data/update.htm
Comment on lines +17 to +18
const infoResp = await fetch(getURL('/json/info'));
if (!infoResp.ok) throw new Error('Failed to fetch device info');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="wled00/data/update.htm"

echo "== File header (first 60 lines) =="
sed -n '1,60p' "$FILE" | nl -ba | sed -e 's/^/ /'

echo
echo "== Lines 1-120 with line numbers (to find autoUpdate and fetches) =="
sed -n '1,140p' "$FILE" | nl -ba | sed -e 's/^/ /'

echo
echo "== Search for fetch usage =="
rg -n "fetch\(" "$FILE" || true

echo
echo "== Show autoUpdate function block (best-effort) =="
# Print around the first occurrence of autoUpdate
LINE_AUTO=$(rg -n "autoUpdate" "$FILE" | head -n 1 | cut -d: -f1 || true)
if [ -n "${LINE_AUTO:-}" ]; then
  START=$((LINE_AUTO-40))
  END=$((LINE_AUTO+180))
  START=$((START<1?1:START))
  sed -n "${START},${END}p" "$FILE" | nl -ba | sed -e 's/^/ /'
fi

echo
echo "== Check for any AbortController/timeout wrapper already present =="
rg -n "AbortController|signal:|timeoutMs|fetchWithTimeout" "$FILE" || true

echo
echo "== Check for WLEDMM markers near additions =="
rg -n "//\s*WLEDMM" "$FILE" || true

echo
echo "== Show nearby lines where // WLEDMM might be missing (lines 1-140) for context =="
sed -n '1,140p' "$FILE" | nl -ba | sed -e 's/^/ /'

Repository: MoonModules/WLED-MM

Length of output: 159


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="wled00/data/update.htm"

echo "== File header (first 80 lines) =="
sed -n '1,80p' "$FILE" | cat -n

echo
echo "== Lines 1-220 with line numbers (find autoUpdate/fetches) =="
sed -n '1,220p' "$FILE" | cat -n

echo
echo "== Search for fetch usage =="
rg -n "fetch\(" "$FILE" || true

echo
echo "== Search for AbortController/timeout wrapper =="
rg -n "AbortController|fetchWithTimeout|timeoutMs|signal:" "$FILE" || true

echo
echo "== Search for WLEDMM markers =="
rg -n "//\s*WLEDMM" "$FILE" || true

echo
echo "== Show full autoUpdate block vicinity (around first autoUpdate) =="
LINE_AUTO=$(rg -n "autoUpdate" "$FILE" | head -n 1 | cut -d: -f1 || true)
if [ -n "${LINE_AUTO:-}" ]; then
  START=$((LINE_AUTO-60))
  END=$((LINE_AUTO+260))
  START=$((START<1?1:START))
  sed -n "${START},${END}p" "$FILE" | cat -n
fi

Repository: MoonModules/WLED-MM

Length of output: 12732


Add fetch timeouts (AbortController) to prevent the Auto update flow from hanging
autoUpdate() has three fetch() calls with no timeout, so the button can remain disabled indefinitely on a stalled network request (device info, GitHub latest release, and firmware download).

  • Add an AbortController-based timeout wrapper and use it for all fetch() calls in autoUpdate().
  • Add the required // WLEDMM marker(s) for the WLED-MM-specific JS additions in this file (there are no // WLEDMM comments in the inline <script>).
Suggested patch
 		async function autoUpdate() {
 			const btn = gId('autoUpdBtn');
 			const status = gId('autoUpdStatus');
+			const fetchWithTimeout = async (url, options = {}, timeoutMs = 15000) => {
+				const controller = new AbortController();
+				const t = setTimeout(() => controller.abort(), timeoutMs);
+				try {
+					return await fetch(url, {...options, signal: controller.signal});
+				} finally {
+					clearTimeout(t);
+				}
+			};
 			btn.disabled = true;
 			status.textContent = '';
 			try {
 				status.textContent = 'Fetching device info...';
-				const infoResp = await fetch(getURL('/json/info'));
+				const infoResp = await fetchWithTimeout(getURL('/json/info'));
 				if (!infoResp.ok) throw new Error('Failed to fetch device info');
 				const info = await infoResp.json();
@@
-				const ghResp = await fetch(`https://api.github.com/repos/${info.repo}/releases/latest`);
+				const ghResp = await fetchWithTimeout(`https://api.github.com/repos/${info.repo}/releases/latest`);
@@
-				const fwResp = await fetch(fwUrl);
+				const fwResp = await fetchWithTimeout(fwUrl);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wled00/data/update.htm` around lines 17 - 18, autoUpdate() currently performs
three fetch() calls (info fetch via getURL('/json/info'), GitHub latest release
fetch, and firmware download) with no timeout; add a small AbortController-based
helper (e.g., fetchWithTimeout or timeoutFetch) that accepts a URL, options, and
a timeout ms, uses AbortController to cancel the request after the timeout, and
throws on timeout, then replace the direct fetch(...) calls inside autoUpdate()
with this helper; mark your additions with the required // WLEDMM comment(s) in
the inline <script> (place a // WLEDMM above the helper and another where you
call the helper in autoUpdate() so WLED-MM-specific changes are clearly
identifiable).

Comment thread wled00/data/update.htm
Comment on lines +29 to +33
const releaseVer = ghRelease.tag_name.replace(/^v/, '');
const assetSuffix = `_${releaseVer}_${info.release}.bin`;
const asset = ghRelease.assets.find(a => a.name.endsWith(assetSuffix));
if (!asset) {
const available = ghRelease.assets.map(a => a.name).join(', ');
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Jun 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show referenced section with line numbers
nl -ba wled00/data/update.htm | sed -n '1,120p'

# Show around the cited lines (29-70 in file are likely different due to offsets; also search exact snippet)
rg -n "ghRelease\.tag_name|assetSuffix|ghRelease\.assets\.find|info\.release" wled00/data/update.htm

# Extract larger surrounding context near matches
rg -n "ghRelease\.tag_name" wled00/data/update.htm | cut -d: -f1 | head -n 5 | while read -r ln; do
  start=$((ln-30)); end=$((ln+80))
  echo "---- context around line $ln ($start-$end) ----"
  nl -ba wled00/data/update.htm | sed -n "${start},${end}p"
done

# Find where ghRelease is fetched/parsed and whether there is any schema guard
rg -n "fetch\\(|api\\.github|releases|json\\(|tag_name|assets" wled00/data/update.htm

# Show any catch blocks / error messaging
rg -n "catch\\(|show.*status|status.*msg|alert\\(|toast\\(|error" wled00/data/update.htm

Repository: MoonModules/WLED-MM

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Basic sanity: list file exists
ls -la wled00/data/update.htm

# Print first ~160 lines with line numbers via awk
awk '{printf "%6d\t%s\n", NR, $0}' wled00/data/update.htm | sed -n '1,160p'

# Print around the referenced snippet area by searching for the exact line fragments
# (no nl needed)
awk '{if ($0 ~ /ghRelease\.tag_name/ || $0 ~ /assetSuffix/ || $0 ~ /ghRelease\.assets\.find/ || $0 ~ /info\.release/) print NR "\t" $0}' wled00/data/update.htm

# Get broader context around where ghRelease.tag_name appears
ln=$(awk '/ghRelease\.tag_name/ {print NR; exit}' wled00/data/update.htm)
start=$((ln-60)); end=$((ln+120))
awk -v s="$start" -v e="$end" '{if(NR>=s && NR<=e) printf "%6d\t%s\n", NR, $0}' wled00/data/update.htm

# Find where ghRelease is constructed/assigned
rg -n --context 3 "ghRelease\s*=" wled00/data/update.htm || true
rg -n --context 3 "tag_name|assets" wled00/data/update.htm || true

# Find where info.release is created/assigned
rg -n --context 3 "info\.release" wled00/data/update.htm || true

# Find relevant error handling paths
rg -n --context 3 "catch\\(|show.*status|status.*msg|alert\\(|toast\\(|error" wled00/data/update.htm || true

Repository: MoonModules/WLED-MM

Length of output: 10817


Harden GitHub release parsing before using release fields
In autoUpdate() the code assumes ghRelease.tag_name is a string and ghRelease.assets is an array, and it uses info.release without checking it exists. If the GitHub/device payload shape differs, tag_name.replace(...) / assets.find(...) / assets.map(...) can throw and fall into the generic Auto-update failed: ... message; add guards for tag_name, assets (array), and info.release and set a targeted status.textContent when any are missing/invalid.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wled00/data/update.htm` around lines 29 - 33, In autoUpdate(), guard use of
ghRelease.tag_name, ghRelease.assets and info.release before calling .replace,
.find or .map: check typeof ghRelease.tag_name === 'string' before computing
releaseVer, ensure Array.isArray(ghRelease.assets) before searching/mapping
assets, and verify info.release is present (non-empty string) before building
assetSuffix; for each missing/invalid condition set a clear status.textContent
(e.g., "Missing release tag", "No assets array in release", "Missing device
info.release") and early-return to avoid the generic error path.

Copy link
Copy Markdown
Collaborator

@softhack007 softhack007 Jun 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please suggest some minimal code that would ensure that the code catches unexpected response content.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@softhack007, here are minimal inline guards to insert right after the two await *.json() calls:

// After:  const info = await infoResp.json();
if (!info || typeof info.release !== 'string' || !info.release) {
    status.textContent = 'Missing device release info (info.release).';
    btn.disabled = false;
    return;
}
// After:  const ghRelease = await ghResp.json();
if (typeof ghRelease.tag_name !== 'string' || !ghRelease.tag_name) {
    status.textContent = 'Missing release tag from GitHub response.';
    btn.disabled = false;
    return;
}
if (!Array.isArray(ghRelease.assets)) {
    status.textContent = 'No assets array in GitHub release response.';
    btn.disabled = false;
    return;
}

That gives a targeted, readable error for each unexpected shape instead of falling through to the generic Auto-update failed: TypeError message. The existing !info.repo guard already covers the repo field, so no change is needed there.


🧠 Learnings used
Learnt from: CR
Repo: MoonModules/WLED-MM PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-14T23:39:33.591Z
Learning: Applies to wled00/**/*.{h,hpp,cpp,js},wled00/data/**/*.{html,css,js} : Repository language is English — suggest translations for non-English content

Learnt from: CR
Repo: MoonModules/WLED-MM PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-14T23:39:33.590Z
Learning: Applies to wled00/html_*.h,wled00/js_*.h : Never edit or commit auto-generated header files `wled00/html_*.h` and `wled00/js_*.h` — these are generated from `wled00/data/` during the build process

Learnt from: CR
Repo: MoonModules/WLED-MM PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-14T23:40:02.031Z
Learning: Applies to wled00/html_*.h wled00/js_*.h : Never edit or commit auto-generated `wled00/html_*.h` or `wled00/js_*.h` files

Learnt from: CR
Repo: MoonModules/WLED-MM PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-14T23:40:02.031Z
Learning: Applies to wled00/data/**/*.{html,js,css} : Run `npm run build` after editing web UI files to regenerate C++ headers

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 353
File: .github/web.instructions.md:8-9
Timestamp: 2026-04-02T14:17:35.133Z
Learning: In the WLED web UI files under wled00/data (HTML and JavaScript: wled00/data/**/*.{htm,html,js}), indent with tabs. Do not enforce spaces in these files.

@softhack007
Copy link
Copy Markdown
Collaborator

@coderabbitai please double-check that the logic for constructing the asset filename is compabile with the WLED-MM release naming sheme.

For example, WLED_RELEASE_NAME=esp32s2_4MB_M (platformio.ini) should lead to selecting this download:
https://github.com/MoonModules/WLED-MM/releases/download/v14.7.1/WLEDMM_14.7.1_esp32s2_4MB_M.bin

See https://github.com/MoonModules/WLED-MM/blob/mdev/.github/workflows/release.yml and https://github.com/MoonModules/WLED-MM/blob/mdev/pio-scripts/output_bins.py

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 7, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== update.htm (PR branch - auto-ota-mm) ==="
cat wled00/data/update.htm

echo ""
echo "=== .github/workflows/release.yml ==="
cat .github/workflows/release.yml

echo ""
echo "=== pio-scripts/output_bins.py ==="
cat pio-scripts/output_bins.py

Length of output: 11027


🏁 Script executed:

#!/bin/bash
echo "=== Search for 'release' in json info construction ==="
rg -n '"release"' wled00/ --type cpp -C3

echo ""
echo "=== Search for 'repo' in json info construction ==="
rg -n '"repo"' wled00/ --type cpp -C3

echo ""
echo "=== WLED_RELEASE_NAME usage in json ==="
rg -n 'WLED_RELEASE_NAME' wled00/ -C2

echo ""
echo "=== Look for json/info handler ==="
rg -n 'serializeInfo\|json.*info\|info.*json' wled00/ --type cpp -C2 | head -80

Length of output: 5409


🏁 Script executed:

#!/bin/bash
echo "=== WLED_REPO / repoString definition ==="
rg -n 'WLED_REPO\|repoString' wled00/ -C3 | head -80

echo ""
echo "=== Check download.wled.me references in codebase ==="
rg -rn 'download\.wled\.me' --type html --type cpp --type js -C2

echo ""
echo "=== Check WLED_VERSION define format (to verify tag format) ==="
rg -n 'WLED_VERSION' platformio.ini | head -20

Length of output: 997



@softhack007 — Here's the full analysis:


✅ Filename construction logic: Compatible with WLED-MM naming scheme

The suffix-match approach works correctly:

Step Value
ghRelease.tag_name v14.7.1
After .replace(/^v/, '') 14.7.1
info.release (from json.cpp:970releaseStringWLED_RELEASE_NAME) esp32s2_4MB_M
assetSuffix _14.7.1_esp32s2_4MB_M.bin
Actual release filename (output_bins.py) WLEDMM_14.7.1_esp32s2_4MB_M.bin
"WLEDMM_14.7.1_esp32s2_4MB_M.bin".endsWith("_14.7.1_esp32s2_4MB_M.bin") true

The .bin.gz files uploaded alongside won't match since the suffix ends with .bin, not .bin.gz. ✓


⚠️ Bug: download.wled.me redirect will not work for WLED-MM

const fwUrl = asset.browser_download_url.replace(/^https?:\/\/[^/]+/, 'https://download.wled.me');

download.wled.me is the upstream WLED project's CDN proxy — it does not serve WLED-MM release assets. The browser_download_url from a WLED-MM GitHub release points to GitHub's CDN (e.g. https://objects.githubusercontent.com/... or https://github.com/MoonModules/WLED-MM/releases/download/...). Replacing that origin with download.wled.me will result in a 404 or a completely wrong file.

Since the download happens in the user's browser (not on the device), there's no embedded SSL limitation — the browser can fetch directly from GitHub. The fix is simply to drop the domain replacement and use browser_download_url directly:

// Remove the domain replacement entirely:
const fwResp = await fetch(asset.browser_download_url);

GitHub's CDN allows CORS for release asset downloads, so this will work from a browser context.


🧠 Learnings used
Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 308
File: platformio.ini:436-436
Timestamp: 2026-01-05T21:35:57.030Z
Learning: In MoonModules/WLED-MM platformio.ini, [esp32_legacy] section intentionally uses NeoPixelBus 2.7.5 while V4 platform builds use 2.7.9 or later. The older V3 Platform builds don't have the same flickering problems that newer versions address, and NPB 2.7.9 provides no added value over 2.7.5 for these legacy builds.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 343
File: platformio_override.ini.olaf.example:6-8
Timestamp: 2026-04-05T16:19:06.776Z
Learning: In MoonModules/WLED-MM platformio_override.ini, custom build environments MUST use `extends = <base_env>` (e.g., `extends = esp32_4MB_V4_M`) to inherit all WLED-MM-specific build flags from the base environment. Redefining a standard target directly (e.g., `[env:esp32_4MB_V4_M]` without `extends =`) will silently drop all WLED-MM-specific build flags defined in platformio.ini, resulting in a broken or non-standard build.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 308
File: platformio.ini:560-560
Timestamp: 2026-01-07T23:30:25.779Z
Learning: In platformio.ini, ESP32-S3 environments intentionally have WLED_USE_SHARED_RMT commented out (keeping RMTHI driver enabled) for testing purposes, while ESP32-S2 has it enabled (using shared RMT driver) to avoid boot loops. This inconsistency is temporary while investigating why RMTHI causes interrupt watchdog resets on S3. Once the S3 issue is understood, both S2 and S3 will use the same driver flags.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 293
File: wled00/udp.cpp:668-669
Timestamp: 2025-12-21T22:26:03.261Z
Learning: In MoonModules/WLED-MM on 32-bit ESP32 platforms, changing pixel index variables to `int` type to align with the `setPixelColor(int, ...)` API signature is intentional and safe. Maximum pixel addresses are bounded by UINT16_MAX, and `setPixelColor()` performs internal overflow checks.

Learnt from: netmindz
Repo: MoonModules/WLED-MM PR: 248
File: platformio.ini:1613-1613
Timestamp: 2025-07-02T23:22:57.175Z
Learning: In WLED platformio.ini, the particle system disable flags (WLED_DISABLE_PARTICLESYSTEM1D and WLED_DISABLE_PARTICLESYSTEM2D) are intentionally varied across different build environments based on platform memory constraints. More memory-limited platforms (like ESP8266, ESP32-C3, ESP32-S2) disable both 1D and 2D particle systems, while platforms with more available memory (like esp32_4MB_V4_S with 4MB flash) may only disable the 1D version to preserve flash space while keeping 2D functionality available.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 343
File: platformio_override.ini.olaf.example:6-8
Timestamp: 2026-04-05T13:58:42.281Z
Learning: In MoonModules/WLED-MM, new PlatformIO build environment examples must NOT be added as separate `.ini` or `.ini.example` files. They must be placed as commented-out named sections (e.g., `;[env:some_name]`) inside `platformio_override.ini.sample`. The generic `[env]` block (which applies globally to all environments) must not be used directly in examples. This convention is enforced by maintainer softhack007.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 0
File: :0-0
Timestamp: 2026-04-04T14:32:02.618Z
Learning: In MoonModules/WLED-MM, clang-format is intentionally NOT enforced via CI or .clang-format config because it would cause merge conflicts when cherry-picking features from upstream WLED (which uses different formatting). Instead, "soft" formatting rules are documented in .github/cpp.instructions.md. Do not recommend adding clang-format to CI as a follow-up to missing automated enforcement — the decision is deliberate.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 343
File: platformio_override.ini.olaf.example:6-8
Timestamp: 2026-04-05T16:19:06.776Z
Learning: In MoonModules/WLED-MM, the correct way to activate a custom data_dir (e.g., `data_dir = ${PROJECT_DIR}/fs_data`) in a local build is to add that directive inside a properly extended named environment in the user's local `platformio_override.ini`. This usage should be documented in the relevant README.md rather than provided as a standalone `.ini` or `.ini.example` template file. No example override file should be committed to the repository for this purpose.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 0
File: :0-0
Timestamp: 2025-12-22T20:31:17.991Z
Learning: In MoonModules/WLED-MM on ESP32/ESP8266 platforms with limited heap memory, when reallocating buffers (e.g., LED buffers), always free the old buffer before allocating the new one. Allocating the new buffer first would temporarily require double the memory and could cause malloc failures when available RAM is low. The free-then-allocate pattern is preferred for resource-constrained embedded devices, even if it creates a brief nullptr window that must be protected by proper synchronization.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 0
File: :0-0
Timestamp: 2025-12-25T00:46:23.516Z
Learning: In MoonModules/WLED-MM file operations using the global file handle `f` in file.cpp, writeObjectToFile() must check `if (doCloseFile) closeFile();` before opening a new file, following the same pattern as readObjectFromFile(). Without this check, opening a new file while a previous file operation has set doCloseFile=true will overwrite the global file handle without flushing buffers, causing data corruption. This is critical for preventing presets.json corruption when async and immediate write paths race.

Learnt from: CR
Repo: MoonModules/WLED-MM PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-14T23:39:33.590Z
Learning: Build firmware to validate code changes using `pio run -e esp32_4MB_V4_M` — this build step must succeed and should never be skipped

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 355
File: wled00/presets.cpp:130-130
Timestamp: 2026-04-05T13:46:56.469Z
Learning: In MoonModules/WLED-MM presets.cpp, the preferred threshold for detecting an uninitialized/empty presets.json file is `f.size() < 4` (not `< 3`), to also catch `{ }` (3 bytes) and `{\n}` (3 bytes) which users commonly write as visually-padded empty JSON placeholders in custom filesystems. Both `initPresetsFile()` in wled00/presets.cpp and `appendObjectToFile()` in wled00/file.cpp should use the same `< 4` threshold for consistency.

@softhack007
Copy link
Copy Markdown
Collaborator

softhack007 commented Jun 7, 2026

download.wled.me is the upstream WLED project's CDN proxy — it does not serve WLED-MM release assets. The browser_download_url from a WLED-MM GitHub release points to GitHub's CDN (e.g. https://objects.githubusercontent.com/... or https://github.com/MoonModules/WLED-MM/releases/download/...). Replacing that origin with download.wled.me will result in a 404 or a completely wrong file.

@netmindz @lost-hope is this finding from the rabbit correct? Should we better redirect to wladi's installer, or does install.wled.me also offer WLED-MM bins?

@lost-hope
Copy link
Copy Markdown
Collaborator

download.wled.me is the cors proxy of @netmindz iirc.
i am not sure how it is configured atm, but adding MM should be possible without a lot of changes.

install.wled.me does not offer MM.

@netmindz
Copy link
Copy Markdown
Collaborator Author

netmindz commented Jun 7, 2026

We've swapped around between different release names and which are included in the release, which makes testing a little tricky, but my proxy should handle both WLED and MoonModules owner paths

@netmindz
Copy link
Copy Markdown
Collaborator Author

netmindz commented Jun 7, 2026

@coderabbitai have you actually tried to fetch any release assets via the CDN or have you just assumed based on the hostname? It's also nothing to do with embedded SSL as the browser fetches the file and you are wrong about the allowed cors hosts when fetching directly from GitHub, especially once you take into account their redirects

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 7, 2026

Tip

For best results, initiate chat on the files or code changes.

@netmindz — You're right, and I apologize. I made two incorrect assumptions:

  1. download.wled.me ownership: I incorrectly assumed it was upstream WLED's CDN and wouldn't serve WLED-MM assets. Since you operate it as a CORS proxy and can configure it to handle MoonModules paths, my concern there was unfounded.

  2. GitHub CORS/redirect behavior: I was wrong to claim a direct fetch(asset.browser_download_url) would "just work" from a browser. GitHub release asset URLs redirect through their CDN (objects.githubusercontent.com and others), and those redirect hops can break browser CORS fetch — which is precisely the reason a proxy like download.wled.me exists. I stated this confidently without having tested it, which I should not have done.

The use of download.wled.me as a CORS proxy is the correct approach here. I'll withdraw that concern.

(╯°□°)╯︵ 🐰


🧠 Learnings used
Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 0
File: :0-0
Timestamp: 2026-04-07T16:49:44.284Z
Learning: In MoonModules/WLED-MM, `.github/agent-build.instructions.md` is intentionally kept in `.github/` (not moved to `docs/`) because it is exclusively meant for GitHub Copilot agent tasks, not for CodeRabbit code reviews. It should NOT be referenced in `.coderabbit.yaml` and should not be flagged as misplaced or missing from `docs/`.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 343
File: fs_data/README.md:12-14
Timestamp: 2026-04-05T13:09:35.315Z
Learning: In MoonModules/WLED-MM, empty JSON files (containing only `{}`) in fs_data (e.g., cfg.json, presets.json, wsec.json) are intended to be treated the same as non-existing files by the deserialization code in wled00/cfg.cpp and related files. The bugfix for this robustness issue (avoiding null/empty-object dereference) is tracked in PR `#355`. After the fix, `{}` is a safe placeholder for these config files.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 7, 2026

Tip

For best results, initiate chat on the files or code changes.

@netmindz — You're right, and I apologize. I made two incorrect assumptions:

  1. download.wled.me ownership: I incorrectly assumed it was upstream WLED's CDN and wouldn't serve WLED-MM assets. Since you operate it as a CORS proxy and have configured it to handle MoonModules paths, my concern was unfounded.

  2. GitHub CORS/redirect behavior: I was wrong to claim a direct fetch(asset.browser_download_url) would "just work" from a browser. GitHub release asset URLs redirect through their CDN (objects.githubusercontent.com and others), and those redirect hops can break browser CORS fetch — which is precisely the reason a proxy like download.wled.me exists. I stated this confidently without having tested it, which I should not have done.

The use of download.wled.me as a CORS proxy is the correct approach here. I'll withdraw that concern.

(╯°□°)╯︵ 🐰


✏️ Learnings added
Learnt from: netmindz
URL: https://github.com/MoonModules/WLED-MM/pull/366

Timestamp: 2026-06-07T19:36:15.528Z
Learning: In MoonModules/WLED-MM, `download.wled.me` is a CORS proxy operated by netmindz (the maintainer). It is configured to handle release asset downloads from both the upstream WLED GitHub org and the MoonModules (WLED-MM) GitHub org. Direct browser `fetch()` of GitHub release asset URLs does NOT reliably work due to CORS issues with GitHub's CDN redirects (through `objects.githubusercontent.com`), which is why routing downloads through `download.wled.me` is the correct approach in the auto-update feature.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 343
File: fs_data/README.md:12-14
Timestamp: 2026-04-05T13:09:35.315Z
Learning: In MoonModules/WLED-MM, empty JSON files (containing only `{}`) in fs_data (e.g., cfg.json, presets.json, wsec.json) are intended to be treated the same as non-existing files by the deserialization code in wled00/cfg.cpp and related files. The bugfix for this robustness issue (avoiding null/empty-object dereference) is tracked in PR `#355`. After the fix, `{}` is a safe placeholder for these config files.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 0
File: :0-0
Timestamp: 2026-04-05T13:40:29.503Z
Learning: In MoonModules/WLED-MM, `appendObjectToFile()` in `wled00/file.cpp` uses `f.size() < 3` to detect an uninitialized presets file and writes `{"0":{}}` as the seed structure. The `initPresetsFile()` in `wled00/presets.cpp` intentionally uses the same `f.size() < 3` threshold for consistency. This threshold catches `{}` (2 bytes) but NOT `{ }` (3 bytes).

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 355
File: wled00/presets.cpp:130-130
Timestamp: 2026-04-05T13:46:56.469Z
Learning: In MoonModules/WLED-MM presets.cpp, the preferred threshold for detecting an uninitialized/empty presets.json file is `f.size() < 4` (not `< 3`), to also catch `{ }` (3 bytes) and `{\n}` (3 bytes) which users commonly write as visually-padded empty JSON placeholders in custom filesystems. Both `initPresetsFile()` in wled00/presets.cpp and `appendObjectToFile()` in wled00/file.cpp should use the same `< 4` threshold for consistency.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 0
File: :0-0
Timestamp: 2026-04-07T16:49:44.284Z
Learning: In MoonModules/WLED-MM, `.github/agent-build.instructions.md` is intentionally kept in `.github/` (not moved to `docs/`) because it is exclusively meant for GitHub Copilot agent tasks, not for CodeRabbit code reviews. It should NOT be referenced in `.coderabbit.yaml` and should not be flagged as misplaced or missing from `docs/`.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 0
File: :0-0
Timestamp: 2025-12-25T00:46:23.516Z
Learning: In MoonModules/WLED-MM file operations using the global file handle `f` in file.cpp, writeObjectToFile() must check `if (doCloseFile) closeFile();` before opening a new file, following the same pattern as readObjectFromFile(). Without this check, opening a new file while a previous file operation has set doCloseFile=true will overwrite the global file handle without flushing buffers, causing data corruption. This is critical for preventing presets.json corruption when async and immediate write paths race.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 355
File: wled00/presets.cpp:130-130
Timestamp: 2026-04-05T13:41:51.469Z
Learning: In MoonModules/WLED-MM presets.cpp, the minimal JSON for a single real preset entry in presets.json format is `{"1":{}}` = 8 bytes (1-digit index with empty body). The `f.size() < 3` threshold in initPresetsFile() and appendObjectToFile() safely identifies only empty/uninitialized files (like `{}` = 2 bytes) well below this 8-byte minimum. Changing the threshold to `< 4` would also catch `{ }` (3 bytes) but would create an inconsistency with appendObjectToFile() which uses the same `< 3` threshold.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 343
File: platformio_override.ini.olaf.example:6-8
Timestamp: 2026-04-05T16:19:06.776Z
Learning: In MoonModules/WLED-MM, the correct way to activate a custom data_dir (e.g., `data_dir = ${PROJECT_DIR}/fs_data`) in a local build is to add that directive inside a properly extended named environment in the user's local `platformio_override.ini`. This usage should be documented in the relevant README.md rather than provided as a standalone `.ini` or `.ini.example` template file. No example override file should be committed to the repository for this purpose.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 0
File: :0-0
Timestamp: 2025-12-23T21:29:14.927Z
Learning: In MoonModules/WLED-MM, presets.json writes must be serialized and atomic: guard all write paths with a dedicated file-level mutex (presetFileMux) and use temp-file + rename to replace the file. The “immediate write” branch in presets.cpp can race with async doSaveState() and corrupt presets.json; prefer routing all saves through the async path or enforce the same file mutex + atomic write there.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 0
File: :0-0
Timestamp: 2026-04-04T14:32:02.618Z
Learning: In MoonModules/WLED-MM, clang-format is intentionally NOT enforced via CI or .clang-format config because it would cause merge conflicts when cherry-picking features from upstream WLED (which uses different formatting). Instead, "soft" formatting rules are documented in .github/cpp.instructions.md. Do not recommend adding clang-format to CI as a follow-up to missing automated enforcement — the decision is deliberate.

Learnt from: softhack007
Repo: MoonModules/WLED-MM PR: 270
File: wled00/fcn_declare.h:403-406
Timestamp: 2025-10-22T21:59:24.331Z
Learning: In MoonModules/WLED-MM PR `#270`, the out-of-bounds null-terminator write in wled00/util.cpp (extractModeSlider) is deferred and tracked in Issue `#272`; do not address it within PR `#270`.

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.

3 participants