Archived
1
0
Fork
You've already forked csm-server
0
Page: Home
1 Home
Lipwig edited this page 2025年12月20日 21:13:02 +01:00

SAPM - Software-Agnostic Plugin Manager

I don't care about what I manage, but I try to do it well.

Un gestionnaire de plugins générique, indépendant du logiciel qui les utilise


Le projet Entropic semble faire un truc similaire.

Idées pour le nom

  • SAPM - Software-Agnostic Plugin Manager
  • UAM - Universal Add-ons Manager
  • GMM - Generic Module Manager
  • CSTK - Crowd-Sourcing Tool-Kit
  • OCP - Open Contributions Platform

Notes fonctionnement

Development tools

Libs used

Backend

Frontend

  • vue ;
  • vue-resource pour appeler l'API rest (tuto) ;
  • si besoin, axios pour faire de l'AJAX avec Vue mais c'est peut-être inutile ;

Divers

Configurer un git hook qui test tout avant chaque commit (si les tests sont courts) ou chaque push (si les tests sont longs) coté client.


l'API doit fonctionner avec un système de pagination de sorte de toujours avoir


Ajouter un en-tête CORS au serveur sapm afin de pouvoir héberger le client n'importe où.


Voir comment installer facilement sapm (ou bien documenter) de sorte qu'il puisse créer le serveur et client web sur le même nom de domaine (avec juste un /api en plus pour le backend).


On peut faire le rendu des templates vue coté serveur, à tester pour voir si ça permet d'utiliser le client web sans js activé.

Dans le cas d'un jeu en ligne où l'utilisateur souhaite charger ou publier des niveaux depuis le navigateur, il faut ajouter les headers CORS sur le site qui héberge les plugins, ce qui n'est pas le cas de GitHub et GitLab.

Une solution serait de faire en sorte que sapm-server intègre un client git et télécharge et met à jour tous les plugins. À partir de là il serait possible que le serveur transmette directement le contenu du plugin, plutôt que ce soit le client qui fasse un git clone/pull sur un dépôt distant.

À partir de là on pourrait envisager que les clients intègrent une fonction qui télécharge / publie les plugins, avec ajax pour le client web.

On pourrait du coup packager ça dans une bibliothèque JS de manière à ce que les devs importent juste cette bibliothèque depuis leur site pour accéder à toutes les fonctionnalités du client et créer leur appli web qui communiquera avec sapm.


L'API renvoie directement une archive de tout le module (statique), ou bien juste l'archive d'un patch correspondant aux modifications appliquées depuis un commit donné (dynamique), que le client appliquerait au plugin.

Plusieurs avantages :

  • le client ne garde pas tout l'historique de chaque plugin, ce qui pourrait être lourd et n'est pas utile pour un utilisateur de plugin ;
  • mais le client ne télécharge pas l'intégralité du plugin lors d'une mise à jour, seulement la différence.

Cela implique que le client doit conserver les sources sans modifications, pour que le patch fonctionne. Si on doit lancer un build après avoir téléchargé un plugin, il est donc nécessaire de conserver les sources et que toutes les modifications se fassent dans un autre dossier.

sapm-server devrait faire un hash des sources pour chaque commit du plugin et les stocker en bdd pour le rendre accessible depuis l'API. Ce hash des sources tiendrait en compte du fichier .gitignore. Le serveur fournirait aussi une méthode d'API permettant, pour un plugin donné, de savoir si tel hash correspond :

  • au contenu de la dernière version du plugin : il y a rien a faire coté client ;
  • a aucun contenu référencé dans toute l'histoire du plugin : il y a eu des modifications dans le dossier du client et le hash est foireux, le client doit donc télécharger de nouveau tout le plugin en écrasant, après confirmation, le contenu existant ;
  • au contenu d'une précédente version, auquel cas on aurait des informations sur cette version, par exemple sa version et sa date : le client propose donc une mise à jour à l'utilisateur et demande la différence des modifications via l'API.

Ceci afin que le client puisse, pour chaque plugin installé et sans avoir accès au dossier .git, après avoir créé un hash du contenu du plugin :

  • connaître sa version ;
  • savoir si son contenu a été altéré, auquel cas le client affiche un message d'erreur et propose de télécharger de nouveau le plugin dans sa dernière version.

