- Python 99.2%
- Shell 0.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .githooks | ||
| resources | ||
| src/wts | ||
| tests | ||
| .gitignore | ||
| .gitlab-ci.yml | ||
| AGENTS.md | ||
| pyproject.toml | ||
| README.md | ||
Warrior‘s TestSuite
WTS lance une campagne pytest, s’arrête au premier défaut et reprend sur ce défaut après correction. Il conserve les tests entièrement terminés après une interruption compatible. Après modification des sources, il conserve le curseur mais invalide les anciennes réussites. Il poursuit jusqu’à la fin, puis revient sur le préfixe dû.
Contrat canonique : carte WTS. Procédure commune : SKILL TestSuite.
Utiliser WTS
L’outil utilise le Python et pytest du projet, sans y installer WTS. Linux, Python ≥3.11 et pytest 8/9 sont requis. La matrice réellement qualifiée figure dans le compte rendu de candidate.
[tool.wts]
hermetic = true
required-profiles = ["default"]
temp-min-free-mib = 1024
state-min-free-mib = 64
test-timeout = 300
[tool.wts.profiles.default]
args = ["tests", "-q"]
uid = "non-root"
Déclarer hermetic = true exige d’avoir établi le contrat d’isolation de cette suite.
Ce réglage ne rend pas ses fixtures hermétiques.
Sans ce contrat, WTS reste utile au diagnostic ; une preuve finale exige un passage entier et ininterrompu dans l’ordre initial.
wts run --python "$VIRTUAL_ENV/bin/python"
# Après correction ou réparation de l’environnement :
wts run --python "$VIRTUAL_ENV/bin/python"
wts status --json
Un venv activé suffit à sélectionner son Python.
Sans venv ni --python, WTS refuse de choisir pytest implicitement.
Les arguments de sélection appartiennent au profil déclaré.
Une invocation ciblant arbitrairement un sous-ensemble ne qualifie pas toute la suite.
wts run --new démarre explicitement une nouvelle campagne.
L’ancienne couverture est invalidée pour cette campagne ; son historique reste consultable dans la base.
Un changement de présentation fourni en CLI change aussi l’identité de l’invocation.
Résultats et reprise
Un test est acquis après setup + call + teardown réussis. Skip, xfail, xpass, crash ou teardown en erreur ne valent jamais PASS. L’ACK envoyé à pytest suit la transaction durable du résultat et du prochain curseur. Le parent surveille le test hors du processus pytest et arrête son propre groupe à l’échéance. La mort du lanceur entraîne la mort de son enfant pytest ; les checkpoints précédents subsistent.
Le verdict contient inventaire, acquis, dus, curseur, empreintes, profil, versions, log et mode de preuve.
Un résultat assemblé est identifié.
Une mutation des sources pendant un fragment invalide ses résultats, même si les bytes sont ensuite restaurés.
status vérifie que les sources, l’environnement et l’outil correspondent encore au résultat enregistré.
Code de run |
Sens |
|---|---|
| 0 | Campagne et profils requis qualifiés avec un outil officiel vérifié |
| 1 | Échec de test ou timeout |
| 2 | Configuration, préflight, fraîcheur ou écrivain concurrent |
| 3 | Interruption, infrastructure, protocole ou persistance |
| 4 | Couverture incomplète, isolation non établie ou diagnostic d’une candidate WTS |
status retourne 0 lorsque sa lecture réussit ; son champ qualified porte le verdict.
Le code pytest natif est enregistré séparément.
Temporaires et état
État : $XDG_STATE_HOME/wts, sinon ~/.local/state/wts.
Le journal SQLite WAL utilise synchronous=FULL.
Chaque test terminé est checkpointé.
Les profils et identités UID restent séparés ; un verrou sérialise les écritures du projet dans ce répertoire d’état.
Trois logs terminés sont conservés, avec l’historique technique dans SQLite.
Le temporaire pytest est un répertoire privé court sur disque, normalement sous /var/tmp.
Un TMPDIR=/tmp ou tmpfs hérité est remplacé par /var/tmp.
WTS contrôle espace, exécution et socket Unix avant les tests.
Son état et son cache pytest ne sont pas dans le temporaire du fragment.
Les temporaires enregistrés d’un processus mort sont récupérés au prochain lancement après vérification d’identité.
Aucun nettoyage global de fichiers, images ou volumes n’est effectué.
Les fichiers suivis et les fichiers non ignorés pertinents entrent dans l’empreinte. Déclarer les assets ignorés et dépendances externes nécessaires avec :
[tool.wts]
source-inputs = ["fixtures/ignored-but-required.json", "/path/to/external-input"]
Cette option complète le même bloc [tool.wts], elle ne doit pas créer une seconde table TOML.
Les dépendances installées sont identifiées par leurs bytes réels, pas seulement leurs numéros de version.
Un cache d’empreintes vérifié par inode, taille, mtime et ctime réduit le coût des lectures répétées.
Plusieurs profils
Déclarer tous les profils requis dans required-profiles.
Chaque profil possède ses arguments, son identité (root, non-root ou any) et éventuellement test-timeout.
Le projet possède le partitionnement et la preuve de couverture de ses tests.
Pour regrouper des profils exécutés sous plusieurs UID, préparer un même XDG_STATE_HOME sous l’identité du projet puis le transmettre explicitement au batch privilégié.
La commande root et ses accès restent soumis à l’autorisation du projet.
Une réussite d’un profil ne remplace jamais un profil manquant.
Source, environnement commun et outil doivent correspondre pour assembler leurs preuves.
Entrées propres aux profils (depuis 0.2.0)
Pour assembler des profils dont une entrée de test diffère, déclarer son nom exact dans le bloc [tool.wts] existant :
profile-environment-inputs = ["ASAMI_PRIVILEGED_CONTAINER_TEST_IMAGE"]
Cette entrée peut alors être absente dans un profil et présente dans un autre.
WTS conserve sa présence et sa valeur dans l’empreinte de chaque profil.
Changer la valeur, la supprimer ou la remplacer par une chaîne vide périme les résultats de ce profil lors de son contrôle par run ou status.
L’assemblage conserve l’environnement effectivement exécuté par chaque profil ; le projet vérifie les valeurs requises, notamment le digest de son image candidate.
Les différences Python, dépendances et variables non déclarées continuent d’empêcher l’assemblage.
La liste est vide par défaut ; seuls des noms POSIX exacts et uniques sont acceptés, sans motifs ni variables déjà techniques ou d’identité.
La déclaration doit être justifiée par le contrat d’isolation de la suite.
Les campagnes 0.1.0 restent attachées à leur artefact ; leurs résultats ne deviennent pas automatiquement des preuves de la version 0.2.0.
Fraîcheur et installation
Avant une nouvelle campagne officielle, le lanceur vérifie la release stable compatible et l’intégrité de ses bytes. Une absence réseau ou de release compatible bloque en amont. Une campagne active conserve son artefact vérifié et peut reprendre hors ligne. Si le lanceur courant a changé, WTS réexécute automatiquement l’ancien artefact sauvegardé lorsque son SHA est encore vérifiable. Une mise à jour ne supprime pas les versions actives.
wts fresh
wts self-update
Source officielle : releases et Generic Packages du projet GitLab WTS.
La release fournit le zipapp wts.pyz, son sidecar wts.pyz.sha256, le manifeste wts-manifest.json, ainsi que les sources exactes et leur sidecar.
Le bootstrap télécharge et vérifie les bytes, puis :
python3 wts.pyz self-update --prefix /usr/local
Installation : /usr/local/lib/wts/releases/<version>/wts.pyz et lanceur /usr/local/bin/wts.
Version stable publiée : 0.2.0.
Le zipapp qualifié compte 25 294 octets, SHA-256
ed741d6ea43b07aab442551b5054c059e7efc562632280e24b6f1d7a92244dfd.
Ses bytes publiés ne sont jamais remplacés.
Pour le bootstrap, télécharger wts.pyz et wts.pyz.sha256 depuis
https://gitlab.com/api/v4/projects/88687597/packages/generic/wts/0.2.0/
puis vérifier sha256sum -c wts.pyz.sha256 avant la commande d’installation ci-dessus.
Le téléchargement et la vérification de fraîcheur ne nécessitent aucun token GitLab.
La publication a été vérifiée anonymement sur un second Atelier : téléchargement,
fresh, installation puis reprise officielle après interruption, avec conservation des acquis.
Deux profils dont une entrée déclarée diffère sont assemblés avec un verdict global positif ; changer cette entrée périme les résultats du profil contrôlé.
--candidate sert exclusivement à exercer un artefact avant publication.
Ce mode indique candidate-qualification, ne déclare jamais fresh ou qualified et retourne 4 même lorsque sa couverture diagnostique est complète.
Ce garde-fou permet de qualifier une nouvelle version du programme avant sa publication ; il n’est pas une exemption de qualification du projet utilisateur.
Développer et qualifier
python3 -m venv .venv
TMPDIR=/var/tmp .venv/bin/python -m pip install -e '.[dev]'
TMPDIR=/var/tmp .venv/bin/python -m pytest -xq --basetemp=/var/tmp/pwts
python3 resources/build.py --version 0.2.0 --channel stable
python3 resources/benchmark.py --artifact "$PWD/dist/wts.pyz" --python "$PWD/.venv/bin/python"
resources/qualify-enospc.py remplit une image ext4 privée de 32 Mio, vérifie la reprise après déplacement du temporaire et détruit image et montage.
L’option --state-volume remplit le disque du journal lui-même et vérifie la récupération des checkpoints après réparation.
Il s’exécute sur un Atelier réservé, sous root dans un namespace de montage privé :
sudo -n unshare --mount --propagation private -- python3 resources/qualify-enospc.py \
--artifact "$PWD/dist/wts.pyz" --python "$PWD/.venv/bin/python"
Les tests d’intégration exercent la vraie CLI, le Python sélectionné, le plugin et le journal.
Le fournisseur de release distant est simulé uniquement à sa frontière HTTP pour les scénarios de fraîcheur.
Les commits utilisent resources/git/agent-commit.
La publication et les tests tournent sur les Ateliers provisionnés ; les pipelines GitLab sont désactivées.