feat(updates): built-in Joomla/Dolibarr update server with auto-transfer and manifest sync #239
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Add a built-in update server feature to MokoGitea that serves Joomla and Dolibarr compatible update XML endpoints directly from repository releases. This eliminates the need to manually maintain updates.xml files and external update servers.
Goals
How it would work
Update server endpoints
GET /{owner}/{repo}/updates.xml— serves a Joomla-compatible update XML feed built from releasesGET /{owner}/{repo}/updates/dolibarr.json— serves a Dolibarr-compatible update feedAuto-transfer updates.xml
updates.xmlfile in root, MokoGitea ingests the channel configuration (stable, rc, dev, security)-rc.suffix goes to RC channel)Auto-update Joomla manifest
mod_example.xml,plg_example.xml,com_example.xml)<updateservers>section to point tohttps://git.mokoconsulting.tech/{owner}/{repo}/updates.xmlJoomla update XML format reference
Dolibarr update format reference
Dolibarr uses a simpler approach — typically a
conf/conf.class.phpwith version info and a URL to download the latest module archive.Implementation areas
References
cli/updates_xml_build.phpandcli/updates_xml_sync.phpCreated by @MokoBot - Claude Opus 4.6
Additional Requirement: License Key System
The update server should support license key validation so that:
How it works in Joomla
Joomla extensions pass an
extra_queryparameter in the update server definition:The update server validates the key and either returns the full update XML or an empty response.
Proposed data model
license_keytable: id, key_hash, owner_id, repo_id (or org-wide), tier, expires_at, max_domains, is_active, created_atlicense_key_usagetable: id, key_id, domain, ip, checked_at (for tracking)@MokoBot - Claude Opus 4.6
Architecture Plan — Built-in Update Server + License Key System
Full plan posted by @MokoBot
Data Model
license_package table
Defines purchasable subscription tiers (e.g. "Pro Annual", "Lifetime").
license_key table
Individual keys issued from a package.
Key behaviors:
license_key_usage table
Tracks update check activity per key.
update_server_config table
Per-repo update server settings.
Endpoints
Update feeds (web routes)
GET /{owner}/{repo}/updates.xml?key=MOKO-XXXX— Joomla XML feedGET /{owner}/{repo}/updates/dolibarr.json?key=MOKO-XXXX— Dolibarr JSON feedLicense key management API
GET/POST /api/v1/repos/{owner}/{repo}/license-keys— list/create keys for repoGET/POST /api/v1/orgs/{org}/license-keys— list/create org-wide keysGET/PATCH/DELETE .../license-keys/{id}— manage individual keyGET .../license-keys/{id}/usage— usage logLicense package management API
GET/POST /api/v1/orgs/{org}/license-packages— list/create packagesGET/PATCH/DELETE .../license-packages/{id}— manage packagePOST .../license-packages/{id}/generate-key— generate a key from this packageValidation Flow
GET /{owner}/{repo}/updates.xml?key=MOKO-XXXXService Layer
services/updateserver/joomla.go— generates updates.xml from releasesservices/updateserver/dolibarr.go— generates dolibarr JSON from releasesservices/updateserver/license.go— key validation, usage trackingservices/updateserver/ingest.go— auto-detect updates.xml in repos, auto-configuremodels/licenses/— license_key, license_package, license_key_usage modelsChannel Mapping (tag -> channel)
vX.Y.Zor no prerelease suffix -> stable-rcsuffix or IsPrerelease + rc -> rc-beta-> beta-alpha-> alpha-dev-> developmentPhased Roadmap
/updates.xmlreturns dynamic feed from releases@MokoBot - Claude Opus 4.6
Additional Requirements Captured
1. Org-level license keys
Keys can be scoped to an entire org so all repos under that org share the same key. The license_package model has
repo_scope = "all"for this. A customer installs multiple extensions from the same org and only needs one key.2. License packages with configurable timeframes
3. Update stream binding (Joomla convention)
License keys should be tiable to specific Joomla update streams (channels). Following Joomla convention:
A license package defines which streams the key grants access to:
["stable"]— only stable releases["stable", "rc", "beta"]— stable + pre-release["stable", "rc", "beta", "alpha", "development"]— everythingThe update XML endpoint filters
<update>entries by the key holder is allowed streams. If a key only has "stable" access, rc/beta/alpha releases are omitted from the XML response.Data model addition to license_package:
This maps directly to Joomla is
<tag>element in updates.xml — the server only returns<update>blocks where<tag>matches one of the key is allowed channels.@MokoBot - Claude Opus 4.6