Skip to content

Add runtime versions summary to system page#231

Merged
matteius merged 3 commits intomainfrom
feature/system-runtime-versions-summary
Mar 9, 2026
Merged

Add runtime versions summary to system page#231
matteius merged 3 commits intomainfrom
feature/system-runtime-versions-summary

Conversation

@matteius
Copy link
Contributor

@matteius matteius commented Mar 9, 2026

Summary

  • add a runtime-generated versions.items summary to GET /api/system/info
  • surface the summary in a dedicated Versions tab on the System page
  • extend API docs and focused integration coverage for the new versions data/UI

Closes #229.

Validation

  • cmake --build build --target lightnvr
  • npm --prefix web run build
  • npx playwright test tests/integration/lightnvr.api.spec.ts --project=api
  • npx playwright test tests/integration/specs/system.ui.spec.ts --project=ui --grep "versions summary in a dedicated tab"

Pull Request opened by Augment Code with guidance from the PR author

@codecov
Copy link

codecov bot commented Mar 9, 2026

Codecov Report

❌ Patch coverage is 0% with 98 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/web/api_handlers_system.c 0.00% 98 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a runtime-generated versions summary to GET /api/system/info and surfaces it in a new "Versions" tab on the System page. It collects version information for LightNVR itself, the base OS, optional services (go2rtc), and all linked libraries (SQLite, libcurl, mbedTLS, libuv, llhttp, FFmpeg components).

Changes:

  • New C helper functions in api_handlers_system.c to collect and serialize runtime library/OS versions into the versions.items JSON array
  • Extended go2rtc_api.c/go2rtc_api.h with a go2rtc_api_get_application_info function that also retrieves go2rtc's version and revision strings
  • New VersionsTable.jsx frontend component and a tab-based layout in SystemView.jsx, backed by updated integration tests and API documentation

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/web/api_handlers_system.c Adds add_versions_to_json, read_os_release_value, trim_copy_value, and format_triplet_version helpers; calls add_versions_to_json in handle_get_system_info
src/video/go2rtc/go2rtc_api.c Refactors go2rtc_api_get_server_info into go2rtc_api_get_application_info with version/revision output params; original function delegates to the new one
include/video/go2rtc/go2rtc_api.h Declares the new go2rtc_api_get_application_info function
web/js/components/preact/system/VersionsTable.jsx New component rendering the versions array in a categorized table
web/js/components/preact/SystemView.jsx Adds tab navigation between System and Versions panels; initializes versions.items state
tests/integration/specs/system.ui.spec.ts New UI integration test for the Versions tab
tests/integration/pages/SystemPage.ts Adds locators and openVersionsTab helper for the new UI
tests/integration/lightnvr.api.spec.ts Extends the system API test to verify versions.items structure
docs/API.md Documents the new versions.items field in the system info response

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +603 to +614
bool go2rtc_api_get_application_info(int *rtsp_port,
char *version, size_t version_size,
char *revision, size_t revision_size) {
if (!g_initialized) {
log_error("go2rtc API client not initialized");
return false;
}

if (version && version_size > 0) {
version[0] = '\0';
}
if (revision && revision_size > 0) {
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

The go2rtc_api_get_application_info function does not set CURLOPT_TIMEOUT on the CURL handle, unlike other functions in the same file (e.g., go2rtc_api_add_stream and go2rtc_api_stream_exists both set CURLOPT_TIMEOUT to 10s). Since add_versions_to_json calls this function on every GET /api/system/info request, a non-responsive go2rtc process will cause the entire system info API call to hang indefinitely until the OS-level TCP timeout fires. A CURLOPT_TIMEOUT of a few seconds (e.g., 5s) should be added to match the pattern used elsewhere in this file.

Copilot uses AI. Check for mistakes.
Comment on lines +299 to +346
{activeTab === 'system' ? (
<>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<SystemInfo systemInfo={systemInfo} formatUptime={formatUptime} />
<MemoryStorage systemInfo={systemInfo} formatBytes={formatBytes} />
</div>

<div className="mb-4">
<StreamStorage systemInfo={systemInfo} formatBytes={formatBytes} />
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<StreamsInfo systemInfo={systemInfo} formatBytes={formatBytes} />
<StorageHealth formatBytes={formatBytes} />
</div>

<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<NetworkInfo systemInfo={systemInfo} />
<WebServiceInfo systemInfo={systemInfo} />
</div>
<div className="mb-4">
<StreamStorage systemInfo={systemInfo} formatBytes={formatBytes} />
</div>

<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<NetworkInfo systemInfo={systemInfo} />
<WebServiceInfo systemInfo={systemInfo} />
</div>

<LogsView
logs={logs}
logLevel={logLevel}
logCount={logCount}
pollingInterval={pollingInterval}
setLogLevel={handleSetLogLevel}
setLogCount={setLogCount}
setPollingInterval={handleSetPollingInterval}
loadLogs={() => {
// Trigger a manual log refresh
console.log('Manually triggering log refresh');
const event = new CustomEvent('refresh-logs');
window.dispatchEvent(event);
}}
clearLogs={clearLogs}
/>
<LogsView
logs={logs}
logLevel={logLevel}
logCount={logCount}
pollingInterval={pollingInterval}
setLogLevel={handleSetLogLevel}
setLogCount={setLogCount}
setPollingInterval={handleSetPollingInterval}
loadLogs={() => {
// Trigger a manual log refresh
console.log('Manually triggering log refresh');
const event = new CustomEvent('refresh-logs');
window.dispatchEvent(event);
}}
clearLogs={clearLogs}
/>

<LogsPoller
logLevel={logLevel}
logCount={logCount}
pollingInterval={pollingInterval}
onLogsReceived={handleLogsReceived}
/>
<LogsPoller
logLevel={logLevel}
logCount={logCount}
pollingInterval={pollingInterval}
onLogsReceived={handleLogsReceived}
/>
</>
) : (
<VersionsTable versions={systemInfo.versions} />
)}
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

The tab content panel (the div containing the System or Versions content) lacks a role="tabpanel" attribute and the associated aria-labelledby attribute linking it to the active tab button. For proper ARIA tab pattern compliance, the content container should have role="tabpanel" and be associated with the controlling tab via aria-labelledby. The active tab button should also have aria-controls pointing to the panel id. Without these, screen readers cannot properly announce the tab structure or identify the active panel.

Copilot uses AI. Check for mistakes.
@matteius matteius merged commit a7ac5ed into main Mar 9, 2026
17 of 19 checks passed
@matteius matteius deleted the feature/system-runtime-versions-summary branch March 9, 2026 10:08
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.

2 participants