[{"data":1,"prerenderedAt":30},["ShallowReactive",2],{"doc:fr:plugins\u002Fpublishing":3},{"title":4,"lede":5,"html":6,"headings":7},"Publier sur le store","Un plugin se publie sur store.escouade.dev depuis son dépôt GitHub public et une étiquette git. Cette page dit comment soumettre une version, ce que le store contrôle, et comment corriger un refus.","\u003Ch2 id=\"soumettre-une-version\">Soumettre une version\u003C\u002Fh2>\n\u003Col>\n\u003Cli>Connecte-toi sur \u003Ca href=\"https:\u002F\u002Fstore.escouade.dev\u002Fsubmit\" rel=\"noopener\">store.escouade.dev\u003C\u002Fa> avec GitHub, et installe l’App « Escouade Store » sur le dépôt du plugin. Elle lit le code et les étiquettes, sans jamais écrire. Un dépôt privé est refusé : le code d’un plugin du store se lit par tous.\u003C\u002Fli>\n\u003Cli>Choisis le dépôt, puis l’étiquette de la version (\u003Ccode class=\"key\">v1.2.0\u003C\u002Fcode> ou \u003Ccode class=\"key\">1.2.0\u003C\u002Fcode>). Le store la résout en commit une fois, à la soumission, et ne la relit plus pour cette version.\u003C\u002Fli>\n\u003Cli>Les dix contrôles tournent sur la page, une ligne chacun. Le store télécharge l’archive du commit une fois, la garde telle quelle et en calcule l’empreinte SHA-256 ; rien du plugin ne s’exécute sur le serveur.\u003C\u002Fli>\n\u003Cli>Si tout passe, publie : une première version demande une à trois catégories et des mots-clés. La version paraît \u003Cstrong>non vérifiée\u003C\u002Fstrong> ; la case « Demander la revue » (cochée) la met dans la file de la revue « Vérifié par Escouade », qui vaut pour cette version seulement.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Chaque version publiée a son fichier \u003Ccode class=\"key\">version.json\u003C\u002Fcode> : l’identifiant, le numéro, le dépôt, le commit, l’empreinte de l’archive, du manifeste et de chaque binaire. Son empreinte est celle de la version, que l’app vérifie et que la revue signe. Une version publiée ne change plus, et son numéro ne se réutilise pas.\u003C\u002Fp>\n\u003Ch2 id=\"les-dix-controles\">Les dix contrôles\u003C\u002Fh2>\n\u003Cdiv class=\"table\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Contrôle\u003C\u002Fth>\n\u003Cth>Ce qu’il demande\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>Manifeste\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">escouade-plugin.json\u003C\u002Fcode> à la racine, valide au schéma : les mêmes règles que dans l’app (\u003Ca href=\"\u002Fdocs\u002Fplugins\u002Fmanifest\u002F\">le manifeste\u003C\u002Fa>).\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Version\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">version\u003C\u002Fcode> égale à l’étiquette (le \u003Ccode class=\"key\">v\u003C\u002Fcode> est facultatif), plus grande que la dernière publiée.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Identifiant\u003C\u002Ftd>\n\u003Ctd>Libre ou déjà à toi, publié depuis ce dépôt ; \u003Ccode class=\"key\">dev.escouade.*\u003C\u002Fcode> est réservé. Un nom trop proche de celui d’un autre plugin passe d’abord par une revue manuelle.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Dépôt\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">repository\u003C\u002Fcode> égal au dépôt soumis, \u003Ccode>https:\u002F\u002Fgithub.com\u002F&lt;propriétaire&gt;\u002F&lt;dépôt&gt;\u003C\u002Fcode>.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Licence\u003C\u002Ftd>\n\u003Ctd>Une licence libre (reconnue par l’OSI ou la FSF) en identifiant SPDX, la même que celle que GitHub reconnaît dans le fichier \u003Ccode class=\"key\">LICENSE\u003C\u002Fcode> ou \u003Ccode class=\"key\">COPYING\u003C\u002Fcode>.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>README\u003C\u002Ftd>\n\u003Ctd>\u003Ccode class=\"key\">README.md\u003C\u002Fcode> (ou \u003Ccode class=\"key\">README.fr.md\u003C\u002Fcode> et \u003Ccode class=\"key\">README.en.md\u003C\u002Fcode>) à la racine, non vide : c’est la page du plugin.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Captures\u003C\u002Ftd>\n\u003Ctd>Celles de \u003Ccode class=\"key\">store.screenshots\u003C\u002Fcode> : 6 au plus, en PNG, JPEG ou WebP, 1600 px de large et 1 Mo chacune au plus. Le store les réencode, sans leurs métadonnées.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Archive\u003C\u002Ftd>\n\u003Ctd>50 Mo au plus, sans lien symbolique, sans chemin absolu ni \u003Ccode class=\"key\">..\u003C\u002Fcode>, sans sous-module ni fichier Git LFS non résolu.\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Permissions\u003C\u002Ftd>\n\u003Ctd>Cohérentes avec le plugin : sans programme ni webhook, il ne demande ni réseau, ni événements, ni secrets ; un secret demandé est déclaré dans \u003Ccode class=\"key\">contributes.secrets\u003C\u002Fcode> ; un hôte s’écrit seul (\u003Ccode class=\"key\">hooks.slack.com\u003C\u002Fcode>).\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Binaires\u003C\u002Ftd>\n\u003Ctd>Le programme de \u003Ccode class=\"key\">run\u003C\u002Fcode> est dans le dépôt, ou dans la release de l’étiquette pour chaque système (voir plus bas).\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Ch2 id=\"la-page-du-plugin\">La page du plugin\u003C\u002Fh2>\n\u003Cp>Une fois publiée, la version a sa page sur le store : son nom, son auteur, « Non vérifié » ou « En revue » jusqu’à sa signature, ce qu’elle pourra faire en mots (la permission la plus forte d’abord), son dépôt, son commit et son empreinte, ses versions, et « Ouvrir dans Escouade », qui ouvre sa page dans l’app.\u003C\u002Fp>\n\u003Cp>Le README y est rendu une fois, à la soumission, dans la langue du visiteur (\u003Ccode class=\"key\">README.fr.md\u003C\u002Fcode> ou \u003Ccode class=\"key\">README.en.md\u003C\u002Fcode>, sinon \u003Ccode class=\"key\">README.md\u003C\u002Fcode>) ; les pages markdown du dossier \u003Ccode class=\"key\">store.docs\u003C\u002Fcode> font l’onglet « Documentation ». Le store en garde le markdown et une courte liste de balises HTML (titres, listes, liens, code, tableaux, \u003Ccode class=\"key\">details\u003C\u002Fcode>) ; il retire les scripts, les styles, les attributs \u003Ccode class=\"key\">style\u003C\u002Fcode> et \u003Ccode class=\"key\">class\u003C\u002Fcode>, les cadres et les formulaires. Les images du dépôt (PNG, JPEG ou WebP, 5 Mo au plus, en chemin relatif ou par leur adresse sur GitHub) sont copiées sur le store et réencodées ; les images d’ailleurs, comme les badges, sont retirées : un visiteur ne charge rien chez un tiers. Un lien vers un fichier du dépôt mène à GitHub, au commit publié.\u003C\u002Fp>\n\u003Cp>Tout le monde peut signaler un plugin depuis sa page, sans compte, avec une adresse e-mail : une personne lit chaque signalement. Tu vois qu’un signalement est ouvert, jamais qui l’a fait.\u003C\u002Fp>\n\u003Ch2 id=\"les-binaires\">Les binaires\u003C\u002Fh2>\n\u003Cp>Un plugin qui lance un programme compilé attache à la release de l’étiquette une archive par système, dont le nom dit le système et l’architecture : \u003Ccode class=\"key\">…-windows-x64.zip\u003C\u002Fcode>, \u003Ccode class=\"key\">…-macos-arm64.tar.gz\u003C\u002Fcode>, \u003Ccode class=\"key\">…-linux-x64.tar.gz\u003C\u002Fcode> (50 Mo au plus chacune). Chaque système qui lance un programme absent du dépôt doit avoir la sienne. Le store les télécharge une fois, les garde et en calcule l’empreinte.\u003C\u002Fp>\n\u003Cp>Construis-les dans un workflow GitHub Actions public avec \u003Ccode>actions\u002Fattest-build-provenance\u003C\u002Fcode> : l’attestation de provenance lie chaque fichier au commit de l’étiquette. Un binaire sans attestation est publié non vérifié et ne pourra pas être vérifié ; un binaire attesté depuis un autre commit est refusé.\u003C\u002Fp>\n\u003Ch2 id=\"corriger-un-refus\">Corriger un refus\u003C\u002Fh2>\n\u003Cp>Chaque contrôle qui échoue dit ce qui ne va pas, où (le champ ou le fichier, comme \u003Ccode>permissions.network[0]\u003C\u002Fcode>), et comment le corriger. Si tu as donné une adresse e-mail dans ton compte, le même texte y part.\u003C\u002Fp>\n\u003Cp>Pour corriger : commite, puis pousse une \u003Cstrong>nouvelle étiquette\u003C\u002Fstrong>. Le store la voit par l’App et relance les contrôles seul. Si la panne venait du store ou de GitHub, la page propose « Relancer les contrôles ».\u003C\u002Fp>\n\u003Ch2 id=\"les-nouvelles-etiquettes\">Les nouvelles étiquettes\u003C\u002Fh2>\n\u003Cp>Une fois le plugin publié, chaque nouvelle étiquette du dépôt devient une version contrôlée seule, qui attend ton clic pour paraître. La case « Publier seul les nouvelles étiquettes » la publie sans attendre, si tous les contrôles passent.\u003C\u002Fp>\n\u003Cp>Une étiquette déplacée après la publication ne change rien à la version publiée : le store garde le commit et l’archive qu’il a figés, la marque « étiquette déplacée sur le dépôt » et te prévient. Pour publier ce nouveau code, pousse une nouvelle étiquette.\u003C\u002Fp>\n\u003Ch2 id=\"gerer-ses-plugins\">Gérer ses plugins\u003C\u002Fh2>\n\u003Cp>Ton compte, sur \u003Ca href=\"https:\u002F\u002Fstore.escouade.dev\u002Faccount\" rel=\"noopener\">store.escouade.dev\u002Faccount\u003C\u002Fa>, montre tes plugins, leur état, leur dernière version et leurs installations (celles des seuls utilisateurs qui ont accepté les statistiques d’Escouade). Une version trouvée sur une nouvelle étiquette y attend en tête, avec les permissions qu’elle demande en plus : « Publier » ou « Ignorer ». Le menu « … » d’un plugin ouvre ses versions, ses installations semaine par semaine et ce que tu peux en faire :\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Retirer une version\u003C\u002Fstrong> : elle n’est plus proposée à l’installation ni comme mise à jour ; ceux qui l’ont la gardent, marquée « retirée par l’auteur ». Son numéro ne revient pas.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Retirer de la liste\u003C\u002Fstrong> : le plugin quitte la recherche et le catalogue de l’app ; sa page reste lisible, les installations gardent leurs versions, sans mises à jour. Il se remet dans la liste d’un clic.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Transférer\u003C\u002Fstrong> : à un autre compte du store, qui l’accepte depuis le sien. Si le dépôt change de propriétaire sur GitHub, le nouveau propriétaire, une fois l’App installée chez lui, peut reprendre le plugin. Dans les deux cas, ses publications sont gelées 7 jours, le temps d’un signalement, et sa page dit le transfert.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Supprimer\u003C\u002Fstrong>, en tapant son identifiant : il quitte le catalogue tout de suite ; sa page et ses archives partent après 30 jours, pendant lesquels tu peux annuler. Son identifiant reste à ton compte, et ses numéros de version ne servent plus.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Chaque action passe au journal et, si tu as donné une adresse, part par e-mail : une action que tu n’as pas faite se voit. Un compte qui a encore des plugins ne se supprime pas : transfère-les ou supprime-les d’abord.\u003C\u002Fp>\n",[8,12,15,18,21,24,27],{"id":9,"text":10,"depth":11},"soumettre-une-version","Soumettre une version",2,{"id":13,"text":14,"depth":11},"les-dix-controles","Les dix contrôles",{"id":16,"text":17,"depth":11},"la-page-du-plugin","La page du plugin",{"id":19,"text":20,"depth":11},"les-binaires","Les binaires",{"id":22,"text":23,"depth":11},"corriger-un-refus","Corriger un refus",{"id":25,"text":26,"depth":11},"les-nouvelles-etiquettes","Les nouvelles étiquettes",{"id":28,"text":29,"depth":11},"gerer-ses-plugins","Gérer ses plugins",1793278985978]