mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-11-04 17:45:24 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c4fa52de3 |
No files matched your search
@@ -20,6 +20,7 @@
|
||||
- Alerts with no icon no longer squeeze their text to one word per line
|
||||
- Password fields with the show button are the same height as the other fields next to them
|
||||
- The Secure your account setup step no longer shows up empty when no passkey or authenticator plugin is on
|
||||
- An installed plugin update older than the copy in a newer image is removed at startup instead of logging an error every boot
|
||||
|
||||
## 26.11.0
|
||||
|
||||
|
||||
@@ -409,6 +409,15 @@ export class PluginLoader {
|
||||
}
|
||||
loaded.push(plugin);
|
||||
} catch (error) {
|
||||
// A newer image ships a newer copy, so the old update can go.
|
||||
if (isArtifact && error instanceof SupersededUpdateError) {
|
||||
await fs.promises.rm(dir, { force: true }).catch(() => {});
|
||||
await fs.promises.rm(`${dir}.sig`, { force: true }).catch(() => {});
|
||||
pluginLogger.info(`Removed ${entry.name}: ${error.message}`, {
|
||||
operation: "plugin_load",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
this.skippedPlugins.push(
|
||||
describeSkipped(dir, entry.name, isArtifact, error),
|
||||
);
|
||||
@@ -948,6 +957,16 @@ function withTimeout<T>(
|
||||
|
||||
const PLUGIN_ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/;
|
||||
|
||||
/** An installed update that the bundled copy has caught up with. */
|
||||
export class SupersededUpdateError extends Error {
|
||||
constructor(id: string, version: string, bundledVersion: string) {
|
||||
super(
|
||||
`update for "${id}" is ${version}, which is not newer than the bundled ${bundledVersion}`,
|
||||
);
|
||||
this.name = "SupersededUpdateError";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws unless an artifact may replace the bundled plugin with the same id:
|
||||
* a trusted key signed it and its version is strictly higher, so an old
|
||||
@@ -971,9 +990,7 @@ export function assertBundledUpdate(
|
||||
// An admin pinning an exact older release is the one allowed downgrade.
|
||||
if (pinnedVersion && pinnedVersion === version) return;
|
||||
if (bundledVersion && !semver.gt(version, bundledVersion)) {
|
||||
throw new Error(
|
||||
`update for "${id}" is ${version}, which is not newer than the bundled ${bundledVersion}`,
|
||||
);
|
||||
throw new SupersededUpdateError(id, version, bundledVersion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -231,6 +231,16 @@ describe("updating a bundled plugin", () => {
|
||||
expect(loader.get("bundled-one")?.manifest.version).toBe("1.0.0");
|
||||
});
|
||||
|
||||
it("removes an update the bundled copy caught up with", async () => {
|
||||
const { userDir } = setup();
|
||||
const file = await writeArtifact(userDir, "bundled-one", "valid", "0.9.0");
|
||||
const loader = new PluginLoader();
|
||||
await loader.loadAll();
|
||||
expect(fs.existsSync(file)).toBe(false);
|
||||
expect(fs.existsSync(`${file}.sig`)).toBe(false);
|
||||
expect(loader.skipped()).toEqual([]);
|
||||
});
|
||||
|
||||
it("refuses a downgrade after the bundled copy was unloaded", async () => {
|
||||
const { userDir } = setup();
|
||||
const loader = new PluginLoader();
|
||||
|
||||
Reference in new issue
Block a user