Skip to content

feat(plugins,skills): add update check and version comparison#27

Open
DeryFerd wants to merge 1 commit into
anvie:mainfrom
DeryFerd:feat/plugin-skill-update-manager
Open

feat(plugins,skills): add update check and version comparison#27
DeryFerd wants to merge 1 commit into
anvie:mainfrom
DeryFerd:feat/plugin-skill-update-manager

Conversation

@DeryFerd
Copy link
Copy Markdown
Contributor

Problem

Right now there's no way to check if plugins or skills have updates available. Users have to manually track versions or check external sources to know when new versions are released. This makes it hard to keep plugins and skills up to date.

What This PR Does

This adds version checking infrastructure for both plugins and skills. The system can now:

  • Parse and compare semantic versions
  • Check if updates are available for installed plugins/skills
  • Provide update information through REST API endpoints

Implementation Details

New Module: plugin_update_manager.py

Created a new module that handles all version comparison logic:

Version Parsing:

  • Supports standard semver: 1.0.0, 2.1.3, 10.20.30
  • Handles short versions: 1.01.0.0, 22.0.0
  • Strips v-prefix: v1.0.01.0.0
  • Recognizes pre-release tags: 1.0.0-beta, 2.1.0-alpha, 1.0.0-rc.1
  • Pre-release versions correctly sort before stable: 1.0.0-beta < 1.0.0

Version Comparison:

  • Returns 1 if update available (latest > current)
  • Returns 0 if up to date (latest == current)
  • Returns -1 if current is newer (latest < current)

Manager Classes:

  • PluginUpdateManager - checks plugin updates via plugin_lifecycle.PluginManager
  • SkillUpdateManager - checks skill updates via skills_manager
  • Both expose singleton instances: plugin_update_manager and skill_update_manager

New API Endpoints

Added four new REST endpoints:

Plugin Endpoints:

  • GET /api/plugins/updates/check

    • Lists all plugins with available updates
    • Returns: {updates: [...], count: N}
    • Each update includes: id, name, current_version, latest_version, update_url, category
  • GET /api/plugins/<plugin_id>/updates/status

    • Checks update status for a specific plugin
    • Returns: current_version, latest_version, update_available (bool), update_url, changelog
    • Returns 404 if plugin not found

Skill Endpoints:

  • GET /api/skills/updates/check

    • Lists all skills with available updates
    • Returns: {updates: [...], count: N}
    • Each update includes: id, name, current_version, latest_version, update_url
  • GET /api/skills/<skill_id>/updates/status

    • Checks update status for a specific skill
    • Returns: current_version, latest_version, update_available (bool), update_url, changelog
    • Returns 404 if skill not found

How It Works

The update manager reads the update field from plugin/skill manifests:

{
  "id": "my-plugin",
  "version": "1.0.0",
  "update": {
    "latest_version": "1.1.0",
    "url": "https://example.com/my-plugin-v1.1.0.zip",
    "changelog": "Bug fixes and improvements"
  }
}

When checking for updates:

  1. Reads current version from manifest
  2. Reads latest_version from update field
  3. Compares versions using semantic versioning rules
  4. Returns update info if latest > current

Testing

Added comprehensive unit tests in unit_tests/test_plugin_update_manager.py:

Test Coverage (25 tests total):

  • ✅ Version parsing (6 tests)
    • Standard semver, short versions, v-prefix, pre-release, invalid versions, whitespace handling
  • ✅ Version comparison (6 tests)
    • Equal versions, newer available, current is newer, pre-release handling, short versions, v-prefix
  • ✅ Plugin update checking (7 tests)
    • No updates, updates available, current newer than latest, multiple plugins, not found, no update info, with update
  • ✅ Skill update checking (4 tests)
    • No updates, updates available, not found, with update
  • ✅ Singleton instances (2 tests)

All 25 tests passing.

Test Examples:

# Version parsing
assert _parse_version("1.0.0") == (1, 0, 0, 0)
assert _parse_version("v2.1.3") == (2, 1, 3, 0)
assert _parse_version("1.0.0-beta") == (1, 0, 0, -1)

# Version comparison
assert compare_versions("1.0.0", "1.0.1") == 1  # update available
assert compare_versions("1.0.0", "1.0.0") == 0  # up to date
assert compare_versions("2.0.0", "1.9.9") == -1  # current is newer

What's NOT Included

This PR focuses on the core checking logic only. The following are intentionally left for future PRs:

  • ❌ UI components to display update notifications in the frontend
  • ❌ Actual download and installation of updates
  • ❌ Background scheduler to check for updates periodically
  • ❌ Update notification system (email, in-app alerts, etc.)
  • ❌ Auto-update functionality

These can be added incrementally once the core version checking logic is reviewed and merged.

Files Changed

  • backend/plugin_update_manager.py - 277 lines (new file)
  • routes/plugins.py - 17 lines added (2 new endpoints)
  • routes/skills.py - 17 lines added (2 new endpoints)
  • unit_tests/test_plugin_update_manager.py - 366 lines (new file)

Total: 677 lines added across 4 files

How to Test Manually

  1. Start the evonic server
  2. Install a plugin/skill with an update field in its manifest
  3. Call the update check endpoints:
# Check all plugin updates
curl http://localhost:5000/api/plugins/updates/check

# Check specific plugin
curl http://localhost:5000/api/plugins/my-plugin/updates/status

# Check all skill updates
curl http://localhost:5000/api/skills/updates/check

# Check specific skill
curl http://localhost:5000/api/skills/my-skill/updates/status

Future Work

After this PR is merged, follow-up PRs could add:

  1. Frontend UI to display update notifications
  2. One-click update installation
  3. Background update checker (runs every 24h)
  4. Update history/changelog viewer
  5. Rollback functionality for failed updates

- Add plugin_update_manager.py with version comparison logic
- Implement PluginUpdateManager and SkillUpdateManager classes
- Add version parsing supporting semver and pre-release versions
- Add API endpoints for checking updates:
  * /api/plugins/updates/check
  * /api/plugins/<id>/updates/status
  * /api/skills/updates/check
  * /api/skills/<id>/updates/status
- Add comprehensive unit tests (25 tests, all passing)
- Tests cover version parsing, comparison, and update checking
jeffrysurya pushed a commit to jeffrysurya/evonic that referenced this pull request May 20, 2026
Database._connect() now caches one connection per thread via threading.local().
First access: open connection + PRAGMAs. Subsequent accesses: return cached conn
with row_factory reset to None for a clean slate each time.

sqlite3.Connection.__exit__ handles transactions but does not close, so the
connection stays alive for the thread lifetime. No caller explicitly closes
connections from _connect(), so this is safe.

Fixes hundreds of call sites across all mixins in one shot.
ureh-terbalik pushed a commit to ureh-terbalik/evonic that referenced this pull request May 20, 2026
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.

1 participant