Skip to content

feat: check for and apply plugin updates from the marketplace#9

Open
aguung wants to merge 4 commits into
enowdev:mainfrom
aguung:feat/plugin-update-check
Open

feat: check for and apply plugin updates from the marketplace#9
aguung wants to merge 4 commits into
enowdev:mainfrom
aguung:feat/plugin-update-check

Conversation

@aguung

@aguung aguung commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Once installed, a plugin had no way to signal it was behind the marketplace's current published version, and no way to update short of deleting and reinstalling.
  • Adds a manual, per-plugin update flow: an "update available" badge in My Plugins, and correct Install/Installed/Update button states in the Marketplace browse tab (which previously always showed "Install", even for an already-installed plugin).

Problem

  • core/plugins/bundle.go's Extract (used by Install) refuses to run if the plugin's folder already exists, so there was no reusable path for updating an installed plugin in place.
  • The Marketplace browse view in PluginsApp.tsx always rendered "Install" regardless of whether the plugin was already installed — clicking it on an installed plugin just failed with an "already exists" error.

Solution

  • Manager.Update(id, zipBytes): mirrors Extract's per-entry loop, but requires the plugin to already exist and never deletes the destination folder first, so any local-only file a plugin wrote at runtime (outside the published bundle) survives an update.
  • POST /api/market/update/{id}: same cloud-metadata + bundle-download flow as Install, but stops the plugin first and calls Update instead of Extract.
  • Frontend: PluginsApp fetches the unfiltered marketplace catalog once and cross-references it against the already-loaded installed-plugins list, purely client-side (compareVersions, a small hand-rolled dot-version comparator — no new dependency). This drives the My Plugins badge and is passed down to the Marketplace view to pick Install vs. Installed vs. Update per listing.
  • Manual, per-plugin only — no auto-update, no bulk "update all".

Changed files

File Change
core/plugins/bundle.go Adds Update.
core/plugins/bundle_test.go New tests for Update (nonexistent plugin, overwrite, local-file preservation, path-escape rejection).
server/handlers/api_market.go Adds the Update handler.
server/server.go Registers POST /api/market/update/{id}.
web/src/lib/semver.ts New compareVersions helper.
web/src/lib/api.ts Adds marketApi.update.
web/src/apps/PluginsApp.tsx Marketplace-catalog fetch, My Plugins update badge, Marketplace Install/Installed/Update button states.

Test plan

  • go test ./core/plugins/... -run TestUpdate -v passes (4/4)
  • go build ./... and go test ./... pass with no regressions
  • Manually verified Manager.Update end-to-end: version bumps correctly, a local-only file survives the update
  • tsc -b --noEmit and oxlint pass on the changed frontend files
  • Visual confirmation of the rendered badge/button states in a running browser — not done in this environment (no browser-automation tooling available); please check before merging

aguung added 4 commits July 9, 2026 07:54
Extract refuses to run if the plugin folder already exists, so there
was no way to apply a newer bundle over an already-installed plugin.
Update mirrors Extract's per-entry logic but requires the plugin to
already exist and never deletes the folder first, so any local-only
file the plugin wrote at runtime survives the upgrade.
Mirrors Install's cloud-metadata + bundle-download flow, but stops the
plugin first and calls the new Manager.Update instead of Extract, so
it works on an already-installed plugin instead of erroring.
Cross-references the already-installed plugin list against an
unfiltered marketplace catalog fetch (both client-side, no new
backend query) to badge outdated plugins in My Plugins and fix the
Marketplace browse view, which previously always showed "Install"
even for an already-installed plugin.
Both ran 3-4 lines; compressed to 1-2 lines per the codebase's
comment-brevity convention.
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