Mélodium 0.11.1 : caches, artefacts et secrets de Cadence.CI
Mélodium 0.11.1 est disponible. Le langage ne change pas, mais la bibliothèque standard s’étoffe beaucoup : les étapes CI/CD gagnent des caches et des artefacts, les valeurs d’un flux peuvent s’exécuter chacune dans sa propre piste, et de nouveaux paquets compressent les données et archivent des répertoires au fil de l’eau. Les programmes exécutés par Cadence.CI peuvent aussi lire les secrets de leur organisation.
Caches et artefacts pour les étapes CI/CD
Une étape peut désormais restaurer un répertoire avant ses commandes et le sauvegarder une fois qu’elles réussissent. Dans la démonstration Pipeline CI, les crates et les sorties de build vivent dans le répertoire cache du volume data de l’étape, et |cache en fait le cache nommé cargo :
variables = |wrap<StringMap>(|map([
|entry("REPO_URL", repo_url),
|entry("CARGO_HOME", "/mnt/data/cache/cargo"),
|entry("CARGO_TARGET_DIR", "/mnt/data/cache/target")
])),
cache = |wrap<Cache>(|cache(|wrap<string>("data"), "cache", "cargo")),Chaque sauvegarde est une nouvelle version, et l’exécution suivante restaure la dernière : rien à changer quand les dépendances évoluent. Quand le nom dépend du programme, par exemple d’une empreinte de Cargo.lock, les variantes Cached des étapes (stepOnCached, simpleStepCached…) le reçoivent sur une entrée cache_name. Un cache absent ou une sauvegarde ratée produisent seulement un avertissement.
Les artefacts fonctionnent de la même façon, dans l’autre sens. |artifact désigne les fichiers d’un répertoire, |artifact_file un fichier seul, et les étapes les reçoivent dans artifacts : une fois les commandes réussies, chaque artefact est envoyé à l’exécution sur Cadence.CI , dans sa propre piste, avant la fin de l’étape. En dehors des étapes, work/artifact envoie et récupère directement des artefacts ; les fichiers récupérés sont vérifiés par leur SHA-256, et un fichier différent est supprimé.
Rien de tout cela n’est une fonctionnalité du moteur : caches et artefacts sont écrits en Mélodium, à partir des briques décrites plus bas. Les sauvegardes sont archivées en tar, vérifiées pour les secrets, compressées en zstd et envoyées en plusieurs parties pendant leur construction. Les restaurations sont téléchargées avec reprise et extraites à côté de leur cible avant de la remplacer.
Disperser et rassembler
std/flow/scatter donne à chaque valeur d’un flux sa propre piste. scatter crée une piste par valeur, au plus parallel à la fois, et la source scattered donne à chaque piste sa valeur ainsi qu’une valeur partagée par toutes. Les pistes héritent des contextes de la piste qui les a créées, avec @Scattered en plus, et indiquent comment elles se sont terminées via gather. Une piste qui se termine sans l’indiquer compte comme un échec. scatterGathering collecte en plus les valeurs que les pistes donnent à gatherValue, dans l’ordre où elles se terminent.
Les artefacts s’en servent pour envoyer chaque fichier dans sa propre piste, et les envois en plusieurs parties pour transmettre leurs parties côte à côte.
Deux évolutions du moteur l’ont rendu possible, toutes deux visibles des auteurs de bibliothèques Rust : les sources des modèles peuvent désormais être génériques, et les pistes qu’elles créent peuvent hériter des contextes de leur piste parente.
Des données en mouvement
Quatre paquets gagnent ce dont les caches et les artefacts avaient besoin, et dont d’autres programmes auront besoin aussi :
compressionest nouveau. Il compresse et décompresse des flux d’octets au fil de l’eau en zstd, gzip, zlib, deflate et brotli, et décompresse le deflate64. Chaque format est en pur Rust et fonctionne en WebAssembly.fsarchive un répertoire de n’importe quel système de fichiers en flux tar avecfs/archive::tar, et en extrait un avecuntar. Les archives sont déterministes, les liens restent des liens et ne sont jamais suivis, et l’extraction n’écrit jamais hors de sa cible. Les systèmes de fichiers savent aussi décrire, lister, lier, supprimer et renommer des entrées, etfs/dir::filesliste les fichiers ordinaires d’une arborescence.httpaccepte les requêtes préparées , comme celles présignées par un stockage objet.http/client::downloadreprend après une coupure de connexion, sans jamais donner un octet deux fois, ethttp/uploadenvoie les données en plusieurs parties, chacune relancée indépendamment.cryptodonne l’empreinte SHA-256 de flux et de vecteurs d’octets, etjsonlit des valeurs par clé , par index ou par pointeur JSON , construit des objets et des tableaux , et convertit des valeurs typées depuis et vers JSON (|into_json,|from_json).
Les secrets de Cadence.CI
Les programmes exécutés par Cadence.CI , avec melodium run ou melodium dist, disposent de trois nouvelles sources de secrets :
api:lit les secrets enregistrés pour l’organisation de l’exécution, commeapi:prod/db-password;api-id:donne un jeton d’identité de l’exécution pour une audience, afin qu’un service qui fait confiance à Cadence.CI puisse l’authentifier, comme Vault :vault::Vault(auth="jwt", jwt="api-id:vault");api-run:tokendonne le jeton de l’exécution elle-même, pour les requêtes vers ses points d’accès.
Aucune n’est jamais révélée en clair, et ailleurs elles sont refusées avec la raison. Les schémas api, api-id et api-run sont réservés : un modèle qui enregistre une source sous l’un de ces noms fait échouer le lancement. Dans l’autre sens, work/secret::store enregistre un secret produit par un programme, comme un mot de passe généré, pour que les exécutions suivantes le lisent via api:.
Les données qui quittent le moteur étaient le dernier angle mort. Les messages de journal étaient déjà masqués, mais pas un fichier envoyé ailleurs. std/secret::scan cherche dans un flux d’octets toute valeur que le moteur a révélée, telle quelle, en base64, encodée pour URL ou en octets bruts, et arrête le flux quand il en trouve une, en nommant le secret mais jamais la valeur. Les caches et les artefacts passent par lui avant d’être envoyés.
La page Secrets de la documentation couvre les nouvelles sources.
Les volumes restent entre leurs murs
work/resources::getFileSystem donne désormais le système de fichiers d’un volume enraciné dans son répertoire, quel que soit l’exécuteur. Les chemins avec .., les chemins absolus et les liens qui mènent hors du volume sont refusés, y compris les liens que d’autres exécuteurs partageant le volume créent entre-temps. |local_filesystem se comporte de même quand il reçoit une racine.
Le retour des vérifications à la genèse
Le moteur vérifie à nouveau les pistes des sources lors de la construction d’un programme, une vérification suspendue depuis février 2025. Elle s’exécute désormais en un temps proportionnel à la taille du programme, quel que soit le nombre de chemins menant à chaque construction. Les boucles de connexion et les contextes manquants échouent de nouveau avant le démarrage du programme, plutôt qu’en cours d’exécution.
Corrections
simpleStepetsimpleStepWithInputtransmettent désormais leurmax_durationau worker, qui gardait la valeur par défaut d’une heure.- Le stockage de leur conteneur est porté à la taille de son volume
/mnt/dataquandout_storageest plus grand, au lieu de voir la demande refusée. - Elles prennent aussi des
tags, des indications jointes à la demande de worker, commename=build. fromNumberU64etfromNumberI64dejsonne réduisent plus les nombres à 16 bits, et ne paniquent plus sur les plus grands.- Compose donne aux conteneurs dont le nom n’est pas un nom d’hôte valide, comme les noms avec
_, un nom d’hôte où les caractères invalides deviennent-, au lieu d’échouer.
Ce qu’il faut mettre à jour
- Conteneurs de service :
|service_containerprendsecret_envaprèsenv. Ajoutez un_aux appels existants, comme le fait la démonstration Pipeline CI. - Secrets de récupération d’images : les secrets joints à une demande de worker passent par leur nom quand ils sont enregistrés sur Cadence.CI (
api:), par valeur quand leur transmission estvalue, et sont refusés enlocal. Les secrets de récupération avec la politique par défaut sont donc désormais refusés. Compose refuse les secrets donnés par nom. - Systèmes de fichiers : les chemins qui sortent d’un volume, ou de la racine de
|local_filesystem, sont refusés.ContainerFileSystemetKubeFileSystemsont supprimés. - Genèse : les programmes avec des boucles de connexion ou des contextes manquants dans les pistes des sources démarraient, et sont de nouveau refusés.
Le détail complet pour chaque crate est dans le CHANGELOG . Comme d’habitude, mise à jour via cargo install melodium ou un binaire précompilé.