Pour le hash des sources, faire une archive du dépôt puis générer le hash de cette archive, c'est beaucoup plus rapide que de faire un hash du contenu de tous les fichiers (de plus, cela prend en compte les droits appliqués aux fichiers).

Pour preuve, sur un même dossier :

  • time for file in $(find . -type f); do echo "$file:"; cat $file; done | md5sum : 49,541 sec.
  • time tar -cf - . | md5sum : 0,533 sec.

Ou alors, dans le cas où le dépôt git distant ne gère pas les CORS, faire en sorte que sapm puisse faire office de proxy entre le dépôt git et le client en backup, avec django-http-proxy ?


Celery permet de lancer des runs, ce qui pourrait être pratique pour lancer des tests sur les plugins par exemple (une sorte de mini-runner CI).


Pour le client, la priorité est de coder un client web avec Vue car cela permet de proposer une demo aux nouveau utilisateurs.

Aussi, il est possible de coder une app native avec Vue en utilisant Electron, donc une grosse partie du code du client web pourra être utilisée pour l'appli GUI native.


Concernant le client cli, il y a un début de projet qui permet de parcourir des specs OpenAPI.

Mais on peut aussi coder notre propre générateur de CLI pour OpenAPI qui :

  • parcours les specs OpenAPI ;
  • utilise si besoin les imports dynamiques de Python ;
  • génère des classes Python correspondants aux modèles et endpoints de l'API, avec des méthodes pour les verbes dispo ;
  • génère les arguments de ligne de commande et les options et pages man, etc. ;
  • par défaut affiche le résultats sur la sortie standard mais possibilité de surcharger les méthodes pour effectuer une action particulière à la place.

Il faut configurer l'intégration continue pour tester les clients SAPM à chaque mise à jour du serveur SAPM, pour vérifier que cette mise à jour ne pète pas des clients.


Bouger les features dans un dépôt séparé (et intégrer les features SAPM dans un sous-module) ? Cela permettrait que les différentes implémentations de SAPM utilisent un même dépôt et de donner des accès spécifiques aux contributeurs pour modifier ces features. Mais bon c'est peut-être pas nécessaire...


Il y aurait un compteur de téléchargements qui permet d'indiquer la popularité du plugin.


S'inspirer des gestionnaires de plugins / modules / bibliothèques existants, à la fois sur la mise en page et sur la façon dont fonctionne le manager (ie. est-ce qu'ils hébergent les sources eux-mêmes, etc.) :


SAPM pourrait aussi utiliser l'API de GitLab / GitHub / Gitea pour pousser directement dans les dépôts d'une orga. Cela permettrait à des non-techs de publier des plugins. Problème : il peut y avoir un nombre max de dépôts par orga (~40 sur Framagit, 100 000 par défaut sur Framagit). Ce serait en option sinon, ou alors on joue avec les branches.

Les APIs Gitea et GitLab permettent de créer des utilisateurs. Du coup on pourrait avoir une instance GitLab / Gitea dédiée et créer un utilisateur lorsqu'un nouvel utilisateur souhaite contribuer.

Vu que git est basé sur un fonctionnement décentralisé, on pourrait même juste avoir un dépôt Git et utiliser :

  • soit les dépôts existants sur GitHub / GitLab / etc. et l'utilisateur se connecte via l'API et renseigne où est son dépôt ;
  • soit créer un nouveau dépôt sur une de ces plateformes via l'API de Github, GitLab ou Gitea.

Autre solution : ne pas passer par leurs APIs, mais se contenter de faire un pull sur tous les dépôts régulièrement, et détecter si le dépôt est hébergé sur une instance de GitLab ou autre pour obtenir quelques infos utiles disponibles via l'API publique (nombre d'étoiles, url, etc.,) obtenues généralement avec un simple GET . Si l'utilisateur est non-tech et qu'il n'existe pas encore de dépôt, expliquer qu'il faut se créer un compte sur GitHub / GitLab / etc. puis créer les dépôts via leurs APIs.


Il pourrait y avoir des plugins considérés officiels, dont les dépôts seraient hébergés dans la même organisation que le développeur.


En fait il y a 2 cas d'utilisation :

  • les plugins sont complexes et nécessitent une maintenance régulière (ex : extension VLC, WordPress, etc.) ;
  • les plugins sont simples et ne nécessitent peu de maintenance (ex : éditeurs de niveaux, thèmes, etc.) ;

