fix(plugins): updatePlugins.sh actually updates installed plugins (closes #6670)#7644
fix(plugins): updatePlugins.sh actually updates installed plugins (closes #6670)#7644JohnMcLear wants to merge 1 commit intodevelopfrom
Conversation
) bin/updatePlugins.sh detected outdated plugins by running `pnpm --filter ep_etherpad-lite outdated --depth=0`, but installed plugins are not registered in src/package.json — bin/plugins.ts adds them via linkInstaller.installPlugin which writes to src/plugin_packages/.versions/<name>@<version>/ and tracks the result in var/installed_plugins.json. pnpm has no view of them, so `outdated` returns empty and the script always reported "All plugins are up-to-date" even when newer versions existed on the registry. PR #7468 fixed npm→pnpm and install→update but kept the same broken detection mechanism, which is why the issue stayed open after that PR landed. Read the plugin list from var/installed_plugins.json instead, then re-invoke linkInstaller.installPlugin(name) for each entry. Calling the installer without a version pin resolves the registry-latest and overwrites the existing pinned copy, so an outdated plugin is brought to head while plugins already at latest are no-ops apart from the pnpm cache hit. Add an `update`/`up` action to bin/plugins.ts so users can also run `pnpm run plugins update` directly, mirroring the existing install/remove/list actions. updatePlugins.sh becomes a one-line wrapper for backwards compatibility. Reproduction (verified): pnpm run install-plugins ep_markdown@11.0.5 # latest is 11.0.18 ./bin/updatePlugins.sh # → 11.0.18 Edge cases tested: no plugins installed, missing installed_plugins.json, already-at-latest re-run. Closes #6670. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ⓘ You've reached your Qodo monthly free-tier limit. Reviews pause until next month — upgrade your plan to continue now, or link your paid account if you already have one. |
Review Summary by QodoFix plugin updates and add update action to plugins.ts
WalkthroughsDescription• Fix plugin update detection by reading from installed_plugins.json instead of pnpm outdated • Add update/up action to bin/plugins.ts for direct plugin updates via pnpm • Simplify updatePlugins.sh to one-line wrapper calling the new update action • Handle edge cases: missing installed_plugins.json, no plugins installed, exclude core package Diagramflowchart LR
A["updatePlugins.sh"] -->|calls| B["pnpm plugins update"]
B -->|invokes| C["bin/plugins.ts update action"]
C -->|reads| D["var/installed_plugins.json"]
D -->|extracts plugin names| E["Filter out ep_etherpad-lite"]
E -->|re-installs each| F["linkInstaller.installPlugin"]
F -->|resolves registry-latest| G["Updates plugin to latest version"]
File Changes1. bin/plugins.ts
|
Code Review by Qodo
Context used✅ Tickets:
🎫 `updatePlugin.sh` doesn't update plugins 1. update() lacks regression test
|
| // Re-install every plugin in installed_plugins.json without a version pin so | ||
| // the registry-latest gets resolved and overwrites the existing pinned copy | ||
| // in src/plugin_packages/. ep_etherpad-lite is excluded because the core is | ||
| // vendored, not plugin-installed. | ||
| const update = ()=> { | ||
| (async () => { | ||
| const path = settings.root+"/var/installed_plugins.json"; | ||
| let plugins: {name: string}[]; | ||
| try { | ||
| plugins = JSON.parse(fs.readFileSync(path, "utf-8")).plugins || []; | ||
| } catch (err: any) { | ||
| if (err.code === 'ENOENT') { | ||
| console.log("No installed_plugins.json found — nothing to update"); | ||
| return; | ||
| } | ||
| throw err; | ||
| } | ||
| const names = plugins | ||
| .map((p) => p.name) | ||
| .filter((n) => n && n !== 'ep_etherpad-lite'); | ||
| if (names.length === 0) { | ||
| console.log("No plugins installed — nothing to update"); | ||
| return; | ||
| } | ||
| console.log(`Updating plugins to latest from registry: ${names.join(', ')}`); | ||
| await checkForMigration(); | ||
| for (const name of names) { | ||
| await linkInstaller.installPlugin(name); | ||
| } | ||
| await persistInstalledPlugins(); | ||
| })(); | ||
| } |
There was a problem hiding this comment.
1. update() lacks regression test 📘 Rule violation ☼ Reliability
This bug fix adds new plugin update behavior but does not include an automated regression test that would fail if the fix were reverted. This increases the risk of the updatePlugins regression reappearing unnoticed.
Agent Prompt
## Issue description
A bug fix was made to `bin/updatePlugins.sh`/`bin/plugins.ts` to correctly update installed plugins, but there is no automated regression test to ensure this behavior remains correct.
## Issue Context
The regression test should fail if the update action returns to the prior broken behavior (for example, not reading `var/installed_plugins.json` or not invoking the installer for installed plugins).
## Fix Focus Areas
- bin/plugins.ts[81-112]
- bin/updatePlugins.sh[5-5]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| const names = plugins | ||
| .map((p) => p.name) | ||
| .filter((n) => n && n !== 'ep_etherpad-lite'); | ||
| if (names.length === 0) { | ||
| console.log("No plugins installed — nothing to update"); | ||
| return; | ||
| } | ||
| console.log(`Updating plugins to latest from registry: ${names.join(', ')}`); | ||
| await checkForMigration(); | ||
| for (const name of names) { | ||
| await linkInstaller.installPlugin(name); | ||
| } |
There was a problem hiding this comment.
2. Unvalidated plugin names 🐞 Bug ⛨ Security
update() installs every name from var/installed_plugins.json (except ep_etherpad-lite) without enforcing the ep_ prefix. If that file is corrupted or modified, running plugins update can install arbitrary packages, unlike checkForMigration() which explicitly restricts to ep_ plugins.
Agent Prompt
### Issue description
`bin/plugins.ts` updates plugins by trusting `var/installed_plugins.json` and installing every entry by name. This should be restricted to actual Etherpad plugins (`ep_` prefix) to prevent accidental or malicious installation of arbitrary packages.
### Issue Context
`checkForMigration()` already enforces `plugin.name.startsWith(plugins.prefix)` before installing from `installed_plugins.json`, but `update()` does not.
### Fix Focus Areas
- Add an explicit `ep_`/`plugins.prefix` validation filter before invoking `installPlugin()`.
- Consider de-duplicating names (e.g., via `new Set(names)`) to avoid repeated installs if the file contains duplicates.
### Fix Focus Areas (code locations)
- bin/plugins.ts[81-112]
- src/static/js/pluginfw/installer.ts[81-134]
- src/static/js/pluginfw/plugins.ts[36-154]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Summary
Closes #6670.
bin/updatePlugins.shhas been silently doing nothing for any non-trivial install: it detected outdated plugins viapnpm --filter ep_etherpad-lite outdated --depth=0, but installed plugins are not registered insrc/package.json—bin/plugins.tsinstalls them vialinkInstaller.installPlugin, which writes tosrc/plugin_packages/.versions/<name>@<version>/and records the result invar/installed_plugins.json. pnpm has no view of them, sooutdatedreturns empty and the script always reportsAll plugins are up-to-date, even withep_markdown@11.0.5installed against a registry latest of11.0.18. PR #7468 fixed the npm→pnpm and install→update parts but kept the same broken detection mechanism — which is why the issue stayed open after that PR landed.This PR enumerates the plugin list from
var/installed_plugins.jsonand callslinkInstaller.installPlugin(name)(no version) for each entry. The installer resolves the registry-latest and overwrites the existing pinned copy, so an outdated plugin is brought to head; plugins already at latest are no-ops apart from a pnpm cache hit.Also adds an
update/upaction tobin/plugins.tsso users can runpnpm run plugins updatedirectly, mirroring the existinginstall/remove/listactions.bin/updatePlugins.shbecomes a one-line wrapper for backwards compatibility.Test plan
Verified locally with a fresh develop checkout:
ep_markdown@11.0.5installed, latest 11.0.18All plugins are up-to-date(no-op)Updating plugins to latest from registry: ep_markdown→ 11.0.18All plugins are up-to-dateep_etherpad-liteininstalled_plugins.jsonAll plugins are up-to-dateNo plugins installed — nothing to updatevar/installed_plugins.jsonmissingAll plugins are up-to-dateNo installed_plugins.json found — nothing to updatepnpm run plugins update(new direct invocation)tsc --noEmit -p .clean in bothsrc/andbin/🤖 Generated with Claude Code