diff --git a/.github/nightly/hintro.html b/.github/nightly/hintro.html new file mode 100644 index 000000000..c8737fd41 --- /dev/null +++ b/.github/nightly/hintro.html @@ -0,0 +1,153 @@ + + + + + + +Meshtastic Nightly v%%VERSION%% + + + + + +
+
+ + + + + + +

MeshtasticNightly Firmware

+
+ +

+ Firmware built straight from the tip of develop, published every night. + Grab a .bin, .uf2 or .hex for your board below, or point the + Web Flasher at the nightly channel and let it pick for you. +

+ +
+
Version
%%VERSION%%
+
Commit
%%COMMIT_SHORT%%
+
Built
%%BUILD_DATE%%
+
Build log
run %%RUN_ID%%
+
+ +

+ Nightlies are untested pre-release builds and can be unstable. Only flash hardware you can afford to + fully erase, and back up your config first. Start with the + release notes — they cover what changed and how to report what you find. +

+ +

Files

+
diff --git a/.github/nightly/houtro.html b/.github/nightly/houtro.html new file mode 100644 index 000000000..02529e1be --- /dev/null +++ b/.github/nightly/houtro.html @@ -0,0 +1,11 @@ +
+ + +
+ + diff --git a/.github/nightly/release_notes.md b/.github/nightly/release_notes.md new file mode 100644 index 000000000..972431e2c --- /dev/null +++ b/.github/nightly/release_notes.md @@ -0,0 +1,161 @@ +# Help Test 2.8 - Flash a Nightly, Send Feedback + +We're preparing the **2.8** release, and we need your help shaking it out on real hardware. The web flasher now has a **built-in feedback form**. Flash a nightly, use your node like you normally would, and tell us what you find. Every report on a real board moves the release forward. + +⚠️ 2.8 nightlies are **experimental, pre-release builds** and can be unstable. Please read the warnings and only flash hardware you can afford to fully erase. Back up your config first. + +## Big changes + +There are a number of fundamental changes to 2.8 that require a heads-up. Please review some of these higher profile changes so that you are aware of them before installing: + +- Node numbers (ID) are now derived from the public-key identity of the node +- XEdDSA based packet signing +- Reduction of long-name to 25 bytes +- Precise position no longer allowed on known-keys (public mesh. Please use private channels for this) +- Telemetry and position are off-by-default and must be opted into +- Ground-up redesigned NodeDB storage and traffic management +- Completely new allocation of LoRa Regions and presets, including ham specific carve-outs + +--- + +## How to help in 3 steps + +1. **Flash a 2.8 nightly** from the web flasher onto supported hardware. +2. Make sure your apps / clients are up to date with the latest release in order to support the 2.8 firmware features like packet signing. +3. **Use it normally** for a while - send messages, move around, let it mesh, sleep, and wake. Try the features you actually rely on. +4. **Open the feedback form in the web flasher and tell us what happened** - good, bad, or broken. "Works great on my board" is genuinely useful data too. + +--- + +## Where we most need coverage + +The more different boards and setups we hear from, the better. Especially valuable: + +- **A variety of supported boards** +- **Both radios and roles** - routers, clients, repeaters, and low-power/sleep configurations. +- **Different regions** and channel/modem-preset combinations. +- **Bluetooth pairing and reconnection** from Android and iOS. +- **Upgrade paths** - flashing 2.8 over an existing 2.x install and confirming your config/keys survive. +- **Peripherals** - GPS, screens (OLED/E-Ink/TFT), sensors, and buttons. + +--- + +## What makes a feedback report actionable + +The feedback form captures a lot automatically, but the more of the following you include, the faster we can act: + +| Include | Why it helps | +| ------------------------- | --------------------------------------------------------------------------------------------- | +| **Exact board / variant** | Behavior is often board-specific (e.g. `rak4631`, `heltec-v3`, `t1000-e`). | +| **Build identifier** | The nightly version / commit / date you flashed, so we can reproduce against the right build. | +| **What you did** | Concrete steps leading up to the problem - the shorter the repro, the better. | +| **Expected vs. actual** | What you thought would happen, and what actually happened. | +| **How often** | Every time? Once? Only after a reboot or after X hours? | +| **Logs / screenshots** | Serial or app logs, and photos of the screen or error, when you have them. | +| **Environment** | Region, phone OS + app version, and anything unusual about your setup. | + +### Especially flag these + +- **Boot loops, hangs, watchdog resets, or unexpected reboots** +- **Config, channel, or key loss** after flashing or upgrading +- **Regressions** - something that worked on your previous (stable) firmware but is now broken +- **Meshing / DM problems** between a 2.8 node and nodes on other firmware +- **Power regressions** - noticeably worse battery life + +--- + +## Good feedback vs. vague feedback + +**Vague:** "It's broken, keeps rebooting." + +**Actionable:** "On a `rak4631` flashed with the 2.8 nightly from , the node reboots every time I open the Android app (v2.7.15) and tap Position. Happens every time. Serial log attached, region US." + +--- + +> [!NOTE] +> Thank you for testing. Reports from real hardware - including the boring "everything works" ones - are exactly what let us promote 2.8 from nightly preview to a stable release with confidence. + +# Changes + +### Radio & mesh protocol + +- **Packet Signing via XEdDSA** (#10478) plus a **BaseUI signing status UI** (#10841), unsigned-packet policy hardening with test coverage (#10858), and runtime-toggleable `MESHTASTIC_LOCKDOWN` hardening for nRF52 (#10349, opt-in via #10712). +- **Traffic Management Module** for packet forwarding - dedup, rate limiting, role-aware policing (#9358 base, #10706 dedup/rate-limit expansion, #10745 next-hop cache overflow store, #9921 congestion-aware position interval/hop-exhaustion tuning). +- **Automatic variable hop limits** based on live mesh activity and message-size estimation (#10176). +- **Mesh beacon** feature and admin controls (#10618 base implementation, #10839 second pass adding beacon admin/config). +- **Noise floor** tracking with a sliding-window estimate (#9347). +- **Hash table index for O(1) packet history lookups** - improves routing/dedup performance on busy meshes (#9499). +- New amateur-radio regions: 70cm (#10627), 1.25m/125cm (#10638), 2m/~144MHz (#10623); EU regions merge plus Narrow/Lite region enablement for EU (#10675, #10120); LoRa region preset map for cleaner per-region defaults (#10736). +- **TinyFast and TinySlow modem presets** added to config and menu (#10597). +- LoRa config changes now apply live without a reboot (#9962); LoRa settings expansion and validation improvements (#9878). +- Position privacy: direct-send position packets are clamped to channel precision (#10383), and public/known-key position precision is clamped similarly (#10665) and honors explicit channel settings to prevent location leaks (#10513). +- Licensed operators are now prevented from rebroadcasting packets to/from unlicensed users, for regulatory compliance (#9958). +- Packets with missing/invalid `hop_start` (pre-hop firmware) are now deprecated/blocked (#9476). +- Spoof detection added for UDP multicast packets (#9905). +- Low-bandwidth conversion support added to MeshRadio (#10595). +- ATAK Plugin V2 implemented (drops legacy unishox2 compression) (#10105), including TAKTALK voice/text chat message and room data structures. +- Ethernet HTTP/HTTPS API server ported to RP2350 + W5500 boards (#10573), plus Ethernet OTA support for RP2350/W5500 (#10136). +- Optional `LED_LORA` indicator to show LoRa TX activity (#10465), and an LED indicator for LoRa RX (#10674). +- GPS time sync: device now sets its clock from GPS every 30 minutes (#10737); GPS is skipped at startup if the LoRa region is unset, to save battery (#10386); GPS model/baudrate now cached across reboots to skip a full sweep (#10544). +- Config: **position & telemetry broadcast are now opt-in** rather than always-on (#10929). +- **Extra-repeat tolerance** - device tolerates a configurable number of heard repeats before cancelling its own rebroadcast, with tolerance suppressed when the mesh is busy or dense (recent local branch work). + +### UI / display - BaseUI + +_BaseUI is the current default graphical UI (`src/graphics/Screen.cpp`, `draw/UIRenderer`, `draw/MenuHandler`, `draw/CompassRenderer`, `draw/NotificationRenderer`, `draw/NodeListRenderer`)._ + +- **"Ham Mode"** - first implementation (#10663). +- **Color support for TFT-equipped nodes** (#10233). +- Status-message display added to Favorite/NodeList screens (#9504, #10197). +- **Hex picker** UI added for entering hex values (#10650). +- Save/restore of frame visibility state across sessions (#10576). +- BLE pairing PIN now shown via a proper on-screen banner (#8902). +- Compass rendering/behavior improvements (#10166). +- Emote handling refactor (#9896). + +### UI / display - InkHUD + +_InkHUD is the e-ink-optimized UI (`src/graphics/niche/InkHUD`)._ + +- **Offline map tiles with zoom controls** (#10785) and general GPS UX improvements (#10846). +- **Full touch support** for the T5 E-Paper S3 (#10286) and a full InkHUD port for the LilyGo T5 E-Paper S3 Pro (#10211). +- **"Wipe all messages"** option (#10721). +- T-mini E-Ink S3 support added (#9856). + +### UI / display - MUI + +_MUI is the older/legacy graphical UI menu system, still selectable alongside BaseUI (`draw/MenuHandler`'s `MuiPicker`/`switchToMUIMenu`)._ + +- WiFi map-tile download adapted for Heltec V4 (#10011). + +### UI / display - shared / cross-cutting + +_Touches the display driver layer or more than one UI system at once._ + +- InkHUD and BaseUI **message store unified** into a shared implementation (#10596). +- T-mini E-Ink S3 support landed for both InkHUD and BaseUI (#9856). +- Board-specific TFT driver support and simplified TFT ifdef chains for easier porting (#10827, #10803); faster TFT color conversion (#10814); touchscreen variant flags (`VARIANT_TOUCHSCREEN`/`ENABLE_TOUCH_INT`) added for new touch boards (#10815). + +## Backend / developer-facing features + +### Memory & stability infrastructure + +- **MemClass.h** - a central memory-class ladder providing fail-safe-small defaults across constrained platforms (#10901). +- **MemAudit** - per-subsystem heap accounting reported in the boot log (#10900). +- nRF52 heap tiers and SoftDevice RAM reservation right-sized, freeing an extra ~8KB heap arena (#10898, #10903). +- Native Portduino malloc shim added for more realistic memory behavior in simulation (#10677). +- Bluetooth memory freed automatically when Wi-Fi is enabled or Bluetooth is disabled (#10398); Bluetooth wait is skipped entirely when disabled (#10571). +- NodeDB "warm store" - new persistent warm-tier node storage layer (#10705 base, #10746/#10759 right-sizing for constrained platforms, #10809 fixing associated spiLock deadlocks). +- 2.8 NodeDB shrink/decoupling/restructuring to reduce per-node memory footprint (#10413). +- Flash hardening, filesystem platform unification, and a write-behind LFS cache for STM32WL/nRF52 - a storage-format break (#10171). + +### New APIs / module-author infrastructure + +- **MCP server** added for interacting with Meshtastic devices and driving a testing framework / TUI, later extracted to its own repo (#10194, #10861). +- Native "sensors" simulation support for Portduino (#10748); `PortduinoSetOptions` to override the `realhardware` flag for tests (#10157). +- Hardfault handler added for STM32, making crashes visibly obvious in logs (#10071). +- `BinarySemaphorePosix` implemented with proper pthread synchronization for native builds (#9895). +- NimBLE parameter overhaul, including a fix attempt for incompatible BLE bond cleanup (#10741). +- STM32 ADC support added to `AnalogBatteryLevel` (#9369). +- JSON library dependency removed from firmware builds while retaining full JSON support in meshtasticd (#10152) - reduces firmware footprint for module authors relying on the JSON path. +- Improved manual build flow / developer build ergonomics (#8839).- External Notifications module logic fully reworked for more flexible notification rules (#10006). diff --git a/.github/workflows/main_matrix.yml b/.github/workflows/main_matrix.yml index d54eae77e..10281b6bd 100644 --- a/.github/workflows/main_matrix.yml +++ b/.github/workflows/main_matrix.yml @@ -731,7 +731,7 @@ jobs: # Nightly publish: refresh the root of the meshtastic-firmware-nightly R2 # bucket with the current develop build. Runs on the cron schedule (or a manual # nightly=true dispatch) and never creates a GitHub release. The bucket's - # release_notes.md is maintained by hand and deliberately left untouched. + # release_notes.md is published from .github/nightly/ in this repo. publish-nightly: runs-on: ubuntu-24.04 if: github.repository_owner == 'meshtastic' && (github.event_name == 'schedule' || github.event.inputs.nightly == 'true') @@ -741,6 +741,11 @@ jobs: esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,rp2350,stm32 r2_bucket: meshtastic-firmware-nightly steps: + # Only the index templates and release notes are needed here. + - uses: actions/checkout@v7 + with: + sparse-checkout: .github/nightly + - name: Get firmware artifacts uses: actions/download-artifact@v8 with: @@ -763,6 +768,10 @@ jobs: '{version: $ver, id: ("v" + $ver), title: ("Meshtastic Firmware " + $ver + " Nightly"), commit: $sha}' \ > ./stage/index.json + # The notes are maintained in-tree and published to the bucket root. + - name: Stage the nightly release notes + run: cp .github/nightly/release_notes.md ./stage/release_notes.md + # For diagnostics - name: Display structure of files to publish run: ls -lR ./stage @@ -782,18 +791,35 @@ jobs: exit 1 fi + # tree renders the file listing; .github/nightly wraps it in the page + # chrome. tree silently skips an --hintro/--houtro file it cannot open, so + # the rendered page is checked for both markers below. - name: Generate nightly html index env: VERSION: ${{ needs.version.outputs.long }} + COMMIT: ${{ github.sha }} + RUN_ID: ${{ github.run_id }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} working-directory: ./stage run: | - tree -H "." -T "Meshtastic Nightly $VERSION" --noreport -I "index.html" --charset utf-8 > index.html + set -euo pipefail + # Substitute placeholders in the nightly index header template. + sed -e "s|%%VERSION%%|$VERSION|g" \ + -e "s|%%COMMIT%%|$COMMIT|g" \ + -e "s|%%COMMIT_SHORT%%|${COMMIT:0:7}|g" \ + -e "s|%%BUILD_DATE%%|$(date -u +'%Y-%m-%d %H:%M UTC')|g" \ + -e "s|%%RUN_ID%%|$RUN_ID|g" \ + -e "s|%%RUN_URL%%|$RUN_URL|g" \ + "$GITHUB_WORKSPACE/.github/nightly/hintro.html" > "$RUNNER_TEMP/hintro.html" + # Render the html index using tree, with custom header and footer templates. + tree -H "." -h --noreport -I "index.html" --charset utf-8 \ + --hintro "$RUNNER_TEMP/hintro.html" \ + --houtro "$GITHUB_WORKSPACE/.github/nightly/houtro.html" \ + > index.html # Mirror the staged directory to Cloudflare R2. --delete at the bucket root # clears stale nightly binaries, and is in scope for the whole bucket because - # this bucket holds nothing but the nightly build. release_notes.md lives only - # in the bucket and is never staged, so it is excluded from the sync to keep - # --delete from removing it. + # this bucket holds nothing but the nightly build. - name: Publish nightly to Cloudflare R2 env: AWS_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} @@ -810,12 +836,10 @@ jobs: set -euo pipefail aws --version # Cache for 1 hour in browser, 1 day on CDN. - # Preserve the release_notes.md (manually maintained) aws s3 sync ./stage "s3://${r2_bucket}/" \ --endpoint-url "$R2_ENDPOINT" \ --no-progress \ --delete \ - --exclude 'release_notes.md' \ --exclude 'index.json' \ --exclude 'index.html' \ --metadata "commit=${{ github.sha }},run=${{ github.run_id }}" \ diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index aec3fc6f8..9c7d77052 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -161,6 +161,12 @@ lint: - test/test_airtime/test_main.cpp - test/test_throttle/test_main.cpp - test/test_uptime_clock/test_main.cpp + # The nightly index templates are halves of one page, not whole documents: + # hintro.html stops mid-
and houtro.html starts with closing tags, so + # that `tree --hintro/--houtro` can splice the file listing between them. + - linters: [ALL] + paths: + - .github/nightly/*.html runtimes: enabled: - python@3.14.4