feat(drivers): pick a version, and see when your own copy has fallen behind#672
Conversation
…behind
Two gaps, both about an operator not being told something.
A local override was skipped entirely by EnrichCatalog, so UpstreamVersion and
UpdateAvailable were never computed for it. An override shadows the channel, so
running your own copy meant never finding out a newer version existed.
It is now told. Resolution is untouched: the local file keeps winning, and the
UI says so rather than offering an Update button that would install a version
the override goes on shadowing. Being told is not being changed.
UpdateAvailable is also gated on both versions being real semver.
compareSemver falls back to comparing strings, so an override versioned
"local" or not versioned at all would have announced an update on alphabetical
luck. RepositoryID stays empty for a local file, because naming a repository
there would read as provenance it does not have.
The second gap: GET /api/device_repository/drivers/{id}/versions has always
existed and no UI called it. Rollback steps back exactly one version, so a
specific older one was unreachable even though the channel keeps every version
it has ever signed -- 110 of them today. Each managed driver now has a Versions
list showing what is downloaded, what the channel offers, and which is live.
Activating something already on disk needs no network; anything else is fetched
first, and the labels say which is happening.
The panel builds DOM rather than assembling HTML. Version strings come from a
signed manifest, but a signed manifest is still remote input.
Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 721c65ea56
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| available.forEach(function (v) { | ||
| var version = typeof v === "string" ? v : (v && v.version); | ||
| if (!version || installedVersions[version]) return; | ||
| rows.push({version: version, active: false, local: false}); |
There was a problem hiding this comment.
Read the version from the nested candidate
When a version exists only in the signed repository, the versions endpoint returns each available item as a VersionCandidate shaped like {repository_id, driver: {version, ...}}, not as an object with a top-level version (the existing update-badge.js consumer follows this shape). Consequently v.version is undefined and every channel-only candidate is skipped, leaving bundled drivers with a blank panel and preventing the advertised selection of older remote versions.
Useful? React with 👍 / 👎.
| var payload = row.local | ||
| ? {version: row.version, sha256: row.sha256 || ""} | ||
| : {version: row.version}; |
There was a problem hiding this comment.
Include the repository when fetching a version
When the operator selects a version that is not downloaded, this payload contains only version, but handleDeviceRepositoryInstall rejects requests unless either repository_id or channel is present. Thus every “Fetch and activate” request will return HTTP 400 even after the available candidates are rendered; preserve the candidate's repository_id in the row and send it with the install request.
Useful? React with 👍 / 👎.
Two gaps, both about an operator not being told something.
A local override never heard about updates
EnrichCatalogskipped local entries outright:So
UpstreamVersionandUpdateAvailablewere never computed for a driver you supply yourself. An override shadows the channel, which means running your own copy meant never finding out a newer version existed.It is now told. Resolution is untouched — the local file keeps winning, and the UI says so rather than offering an Update button that would install a version the override goes on shadowing:
Being told is not being changed. You keep your copy until you decide otherwise.
Two details that matter:
UpdateAvailableis gated on both versions being real semver.compareSemverfalls back to comparing strings, so an override versioned"local"— or not versioned at all — would have announced an update on alphabetical luck.RepositoryIDstays empty for a local file. Naming a repository there would read as provenance it does not have, and an existing test rightly guards that.The version list existed and nothing used it
GET /api/device_repository/drivers/{id}/versionshas been there all along with no caller. Rollback steps back exactly one version, so a specific older one was unreachable — even though the channel keeps every version it has ever signed, 110 of them today. That history is the whole point of an immutable channel and none of it was reachable.Each managed driver now has a Versions… list:
v1.4.0 · running,v1.3.1→ Activate (no network)v2.0.0→ Fetch and activateThe labels distinguish the two so it is clear why one is instant. The running version carries no button.
The panel builds DOM rather than assembling HTML. Version strings come from a signed manifest, but a signed manifest is still remote input.
Tests
web/driver-versions.test.mjspins both properties, including the one that pulls against the other: an override must be told, and must not be quietly replaced.Go:
internal/driverrepocovers the override being told what the channel has, an older override genuinely offering an update, and an unversioned one making no claim either way.Web 117 passed ·
make verifyclean.🤖 Generated with Claude Code