From 2b1855585a9f0f1943e34fbaee9883fb25e0cabe Mon Sep 17 00:00:00 2001 From: Brandon Harvey <8107750+bharvey88@users.noreply.github.com> Date: Fri, 24 Jul 2026 10:59:12 -0500 Subject: [PATCH 1/5] Re-point beta-fw tag on every beta publish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rolling beta-fw release tag stays on the commit that was default-branch HEAD when the release was first created. gh release create without --target tags default-branch HEAD, and gh release upload never moves the tag, so the published assets track every beta build while the release source commit does not. Add a step to build-beta.yml that PATCHes the beta-fw tag ref to the built commit after each upload, so the tag always matches the assets. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- .github/workflows/build-beta.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/build-beta.yml b/.github/workflows/build-beta.yml index e07128a..fc6efc4 100644 --- a/.github/workflows/build-beta.yml +++ b/.github/workflows/build-beta.yml @@ -103,3 +103,14 @@ jobs: gh release upload beta-fw {} -R "${{ github.repository }}" --clobber \; done echo "Beta assets published." + + - name: Point beta-fw tag at the built commit + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # gh release create tags default-branch HEAD, and uploads never move + # the tag, so without this the release's source commit drifts away + # from the assets actually published. + gh api -X PATCH "repos/${{ github.repository }}/git/refs/tags/beta-fw" \ + -f sha="${{ github.sha }}" -F force=true + echo "beta-fw -> ${{ github.sha }}" From 388de43158b6532f96e13c28de01e7821f0d73e4 Mon Sep 17 00:00:00 2001 From: Brandon Harvey <8107750+bharvey88@users.noreply.github.com> Date: Tue, 28 Jul 2026 19:44:52 -0500 Subject: [PATCH 2/5] Keep Bluetooth Proxy on for legacy BLE builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Bluetooth Proxy switch does restore from flash, but the _OFF half of RESTORE_DEFAULT_OFF decides the boot where nothing is stored yet, which is the first boot after the switch shipped. MSR-1_BLE.yaml inherited that mode from Core, so legacy BLE devices that had always proxied came up with the proxy off after updating. Core now reads the mode from a bluetooth_proxy_restore_mode substitution defaulting to RESTORE_DEFAULT_OFF, and MSR-1_BLE.yaml overrides it to RESTORE_DEFAULT_ON, the same override pattern the file already uses for its OTA manifest URLs. The unified image is unchanged and a user's saved choice still wins on every later boot. Refs ApolloAutomation/MSR-2#92 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- Integrations/ESPHome/Core.yaml | 12 +++++++++--- Integrations/ESPHome/MSR-1_BLE.yaml | 4 ++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index 5b5cfc1..fea80bf 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,5 +1,5 @@ substitutions: - version: "26.7.9.1" + version: "26.7.29.1" device_description: ${name} made by Apollo Automation - version ${version}. # Default OTA password. Override in your device YAML by re-declaring # `substitutions: { ota_password: !secret _ota_password }` so each @@ -20,6 +20,12 @@ substitutions: ota_stable_manifest: "${stable_manifest_base}/firmware/manifest.json" ota_beta_manifest: "${beta_manifest_base}/manifest-standard.json" + # Bluetooth Proxy switch state on a device with no stored preference yet + # (first boot after this switch was added, or after a factory reset). The + # unified image ships the proxy off; MSR-1_BLE.yaml overrides this to ON so + # legacy BLE devices keep proxying instead of going quiet after an update. + bluetooth_proxy_restore_mode: RESTORE_DEFAULT_OFF + esphome: # List form so package merging concatenates with each variant's own on_boot # entries (mapping form would be replaced by the variant's block instead). @@ -28,7 +34,7 @@ esphome: then: - script.execute: apply_ota_source # Re-apply the Bluetooth Proxy switch after all components set up, so BLE - # scanning matches the persisted switch (proxy stays off by default). + # scanning matches the switch state restored from flash. - priority: -300 then: - if: @@ -755,7 +761,7 @@ switch: id: bluetooth_proxy_switch icon: mdi:bluetooth entity_category: "config" - restore_mode: RESTORE_DEFAULT_OFF + restore_mode: ${bluetooth_proxy_restore_mode} optimistic: true on_turn_on: - esp32_ble_tracker.start_scan: diff --git a/Integrations/ESPHome/MSR-1_BLE.yaml b/Integrations/ESPHome/MSR-1_BLE.yaml index 8c1b573..97ea4f6 100644 --- a/Integrations/ESPHome/MSR-1_BLE.yaml +++ b/Integrations/ESPHome/MSR-1_BLE.yaml @@ -3,6 +3,10 @@ substitutions: ota_stable_manifest: "https://apolloautomation.github.io/MSR-1/firmware-ble/manifest.json" ota_beta_manifest: "https://github.com/ApolloAutomation/MSR-1/releases/download/beta-fw/manifest-ble.json" + # Legacy BLE devices proxied unconditionally before the Bluetooth Proxy + # switch existed, so default it on rather than dropping the proxy on update. + bluetooth_proxy_restore_mode: RESTORE_DEFAULT_ON + esphome: name: apollo-msr-1 friendly_name: Apollo Multisensor Mk1 (MSR-1) From 1370f2aaef97c893707b02cb60bc8b735853e0f4 Mon Sep 17 00:00:00 2001 From: Brandon Harvey <8107750+bharvey88@users.noreply.github.com> Date: Tue, 18 Aug 2026 10:23:00 -0500 Subject: [PATCH 3/5] Bump version to 26.8.18.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Re-dated for the merge day per versioning policy. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- Integrations/ESPHome/Core.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index fea80bf..93b29aa 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,5 +1,5 @@ substitutions: - version: "26.7.29.1" + version: "26.8.18.1" device_description: ${name} made by Apollo Automation - version ${version}. # Default OTA password. Override in your device YAML by re-declaring # `substitutions: { ota_password: !secret _ota_password }` so each From de0189a033706bd3133b4f939f651e46367808ea Mon Sep 17 00:00:00 2001 From: Brandon Harvey <8107750+bharvey88@users.noreply.github.com> Date: Tue, 18 Aug 2026 16:22:28 -0500 Subject: [PATCH 4/5] Default the Firmware Channel select to Stable on all builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the beta-channel wrapper configs and build the plain variant files on the beta branch, so beta and stable images are identical and the Firmware Channel select always defaults to Stable on a fresh flash. Mirrors CAST-1 #60. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- .github/workflows/build-beta.yml | 4 ++-- Integrations/ESPHome/Core.yaml | 9 ++------- Integrations/ESPHome/beta-channel/MSR-1.yaml | 9 --------- Integrations/ESPHome/beta-channel/MSR-1_BLE.yaml | 9 --------- 4 files changed, 4 insertions(+), 27 deletions(-) delete mode 100644 Integrations/ESPHome/beta-channel/MSR-1.yaml delete mode 100644 Integrations/ESPHome/beta-channel/MSR-1_BLE.yaml diff --git a/.github/workflows/build-beta.yml b/.github/workflows/build-beta.yml index e07128a..8ffbdaf 100644 --- a/.github/workflows/build-beta.yml +++ b/.github/workflows/build-beta.yml @@ -41,8 +41,8 @@ jobs: include: # Beta serves OTA updates only, so it builds the end-user image # (MSR-1.yaml), not the first-flash Factory image. - - { yaml: Integrations/ESPHome/beta-channel/MSR-1.yaml, name: firmware-standard } - - { yaml: Integrations/ESPHome/beta-channel/MSR-1_BLE.yaml, name: firmware-ble-beta } + - { yaml: Integrations/ESPHome/MSR-1.yaml, name: firmware-standard } + - { yaml: Integrations/ESPHome/MSR-1_BLE.yaml, name: firmware-ble-beta } uses: esphome/workflows/.github/workflows/build.yml@025a1e6255610c498ed590403b7e510b69e474df # 2026.4.1 with: files: ${{ matrix.yaml }} diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index 93b29aa..5e1c6ce 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,15 +1,10 @@ substitutions: - version: "26.8.18.1" + version: "26.8.18.2" device_description: ${name} made by Apollo Automation - version ${version}. # Default OTA password. Override in your device YAML by re-declaring # `substitutions: { ota_password: !secret _ota_password }` so each # device on your network uses a unique secret instead of the shared default. ota_password: "apolloautomation" - # Default update channel on first boot (no stored user choice yet, i.e. a - # fresh flash). The beta-channel builds override this to "Beta" (see - # Integrations/ESPHome/beta-channel/) so firmware obtained from the beta - # channel keeps tracking it instead of offering a stable "downgrade". - firmware_channel_default: "Stable" # Manifest URL bases. Stable = GitHub Pages (main branch builds). # Beta = rolling "beta" pre-release assets (beta branch builds). stable_manifest_base: "https://apolloautomation.github.io/MSR-1" @@ -804,7 +799,7 @@ select: options: - "Stable" - "Beta" - initial_option: "${firmware_channel_default}" + initial_option: "Stable" on_value: then: - script.execute: apply_ota_source diff --git a/Integrations/ESPHome/beta-channel/MSR-1.yaml b/Integrations/ESPHome/beta-channel/MSR-1.yaml deleted file mode 100644 index 63b5067..0000000 --- a/Integrations/ESPHome/beta-channel/MSR-1.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# Beta-channel build of MSR-1.yaml: the identical image except the Firmware -# Channel select defaults to "Beta" on first boot, so firmware obtained from -# the beta channel keeps tracking it. Built by build-beta.yml only; the -# stable (GitHub Pages) builds use MSR-1.yaml directly. -substitutions: - firmware_channel_default: "Beta" - -packages: - base: !include ../MSR-1.yaml diff --git a/Integrations/ESPHome/beta-channel/MSR-1_BLE.yaml b/Integrations/ESPHome/beta-channel/MSR-1_BLE.yaml deleted file mode 100644 index 1316fa6..0000000 --- a/Integrations/ESPHome/beta-channel/MSR-1_BLE.yaml +++ /dev/null @@ -1,9 +0,0 @@ -# Beta-channel build of MSR-1_BLE.yaml: the identical image except the Firmware -# Channel select defaults to "Beta" on first boot, so firmware obtained from -# the beta channel keeps tracking it. Built by build-beta.yml only; the -# stable (GitHub Pages) builds use MSR-1_BLE.yaml directly. -substitutions: - firmware_channel_default: "Beta" - -packages: - base: !include ../MSR-1_BLE.yaml From 63ef089f799908abfdeee3852a499eda21229910 Mon Sep 17 00:00:00 2001 From: Brandon Harvey <8107750+bharvey88@users.noreply.github.com> Date: Wed, 19 Aug 2026 10:58:58 -0500 Subject: [PATCH 5/5] Bump version to 26.8.19.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- Integrations/ESPHome/Core.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Integrations/ESPHome/Core.yaml b/Integrations/ESPHome/Core.yaml index 5e1c6ce..8e7ad44 100644 --- a/Integrations/ESPHome/Core.yaml +++ b/Integrations/ESPHome/Core.yaml @@ -1,5 +1,5 @@ substitutions: - version: "26.8.18.2" + version: "26.8.19.1" device_description: ${name} made by Apollo Automation - version ${version}. # Default OTA password. Override in your device YAML by re-declaring # `substitutions: { ota_password: !secret _ota_password }` so each