Publier
Du dossier d'un plugin au bouton Installer de chaque Hodi : tester, essayer sur un Hodi de test, construire le fichier, puis le faire vérifier et signer par le registre des plugins.
En bref
Un plugin passe par quatre étapes avant d'arriver chez les gens. Les trois premières se font seul, sur sa machine. La dernière passe par le mainteneur de Hodi.
Cette étape vérifie la partie serveur du plugin, sans avoir besoin d'un Hodi. La commande à lancer est npm test.
Cette étape installe le plugin sur un Hodi de test, à chaque enregistrement d'un fichier. La commande à lancer est npx hodi-plugin dev.
Cette étape fabrique le fichier .hodi-plugin, le fichier que Hodi installe. La commande à lancer est npm run build.
Pendant cette étape, le mainteneur de Hodi relit le code du plugin et signe le fichier .hodi-plugin. Cette étape passe par une pull request.
Le modèle de plugin contient déjà tout : le SDK, les scripts et la CI. Il n'y a rien à installer en plus.
Tester
Ce que fait un test
Un test lance la partie serveur du plugin comme Hodi la lance :
- Le SDK construit le plugin.
- Il le charge dans le même bac à sable que Hodi.
- Il appelle ses routes avec les mêmes vérifications que Hodi.
Autour, il y a un petit Hodi en mémoire : un foyer, son admin, et des remplaçants pour les sites, les e-mails, les notifications et l'IA. Un test n'envoie donc jamais rien à personne. Il tourne pareil sur sa machine et dans la CI.
Un exemple
Le modèle de plugin a déjà ce fichier. Il demande la route POST /hello et regarde la réponse :
import assert from 'node:assert/strict'
import { after, describe, it } from 'node:test'
import { testPlugin } from '@hodi-app/plugin-sdk/testing'
describe('my-plugin', async () => {
const hodi = await testPlugin('.', {
settings: {
greeting: 'Salut'
}
})
after(() => hodi.stop())
it('answers a child too', async () => {
const child = await hodi.addPerson({
name: 'Zoé',
kind: 'child'
})
const answer = await hodi.route('POST /hello', {
as: child
})
assert.equal(answer.status, 200)
})
})Pour lancer les tests :
npm testLa CI du modèle les relance à chaque push. Un plugin qui passe ses tests se comporte pareil une fois installé dans un vrai Hodi.
Les options de testPlugin
testPlugin('.') prend le dossier du plugin. Le deuxième argument, facultatif, prépare le petit Hodi :
settingsobjectLes réglages, comme l'admin les aurait choisis. Les autres gardent leur valeur par défaut.
sitesobjectLa réponse de chaque site de permissions.network, par adresse. Une autre adresse échoue, comme un site fermé.
articlesobjectLes articles que Hodi connaît, par id, pour ctx.articles.
ai(question) => stringLa réponse de l'IA à chaque question. Sans cette option, le foyer n'a pas d'IA.
mailbooleanL'e-mail est configuré sur le serveur (true par défaut).
householdobjectLe nom (name) et la langue (language) du foyer.
unsignedbooleanLe plugin est construit sans signature. Hodi refuse alors ce qu'il refuserait en vrai.
Ce que le petit Hodi permet
route('POST /hello', { as, body, query })Appelle une route du plugin. Sans as, c'est l'admin du foyer qui appelle.
addPerson({ name, kind })Ajoute quelqu'un au foyer : adult, teen ou child.
click(action, input)Simule un clic sur l'AiButton du plugin.
runTask(name)Lance une tâche, comme Hodi le ferait à son heure.
readFeed(key)Lit un flux du plugin, comme un foyer qui le suit.
exportData(person)Demande la copie des données d'une personne.
mailsLes e-mails que le plugin a envoyés, dans l'ordre.
notificationsLes notifications que le plugin a envoyées, dans l'ordre.
questionsLes questions que le plugin a posées à l'IA, dans l'ordre.
logLes lignes du journal du plugin, et celles de Hodi à son sujet (une permission refusée, par exemple).
stop()Arrête le petit Hodi à la fin des tests.
Essayer sur un Hodi de test
Un test vérifie la partie serveur. Pour voir aussi la partie web, il faut un vrai Hodi : le mode développeur y installe le plugin, puis le remet à jour à chaque enregistrement.
Ce qu'il faut
- Un Hodi à soi, sur sa machine par exemple (
http://localhost:3000). - Être l'admin de son serveur.
Un Hodi de test évite de mélanger ses essais avec les données de son foyer.
Les étapes
- Ouvrir Serveur › Plugins sur le Hodi de test.
- Activer le mode développeur : Hodi affiche un code, une seule fois.
- Copier ce code.
- Dans le dossier du plugin, lancer la commande ci-dessous en remplaçant
LE_CODE. - Laisser la commande tourner pendant le travail.
npx hodi-plugin dev --server http://localhost:3000 --code LE_CODE--serverL'adresse du Hodi de test.
--codeLe code du mode développeur. Il peut aussi venir de la variable HODI_DEV_CODE, pour qu'il ne reste pas dans l'historique du terminal.
Le dossier du plugin, si la commande n'est pas lancée depuis ce dossier.
Ce qui se passe ensuite
À chaque enregistrement d'un fichier, la commande :
- reconstruit le plugin ;
- l'envoie au Hodi de test ;
- attend que Hodi redémarre avec la nouvelle version (quelques secondes) ;
- affiche le journal du plugin dans le terminal.
Dans Hodi, le plugin porte le badge En développement. Ses pages s'affichent même sans signature, et il garde ses données d'une version à l'autre. Ctrl+C arrête la commande.
Construire
Le fichier du plugin
npm run buildLa commande écrit un seul fichier, dist/<id>-<version>.hodi-plugin. Par exemple dist/hello-world-0.1.0.hodi-plugin. C'est ce fichier que les gens installent.
L'installer à la main
N'importe quel admin peut installer ce fichier, même sur un serveur qu'il ne gère que depuis son navigateur :
- Ouvrir Serveur › Plugins.
- Cliquer sur Ajouter un plugin et choisir le fichier.
- Lire ce que Hodi montre : le nom, la version et les permissions.
- Confirmer l'installation.
Ce que l'admin voit avant d'installer
Hodi regarde si le fichier est signé, et le dit à l'admin :
QuandLe fichier est signé par la clé du mainteneur de Hodi.
Ce qui se passeLe plugin s'installe avec tout ce qu'il demande.
QuandLe fichier n'est pas signé, ou par une autre clé.
Ce qui se passeLe plugin s'installe après une confirmation de plus. Ses pages ne s'affichent pas.
QuandLe fichier n'est pas signé et demande une permission réservée aux plugins signés.
Ce qui se passeHodi refuse de l'installer.
Les permissions réservées aux plugins signés sont listées dans Le manifeste.
Être vérifié
Pourquoi une signature
Une signature dit à Hodi qui a fait un plugin. Hodi ne fait confiance qu'à une seule clé : celle de son mainteneur.
Les pages d'un plugin tournent dans la page de Hodi, avec la session de la personne connectée. C'est pour ça que seul un plugin signé, ou celui qui est en développement, peut afficher les siennes.
Les étapes
- Mettre le plugin dans un dépôt GitHub public.
- Publier une release
v<version>(par exemplev0.1.0) avec son fichier.hodi-plugin. - Ajouter le plugin au registre des plugins par une pull request.
- Le mainteneur lit le code du plugin.
- S'il suit les règles de Hodi, il signe cette version et accepte la pull request.
Dans le modèle de plugin, pousser un tag v0.1.0 suffit pour l'étape 2 : la CI construit le fichier et crée la release toute seule.
L'entrée dans le registre
Le registre est une simple liste, le fichier plugins.json. Une entrée demande deux champs, et la commande npm run index du registre remplit le reste depuis la release :
{
"repo": "https://github.com/me/hodi-plugin-hello-world",
"version": "0.1.0"
}Le README du registre détaille les commandes à lancer avant la pull request.
Ensuite
- Le plugin apparaît dans Serveur › Plugins › Disponibles de chaque Hodi.
- Il s'y installe en un clic.
- Chaque nouvelle version passe par une nouvelle pull request.
Cette nouvelle version est relue, puis signée à son tour.
Les règles de Hodi
Le mainteneur vérifie chacune de ces règles avant de signer un plugin.
AiButton interroge l'IA, une fois par clic.L'IA coûte de l'argent au foyer : rien ne doit la lancer dans son dos.
Hodi est bilingue, et parle à chacun de la même façon.
Le plugin ressemble au reste de Hodi, dans les trois thèmes.
Chacun peut récupérer ou effacer ce que Hodi sait de lui.
Un Hodi qui a déjà installé une version doit pouvoir passer à la suivante.
Une clé publiée permettrait à n'importe qui de signer à la place de son auteur.