eqs openapi export refuse d'exporter parce qu'un fichier de test a bougé — or test/ n'est jamais compilé dans dist/ #52
Closed
opened 2026-09-10 15:15:58 +00:00 by nicolas-fryder
·
2 comments
No Branch/Tag specified
main
dev
@eqs/tooling@0.24.3
@eqs/testing@0.24.3
@eqs/telemetry@0.24.3
@eqs/platform-next@0.24.3
@eqs/platform-nest@0.24.3
@eqs/http@0.24.3
@eqs/errors@0.24.3
@eqs/config@0.24.3
@eqs/cli@0.24.3
@eqs/auth@0.24.3
@eqs/tooling@0.24.2
@eqs/testing@0.24.2
@eqs/telemetry@0.24.2
@eqs/platform-next@0.24.2
@eqs/platform-nest@0.24.2
@eqs/http@0.24.2
@eqs/errors@0.24.2
@eqs/config@0.24.2
@eqs/cli@0.24.2
@eqs/auth@0.24.2
@eqs/tooling@0.24.1
@eqs/testing@0.24.1
@eqs/telemetry@0.24.1
@eqs/platform-next@0.24.1
@eqs/platform-nest@0.24.1
@eqs/http@0.24.1
@eqs/errors@0.24.1
@eqs/config@0.24.1
@eqs/cli@0.24.1
@eqs/auth@0.24.1
@eqs/tooling@0.24.0
@eqs/testing@0.24.0
@eqs/telemetry@0.24.0
@eqs/platform-next@0.24.0
@eqs/platform-nest@0.24.0
@eqs/http@0.24.0
@eqs/errors@0.24.0
@eqs/config@0.24.0
@eqs/cli@0.24.0
@eqs/auth@0.24.0
@eqs/tooling@0.23.0
@eqs/testing@0.23.0
@eqs/telemetry@0.23.0
@eqs/platform-next@0.23.0
@eqs/platform-nest@0.23.0
@eqs/http@0.23.0
@eqs/errors@0.23.0
@eqs/config@0.23.0
@eqs/cli@0.23.0
@eqs/auth@0.23.0
@eqs/tooling@0.22.0
@eqs/testing@0.22.0
@eqs/telemetry@0.22.0
@eqs/platform-next@0.22.0
@eqs/platform-nest@0.22.0
@eqs/http@0.22.0
@eqs/errors@0.22.0
@eqs/config@0.22.0
@eqs/cli@0.22.0
@eqs/auth@0.22.0
@eqs/tooling@0.21.0
@eqs/testing@0.21.0
@eqs/telemetry@0.21.0
@eqs/platform-next@0.21.0
@eqs/platform-nest@0.21.0
@eqs/http@0.21.0
@eqs/errors@0.21.0
@eqs/config@0.21.0
@eqs/cli@0.21.0
@eqs/auth@0.21.0
@eqs/tooling@0.20.0
@eqs/testing@0.20.0
@eqs/telemetry@0.20.0
@eqs/platform-next@0.20.0
@eqs/platform-nest@0.20.0
@eqs/http@0.20.0
@eqs/errors@0.20.0
@eqs/config@0.20.0
@eqs/cli@0.20.0
@eqs/auth@0.20.0
@eqs/tooling@0.19.0
@eqs/testing@0.19.0
@eqs/telemetry@0.19.0
@eqs/platform-next@0.19.0
@eqs/platform-nest@0.19.0
@eqs/http@0.19.0
@eqs/errors@0.19.0
@eqs/config@0.19.0
@eqs/cli@0.19.0
@eqs/auth@0.19.0
@eqs/tooling@0.17.1
@eqs/testing@0.17.1
@eqs/telemetry@0.17.1
@eqs/platform-next@0.17.1
@eqs/platform-nest@0.17.1
@eqs/http@0.17.1
@eqs/errors@0.17.1
@eqs/config@0.17.1
@eqs/cli@0.17.1
@eqs/auth@0.17.1
@eqs/tooling@0.17.0
@eqs/testing@0.17.0
@eqs/telemetry@0.17.0
@eqs/platform-next@0.17.0
@eqs/platform-nest@0.17.0
@eqs/http@0.17.0
@eqs/errors@0.17.0
@eqs/config@0.17.0
@eqs/cli@0.17.0
@eqs/auth@0.17.0
@eqs/tooling@0.16.0
@eqs/testing@0.16.0
@eqs/telemetry@0.16.0
@eqs/platform-next@0.16.0
@eqs/platform-nest@0.16.0
@eqs/http@0.16.0
@eqs/errors@0.16.0
@eqs/config@0.16.0
@eqs/cli@0.16.0
@eqs/auth@0.16.0
@eqs/tooling@0.15.0
@eqs/testing@0.15.0
@eqs/telemetry@0.15.0
@eqs/platform-next@0.15.0
@eqs/platform-nest@0.15.0
@eqs/http@0.15.0
@eqs/errors@0.15.0
@eqs/config@0.15.0
@eqs/cli@0.15.0
@eqs/auth@0.15.0
@eqs/tooling@0.14.0
@eqs/testing@0.14.0
@eqs/telemetry@0.14.0
@eqs/platform-next@0.14.0
@eqs/platform-nest@0.14.0
@eqs/http@0.14.0
@eqs/errors@0.14.0
@eqs/config@0.14.0
@eqs/cli@0.14.0
@eqs/auth@0.14.0
@eqs/tooling@0.13.0
@eqs/testing@0.13.0
@eqs/telemetry@0.13.0
@eqs/platform-next@0.13.0
@eqs/platform-nest@0.13.0
@eqs/http@0.13.0
@eqs/errors@0.13.0
@eqs/config@0.13.0
@eqs/cli@0.13.0
@eqs/auth@0.13.0
@eqs/tooling@0.12.2
@eqs/testing@0.12.2
@eqs/telemetry@0.12.2
@eqs/platform-next@0.12.2
@eqs/platform-nest@0.12.2
@eqs/http@0.12.2
@eqs/errors@0.12.2
@eqs/config@0.12.2
@eqs/cli@0.12.2
@eqs/auth@0.12.2
@eqs/tooling@0.12.1
@eqs/testing@0.12.1
@eqs/telemetry@0.12.1
@eqs/platform-next@0.12.1
@eqs/platform-nest@0.12.1
@eqs/http@0.12.1
@eqs/errors@0.12.1
@eqs/config@0.12.1
@eqs/cli@0.12.1
@eqs/auth@0.12.1
@eqs/tooling@0.12.0
@eqs/testing@0.12.0
@eqs/telemetry@0.12.0
@eqs/platform-next@0.12.0
@eqs/platform-nest@0.12.0
@eqs/http@0.12.0
@eqs/errors@0.12.0
@eqs/config@0.12.0
@eqs/cli@0.12.0
@eqs/auth@0.12.0
@eqs/tooling@0.11.2
@eqs/testing@0.11.2
@eqs/telemetry@0.11.2
@eqs/platform-next@0.11.2
@eqs/platform-nest@0.11.2
@eqs/http@0.11.2
@eqs/errors@0.11.2
@eqs/config@0.11.2
@eqs/cli@0.11.2
@eqs/auth@0.11.2
@eqs/tooling@0.11.1
@eqs/testing@0.11.1
@eqs/telemetry@0.11.1
@eqs/platform-next@0.11.1
@eqs/platform-nest@0.11.1
@eqs/http@0.11.1
@eqs/errors@0.11.1
@eqs/config@0.11.1
@eqs/cli@0.11.1
@eqs/auth@0.11.1
@eqs/tooling@0.11.0
@eqs/testing@0.11.0
@eqs/telemetry@0.11.0
@eqs/platform-next@0.11.0
@eqs/platform-nest@0.11.0
@eqs/http@0.11.0
@eqs/errors@0.11.0
@eqs/config@0.11.0
@eqs/cli@0.11.0
@eqs/auth@0.11.0
@eqs/tooling@0.10.1
@eqs/testing@0.10.1
@eqs/telemetry@0.10.1
@eqs/platform-next@0.10.1
@eqs/platform-nest@0.10.1
@eqs/http@0.10.1
@eqs/errors@0.10.1
@eqs/config@0.10.1
@eqs/cli@0.10.1
@eqs/auth@0.10.1
@eqs/tooling@0.10.0
@eqs/testing@0.10.0
@eqs/telemetry@0.10.0
@eqs/platform-next@0.10.0
@eqs/platform-nest@0.10.0
@eqs/http@0.10.0
@eqs/errors@0.10.0
@eqs/config@0.10.0
@eqs/cli@0.10.0
@eqs/auth@0.10.0
@eqs/tooling@0.9.0
@eqs/testing@0.9.0
@eqs/telemetry@0.9.0
@eqs/platform-next@0.9.0
@eqs/platform-nest@0.9.0
@eqs/http@0.9.0
@eqs/errors@0.9.0
@eqs/config@0.9.0
@eqs/cli@0.9.0
@eqs/auth@0.9.0
@eqs/tooling@0.8.1
@eqs/testing@0.8.1
@eqs/telemetry@0.8.1
@eqs/platform-next@0.8.1
@eqs/platform-nest@0.8.1
@eqs/http@0.8.1
@eqs/errors@0.8.1
@eqs/config@0.8.1
@eqs/cli@0.8.1
@eqs/auth@0.8.1
@eqs/tooling@0.8.0
@eqs/testing@0.8.0
@eqs/telemetry@0.8.0
@eqs/platform-next@0.8.0
@eqs/platform-nest@0.8.0
@eqs/http@0.8.0
@eqs/errors@0.8.0
@eqs/config@0.8.0
@eqs/cli@0.8.0
@eqs/auth@0.8.0
@eqs/tooling@0.7.0
@eqs/testing@0.7.0
@eqs/telemetry@0.7.0
@eqs/platform-next@0.7.0
@eqs/platform-nest@0.7.0
@eqs/http@0.7.0
@eqs/errors@0.7.0
@eqs/config@0.7.0
@eqs/cli@0.7.0
@eqs/auth@0.7.0
@eqs/tooling@0.6.0
@eqs/testing@0.6.0
@eqs/telemetry@0.6.0
@eqs/platform-next@0.6.0
@eqs/platform-nest@0.6.0
@eqs/http@0.6.0
@eqs/errors@0.6.0
@eqs/config@0.6.0
@eqs/cli@0.6.0
@eqs/auth@0.6.0
@eqs/tooling@0.5.1
@eqs/testing@0.5.1
@eqs/telemetry@0.5.1
@eqs/platform-next@0.5.1
@eqs/platform-nest@0.5.1
@eqs/http@0.5.1
@eqs/errors@0.5.1
@eqs/config@0.5.1
@eqs/cli@0.5.1
@eqs/auth@0.5.1
@eqs/tooling@0.5.0
@eqs/testing@0.5.0
@eqs/telemetry@0.5.0
@eqs/platform-next@0.5.0
@eqs/platform-nest@0.5.0
@eqs/http@0.5.0
@eqs/errors@0.5.0
@eqs/config@0.5.0
@eqs/cli@0.5.0
@eqs/auth@0.5.0
@eqs/tooling@0.4.0
@eqs/testing@0.4.0
@eqs/telemetry@0.4.0
@eqs/platform-next@0.4.0
@eqs/platform-nest@0.4.0
@eqs/http@0.4.0
@eqs/errors@0.4.0
@eqs/config@0.4.0
@eqs/cli@0.4.0
@eqs/auth@0.4.0
@eqs/tooling@0.2.0
@eqs/telemetry@0.2.0
@eqs/errors@0.2.0
@eqs/config@0.2.0
@eqs/tooling@0.1.0
Labels
No labels
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
Infrastructure/eqs-platform#52
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Le contrôle de fraîcheur de
eqs openapi exportcompare la date dedist/openapi.jsà tous les fichiers source de l'application,test/compris. Ortsconfig.build.jsonn'inclut quesrc/: un fichier de test ne peut pas rendredist/périmé, et le refus est un faux positif.Reproduction
Dans un satellite,
dist/à jour :Sortie :
pnpm --filter api buildfait passer — mais il n'a rien recompilé d'utile, puisque le fichier incriminé n'entre dans aucundist/.Où le maillon manque
node_modules/@eqs/cli/dist/outils.js:sourcePlusRecentedescend récursivement depuis la racine de l'app en écartant seulement ces sept noms.testn'y est pas.Et le
tsconfig.build.jsondu gabarit, celui-là même que la commande suppose :Le contrôle compare donc
dist/à des fichiers qu'il ne produit jamais.Ce que ça coûte
Non bloquant : un
buildde plus et ça passe. Mais c'est un cycle inutile à chaque fois qu'on touche un test avant de régénérer le contrat — c'est-à-dire tout le temps, puisqu'ajouter une route s'accompagne d'ajouter ses tests.Le coût réel est ailleurs : le message nomme un fichier de test comme cause d'un contrat périmé. C'est faux, et c'est exactement le genre d'affirmation qui apprend à ne plus lire les messages. Un contrôle qui crie au loup sur un cas impossible perd son crédit pour le cas réel — lequel est excellent par ailleurs (le ticket #33 l'a introduit pour de bonnes raisons, et il nous a déjà servi).
Aucun contournement posé de notre côté : on rejoue
build.Ce que je proposerais
Par ordre de préférence :
apps/mcpchez nous a une arborescence différente d'apps/api.test,tests,__tests__,e2eet.superpowersàIGNORES. Plus simple, mais ce n'est qu'une liste de plus à tenir : le prochain dossier non compilé repassera par la même case..test.ts/.spec.tsoù qu'ils soient. Cela couvre le cas d'un test posé à côté de son module danssrc/, que ni (1) ni (2) n'attrapent —include: ["src"]les compile, alors quetsconfig.builddu gabarit ne les exclut pas explicitement.Versions
@eqs/cli: 0.8.1eqs --version: 0.8.1packageManager:pnpm@11.8.0, Node v24.15.0, Windows 11 Pro 26200Trouvé en développant le premier satellite réel (Pilotage), relevé par une relecture puis reproduit à l'identique.
Vrai, reproduit à l'identique sur le gabarit, corrigé — et en cherchant la classe ailleurs, j'ai trouvé la même faute dans l'autre sens, en pire.
Reproduction
Il a fallu construire d'abord : le
dist/du gabarit était déjà en retard, donc le premier essai accusait une source réelle. Une foisapps/apiconstruit :Exactement votre trace.
La correction : votre option 1
Le périmètre est lu dans le tsconfig que le script
buildde l'application nomme —tsc -p <fichier>, ou--project— avec repli surtsconfig.build.jsonpuistsconfig.json. On ne devine pas : comme vous le dites,apps/mcpchez vous n'a pas l'arborescence d'apps/api, et c'est le script qui dit la vérité.includeetexcludesont convertis en expressions régulières selon les règles de TypeScript :*ne traverse pas les séparateurs,?vaut un caractère,**/descend, et un motif sans extension ni joker —"src"— désigne le dossier.Quand le tsconfig est illisible, on retombe sur « tout le dossier ». Ça sur-signale, mais ça ne rate jamais un
disten retard : entre les deux erreurs possibles, c'est celle-là qu'on veut.Vérifié sur votre gabarit, les deux sens :
touch apps/api/test/ping.test.tstouch apps/api/src/ping/ping.controller.tsSur votre option 3
Je ne l'ai pas prise, et voici pourquoi — dites-moi si vous n'êtes pas d'accord.
Un
.test.tsposé danssrc/est réellement compilé parinclude: ["src"]: il atterrit dansdist/, doncdist/est vraiment en retard, et le contrôle a raison de le dire. L'exclure d'office ferait mentir le contrôle dans l'autre sens.Le bon endroit pour trancher est le
tsconfig.build.jsondu satellite : s'il ne veut pas de ses tests dansdist/, il les exclut là — et le contrôle suivra tout seul, sans rien savoir de la convention. L'option 1 subsume donc l'option 3, à condition que le tsconfig soit honnête. C'est un endroit de plus où la vérité est écrite une fois.La chasse : la même faute, muette
J'ai regardé les autres comparaisons de dates du socle.
cli.baseline-presentedatait le code ainsi :Un satellite range son code dans
apps/*/srcet n'a pas desrc/à la racine. Vérifié sur le gabarit : la commande rend une sortie vide. DoncdernierCommitvalaitnull, et le contrôle sortait[].Une baseline périmée n'était signalée dans aucun satellite. Vert, en silence, sans même se déclarer non exécutable.
eqs openapi export(le vôtre)cli.baseline-presenteC'est la règle qui revient à chaque chasse : un faux positif se voit, un faux négatif non, et c'est le second qui coûte.
Corrigé : les dossiers de sources sont ceux qui existent (
src,apps,packages), et les deux impasses — aucun dossier reconnu, git muet — se déclarent non exécutables au lieu de rendre[]. Un contrôle qui ne peut pas s'exécuter le dit ; c'est écrit dansdocs/conformite.mdet ce n'était pas respecté ici.Ce qui est ancré
Sept cas ajoutés, chacun dans les deux sens :
apps/*/srcavec une baseline de l'an 2000 → rougit ;[].Le premier de ces cas a demandé de poser explicitement la date de
dist/après celle des sources dans la fixture : sans ça, tout est écrit dans la même seconde et le cas ne prouve rien. Une porte qui n'a jamais rougi ne garde rien.Ce que ça ne couvre pas
motifVersRegextraite*,?et**, c'est-à-dire l'essentiel desincluderéels. Les formes rares de TypeScript — extensions implicites, champfiles— ne sont pas gérées : on retombe alors sur le périmètre large, donc sur l'ancien comportement.pnpm client && git diff --exit-code), il n'est dans aucune porte, faute d'avoir tranché où il tourne — lepre-push, qui doit rester court, ou la CI, qui constate après le déploiement. C'est une décision qui vous revient, pas un oubli ; elle est écrite dansreference/chasses.mddepuis deux jours.État
Branche
chasse/knip-et-code-mortsureqs-platform. Ticket laissé ouvert jusqu'à la publication : chez vous, le refus ne cessera qu'à ce moment-là.Corrigé.
eqs openapi exportlit le tsconfig nommé par le scriptbuilddu dépôt au lieu d'en supposer un (packages/cli/src/outils.ts) : un fichier de test qui bouge ne fait plus dérailler l'export, puisquetest/n'est effectivement jamais compilé dansdist/. La classe est consignée dansreference/chasses.mdsous la chasse n°9, « un contrôle dont le périmètre n'est pas celui qu'il mesure ».Fermé après vérification contre le code de
devle 2026-09-21. Ce ticket restait ouvert faute d'unCloses #52dans le commit, pas faute de correctif.