voici un petit schéma qui illustre ce que j'ai en tête :
la branche principale contient toutes les mises à jour (client et runtime)
les runtime sont releasés depuis la branche principale et correspondent à un snapshot de l'état des pallets et de la config du runtime, on peut release indépendamment chaque runtime (gdev, gtest, g1)
le release des clients sont faites par rebase sur la branche principale, les commits externes qui ne seront jamais fusionnés peuvent contenir :
x : des chainspecs avec le genesis (y compris le runtime au genesis) spécifiques à un réseau
y : des mises à jour des bootnodes spécifiques au réseau
Il y a donc deux processus différents :
le release du runtime destiné à être publié sur un réseau
le release d'un client plus à jour mais néanmoins capable d'exécuter le runtime du genesis et tout ceux qu'il rencontrera au cours des blocs
Le nouveau client intègre deux runtime :
le runtime du genesis intégré aux chainspecs au format wasm compilé avec srtool
le runtime natif correspondant au code le plus récent et capable de prendre le relais s'il est identique au runtime actuellement en cours sur le réseau. À noter que cette distinction est essentiellement conceptuelle puisqu'on préférera toujours exécuter le runtime wasm pour éviter les bugs tels que https://forum.duniter.org/t/exemple-de-bug-lie-a-la-difference-entre-runtime-wasm-et-natif/11574
Suite à !261 (merged) et des incompréhensions sur les versions des logiciels utilisées, je pense qu'on devrait avoir une version "générique" du client et du runtime sur la branche master. Du genre version = '1.0.0' et spec_version: 100,. Toutes les modifications sont mergées sur master sauf les chainspecs, les bootnodes, et les numéros de version qui sont à mettre dans des branches dédiées.
Et je reviens sur l'idée "Dissociate release of Runtime and release of Client". En fait, il ne faut pas les dissocier, car même si on publie un runtime uniquement pour une chaîne live (comme le 801), il est intéressant de pouvoir booter un réseau local basé sur ce runtime à partir d'une image docker. Donc à chaque release, il faut releaser le client avec le runtime intégré et le runtime séparément pour pouvoir l'utiliser dans System.SetCode().
Et donc ça montre que bien choisir le numéro de version du client et du runtime est important pour être bien compris. D'où l'idée de garder "1.0.0" et "100" en dev, comme ça c'est évident quand quelqu'un travaille avec une version de dev compilée sur master ou une version de release compilée sur une branche de release (dont les images docker utilisées par les développeurs comme kimamila et txels sur Cesium v2 ou vit sur Tikka).
Ceci implique quand même de préciser la procédure pour publier une nouvelle version du client avec des anciennes chainspecs compatibles avec un réseau live. C'est la partie cargo xtask inject-runtime-code mais il me semble qu'on ne l'a pas encore utilisée donc elle peut être cassée.
Ne serait-ce pas plutôt l'option --chain=<PATH> ? L'injection du Runtime a déjà été faite dans les anciennes chainspecs, l'opération n'est pas à refaire.
La seule contrainte à bien documenter c'est que le début de nom de fichier identifie le code du client qui va gérer cette spec, il faut que ce soit gdev, gtest ou g1 (par exemple : gdev_801_rawspecs.json), et que le client soit compilé avec la feature correspondante.
Je pourrais mettre à jour la documentation launch-a-live-network.md je suppose.
L'option --chain=<PATH> c'est une option au runtime pour choisir un fichier de chainspecs. Or ce qu'on veut faire, c'est produire un binaire avec les bonnes chainspecs à la compilation.
On pourrait effectivement s'en passer si on produisait une image docker qui inclut le fichier de raw chainspecs, mais ça ne marcherait pas pour les autres paquetages dans lesquels on publie seulement un binaire.
En gros quand les utilisateurs lancent duniter --chain=g1 il faut qu'il y ait les bonnes chainspecs et les bons bootnodes, ils ne devraient pas avoir à télécharger un fichier et l'indiquer en argument.
[edit] ah non, je vois ce que tu veux dire, tu parles du &include_bytes!("../specs/gdev-raw.json")[..], ?
C'est moi qui me plante, je crois que le seul intérêt de cargo xtask inject-runtime-code est de remplacer un runtime natif par un runtime srtool. Mais c'est toujours un peu confus dans ma tête
Oui en fait le inject-runtime-code n'est plus utilisé, son seul intérêt connu de ma part c'est effectivement d'injecter le runtime produit par srtool. Mais désormais l'injection se fait directement avec la variable WASM_FILE.
Concernant le build du client, aujourd'hui on n'a que deux packaging il me semble :
Docker avec la CI
Build natif avec Cargo
Pour Docker c'est facile : la CI s'occupe de générer les chainspecs et les inclut dans l'image finale.
Mais pour le build natif, il faudrait que l'on commite les chainspecs sur la branche de release. Ce qui est possible, mais ça va faire grossir le dépôt vu la taille du Genesis.
Pour le build natif oui, c'est pour ça que je préfère commiter les chainspecs dans une branche qui ne sera pas mergée ('x' sur le schéma). Et normalement on n'en aura que quelques unes correspondant aux réseaux en cours. Si un réseau gdev périme, on peut supprimer la branche.
Si ce n'est pas trop d'effort, on pourrait plutôt mettre en numéro de version du client et nom du runtime le hash du commit utilisé pour compiler. Comme ça même avec une version locale, pas d'ambiguité.
Si tu réponds favorablement, alors je proposerai la CI suivante :
pour la branche release/gdev (extrapoler pour les branches release/gtest et release/g1) la CI proposera un pipeline manuel qui, sur activation :
reconstruira le fichier g1-data.json (modifié uniquement si dump de la Ğ1 différent ou format généré par py-g1-migrator différent)
mettra à jour le fichier de specs de la monnaie concernée
commitera le fichier de spec et g1-data.json via un compte "gitbot" de la CI
pour tout tag posé sur une branche release/, la CI réalisera automatiquement une release basée sur le code source du tag :
uploadera le runtime de chaque monnaie (gdev seulement au début, puis progressivement gtest et g1)
uploadera le fichier g1-data.json
uploadera le fichier de spec de chaque monnaie
uploadera le fichier de spec Client de chaque monnaie
uploadera le fichier RAW de chaque monnaie
buildera et publiera l'image Docker pour chaque monnaie
les branches de release/ peuvent être mergées entre-elles (afin de créer une release commune avec un Genesis différent par monnaie) mais peuvent aussi être écrasées à tout moment. Ainsi, on peut "détruire" les commits de mise à jour de Genesis (évite le grossissement du dépôt Git), mais si l'on veut conserver un snapshot à un moment donné, on peut donc poser un tag qui créera une release et sauvegardera donc les fichiers de specs, etc via les artifacts.
J'avais un peu de retard sur mes mails et n'ai donc pas vu la notif, désolé. Tout me semble correct, j'ai juste quelques points à reformuler pour être sûr qu'on est en phase :
Runtime : démarrer une nouvelle monnaie (en local par exemple)
Specs : suivre une monnaie existante (ex. gdev-800)
Client : assurer la compatibilité avec un futur Runtime
On peut vouloir publier un runtime dans l'objectif d'un runtime upgrade (system.setCode()). Dans ce cas, la chaîne sera mise à jour à partir de l'exécutable wasm produit par srtool seul. Le client intégrant le nouveau runtime dans ses specs dev sera utile pour les environnements de développement.
Les specs gdev permettent en effet de suivre une monnaie existante, on peut nommer la chaîne "gdev-800" si on veut, au sens où c'est ce runtime qui est utilisé au genesis, mais il faut garder en tête que cette chaîne pourra connaître des runtime upgrade successifs (gdev-801, gdev-802...) sans redémarrer.
Pour ce qui est du client, il ne s'agit pas uniquement d'assurer la compatibilité avec un futur runtime, on peut introduire d'autres fonctionnalités. Par exemple ajouter des calls à l'API RPC, des options en ligne de commande, changer l'oracle de distance, modifier l'algorithme de priorisation des transactions... ou même ne pas toucher au binaire, mais uniquement à l'image docker (entrypoints, ports, variables d'environnement...). Tout ça peut conduire à publier un nouveau client, mais sans changer de réseau (genesis specs) et sans changer de runtime natif (pas de modifs du runtime).
Reste les Specs qu'on peut vouloir rebuilder de façon optionnelle (TODO).
Effectivement, si on veut démarrer un nouvelle donnée avec des paramètres genesis ou des données différentes, on rebuild des specs.
L'autre raison pour rebuild les specs est de modifier les "client specs", c'est-à-dire les bootnodes, les métadonnées de chaîne (symbole, nombre de décimales...).
les branches de release ne sont jamais mergées sur master
Effectivement, c'est l'innovation que je propose puisque j'ai trouvé ça très perturbant par le passé. Si on fait des hotfix sur les branches de release (par exemple sur de la doc ou de la CI), alors on pourra soumettre une MR sur master avec des cherry-pick, c'est plus facile à comprendre comme ça.
je proposerai la CI suivante
Ça me paraît compliqué. Pour moi, une branche de release = un réseau. Donc il n'y aura qu'une seule branche gtest, une seule branche g1, et autant de branches gdev que de fois où on rebootera le réseau.
pour tout tag posé sur une branche release/, la CI [...] uploadera le runtime de chaque monnaie
Je ne saisis pas l'idée derrière ça. Si on est sur une branche de release, alors on ne parle que d'un réseau. Donc on ne doit publier que le runtime de ce réseau.
uploadera le fichier g1-data.json
Cette opération n'est à faire qu'au démarrage d'un réseau, donc une seule fois par branche, au début de celle-ci. Il n'y a pas de raison de publier à nouveau le même fichier, ni de publier un fichier différent puisque celui-ci ne sera jamais utilisé, la seule utilisation étant au genesis.
les branches de release/ peuvent être mergées entre-elles (afin de créer une release commune avec un Genesis différent par monnaie)
Pour moi ça n'a pas de sens. La seule chose qu'on peut merger dans un branche de release, c'est master pour y amener une nouvelle version du client, et encore, il faut ne pas avoir introduit d'incompatibilité entre le runtime du réseau (qui peut être très différent de celui de master) et l'oracle de distance par exemple.
En fait après lecture, je pense qu'on n'est pas en phase, je veux bien qu'on se fasse une visio sur ce sujet parce que ça vaut le coup de se mettre d'accord sur un schéma de release. Je vais essayer de poser quelques bases sur le forum pour que d'autres puissent nous suivre et faire des retours.