Publier un modèle
Un modèle est une véritable pile Kuploy — une NativeStackSpec — accompagnée d'une entrée de catalogue qui la décrit. Qui parcourt kuploy.app/templates voit l'entrée ; ce qu'il importe, c'est la spécification. Ce n'est pas un catalogue Compose : l'unité est une pile Kuploy, et les modèles payants réutilisent la facturation que kuploy-hub possède déjà, plutôt qu'un péage parallèle.
Les modèles vivent dans kuploy/kuploy-templates.
L'arborescence du dépôt
meta.json # le catalogue
templates/<id>/stack.yaml # la spécification de pile qui est importée
templates/<id>/logo.svg
scripts/validate-meta.mjs # la vérification d'intégration continue
L'entrée de catalogue
Chaque entrée du tableau templates de meta.json :
| Champ | Obligatoire | Ce que c'est |
|---|---|---|
id | oui | Un identifiant unique ; c'est aussi le nom du répertoire sous templates/ |
name | oui | Le nom affiché dans la galerie |
version | oui | La version du modèle, et non celle de l'application amont |
description | oui | Un paragraphe ; c'est le texte de la galerie |
logo | oui | Le chemin du SVG, par exemple templates/<id>/logo.svg |
stack | oui | Le chemin de la spécification, par exemple templates/<id>/stack.yaml |
links | oui | github, website, docs — ceux qui s'appliquent |
tags | oui | Pour la recherche et le filtrage |
access | oui | free, pro ou cloud |
product | seulement quand access n'est pas free | Le product.slug de kuploy-hub, avec éventuellement un identifiant d'offre |
variables | non | Les secrets qu'un parcours de mise en service doit générer — {key, generate, component} |
domains | non | Les composants qui ont besoin d'un nom d'hôte |
{
"id": "learnhouse",
"name": "LearnHouse LMS",
"version": "0.1.0",
"description": "Open-source LMS: courses, quizzes, assignments, certificates.",
"logo": "templates/learnhouse/logo.svg",
"stack": "templates/learnhouse/stack.yaml",
"links": {"github": "https://github.com/learnhouse/learnhouse"},
"tags": ["lms", "education"],
"access": "free",
"product": null,
"variables": [{"key": "NEXTAUTH_SECRET", "generate": "random32", "component": "learnhouse-app"}],
"domains": ["learnhouse-app"]
}
Les niveaux d'accès
access décide qui peut voir la spécification, et la vérification se fait contre la facturation que vous avez déjà :
access | Qui obtient la spécification |
|---|---|
free | Tout le monde, connecté ou non |
pro / cloud | Un exploitant ayant un abonnement actif ou en période d'essai au produit nommé |
Un visiteur dépourvu de cet abonnement voit l'entrée et un lien View plans, plutôt que la spécification ; un visiteur anonyme est invité à se connecter. La garde lit tenant_subscription pour le product.slug que vous nommez : il n'y a pas de magasin de droits distinct à alimenter.
validate-meta.mjs fait échouer la construction lorsque access vaut pro ou cloud et que product.slug est absent. Sans lui, la galerie n'a rien à vérifier : le modèle serait donc soit gratuit pour tous, soit inutilisable.
Valider avant d'ouvrir la pull request
node scripts/validate-meta.mjs
Le script vérifie les champs obligatoires, l'unicité des id, l'existence réelle des chemins stack et logo, le fait qu'access soit l'une des trois valeurs, et la règle de produit ci-dessus. L'intégration continue exécute le même script : un modèle qui passe en local passe la relecture.
Ce qu'un utilisateur en fait
Depuis la galerie, Import into kuploy copie la spécification de pile dans le presse-papiers ; il la collera dans Stacks → Import, dans son environnement. Deploy on cloud confie plutôt le modèle à une instance Kuploy Cloud.
La fenêtre d'import propose deux modes, et votre entrée alimente le premier :
- Provision new services crée chaque composant d'après la spécification, génère les secrets que vous avez déclarés sous
variables(random32,keypair) et attribue un nom d'hôte à chaque composant figurant dansdomains. Une valeur peut faire référence au nom d'hôte attribué par le jeton${domain}. - Wire existing services fait correspondre les composants aux services que l'utilisateur possède déjà, par leur nom, et ne crée que les connexions d'environnement entre eux.
Déclarez donc des variables pour chaque secret dont l'application a besoin, plutôt que d'y inscrire une valeur de remplacement en dur : sur le chemin de mise en service, elles sont générées à chaque déploiement, alors qu'une valeur en dur serait partagée par tous ceux qui importent votre modèle.
Écrire la spécification de pile
La spécification est une pile Kuploy ordinaire : le guide du développeur sur les Piles en est donc la référence. Deux choses valent la peine d'être faites, spécifiquement pour un modèle :
- Figez les étiquettes d'image.
latestfait qu'un modèle qui fonctionnait le mois dernier échoue aujourd'hui, et la personne qui l'importe n'a aucune idée du pourquoi. - Documentez les réserves de déploiement dans la description. Tout ce que la pile ne sait pas exprimer — les exigences UDP et TURN de LiveKit, par exemple — appartient au texte, puisque c'est tout ce que l'utilisateur lit avant d'importer.