Skip to content

chat: fix per-marketplace plugin auto-update never running - #333289

Draft
joshspicer wants to merge 2 commits into
mainfrom
fix/per-marketplace-plugin-auto-update
Draft

chat: fix per-marketplace plugin auto-update never running#333289
joshspicer wants to merge 2 commits into
mainfrom
fix/per-marketplace-plugin-auto-update

Conversation

@joshspicer

@joshspicer joshspicer commented Aug 29, 2026

Copy link
Copy Markdown
Member

Fixes #330090

Root cause — a real product bug, not tester environment

The per-marketplace autoUpdate plumbing from microsoft/vscode-internalbacklog#8462 is correct end to end (managed settings → copilotManagedSettings normalization → chat.plugins.extraMarketplacesmarketplaceReference parsing → isMarketplaceAutoUpdateEnabled). Six of the seven new tests pass on main unchanged, which is the evidence that the policy layer itself was never broken.

The defect is one layer down, in the periodic update check that the policy gates:

  1. Installed plugin metadata hydrates asynchronously (_hydratePluginMetadata re-reads each marketplace to rebuild descriptors from installed.json).
  2. _scheduleUpdateCheck() is armed from runWhenGlobalIdle, which fires long before that completes.
  3. _doRunUpdateCheck() therefore sees installedPlugins.get().length === 0 and returns early.
  4. Its finally block unconditionally re-armed with _scheduleUpdateCheck(PLUGIN_UPDATE_CHECK_INTERVAL_MS) — a hard 24 h delay — and nothing observed installedPlugins to re-arm sooner.

So in every real session the one scheduled check lost the race against hydration, then went quiet for a day. No marketplace was fetched, marketplacesWithUpdates stayed empty, PluginAutoUpdate was never signalled, and no plugin ever auto-updated — which is why Eleanor Boyd (@eleanorjboyd) saw no update with extensions.autoUpdate disabled and enabled. The early return also never wrote PLUGIN_UPDATE_LAST_CHECK_STORAGE_KEY, so restarting just repeated the lost race.

This is independent of the autoUpdate override, which is why the feature looked correct in review but shipped non-functional. microsoft/vscode-internalbacklog#8462 should be reopened.

Fix

Track whether the last check bailed out purely because metadata had not hydrated, and re-arm as soon as installed entries appear:

  • _lastCheckFoundNoInstalledPlugins records that state, set only by an actual empty check.
  • An autorun on installedPlugins re-schedules with delay 0 the first time entries appear, guarded on _updateCheckRunning so it cannot overlap an in-flight check.
  • The check's own backoff picks 0 instead of a full interval when it previously found nothing and entries have since appeared — covering hydration landing while a check runs.

The flag returns to false as soon as a check observes installed plugins, so this cannot loop; normal 24 h backoff resumes. With no plugins installed, both paths short-circuit to exactly the previous behaviour.

Enforcement stays strictly per-marketplace: _doRunUpdateCheck still filters every marketplace through isMarketplaceAutoUpdateEnabled(ref) and _isMarketplaceAllowedByStrictPolicy(ref) before fetching, and reports only canonical IDs with real upstream commits, so PluginAutoUpdate keeps calling updateAllPlugins({ marketplaceIds }) with a targeted set rather than acting on a global "something has updates" signal. strictKnownMarketplaces gating is unchanged on every refresh and update path.

Tests

New suite PluginMarketplaceService - per-marketplace auto-update enforcement, covering the matrix from #8462:

case expectation
autoUpdate: true, global off marketplace is refreshed anyway
autoUpdate: false, global on marketplace is not refreshed
undefined, global on follows global (refreshed)
undefined, global off follows global (not refreshed)
mixed marketplaces in one config only the permitted subset is fetched
strictKnownMarketplaces + autoUpdate: true still blocked when not allow-listed
regression plugins hydrated after startup idle are still checked
regression a recent successful check is not re-run when metadata is already hydrated at startup

Both regression tests were verified to fail without their corresponding fix and pass with it.

Validation

  • npm run transpile-client, npm run typecheck-client — no errors in touched files
  • npm run valid-layers-check — clean
  • ./scripts/test.sh --grep "PluginMarketplaceService|PluginAutoUpdate|PluginInstallService" — 124 passing

Scope is deliberately minimal: 2 files, 21 production lines changed.

