Auto-démarrage OpenAPI
Testez l'API HTTP de Shepherd avec ses propres capacités : définitions d'API + cas + orchestration de scénarios + exécution.
Exécution
# A. Démarrage en chaîne unique (connexion → extraction → chaîne authentifiée + négative 401) :
# vérifie le mécanisme d'exécution de la chaîne réelle
python3 .claude/skills/openapi-bootstrap/selftest.py
# B. Couverture de scénarios complète par module : un scénario CRUD/cycle de vie par balise OpenAPI,
# exécuté avec un rapport par module
python3 .claude/skills/openapi-bootstrap/scenarios_all.py
# C. Auto-vérification des opérations de plan de test (CRUD de plan, document de planification, liens de cas,
# exécution de plan, ré-exécution d'un seul cas, planification)
python3 .claude/skills/openapi-bootstrap/plans_selftest.py
scenarios_all.py construit un scénario chaîné réel par module métier (20
modules), en référençant des cas d'API (kind=CASE, avec en-têtes d'authentification / extraction
de variables / assertions), ordonnés en chaînes CRUD/cycle de vie et exécutés
en mémoire avec un environnement. Stratégie d'échec CONTINUE → une exécution produit
succès/échec par étape + raisons pour chaque module. Actuellement tout vert :
20/20 modules, 114/114 étapes. Il n'y a pas de point de terminaison « mise à jour de cas » → chaque
exécution supprime l'ancienne définition de conteneur (en cascade sur ses cas) et la reconstruit.
Les ressources persistantes (projet/utilisateur/exigence) portent un suffixe unique par exécution
afin que les exécutions répétées ne heurtent pas les contraintes d'unicité.
Contraintes réelles confirmées lors de la construction (intégrées dans les chaînes ; à maintenir synchronisées si les énumérations du backend changent) :
- Pool de ressources
poolType∈ {Node,Kubernetes} (pas de LOCAL) ; avecallOrg=false,orgIdsdoit être non vide. - Création de tâche
POST /decomposition/{id}/taskretourne{"taskId": <slug>}(pasid) ; les points de terminaison points/statut utilisent ce taskId. - Les exécuteurs de livraison
CLAUDE_CODE/CODEXsont des souches synchrones :POST /deliveryse termine en une étape, créé directement enDELIVERED(pas de transitions asynchrones running/complete). /runner/probeet/runner-agent/{id}/runnécessitent un agent d'exécution en ligne (502 sinon) ; la chaîne locale ne couvre que le plan de gestion.- Plusieurs points de terminaison de liste nécessitent
?projectId=(exigence / compétence / cas fonctionnel / révision de cas). - Les créations retournent 201, les suppressions/mises à jour partielles retournent 204 → utiliser l'assertion
générique
ResponseCode < 400au lieu d'unStatusIs(200)exact.
| Variable d'env | Défaut | Description |
|---|---|---|
SHEPHERD_BASE | http://127.0.0.1:9180 | Adresse du backend |
SHEPHERD_USER / SHEPHERD_PASS | admin / s3cret | Identifiants de connexion (SHEPHERD_ADMIN_PASSWORD) |
SHEPHERD_PROJECT_ID | auto-résolu | Projet cible ; par défaut le premier projet de la première organisation, créé si manquant |
Les scripts, environnements, définitions, cas et scénarios sont tous
créés-ou-réutilisés par nom — les exécutions répétées ne s'accumulent pas.
(Les noms de ressources préexistants comme 自举环境 / 自举链路 sont conservés
en chinois : ce sont des clés persistantes réutilisées par nom ; les renommer orphelinerait
les lignes existantes.)
Flux (7 étapes)
- Connexion pour obtenir un jeton (appels admin uniquement pour la configuration des ressources)
- Résolution/création de l'organisation → projet
- Récupération de l'OpenAPI de ce système (
GET /api-docs/openapi.json) → import idempotent (POST /api/definition/import; même méthode+chemin écrase la spécification, pas de doublons) ; vérification par échantillon que les spécifications sont peuplées et que chaque interface possède un cas avec assertion - Création ou réutilisation d'un environnement pointant vers cet hôte (
baseUrl= ce serveur) - Création ou réutilisation de 4 cas réels sous la définition de la chaîne de démarrage
- Création ou réutilisation d'un scénario référençant ces cas comme étapes
(
kind=CASE), alignement de l'ordre, exécution avec l'environnement - Récupération du rapport ; affichage par étape ✅/❌ + variables extraites + nombre d'assertions
C'est une chaîne réelle, pas des GET codés en dur
Le scénario référence des cas d'API (kind=CASE) au lieu d'intégrer
des requêtes codées en dur. Les cas couvrent POST + GET + en-têtes d'authentification + extraction
de variables + chaînage entre étapes :
① connexion et extraction du jeton POST /auth/login assert statut 200 + contient "token" → extraire token = $.token
② liste authentifiée des organisations GET /organization en-tête Authorization: Bearer ${token} → extraire orgId = $.items[0].id
③ liste authentifiée des projets par orgId GET /project?organizationId=${orgId} (token et orgId substitués)
④ négatif : jeton manquant rejeté GET /organization assert statut 401
Mécanisme d'exécution clé (voir crates/api-test/src/adapters/{plan,local,pg}.rs,
crates/api-runner/src/domain/runner.rs) :
- Les étapes CASE s'exécutent en mémoire, chargeant la méthode/url/corps/en-têtes/authentification/assertions/processeurs complets du cas
— aucun pool de ressources nécessaire (les étapes
REQUESTen ligne suppriment les en-têtes, d'où CASE). - Les processeurs EXTRACT écrivent
$.tokenetc. dans les variables d'exécution, transmises d'une étape à l'autre. - La substitution
${var}à une seule accolade s'applique à l'url / aux valeurs d'en-tête / au corps (attention : pas{{}}). - L'environnement baseUrl est préfixé aux urls relatives ; les en-têtes par défaut comblent les lacunes (les en-têtes de cas de même nom l'emportent).
- Limitation connue : les assertions
Variablene peuvent pas voir les variables d'exécution à l'intérieur d'un scénario (plan.rsne transmet pas les variables à l'évaluation des assertions), donc ce script utiliseStatusIs/BodyContainsau lieu d'assertionsVariable.
Auto-vérification des opérations de plan de test
plans_selftest.py vérifie les opérations de plan de test de bout en bout via l'API
HTTP : création/réutilisation de plan (l'identifiant du plan est conservé dans le fichier d'état local
.plan_selftest_id, car il n'y a pas de point de terminaison de liste/suppression de plan), aller-retour
PUT de mise à jour (description/tags/passThreshold), sauvegarde du document de planification + synchronisation des liens,
liaison de cas (un scénario + un cas d'API), exécution complète du plan (toutes les lignes
SUCCESS, la ligne de scénario porte un reportId dont les étapes sont tous SUCCESS),
r é-exécution d'un seul cas, création/suppression de planification (201/204/404), et déliaison de cas
(204 + liste réduite). Idempotent : une exécution deux fois de suite doit être entièrement verte
les deux fois.
Améliorations de l'importateur backend (livrées simultanément)
POST /api/definition/import désormais :
- analyse les
parametersde chaque opération (query/header/path ; les indicateurs requis encodés dans la remarque),requestBody($ref/allOfrésolus surcomponentsen une arborescence bodySchema + exemple) etresponses(code de statut- exemple de schéma) → écrits dans la
specde la définition ;
- exemple de schéma) → écrits dans la
- génère un cas par défaut (code de statut + assertion métier de base) pour chaque nouvelle interface ;
- est idempotent : un projet+méthode+chemin existant voit seulement sa spécification
écrasée (les cas modifiés par l'utilisateur sont préservés) ; retourne
{created, updated, skipped}.
Code : crates/api-definition/src/domain/import.rs,
application/import_api_definitions.rs, domain/api_definition.rs (with_spec).
Codes de sortie
0 tout vert ; 1 une étape a échoué ; 2 le flux de démarrage lui-même a généré une erreur.