refactor(plugins): no plugin catalog; plugins ship in the image or are mounted (#5374)
First-party plugins have shipped inside the image since a7a281c, and the
catalog's only repository (Steward-plugins) answers 404, so Steward polled a
dead URL every minute for nothing. The operator chose to remove the catalog
entirely (#5214 "Review: readable and fast on the live instance").
Removed:
- core/plugin_index.py and the plugin_catalog_refresh startup task;
- the plugins.index_url default, and migration 0035 deletes the stored
plugins.index_url / plugins.repositories rows;
- the Settings -> Plugins repository editor, catalog, refresh, install and
reload routes and their templates;
- the download/checksum/extract install path in plugin_manager, and the
PLUGIN_INSTALL_DIR config it wrote to;
- plugins/index.yaml, docs/plugins/index.yaml.example and the guide's
"Publishing to the Catalog" section (now "Shipping a Plugin").
Kept: enabling and configuring plugins, hot-reload on enable, restart, orphan
cleanup, and the external root (/data/plugins) for operator-mounted plugins.
tests/test_no_plugin_catalog.py guards the routes, default and task.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,14 +28,12 @@ def create_app(
|
||||
"secret_key": "test-secret-key",
|
||||
"db_connect_timeout": DB_CONNECT_TIMEOUT_SECONDS,
|
||||
"plugin_dirs": ["plugins"],
|
||||
"plugin_install_dir": "plugins",
|
||||
}
|
||||
|
||||
app.config.update(
|
||||
SECRET_KEY=bootstrap["secret_key"],
|
||||
DATABASE_URL=bootstrap["database_url"],
|
||||
PLUGIN_DIRS=bootstrap["plugin_dirs"],
|
||||
PLUGIN_INSTALL_DIR=bootstrap["plugin_install_dir"],
|
||||
TESTING=testing,
|
||||
# Lax keeps the session cookie off cross-site POSTs and iframes; the
|
||||
# CSRF token below is the check that does not depend on the browser.
|
||||
@@ -477,26 +475,6 @@ def _register_core_tasks(app: Quart) -> None:
|
||||
)
|
||||
)
|
||||
|
||||
# Fetch the plugin catalog from the configured repositories as each copy
|
||||
# falls due (plugin_index.refresh_due), so Settings → Plugins only reads
|
||||
# what is stored (Background Jobs ruling, 2026-10-08). The repositories are
|
||||
# read on every tick, so an edit in Settings is fetched within a minute.
|
||||
async def run_catalog_refresh():
|
||||
from .core.plugin_index import refresh_due, repo_urls
|
||||
from .core.settings import get_all_settings
|
||||
async with app.db_sessionmaker() as db:
|
||||
settings = await get_all_settings(db)
|
||||
await refresh_due(repo_urls(settings))
|
||||
|
||||
app._task_registry.append(
|
||||
ScheduledTask(
|
||||
name="plugin_catalog_refresh",
|
||||
coro_factory=run_catalog_refresh,
|
||||
interval_seconds=60,
|
||||
run_on_startup=True,
|
||||
)
|
||||
)
|
||||
|
||||
# Fire due Ansible schedules (recurring playbook runs). Checks every minute;
|
||||
# each schedule's own interval gates whether it actually runs.
|
||||
async def run_ansible_schedules():
|
||||
|
||||
Reference in New Issue
Block a user