Skip to content

Add HTTP firmware command headers for image URL updates and reboots.#864

Merged
tavdog merged 1 commit into
mainfrom
feature/http-firmware-command-headers
Jul 22, 2026
Merged

Add HTTP firmware command headers for image URL updates and reboots.#864
tavdog merged 1 commit into
mainfrom
feature/http-firmware-command-headers

Conversation

@tavdog

@tavdog tavdog commented Jul 21, 2026

Copy link
Copy Markdown
Member

Queue reboot and image URL changes for HTTP-polling devices and deliver them via /next response headers, with matching controls on the device update page.

Summary by CodeRabbit

  • New Features

    • Added HTTP-based firmware controls for compatible devices, including image URL synchronization and reboot commands.
    • Devices now receive pending OTA, image, and reboot instructions through HTTP response headers during image polling.
    • Added a simplified Live Firmware Settings interface for HTTP-capable devices.
  • Bug Fixes

    • Improved firmware image URL display when using HTTP-connected devices.
    • Added clearer handling and delivery of pending firmware actions.
  • Documentation

    • Added guidance that HTTP firmware commands require version 1.6.5 or later.

Queue reboot and image URL changes for HTTP-polling devices and deliver them via /next response headers, with matching controls on the device update page.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds HTTP firmware command support for eligible devices, including queued image/reboot state, context-aware command dispatch, pending response headers, device UI controls, localization, and coverage for queueing and header delivery.

Changes

HTTP firmware commands

Layer / File(s) Summary
HTTP firmware capability and management UI
internal/data/models.go, internal/data/models_test.go, web/templates/manager/update.html, web/i18n/*.json
Devices identify HTTP firmware command support, while the management UI adds image URL synchronization and reboot controls with localized messaging.
Command queueing and dispatch
internal/server/helpers.go, internal/server/handlers_api.go, internal/server/handlers_device.go, internal/server/handlers_api_test.go, internal/data/models.go
Reboot and firmware settings commands persist pending state, broadcast payloads, and propagate request contexts; tests verify queued image URLs and reboot flags.
Pending HTTP header delivery
internal/server/helpers.go, internal/server/handlers_device_api.go, internal/server/handlers_device.go, internal/server/handlers_device_api_test.go
HTTP polling returns pending OTA, image, and reboot headers, clears pending state, and uses the stored image URL when the reported URL is unavailable.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ManagerUI
  participant Server
  participant DeviceDB
  participant HTTPDevice
  ManagerUI->>Server: submit image URL or reboot command
  Server->>DeviceDB: persist pending command state
  Server->>HTTPDevice: broadcast firmware command
  HTTPDevice->>Server: request next image
  Server->>HTTPDevice: return pending HTTP headers
  Server->>DeviceDB: clear pending command state
Loading

Possibly related PRs

  • tronbyt/server#863: Both changes update HTTP firmware image URL handling in handleUpdateDeviceGet.

Suggested reviewers: ingmarstein

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding HTTP firmware command headers for image URL updates and reboots.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/http-firmware-command-headers

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
internal/server/handlers_api_test.go (1)

1203-1209: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use require and assert in the new tests.

  • internal/server/handlers_api_test.go#L1203-L1209: use require.NoError for the query and assert.Equal for PendingImageURL.
  • internal/server/handlers_api_test.go#L1231-L1237: use require.NoError for the query and assert.True for PendingReboot.
  • internal/server/handlers_device_api_test.go#L99-L135: replace new direct failure checks with require for setup/fatal prerequisites and assert for response and persisted-state assertions.

As per coding guidelines, **/*_test.go: “Use the testify library, specifically assert and require, in unit tests.”

🤖 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 `@internal/server/handlers_api_test.go` around lines 1203 - 1209, Replace
direct testing failures with testify assertions: in
internal/server/handlers_api_test.go lines 1203-1209, use require.NoError for
the database query and assert.Equal for PendingImageURL; in lines 1231-1237, use
require.NoError and assert.True for PendingReboot. In
internal/server/handlers_device_api_test.go lines 99-135, use require for setup
or fatal prerequisites and assert for response and persisted-state checks.

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 `@internal/server/helpers.go`:
- Around line 704-729: Update the pending command handling in handleNextApp so
acknowledgement is serialized with enqueueing: reload the device state and claim
each pending update under a row lock, or use generation-aware conditional
updates. Ensure clearing pending_update_url, pending_image_url, and
pending_reboot only acknowledges the command that was sent, preserving any newer
command queued after the initial device load.

---

Nitpick comments:
In `@internal/server/handlers_api_test.go`:
- Around line 1203-1209: Replace direct testing failures with testify
assertions: in internal/server/handlers_api_test.go lines 1203-1209, use
require.NoError for the database query and assert.Equal for PendingImageURL; in
lines 1231-1237, use require.NoError and assert.True for PendingReboot. In
internal/server/handlers_device_api_test.go lines 99-135, use require for setup
or fatal prerequisites and assert for response and persisted-state checks.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 91569ee6-67c7-4e3f-864b-a10bf9fd6e22

📥 Commits

Reviewing files that changed from the base of the PR and between 4765dc3 and 9cf9143.

📒 Files selected for processing (11)
  • internal/data/models.go
  • internal/data/models_test.go
  • internal/server/handlers_api.go
  • internal/server/handlers_api_test.go
  • internal/server/handlers_device.go
  • internal/server/handlers_device_api.go
  • internal/server/handlers_device_api_test.go
  • internal/server/helpers.go
  • web/i18n/de.json
  • web/i18n/en.json
  • web/templates/manager/update.html

Comment on lines +704 to +729
if _, err := gorm.G[data.Device](s.DB).Where("id = ?", device.ID).Update(ctx, "pending_update_url", ""); err != nil {
slog.Error("Failed to clear pending update", "error", err)
} else {
device.PendingUpdateURL = ""
}
}

if imageURL := device.PendingImageURL; imageURL != "" {
slog.Info("Sending image URL update header", "device", device.ID, "url", imageURL)
w.Header().Set("Tronbyt-Image-URL", imageURL)

if _, err := gorm.G[data.Device](s.DB).Where("id = ?", device.ID).Update(ctx, "pending_image_url", ""); err != nil {
slog.Error("Failed to clear pending image URL", "error", err)
} else {
device.PendingImageURL = ""
}
}

if device.PendingReboot {
slog.Info("Sending reboot header", "device", device.ID)
w.Header().Set("Tronbyt-Reboot", "true")

if _, err := gorm.G[data.Device](s.DB).Where("id = ?", device.ID).Update(ctx, "pending_reboot", false); err != nil {
slog.Error("Failed to clear pending reboot", "error", err)
} else {
device.PendingReboot = false

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Serialize command acknowledgement with queueing.

These unconditional clears race with a new command queued after handleNextApp loaded device. A poll can send image URL A, a request can queue B, and this update then clears B—so B is never delivered. Reload and claim/ack pending commands under a row lock or use command generations/conditional acknowledgements so a later enqueue survives.

🤖 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 `@internal/server/helpers.go` around lines 704 - 729, Update the pending
command handling in handleNextApp so acknowledgement is serialized with
enqueueing: reload the device state and claim each pending update under a row
lock, or use generation-aware conditional updates. Ensure clearing
pending_update_url, pending_image_url, and pending_reboot only acknowledges the
command that was sent, preserving any newer command queued after the initial
device load.

@tavdog
tavdog merged commit 1bbb090 into main Jul 22, 2026
11 checks passed
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.

1 participant