Installed plugin metadata is hydrated asynchronously from `installed.json`,
so the periodic update check scheduled at startup idle almost always observed
an empty installed list. It then bailed out and its `finally` block re-armed
with a hard `PLUGIN_UPDATE_CHECK_INTERVAL_MS` (24h) delay, so no marketplace
was ever fetched and no plugin was ever auto-updated -- regardless of
`extensions.autoUpdate` or a managed marketplace's `autoUpdate` override.

Track whether the last check bailed out for that reason and re-arm as soon as
installed entries become observable, both from an autorun on `installedPlugins`
and from the check's own backoff decision. Enforcement stays strictly
per-marketplace and `strictKnownMarketplaces` continues to gate every
refresh path.

Adds the auto-update policy matrix from the feature spec: `true`, `false`,
`undefined`, mixed marketplaces, global auto-update disabled, strict-policy
gating, plus a regression test for the hydration race.

Fixes #330090

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings August 29, 2026 00:01

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: 1 Medium severity · 2 Low severity

New issues introduced by this change (3)
Severity Finding
Medium severity src/​vs/​workbench/​contrib/​chat/​common/​plugins/​pluginMarketplaceService.ts — Initializing this flag to true treats “no check has run yet” as if an update check observed no…
Low severity src/​vs/​workbench/​contrib/​chat/​test/​common/​plugins/​pluginMarketplaceService.test.ts — This test comment exceeds the one-line inline-comment convention and only describes the setup…
Low severity src/​vs/​workbench/​contrib/​chat/​common/​plugins/​pluginMarketplaceService.ts — This private-field JSDoc includes startup control flow and issue history that are also described at…
What changed in this PR

Fixes plugin auto-update checks missed during asynchronous metadata hydration.

Changes:

  • Re-schedules checks when installed plugins become observable.
  • Adds per-marketplace policy and hydration regression tests.
File Description
pluginMarketplaceService.ts Adds hydration-aware update scheduling.
pluginMarketplaceService.test.ts Tests policy combinations and delayed hydration.
Suppressed comments (2)

src/vs/workbench/contrib/chat/common/plugins/pluginMarketplaceService.ts:426

  • This multi-line inline comment narrates the immediately following autorun and duplicates the field documentation. Keep the non-obvious timing constraint in a single concise line.
			// Installed plugin metadata is hydrated asynchronously, so the
			// check above typically runs against an empty list. Re-arm as soon
			// as installed entries become observable instead of waiting a full
			// check interval.

src/vs/workbench/contrib/chat/common/plugins/pluginMarketplaceService.ts:890

  • This two-line inline comment restates the condition below it. Condense it to a single line so the retry invariant remains clear without narrating the expression.
					// A check that found nothing installed did not really run;
					// retry immediately if entries have appeared since.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/vs/workbench/contrib/chat/common/plugins/pluginMarketplaceService.ts Outdated
Comment thread src/vs/workbench/contrib/chat/common/plugins/pluginMarketplaceService.ts Outdated
@github-actions

github-actions Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Base: 006c4ca9 Current: e7a623aa

No screenshot changes.

- Start `_lastCheckFoundNoInstalledPlugins` as `false` so a fresh session no
  longer treats "no check has run yet" as an empty check. Previously, when
  metadata happened to be hydrated before startup idle, the autorun forced
  `_scheduleUpdateCheck(0)` and overrode the deadline derived from
  `PLUGIN_UPDATE_LAST_CHECK_STORAGE_KEY`, refetching every eligible
  marketplace on each restart. `_doRunUpdateCheck` now sets the flag only
  after an actual empty check.
- Condense the field JSDoc and the two scheduling-site comments to one line
  each, keeping the rationale at the scheduling site only.

Adds a regression test asserting that a recent successful check is not re-run
when metadata is already hydrated at startup; it fails with the previous
`true` initializer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

Review tier: Balanced
Findings: None

Issues resolved since last review (3)
Severity Finding
Low severity src/​vs/​workbench/​contrib/​chat/​common/​plugins/​pluginMarketplaceService.ts — This private-field JSDoc includes startup control flow and issue history that are also described at… View resolved comment
Low severity src/​vs/​workbench/​contrib/​chat/​test/​common/​plugins/​pluginMarketplaceService.test.ts — This test comment exceeds the one-line inline-comment convention and only describes the setup… View resolved comment
Medium severity src/​vs/​workbench/​contrib/​chat/​common/​plugins/​pluginMarketplaceService.ts — Initializing this flag to true treats “no check has run yet” as if an update check observed no… View resolved comment

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.

auto update plugin not working

2 participants