Pour s'adapter à ces différents scénarios, il pourrait y avoir une option sur le serveur SAPM pour que les plugins des utilisateurs soient, au choix :

  • dans des dépôts séparés ;
  • dans des dossiers séparés dans un dépôt unique par utilisateur ;
  • dans des dossiers séparés dans un dossier par utilisateur dans un gros dépôt unique.

L'utilisateur pourrait lui aussi avoir le choix : par exemple, l'admin autorise le fait que les utilisateurs poeuvent créer des plugins dans un gros dépôt unique, mais un utilisateur avancé peut choisir d'héberger son plugin dans son propre dépôt.


Faire une démo avec un petit jeu qui utilise les assets libres de droit Kenney et un éditeur de niveau. Présenter cette démo avec un workflow complet (jouer, chercher des niveaux, installer un niveau, y jouer, créer un nouveau niveau, le publier) lors d'éventuelles conférences.


On pourrait imaginer un systèmes de variables personnalisées : par exemple, dans un éditeur de niveau le créateur du plugin aurait la possibilité de créer plusieurs étages. Dans ce cas, lors du test du module, un script (codé par le développeur du jeu) compte le nombre d'étages, et sapm comptaibilise cette variable, ainsi l'interface de sapm pourrait afficher le nombre d'étages, ce qui serait pratique pour l'utilisateur qui veut choisir un niveau.


Ce serait utilisé pour :

  • éditeurs de niveaux ;
  • OFI ;
  • plateforme de partage de modèles 3D ;
  • youtube-dl
  • Zapier - like

Mettre en place un serveur Sentry pour analyser les éventuelles erreurs et les reporter. Éventuellement réinitialiser cette demo régulièrement.


Dans la config de SAPM server, possibilité de mettre le lien vers notre serveur Sentry, comme ça je récupère les erreurs des autres instances.


Faire un tutoriel autour de cette demo.


Au final si un logiciel est codé dans un autre langage que Python, il faut juste recoder le client, ce qui n'est pas si difficile. Éventuellement, coder une bibliothèque sapm-client dans différents langages pour faciliter son intégration dans d'autres logiciels (notamment en C++ pour VLC).


Placer la suite de test du client dans un dépôt séparé, pour pouvoir tester les différentes implémentations et vérifier leur compatibilité avec les différentes versions de l'API.


