Installing a plugin is done in place, with nothing to go back to #246

Closed
opened 2026-09-16 13:31:01 +00:00 by tiagoagueda · 0 comments
Owner

Split out of #228, which fixed the four defects in that issue and deliberately left this
one alone: it is a piece of building rather than a repair, and half of it would be worse
than none.

run_install runs --target <the live plugins directory> --upgrade, so an upgrade
overwrites the working version before anything has checked that the new one even imports.
There is no staging directory, no import check, and no previous version kept — an upgrade
that fails leaves an instance with a plugin that cannot load and no way back except finding
the old wheel again.

remove() deletes only the files listed in the plugin's own RECORD, so its dependencies
stay on the volume and stay importable for ever. Nothing counts who else is using them.

And install_wheel writes a constraint file holding only the core environment's pins, so
installing one plugin can move a dependency another plugin is using. Nothing refuses it and
nothing says it happened; the other plugin simply starts failing.

Proposal

  • Install into a staging directory beside the live one. Import every entry point the wheel
    declares, in a subprocess, and swap only if that succeeds.
  • Keep the previous version, so a failed upgrade rolls back by itself and an administrator
    can roll back one that installed cleanly and turned out to be wrong.
  • Reference-count dependencies across the record's dependencies lists before removing any.
  • Put the other installed plugins' pins into the constraint file, excluding the package
    being installed, so a conflict is a refusal naming the plugin that owns the pin rather
    than a silent breakage.

Touches installing.run_install, install_wheel, remove, _paths_of and constraints.
The record's dependencies field already exists and is what the reference count should be
built from.

Split out of #228, which fixed the four defects in that issue and deliberately left this one alone: it is a piece of building rather than a repair, and half of it would be worse than none. `run_install` runs `--target <the live plugins directory> --upgrade`, so an upgrade overwrites the working version before anything has checked that the new one even imports. There is no staging directory, no import check, and no previous version kept — an upgrade that fails leaves an instance with a plugin that cannot load and no way back except finding the old wheel again. `remove()` deletes only the files listed in the plugin's own `RECORD`, so its dependencies stay on the volume and stay importable for ever. Nothing counts who else is using them. And `install_wheel` writes a constraint file holding only the *core* environment's pins, so installing one plugin can move a dependency another plugin is using. Nothing refuses it and nothing says it happened; the other plugin simply starts failing. ## Proposal - Install into a staging directory beside the live one. Import every entry point the wheel declares, in a subprocess, and swap only if that succeeds. - Keep the previous version, so a failed upgrade rolls back by itself and an administrator can roll back one that installed cleanly and turned out to be wrong. - Reference-count dependencies across the record's `dependencies` lists before removing any. - Put the other installed plugins' pins into the constraint file, excluding the package being installed, so a conflict is a refusal naming the plugin that owns the pin rather than a silent breakage. Touches `installing.run_install`, `install_wheel`, `remove`, `_paths_of` and `constraints`. The record's `dependencies` field already exists and is what the reference count should be built from.
tiagoagueda added this to the 0.4.0 milestone 2026-09-16 13:31:01 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Postulo/postulo#246
No description provided.