Au final il y a 2 types de tests :

  • les tests définis par le développeur du logiciel, pour vérifier que les plugins publiés sont bien compatibles avec son logiciel, qu'il n'y a pas n'importe-quoi dedans et qu'il soit bien écrit (ça pourrait même vérifier qu'il y a une licence, vérifier la syntaxe pour que le code soit pas trop dégueu, etc.) ;
  • les tests définis par le développeur du plugin, pour vérifier que son plugin est fonctionnel et qu'il le reste, même si le logiciel évolue.

Il faut donc, via l'intégration continue :

  • executer tous ces tests lorsque le logiciel est mis à jour, pour vérifier qu'une modification sur le logiciel ne pète pas des plugins ;
  • executer tous ces tests lorsque le plugin est mis à jour, pour vérifier que cette modif sur le plugin soit bien compatible avec la dernière version du programme.

Dans la liste des plugins, on pourrait imaginer un statut broken qui indique qu'un plugin n'est pas compatible avec la dernière version du logiciel. Cela implique de communiquer avec l'API de l'outil d'intégration continue utilisé et utiliser des webhooks.

Il faut trouver un fonctionnement qui :

  • encourage le fait d'écrire des tests, que ce soit plus ou moins inclus dedans ;
  • permet de faire ça simplement, pour des utilisateurs pas trop expériementés avec l'intégration continue.

Dans ce cas, il est nécessaire de mettre les plugins sur la même instance d'intégration continue (sinon ça va être le bordel), quitte à utiliser des sous-modules git.

En fait lorsqu'un plugin est considéré comme officiel, on pourrait l'ajouter en tant que sous-module à un gros dépôt : de cette manière ce dépôt contient tous les plugins à tester, et on peut executer l'intégration continue sur celui-ci.

Personnalisation du client

Avec import

Le développeur utilise les bibliothèque Python des clients (sapm-cli, sapm-gtk, sapm-qt, etc.) pour développer son propre client.

Il l'importe alors, ce qui lui permet d'avoir son propre installeur (par exemple vlc-plugins) qui va hériter des commandes sapm cli (par exemple vlc-plugins install subs, vlc-plugins update, etc.) tout en offrant une certaine flexibilité si nécessaire.

De même, le dev construit son appli GUI qui hérite de sapm-gtk par exemple, ce qui lui offre une certaine flexibilité puisqu'il pourra facilement modifier le titre de la fenêtre, le style, etc.

Le développeur peut aussi implémenter des fonctions qui seront automatiquement appelées par SAPM lors d'événements définis :

  • coté utilisation des plugins :
    • before_download() : déclenché avant de télécharger un plugin (git clone) ;
    • after_download() : déclenché après avoir téléchargé un plugin (git clone) ;
    • before_update() : déclenché avant de mettre à jour un plugin (git pull) ;
    • after_update() : déclenché après avoir mis à jour un plugin (git pull) ;
    • before_remove(): déclenché avant de supprimer le dossier d'un plugin (rm -r) ;
    • after_remove(): déclenché après avoir supprimé le dossier d'un plugin (rm -r).
  • coté création de plugins :
    • before_push() : déclenché avant que l'utilisateur de publie un nouveau plugin ;
    • after_push() : déclenché après que le plugin de l'utilisateur soit publié ;
    • before_upgrade() : déclenché avant que l'utilisateur de publie un nouveau plugin ;
    • after_upgrade() : déclenché après que le plugin de l'utilisateur soit publié ;
    • before_delete() : déclenché avant que l'utilisateur de publie un nouveau plugin ;
    • after_delete() : déclenché après que le plugin de l'utilisateur soit publié ;
  • alias :
    • test() : déclenché par after_install(), after_update(), before_push() et before_upgrade().

Cette fonction test() permet de tester le bon fonctionnement d'un plugin au sein du logiciel.

Avec fichier de config

Solution moins souple mais plus rapide pour le développeur (mais moins pratique pour l'utilisateur et moins sécure) : utiliser sapm-cli "vanilla", en spécifiant un fichier de configuration en paramètre :

sapm-cli --config=vlc-plugins.yaml

Ce fichier contiendrait entre autres les scripts à exécuter lors des différents événements :

plugins_path:~/.vlc-plugins/exec:before_download:./scripts/before_download.sh $plugin_name# un plugin a été téléchargé# ...

Personnalisation du serveur SAPM

Coté serveur, étant donné qu'il est plus compliqué de le recoder dans un autre langage et que le dev ne voudra pas forcément coder du Python pour l'importer et que le nom du programme importe peu, on passe donc par un fichier de configuration, permettant de définir différents paramètres (taille maximum pour les plugins, etc.) et aussi les script exécuter, en passant des variables concernant l'événement (ce qui permet d'utiliser n'importe quel langage ) :

exec:on_download:./scripts/on_download.sh $plugin_name# un plugin a été téléchargéon_push:python ./scripts/on_push.py $plugin_git_url# un utilisateur ajoute un nouveau pluginon_upgrade:# un utilisateur met à jour un de ses pluginson_remove:# un utilisateur supprime un de ses pluginstest:# alias, déclenché par on_push et on_upgrade

La fonction test permet de tester un plugin avant de le publier et de le rendre disponible aux autres utilisateurs. C'est donc le dev qui gère lui-même le niveau de sécurité en exécutant les tests qu'il souhaite sur les plugins au moment où ils sont mis à jour. Il peut par exemple isoler chaque plugin dans un conteneur Docker pour faire les tests afin d'éviter que l'utilisateur pète le serveur si ce plugin contient du code exécutable.

Ressources

S'inspirer d'applications existantes pour la structure de l'appli :

Sécuriser une API publique :

Donc les clients qui peuvent effectivement installer un plugin (hors client web donc) possèdent un token qui est vérifié par le serveur SAPM et envoient une requête pour dire "je télécharge tel plugin" ?

Client

Client utilisé par les utilisateurs pour gérer les plugins.

Commandes

  • search <string> : interroge le serveur distant pour checher un plugin correspondant au critère de recherche donné ;
  • list : liste les plugins installés ;
  • install <plugin name> : installe un plugin
  • update [plugin name] : met à jour la liste des plugins disponibles
  • upgrade [plugin name] : met à jour un ou tous les plugins
  • remove <plugin name> : supprime un plugin

CLI usage

sapm <software> <command>

Par exemple, si le logiciel avec lequel on veut utiliser ce plugin est vlc, sapm vlc list permet d'afficher les plugins installés (cf. plugins commands).

  • sapm --add <respository> [plugins path] ajoute un dépôt sapm.
    • repository adresse d'un serveur sapm.
    • plugins path chemin dans lequel les plugins de ce projet seront installés.

Par exemple, sapm --add sapm.vlc.com permet d'ajouter le dépôt de plugins de vlc à la liste des dépôts de plugins gérés par sapm et permetra par la suite d'utiliser la commande sapm vlc. sapm --add sapm.vlc.com ~/vlc/plugins installe ces plugins dans le dossier ~/vlc/plugins.

GUI

Une interface graphique pourrait aussi bien être utilisée.

Pour le lancer : sapm-gui <software>

Par exemple, sapm-gui vlc lance l'interface graphique permetant de gérer les plugins vlc.

Web

sapm-server intègre une interface web permetant aux utilisateurs de chercher des plugins (tout comme https://pypi.org/ est une interface web pour chercher des modules pip).

Bindings

Des bindings pourraient voir le jour permetant d'utiliser sapm dans différents langages de programmation et donc permettre aux développeurs d'intégrer la gestion de leurs plugins directement dans leurs logiciels.

Fonctionnement

Par défaut les plugins sont installés dans ~/.sapm/<project> (par exemple : ~/.sapm/vlc), mais il est possible de les installer ailleurs (cf. CLI usage).

Le fichier ~/.sapm/repositories.yml contient la liste des dépôts de plugins gérés par sapm :

- name:vlchost:sapm.vlc.compath:~/.vlc/plugins- name:ofihost:sapm.ofi.compath:~/.ofi/plugins

Lorsqu'on tape la commande sapm vlc, sapm cherche dans ce fichier le projet portant le nom vlc et accède au chemin correspondant pour effectuer l'action désirée.

(削除) Le dossier <project plugins path>/available liste les fichiers manifestes de tous plugins disponibles (cf. Plugin manifest). (削除ここまで) (削除) Ce dossier est mis à jour avec la commande sapm <project> update. (削除ここまで)

(削除) Il s'agit en fait un dépot git (cf. sapm server). (削除ここまで)

sapm server

Le serveur sapm fait permet de servir les informations concernant les plugins. Il dispose d'une API et d'une base de données.

N'héberge pas les plugins, se contente de les lister.

Il interroge à intervalle réguliers les plugins, ou bien utilise des webhooks, pour mettre à jour les informations concernant les versions.

(削除) Toutes ces metadonnées sont en fait stockées dans un dépôt git mis à jour régulièrement. (削除ここまで)

À intervalle réguliers, le serveur fait un git pull sur chaque dépôt git correspondant aux plugins qu'il gère.

Gestion des utilisateurs pour que ces derniers puissent ajouter leurs plugins.

Par la suite : gérer les likes, intégration avec API de GitLab ou GitHub

sapm API

Les clients sapm (web, cli et gui) communiquent avec les serveurs sapm via une api, qui permet d'effectuer ces actions :

actions publiques :

  • rechercher un plugin à partir d'un texte donné ;
  • récupérer des informations détaillées concernant un plugin spécifique ;
  • récupérer les versions d'une liste de plugins donnée (pour vérifier les mises à jour) ;

actions privées :

  • ajouter un plugin ;
  • déclencher la mise jour un plugin (il va alors récupérer les metadonnées sur le dépôt) ;
  • mettre à jour directement les metadonnées d'un plugin (en POST) ;
  • supprimer un plugin ;
  • ajouter une étoile à un plugin ;

Plugin manifest

Fichier yaml présent sur le dépôt d'un plugin qui affiche des metadonnées sur ce plugin :

name:subauthor:John Doerelease:2.1description:Download subtitles corresponding to the current videoicon:./sub.pngtags:[subtitles]source:https://github.com/vlc/vlc-sub.git licence:mit

FAQ

Gestion des dépendances ?

Non. Nous souhaitons garder le sapm aussi simple et léger que possible. Pour gérer les dépendances, vous pouvez utiliser des git-submodules à l'intérieur du dépôt correspondant à votre plugin.