@mostajs/mjs-unit 0.10.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/bin/cli.mjs +6 -0
- package/dist/qatrax.d.ts +80 -0
- package/dist/qatrax.d.ts.map +1 -0
- package/dist/qatrax.js +315 -0
- package/dist/qatrax.js.map +1 -0
- package/llms.txt +8 -0
- package/package.json +10 -3
package/README.md
CHANGED
|
@@ -148,6 +148,22 @@ qatrax.dev). Les lecteurs sont exportés : `import { lireRapportEssais, refDuPla
|
|
|
148
148
|
Ce que le sceau prouve : le rapport n'a pas changé **après sa lecture**, avec **cette** SBOM et **ce** plan. Il ne
|
|
149
149
|
prouve pas que l'outil du langage a joué les essais honnêtement.
|
|
150
150
|
|
|
151
|
+
## La boucle avec qatrax (0.11)
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
npx mjs-unit qatrax etat # « 2 nouveau(x), 1 changé(s) en recette » — rien d'autre si rien n'a bougé
|
|
155
|
+
npx mjs-unit qatrax rapatrier # la fiche des défauts et les captures, dans docs/recette/defauts/
|
|
156
|
+
npx mjs-unit qatrax pris <id> # puis réparer, écrire l'essai, npm test
|
|
157
|
+
npx mjs-unit qatrax corrige <id> # « corrigé dans <projet> <version> — à rejouer en recette »
|
|
158
|
+
npx mjs-unit qatrax pousser --si-vert # plan, run, SBOM — seulement si le dernier run est vert
|
|
159
|
+
npx mjs-unit qatrax pousser sources # (0.11.1) le code des essais : test-scripts/**/*.test.*, hors plan et sans code signalés
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Dans le `package.json` du projet : `"qatrax": { "projet": "speaking", "url": "https://speaking.qatrax.dev", "nom": "Speaking" }`.
|
|
163
|
+
La clé de CI (opération « pousser ») : `QATRAX_CLE_CI`, sinon `~/.config/qatrax/cle-ci-<projet>` en mode 600.
|
|
164
|
+
qatrax prévient de son côté (webhook signé, courriel) quand un rapport de recette arrive. En code :
|
|
165
|
+
`import { configQatrax, creerClientQatrax } from '@mostajs/mjs-unit/qatrax'`.
|
|
166
|
+
|
|
151
167
|
## API
|
|
152
168
|
|
|
153
169
|
| Fonction | Rôle |
|
package/bin/cli.mjs
CHANGED
|
@@ -21,12 +21,18 @@
|
|
|
21
21
|
* --depuis les arguments sont des RAPPORTS : mjs-unit --depuis target/surefire-reports/*.xml
|
|
22
22
|
* JUnit XML, NUnit 2/3, TRX, TestNG, Robot Framework, CTest, Cucumber JSON, Behave JSON,
|
|
23
23
|
* Allure 2, CTRF, TAP, JSON mjs-unit — reconnus à leur contenu
|
|
24
|
+
* 0.11.0 — LE CLIENT QATRAX : mjs-unit qatrax <etat|rapatrier|pris|corrige|pousser> (voir : mjs-unit qatrax aide)
|
|
24
25
|
* --depuis=chemin un dossier (tous ses .xml, .json, .tap, .trx ; dans allure-results, les *-container et
|
|
25
26
|
* *-attachment sont écartés) ou un fichier
|
|
26
27
|
* → les mêmes sorties : --compte-rendu, --ctrf, --intoto, --json, --junit, --report
|
|
27
28
|
*
|
|
28
29
|
* @author Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
|
|
29
30
|
*/
|
|
31
|
+
// 0.11.0 — `mjs-unit qatrax …` : le client qatrax, chargé SEULEMENT pour cette sous-commande (le runner reste sans réseau).
|
|
32
|
+
if (process.argv[2] === "qatrax") {
|
|
33
|
+
const { principal } = await import("../dist/qatrax.js");
|
|
34
|
+
process.exit(await principal(process.argv.slice(3)));
|
|
35
|
+
}
|
|
30
36
|
import { register } from "node:module";
|
|
31
37
|
import { pathToFileURL } from "node:url";
|
|
32
38
|
import { writeFileSync, readFileSync, mkdirSync, statSync, readdirSync } from "node:fs";
|
package/dist/qatrax.d.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/** La configuration résolue d'un projet. */
|
|
2
|
+
export interface ConfigQatrax {
|
|
3
|
+
racine: string;
|
|
4
|
+
projet: string;
|
|
5
|
+
nom: string;
|
|
6
|
+
url: string;
|
|
7
|
+
version: string;
|
|
8
|
+
plan: string;
|
|
9
|
+
run: string;
|
|
10
|
+
sbom: string;
|
|
11
|
+
defauts: string;
|
|
12
|
+
curseur: string;
|
|
13
|
+
sources: string;
|
|
14
|
+
cle: string;
|
|
15
|
+
avertissements: string[];
|
|
16
|
+
}
|
|
17
|
+
/** Un défaut tel que qatrax le rend (GET /recette/defauts). */
|
|
18
|
+
export interface DefautRecette {
|
|
19
|
+
id: string;
|
|
20
|
+
ref: string;
|
|
21
|
+
gravite: string;
|
|
22
|
+
etat: string;
|
|
23
|
+
titre: string;
|
|
24
|
+
campagnes: string[];
|
|
25
|
+
exigence?: string;
|
|
26
|
+
faire?: string;
|
|
27
|
+
attendu?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
pieces: Array<{
|
|
30
|
+
id: string;
|
|
31
|
+
nom: string;
|
|
32
|
+
sha256: string;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
/** Une erreur qui porte son code de sortie : 1 refus ou fichier absent, 2 usage ou configuration. */
|
|
36
|
+
export declare class ErreurQatrax extends Error {
|
|
37
|
+
code: 1 | 2;
|
|
38
|
+
constructor(message: string, code?: 1 | 2);
|
|
39
|
+
}
|
|
40
|
+
/** Un nom de fichier sûr : ni chemin, ni caractère exotique (comme defauts-recette.sh). */
|
|
41
|
+
export declare const nomSur: (s: unknown) => string;
|
|
42
|
+
/**
|
|
43
|
+
* Lit la configuration : le bloc « qatrax » du package.json du projet, l'environnement par-dessus (QATRAX_URL), la clé
|
|
44
|
+
* de CI dans QATRAX_CLE_CI, sinon ~/.config/qatrax/cle-ci-<projet> (avertissement si le fichier n'est pas en 600).
|
|
45
|
+
*/
|
|
46
|
+
export declare function configQatrax({ racine, env }?: {
|
|
47
|
+
racine?: string;
|
|
48
|
+
env?: Record<string, string | undefined>;
|
|
49
|
+
}): ConfigQatrax;
|
|
50
|
+
/** Le client d'un projet. Chaque méthode rend des lignes à afficher, ou lève une ErreurQatrax. */
|
|
51
|
+
export declare function creerClientQatrax(c: ConfigQatrax): {
|
|
52
|
+
config: ConfigQatrax;
|
|
53
|
+
/** Le nouveau depuis le dernier passage. Le curseur (identifiant → état et campagnes) est réécrit à chaque fois. */
|
|
54
|
+
etat({ bref }?: {
|
|
55
|
+
bref?: boolean | undefined;
|
|
56
|
+
}): Promise<string[]>;
|
|
57
|
+
/** La fiche des défauts (et, avec tous, l'historique) et leurs pièces, sous c.defauts. */
|
|
58
|
+
rapatrier({ tous }?: {
|
|
59
|
+
tous?: boolean | undefined;
|
|
60
|
+
}): Promise<string[]>;
|
|
61
|
+
/** « pris » (en_cours) ou « corrige » (version : « <projet> <version du package.json> » par défaut). */
|
|
62
|
+
poserEtat(id: string, etat: "en_cours" | "corrige", { version, note }?: {
|
|
63
|
+
version?: string | undefined;
|
|
64
|
+
note?: string | undefined;
|
|
65
|
+
}): Promise<string[]>;
|
|
66
|
+
/**
|
|
67
|
+
* Plan, run, SBOM, dans cet ordre, puis — seulement si on le demande — les sources des essais. Un run absent n'est
|
|
68
|
+
* jamais un succès ; siVert refuse un run qui a des échecs ; un dossier d'essais absent ou vide non plus.
|
|
69
|
+
*/
|
|
70
|
+
pousser({ niveaux, siVert }?: {
|
|
71
|
+
niveaux?: string[];
|
|
72
|
+
siVert?: boolean;
|
|
73
|
+
}): Promise<string[]>;
|
|
74
|
+
};
|
|
75
|
+
/** La sous-commande du CLI : `mjs-unit qatrax <commande> [arguments]`. Rend le code de sortie. */
|
|
76
|
+
export declare function principal(args: string[], { racine, ecrire }?: {
|
|
77
|
+
racine?: string | undefined;
|
|
78
|
+
ecrire?: ((s: string) => void) | undefined;
|
|
79
|
+
}): Promise<number>;
|
|
80
|
+
//# sourceMappingURL=qatrax.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qatrax.d.ts","sourceRoot":"","sources":["../src/qatrax.ts"],"names":[],"mappings":"AAuBA,4CAA4C;AAC5C,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAC1E,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAC3F,GAAG,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAC;CACvC;AACD,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAC3F,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC1E,MAAM,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5D;AACD,qGAAqG;AACrG,qBAAa,YAAa,SAAQ,KAAK;IACD,IAAI,EAAE,CAAC,GAAG,CAAC;gBAAnC,OAAO,EAAE,MAAM,EAAS,IAAI,GAAE,CAAC,GAAG,CAAK;CACpD;AAeD,2FAA2F;AAC3F,eAAO,MAAM,MAAM,GAAI,GAAG,OAAO,WAA6E,CAAC;AAE/G;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAAE,MAAsB,EAAE,GAAiB,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;CAAO,GAAG,YAAY,CA0B5J;AAOD,kGAAkG;AAClG,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,YAAY;;IA4B7C,oHAAoH;;;QACjF,OAAO,CAAC,MAAM,EAAE,CAAC;IA2BpD,0FAA0F;;;QAClD,OAAO,CAAC,MAAM,EAAE,CAAC;IAyCzD,wGAAwG;kBACpF,MAAM,QAAQ,UAAU,GAAG,SAAS;;;QAAqC,OAAO,CAAC,MAAM,EAAE,CAAC;IAQ9G;;;OAGG;kCACkE;QAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,GAAQ,OAAO,CAAC,MAAM,EAAE,CAAC;EA6CzI;AAED,kGAAkG;AAClG,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAsB,EAAE,MAAsC,EAAE;;kBAA3B,MAAM;CAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,CA+BxI"}
|
package/dist/qatrax.js
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @mostajs/mjs-unit/qatrax — LE CLIENT QATRAX (0.11.1) : la boucle tests → qatrax → recette → défauts → poste.
|
|
3
|
+
*
|
|
4
|
+
* etat le nouveau depuis le dernier passage (curseur local) : défauts nouveaux, rouverts, corrigés, clos
|
|
5
|
+
* rapatrier la fiche des défauts de recette et leurs pièces (empreintes vérifiées)
|
|
6
|
+
* pris « je le prends » : le défaut passe « en cours » chez qatrax
|
|
7
|
+
* corrige « corrigé dans <version> — à rejouer en recette » (la recette suivante le clôt, ou le rouvre)
|
|
8
|
+
* pousser plan Dev+Test, run, SBOM — dans cet ordre (DEVRULES-QA §4, §5.bis, §4.ter) ; et, sur demande, les
|
|
9
|
+
* sources des essais (0.11.1 : ce qui montre qu'un essai vert vérifie encore quelque chose)
|
|
10
|
+
*
|
|
11
|
+
* Remplace les scripts recopiés de projet en projet (push-qatrax-*-prod.sh, outils/pousser-devtest.sh,
|
|
12
|
+
* outils/defauts-recette.sh : docs/13-AUDIT-EXISTANT-CLIENT-QATRAX-27102026.md). Le CŒUR de mjs-unit n'importe pas
|
|
13
|
+
* ce fichier : il reste sans réseau ni secret. La clé de CI ne passe jamais en argument d'un processus, et n'est
|
|
14
|
+
* jamais écrite dans une sortie.
|
|
15
|
+
*
|
|
16
|
+
* @author Dr Hamid MADANI <drmdh@msn.com>
|
|
17
|
+
* @license AGPL-3.0-or-later
|
|
18
|
+
*/
|
|
19
|
+
import { createHash } from "node:crypto";
|
|
20
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
21
|
+
import { homedir } from "node:os";
|
|
22
|
+
import { join, relative, resolve, sep } from "node:path";
|
|
23
|
+
/** Une erreur qui porte son code de sortie : 1 refus ou fichier absent, 2 usage ou configuration. */
|
|
24
|
+
export class ErreurQatrax extends Error {
|
|
25
|
+
constructor(message, code = 1) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.code = code;
|
|
28
|
+
this.name = "ErreurQatrax";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const lireJson = (f) => JSON.parse(readFileSync(f, "utf8"));
|
|
32
|
+
const sha256 = (b) => createHash("sha256").update(b).digest("hex");
|
|
33
|
+
/** Les fichiers d'essai sous un dossier, sans node_modules ni sorties de run (.out) : comme push-sources-prod.sh. */
|
|
34
|
+
function fichiersEssai(dossier, acc = []) {
|
|
35
|
+
for (const e of readdirSync(dossier).sort()) {
|
|
36
|
+
if (e === "node_modules" || e === ".out")
|
|
37
|
+
continue;
|
|
38
|
+
const p = join(dossier, e);
|
|
39
|
+
if (statSync(p).isDirectory())
|
|
40
|
+
fichiersEssai(p, acc);
|
|
41
|
+
else if (/\.test\.(mjs|js|cjs|ts)$/.test(e))
|
|
42
|
+
acc.push(p);
|
|
43
|
+
}
|
|
44
|
+
return acc;
|
|
45
|
+
}
|
|
46
|
+
/** Un nom de fichier sûr : ni chemin, ni caractère exotique (comme defauts-recette.sh). */
|
|
47
|
+
export const nomSur = (s) => String(s ?? "").replace(/[^A-Za-z0-9._-]/g, "_").slice(0, 80) || "piece";
|
|
48
|
+
/**
|
|
49
|
+
* Lit la configuration : le bloc « qatrax » du package.json du projet, l'environnement par-dessus (QATRAX_URL), la clé
|
|
50
|
+
* de CI dans QATRAX_CLE_CI, sinon ~/.config/qatrax/cle-ci-<projet> (avertissement si le fichier n'est pas en 600).
|
|
51
|
+
*/
|
|
52
|
+
export function configQatrax({ racine = process.cwd(), env = process.env } = {}) {
|
|
53
|
+
const r = resolve(racine);
|
|
54
|
+
const fpkg = join(r, "package.json");
|
|
55
|
+
if (!existsSync(fpkg))
|
|
56
|
+
throw new ErreurQatrax(`package.json introuvable dans ${r}`, 2);
|
|
57
|
+
const pkg = lireJson(fpkg);
|
|
58
|
+
const q = pkg.qatrax ?? {};
|
|
59
|
+
const projet = String(q.projet ?? "").trim();
|
|
60
|
+
if (!projet)
|
|
61
|
+
throw new ErreurQatrax('bloc « qatrax » absent du package.json : { "qatrax": { "projet": "…", "url": "https://….qatrax.dev" } }', 2);
|
|
62
|
+
const url = String(env.QATRAX_URL || q.url || "").replace(/\/+$/, "");
|
|
63
|
+
if (!/^https?:\/\//.test(url))
|
|
64
|
+
throw new ErreurQatrax(`adresse de qatrax absente ou invalide (qatrax.url ou QATRAX_URL) : « ${url} »`, 2);
|
|
65
|
+
const avertissements = [];
|
|
66
|
+
let cle = String(env.QATRAX_CLE_CI ?? "").trim();
|
|
67
|
+
const fcle = join(env.HOME || homedir(), ".config", "qatrax", `cle-ci-${projet}`);
|
|
68
|
+
if (!cle && existsSync(fcle)) {
|
|
69
|
+
cle = readFileSync(fcle, "utf8").replace(/\s+/g, "");
|
|
70
|
+
const mode = statSync(fcle).mode & 0o777;
|
|
71
|
+
if (mode & 0o077)
|
|
72
|
+
avertissements.push(`⚠ ${fcle} est lisible par d'autres (mode ${mode.toString(8)}) : chmod 600`);
|
|
73
|
+
}
|
|
74
|
+
if (!cle)
|
|
75
|
+
throw new ErreurQatrax(`clé de CI absente : QATRAX_CLE_CI ou ${fcle} (écran « Projets » de ${url}, opération « pousser »)`, 2);
|
|
76
|
+
const chemin = (v, defaut) => resolve(r, String(v || defaut));
|
|
77
|
+
return {
|
|
78
|
+
racine: r, projet, nom: String(q.nom || projet), url, version: String(pkg.version ?? "0.0.0"),
|
|
79
|
+
plan: chemin(q.plan, `docs/DEVTEST-PLAN.${projet}.json`), run: chemin(q.run, "test-scripts/.out/report.json"),
|
|
80
|
+
sbom: chemin(q.sbom, "sbom.cyclonedx.json"), defauts: chemin(q.defauts, "docs/recette/defauts"),
|
|
81
|
+
curseur: chemin(q.curseur, "test-scripts/.out/qatrax-etat.json"), sources: chemin(q.sources, "test-scripts"), cle, avertissements,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const ETATS = { open: "ouvert", in_progress: "en cours", resolved: "corrigé, à rejouer", closed: "clos (confirmé en recette)", rejected: "rejeté" };
|
|
85
|
+
const GRAVITES = { critical: "bloquant", high: "panne", medium: "écart", low: "mineur" };
|
|
86
|
+
const etatLisible = (e) => ETATS[e] ?? e;
|
|
87
|
+
const graviteLisible = (g) => GRAVITES[g] ?? g;
|
|
88
|
+
/** Le client d'un projet. Chaque méthode rend des lignes à afficher, ou lève une ErreurQatrax. */
|
|
89
|
+
export function creerClientQatrax(c) {
|
|
90
|
+
const entetes = (json = false) => ({ authorization: `Bearer ${c.cle}`, accept: "application/json", ...(json ? { "content-type": "application/json" } : {}) });
|
|
91
|
+
/** Le message d'erreur du serveur, et ses erreurs de validation (jamais la clé : elle n'est pas dans la réponse). */
|
|
92
|
+
async function erreurDe(r, quoi) {
|
|
93
|
+
const texte = await r.text();
|
|
94
|
+
let detail = texte.slice(0, 300);
|
|
95
|
+
try {
|
|
96
|
+
const j = JSON.parse(texte);
|
|
97
|
+
detail = [j.error ?? j.message ?? "", ...(Array.isArray(j.errors) ? j.errors.map((e) => ` ${e.path ?? ""} : ${e.message ?? e}`) : [])].filter(Boolean).join("\n");
|
|
98
|
+
}
|
|
99
|
+
catch { /* corps non JSON : ses premiers caractères */ }
|
|
100
|
+
return new ErreurQatrax(`✗ HTTP ${r.status} — ${quoi} : ${detail}`);
|
|
101
|
+
}
|
|
102
|
+
async function appel(methode, chemin, corps) {
|
|
103
|
+
try {
|
|
104
|
+
return await fetch(`${c.url}${chemin}`, { method: methode, headers: entetes(corps !== undefined), body: corps, signal: AbortSignal.timeout(60000) });
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
throw new ErreurQatrax(`✗ ${c.url} injoignable (${e?.cause?.code ?? e?.name ?? "réseau"})`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
async function lireDefauts(tous = false) {
|
|
111
|
+
const r = await appel("GET", `/recette/defauts?p=${encodeURIComponent(c.projet)}${tous ? "&etat=tous" : ""}`);
|
|
112
|
+
if (!r.ok)
|
|
113
|
+
throw await erreurDe(r, `${c.url}/recette/defauts`);
|
|
114
|
+
return (await r.json()).defauts ?? [];
|
|
115
|
+
}
|
|
116
|
+
return {
|
|
117
|
+
config: c,
|
|
118
|
+
/** Le nouveau depuis le dernier passage. Le curseur (identifiant → état et campagnes) est réécrit à chaque fois. */
|
|
119
|
+
async etat({ bref = false } = {}) {
|
|
120
|
+
const ds = await lireDefauts(true);
|
|
121
|
+
const avant = existsSync(c.curseur) ? lireJson(c.curseur).defauts ?? {} : {};
|
|
122
|
+
const nouveaux = [];
|
|
123
|
+
const changes = [];
|
|
124
|
+
for (const d of ds) {
|
|
125
|
+
const a = avant[d.id];
|
|
126
|
+
if (!a) {
|
|
127
|
+
if (d.etat !== "closed")
|
|
128
|
+
nouveaux.push(d);
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (a.etat !== d.etat)
|
|
132
|
+
changes.push([d, a.etat === "resolved" && d.etat === "open" ? "rouvert en recette" : `${etatLisible(a.etat)} → ${etatLisible(d.etat)}`]);
|
|
133
|
+
else if ((d.campagnes ?? []).length > (a.campagnes ?? []).length)
|
|
134
|
+
changes.push([d, `relevé de nouveau (campagne ${d.campagnes[d.campagnes.length - 1]})`]);
|
|
135
|
+
}
|
|
136
|
+
mkdirSync(join(c.curseur, ".."), { recursive: true });
|
|
137
|
+
writeFileSync(c.curseur, `${JSON.stringify({ projet: c.projet, vuLe: new Date().toISOString(), defauts: Object.fromEntries(ds.map((d) => [d.id, { etat: d.etat, campagnes: d.campagnes ?? [] }])) }, null, 1)}\n`);
|
|
138
|
+
const ouverts = ds.filter((d) => d.etat === "open" || d.etat === "in_progress").length;
|
|
139
|
+
if (bref) {
|
|
140
|
+
return [!nouveaux.length && !changes.length
|
|
141
|
+
? `qatrax ${c.projet} : rien de nouveau en recette (${ouverts} ouvert(s))`
|
|
142
|
+
: `qatrax ${c.projet} : ${nouveaux.length} nouveau(x), ${changes.length} changé(s) en recette — mjs-unit qatrax rapatrier`];
|
|
143
|
+
}
|
|
144
|
+
if (!nouveaux.length && !changes.length)
|
|
145
|
+
return [`✓ ${c.nom} (${c.url}) : aucun changement en recette depuis le dernier passage — ${ouverts} défaut(s) ouvert(s)`];
|
|
146
|
+
return [
|
|
147
|
+
`${c.nom} (${c.url}) : ${nouveaux.length} nouveau(x), ${changes.length} changé(s)`,
|
|
148
|
+
...nouveaux.map((d) => ` + ${d.ref.padEnd(8)} ${graviteLisible(d.gravite).padEnd(9)} ${d.titre.slice(0, 80)}`),
|
|
149
|
+
...changes.map(([d, quoi]) => ` ~ ${d.ref.padEnd(8)} ${quoi} — ${d.titre.slice(0, 60)}`),
|
|
150
|
+
" → mjs-unit qatrax rapatrier",
|
|
151
|
+
];
|
|
152
|
+
},
|
|
153
|
+
/** La fiche des défauts (et, avec tous, l'historique) et leurs pièces, sous c.defauts. */
|
|
154
|
+
async rapatrier({ tous = false } = {}) {
|
|
155
|
+
const ds = await lireDefauts(tous);
|
|
156
|
+
const lignes = [];
|
|
157
|
+
mkdirSync(c.defauts, { recursive: true });
|
|
158
|
+
for (const d of ds)
|
|
159
|
+
for (const p of d.pieces ?? []) {
|
|
160
|
+
const dossier = join(c.defauts, nomSur(d.ref));
|
|
161
|
+
mkdirSync(dossier, { recursive: true });
|
|
162
|
+
const r = await appel("GET", `/recette/defauts/piece?p=${encodeURIComponent(c.projet)}&id=${encodeURIComponent(p.id)}`);
|
|
163
|
+
if (!r.ok) {
|
|
164
|
+
lignes.push(` ⚠ pièce ${p.nom} (HTTP ${r.status})`);
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const octets = Buffer.from(await r.arrayBuffer());
|
|
168
|
+
writeFileSync(join(dossier, nomSur(p.nom)), octets);
|
|
169
|
+
if (sha256(octets) !== p.sha256)
|
|
170
|
+
lignes.push(` ⚠ pièce ${p.nom} : empreinte différente de celle signée par ValiTrax`);
|
|
171
|
+
}
|
|
172
|
+
const plan = existsSync(c.plan) ? lireJson(c.plan) : { specs: [], tests: [] };
|
|
173
|
+
const specs = Object.fromEntries((plan.specs ?? []).map((s) => [s.ref, s.title]));
|
|
174
|
+
const essais = Object.fromEntries((plan.tests ?? []).map((t) => [t.ref, t]));
|
|
175
|
+
const L = [`# Défauts relevés en recette — ${c.nom}`, "",
|
|
176
|
+
"**Auteur** : Dr Hamid MADANI <drmdh@msn.com> ",
|
|
177
|
+
`**Source** : ${c.url}/recette/defauts?p=${c.projet} — rapatrié le ${new Date().toLocaleString("fr-FR", { dateStyle: "short", timeStyle: "short" })} `,
|
|
178
|
+
"**Boucle** : qatrax (spec→dev→test) → ValiTrax (recette→défaut) → qatrax → poste du développeur → recette suivante", "",
|
|
179
|
+
`${ds.length} défaut(s). Fiche ENGENDRÉE par \`mjs-unit qatrax rapatrier\` : ne pas la modifier à la main. Les pièces`,
|
|
180
|
+
"appartiennent à qatrax, qui en garde l'original pour la validation finale et le suivi des bugs : copie de travail.", "",
|
|
181
|
+
"Pour chaque défaut : `mjs-unit qatrax pris <id>` en commençant, réparer, ajouter ou ajuster l'essai qui le couvre,",
|
|
182
|
+
"livrer, puis `mjs-unit qatrax corrige <id> [version]`. La recette suivante le clôt (ligne rejouée ok) ou le rouvre (ko).", "",
|
|
183
|
+
"| réf. | gravité | état | campagnes | titre |", "|---|---|---|---|---|",
|
|
184
|
+
...ds.map((d) => `| [${d.ref}](#${nomSur(d.ref).toLowerCase()}) | ${graviteLisible(d.gravite)} | ${etatLisible(d.etat)} | ${(d.campagnes ?? []).join(", ")} | ${d.titre.replace(/\|/g, "/")} |`)];
|
|
185
|
+
for (const d of ds) {
|
|
186
|
+
const e = essais[d.ref];
|
|
187
|
+
L.push("", `## ${d.ref}`, "", `- **id** : \`${d.id}\``, `- **état** : ${etatLisible(d.etat)} · **gravité** : ${graviteLisible(d.gravite)} · **campagnes** : ${(d.campagnes ?? []).join(", ") || "—"}`, `- **exigence** : ${d.exigence || "—"}${d.exigence && specs[d.exigence] ? ` — ${specs[d.exigence]}` : ""}`, `- **essai du plan** : ${d.ref}${e ? ` — ${e.title ?? ""}` : " (absent du plan Dev+Test)"}`, `- **à faire** : ${d.faire || "—"}`, `- **attendu** : ${d.attendu || "—"}`);
|
|
188
|
+
if (d.pieces?.length)
|
|
189
|
+
L.push(`- **pièces** : ${d.pieces.map((p) => `[${p.nom}](${nomSur(d.ref)}/${nomSur(p.nom)})`).join(", ")}`);
|
|
190
|
+
L.push("", "```text", String(d.description ?? "").trim(), "```", "", `\`mjs-unit qatrax pris ${d.id}\` · \`mjs-unit qatrax corrige ${d.id}\``);
|
|
191
|
+
}
|
|
192
|
+
const fiche = join(c.defauts, "DEFAUTS-RECETTE.md");
|
|
193
|
+
writeFileSync(fiche, `${L.join("\n")}\n`);
|
|
194
|
+
return [`✓ ${ds.length} défaut(s) — ${fiche}`, ...lignes,
|
|
195
|
+
...ds.map((d) => ` ${d.ref.padEnd(8)} ${graviteLisible(d.gravite).padEnd(9)} ${etatLisible(d.etat).padEnd(22)} ${d.id} ${d.titre.slice(0, 70)}`)];
|
|
196
|
+
},
|
|
197
|
+
/** « pris » (en_cours) ou « corrige » (version : « <projet> <version du package.json> » par défaut). */
|
|
198
|
+
async poserEtat(id, etat, { version = "", note = "" } = {}) {
|
|
199
|
+
if (!id)
|
|
200
|
+
throw new ErreurQatrax(`usage : mjs-unit qatrax ${etat === "corrige" ? "corrige <id> [version] [note]" : "pris <id> [note]"}`, 2);
|
|
201
|
+
const v = etat === "corrige" ? (version || `${c.projet} ${c.version}`) : "";
|
|
202
|
+
const r = await appel("POST", `/recette/defauts/etat?p=${encodeURIComponent(c.projet)}`, JSON.stringify({ id, etat, version: v, note }));
|
|
203
|
+
if (!r.ok)
|
|
204
|
+
throw await erreurDe(r, "état du défaut");
|
|
205
|
+
return [etat === "corrige" ? `✓ ${id} : corrigé dans ${v} — à rejouer en recette` : `✓ ${id} : en cours`];
|
|
206
|
+
},
|
|
207
|
+
/**
|
|
208
|
+
* Plan, run, SBOM, dans cet ordre, puis — seulement si on le demande — les sources des essais. Un run absent n'est
|
|
209
|
+
* jamais un succès ; siVert refuse un run qui a des échecs ; un dossier d'essais absent ou vide non plus.
|
|
210
|
+
*/
|
|
211
|
+
async pousser({ niveaux = ["plan", "run", "sbom"], siVert = false } = {}) {
|
|
212
|
+
const inconnus = niveaux.filter((n) => !["plan", "run", "sbom", "sources"].includes(n));
|
|
213
|
+
if (inconnus.length)
|
|
214
|
+
throw new ErreurQatrax(`niveau inconnu : ${inconnus.join(", ")} (attendus : plan, run, sbom, sources)`, 2);
|
|
215
|
+
const a = (n) => niveaux.includes(n);
|
|
216
|
+
if (a("plan") && !existsSync(c.plan))
|
|
217
|
+
throw new ErreurQatrax(`✗ plan absent : ${c.plan}`);
|
|
218
|
+
if ((a("run") || siVert) && !existsSync(c.run))
|
|
219
|
+
throw new ErreurQatrax(`✗ aucun rapport d'exécution (${c.run}) : lancer d'abord npm test`);
|
|
220
|
+
if (a("sbom") && !existsSync(c.sbom))
|
|
221
|
+
throw new ErreurQatrax(`✗ SBOM absente (${c.sbom}) : npx -y -p @mostajs/mjs-sbom mjs-sbom --version=${c.version}`);
|
|
222
|
+
let corpsSources = "";
|
|
223
|
+
if (a("sources")) {
|
|
224
|
+
if (!existsSync(c.sources) || !statSync(c.sources).isDirectory())
|
|
225
|
+
throw new ErreurQatrax(`✗ dossier des essais absent : ${c.sources} (qatrax.sources du package.json)`);
|
|
226
|
+
// Chemins relatifs à la racine du projet, comme les autoRef du plan ; jamais absolus (nom de la machine)
|
|
227
|
+
const files = fichiersEssai(c.sources).map((f) => ({ path: relative(c.racine, f).split(sep).join("/"), content: readFileSync(f, "utf8") }));
|
|
228
|
+
if (!files.length)
|
|
229
|
+
throw new ErreurQatrax(`✗ aucun fichier d'essai (*.test.mjs|js|cjs|ts) sous ${c.sources}`);
|
|
230
|
+
corpsSources = JSON.stringify({ files });
|
|
231
|
+
}
|
|
232
|
+
if (siVert) {
|
|
233
|
+
const s = lireJson(c.run).summary ?? {};
|
|
234
|
+
if (Number(s.failed) > 0)
|
|
235
|
+
throw new ErreurQatrax(`✗ ${s.failed} échec(s) au dernier run : rien n'est poussé (--si-vert)`);
|
|
236
|
+
}
|
|
237
|
+
const envois = [];
|
|
238
|
+
if (a("plan"))
|
|
239
|
+
envois.push(["plan Dev+Test", "/import", c.plan]);
|
|
240
|
+
if (a("run"))
|
|
241
|
+
envois.push(["exécutions", `/runs?p=${encodeURIComponent(c.projet)}`, c.run]);
|
|
242
|
+
if (a("sbom"))
|
|
243
|
+
envois.push([`SBOM ${c.projet} ${c.version}`, `/sbom?p=${encodeURIComponent(c.projet)}&version=${encodeURIComponent(c.version)}`, c.sbom]);
|
|
244
|
+
if (a("sources"))
|
|
245
|
+
envois.push(["sources des essais", `/sources?p=${encodeURIComponent(c.projet)}`, ""]);
|
|
246
|
+
const lignes = [];
|
|
247
|
+
for (const [quoi, route, fichier] of envois) {
|
|
248
|
+
const r = await appel("POST", route, fichier ? readFileSync(fichier, "utf8") : corpsSources);
|
|
249
|
+
if (!r.ok)
|
|
250
|
+
throw new ErreurQatrax([...lignes, (await erreurDe(r, quoi)).message].join("\n"));
|
|
251
|
+
const j = await r.json().catch(() => ({}));
|
|
252
|
+
const resume = j.report?.counts ? ` — ${j.report.counts.pass ?? 0} ok, ${j.report.counts.fail ?? 0} échec(s)` : j.revision ? ` — révision ${j.revision}` : "";
|
|
253
|
+
if (route.startsWith("/sources")) {
|
|
254
|
+
const rep = j.report ?? {};
|
|
255
|
+
const im = rep.imported ?? [];
|
|
256
|
+
const n = (st) => im.filter((i) => i.status === st).length;
|
|
257
|
+
lignes.push(`✓ HTTP ${r.status} — ${quoi} (${c.url}/sources) — ${im.length} fichier(s) : ${n("created")} nouveau(x), ${n("updated")} mis à jour, ${n("unchanged")} inchangé(s)`);
|
|
258
|
+
// Les deux écarts sont AFFICHÉS, jamais tus : un import muet laisse croire que la preuve est complète
|
|
259
|
+
const horsPlan = rep.unplanned ?? [];
|
|
260
|
+
const sansCode = rep.missingSource ?? [];
|
|
261
|
+
if (horsPlan.length)
|
|
262
|
+
lignes.push(` ⚠ ${horsPlan.length} essai(s) HORS PLAN : ${horsPlan.map((u) => u.ref).join(", ")}`);
|
|
263
|
+
if (sansCode.length)
|
|
264
|
+
lignes.push(` ⚠ ${sansCode.length} cas du plan SANS CODE : ${sansCode.map((m) => m.autoRef).join(", ")}`);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
lignes.push(`✓ HTTP ${r.status} — ${quoi} (${c.url}${route.split("?")[0]})${resume}`);
|
|
268
|
+
}
|
|
269
|
+
return lignes;
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
/** La sous-commande du CLI : `mjs-unit qatrax <commande> [arguments]`. Rend le code de sortie. */
|
|
274
|
+
export async function principal(args, { racine = process.cwd(), ecrire = (s) => console.log(s) } = {}) {
|
|
275
|
+
const [cmd = "aide", ...reste] = args;
|
|
276
|
+
const options = reste.filter((x) => x.startsWith("--"));
|
|
277
|
+
const pos = reste.filter((x) => !x.startsWith("--"));
|
|
278
|
+
if (cmd === "aide" || cmd === "--help" || cmd === "-h") {
|
|
279
|
+
ecrire(["usage : mjs-unit qatrax <commande>",
|
|
280
|
+
" etat [--bref] le nouveau en recette depuis le dernier passage",
|
|
281
|
+
" rapatrier [--tous] fiche des défauts + pièces → docs/recette/defauts/",
|
|
282
|
+
" pris <id> [note] le défaut passe « en cours »",
|
|
283
|
+
" corrige <id> [version] [note] « corrigé dans <version> — à rejouer »",
|
|
284
|
+
" pousser [plan,run,sbom,sources] [--si-vert] plan, run, SBOM (dans cet ordre) ; sources : sur demande",
|
|
285
|
+
'configuration : package.json → "qatrax": { "projet", "url", "nom" } ; QATRAX_URL ; clé QATRAX_CLE_CI ou ~/.config/qatrax/cle-ci-<projet>'].join("\n"));
|
|
286
|
+
return 0;
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
const c = configQatrax({ racine });
|
|
290
|
+
for (const a of c.avertissements)
|
|
291
|
+
ecrire(a);
|
|
292
|
+
const client = creerClientQatrax(c);
|
|
293
|
+
let lignes;
|
|
294
|
+
if (cmd === "etat")
|
|
295
|
+
lignes = await client.etat({ bref: options.includes("--bref") });
|
|
296
|
+
else if (cmd === "rapatrier")
|
|
297
|
+
lignes = await client.rapatrier({ tous: options.includes("--tous") });
|
|
298
|
+
else if (cmd === "pris")
|
|
299
|
+
lignes = await client.poserEtat(pos[0] ?? "", "en_cours", { note: pos[1] ?? "" });
|
|
300
|
+
else if (cmd === "corrige")
|
|
301
|
+
lignes = await client.poserEtat(pos[0] ?? "", "corrige", { version: pos[1] ?? "", note: pos[2] ?? "" });
|
|
302
|
+
else if (cmd === "pousser")
|
|
303
|
+
lignes = await client.pousser({ niveaux: pos.length ? pos.join(",").split(",").filter(Boolean) : undefined, siVert: options.includes("--si-vert") });
|
|
304
|
+
else
|
|
305
|
+
throw new ErreurQatrax(`commande inconnue : ${cmd} (mjs-unit qatrax aide)`, 2);
|
|
306
|
+
for (const l of lignes)
|
|
307
|
+
ecrire(l);
|
|
308
|
+
return 0;
|
|
309
|
+
}
|
|
310
|
+
catch (e) {
|
|
311
|
+
ecrire(e instanceof ErreurQatrax ? e.message : `✗ ${e?.message ?? e}`);
|
|
312
|
+
return e instanceof ErreurQatrax ? e.code : 1;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=qatrax.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qatrax.js","sourceRoot":"","sources":["../src/qatrax.ts"],"names":[],"mappings":"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"}
|
package/llms.txt
CHANGED
|
@@ -111,6 +111,14 @@ node node_modules/@mostajs/mjs-unit/bin/cli.mjs test-scripts/*.test.mjs
|
|
|
111
111
|
sort en code 1 avec un message. Le compte s'imprime : « ✓ N/N test(s) exécutés sur F fichier(s) ».
|
|
112
112
|
- Le resolver n'agit que sur les specifiers RELATIFS sans extension ; les packages (bare) passent normalement.
|
|
113
113
|
|
|
114
|
+
## CLIENT QATRAX (0.11.0)
|
|
115
|
+
`mjs-unit qatrax etat [--bref] | rapatrier [--tous] | pris <id> [note] | corrige <id> [version] [note] | pousser [plan,run,sbom,sources] [--si-vert]` (sans niveau : plan, run, sbom ; sources sur demande, 0.11.1).
|
|
116
|
+
Config : package.json "qatrax": { projet, url, nom?, plan?, run?, sbom?, defauts?, curseur?, sources? (défaut test-scripts) } ; QATRAX_URL l'emporte ; clé QATRAX_CLE_CI
|
|
117
|
+
ou ~/.config/qatrax/cle-ci-<projet> (600). Codes : 0 ok, 1 refus/fichier absent, 2 usage/config. API : `@mostajs/mjs-unit/qatrax`
|
|
118
|
+
→ configQatrax({ racine, env }), creerClientQatrax(c) → { etat, rapatrier, poserEtat(id, 'en_cours'|'corrige', { version, note }), pousser({ niveaux, siVert }) }.
|
|
119
|
+
Routes qatrax : GET /recette/defauts?p=, GET /recette/defauts/piece?p=&id=, POST /recette/defauts/etat?p=, POST /import, /runs?p=, /sbom?p=&version=, /sources?p= (corps { files: [{ path, content }] }, chemins relatifs à la racine).
|
|
120
|
+
Le cœur (`.`) n'importe pas ce client.
|
|
121
|
+
|
|
114
122
|
## CONVENTION (écosystème)
|
|
115
123
|
Tout test ET son runner (`run-tests.sh`) sont versionnés dans `test-scripts/` ; `package.json` `scripts.test`
|
|
116
124
|
pointe sur le runner. Jamais de test jetable.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/mjs-unit",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Micro-framework de test pour l'écosystème @mostajs/* : zéro dépendance, API minimale (test/expect/run), runner CLI (preuves HTML/JSON/JUnit XML via --report/--json/--junit ; compte rendu de validation CRA lié à la SBOM, CTRF, in-toto test-result via --compte-rendu/--ctrf/--intoto ; mode lecteur --depuis : lit le rapport natif de Java, C#, Python, Go, C++… — JUnit XML, NUnit, TRX, TestNG, Robot Framework, CTest, Cucumber JSON, Behave JSON, Allure 2, CTRF, TAP — et en fait le même compte rendu ; lecteurs réutilisables ./lecteurs ; menu en shell mjs-unit-menu), notions JUnit (échec/erreur, classname, crochets, délai, étiquettes, tests paramétrés), reporters réutilisables (./report), et un resolver ESM qui exécute sous Node les dist à imports sans extension (convention moduleResolution=bundler).",
|
|
3
|
+
"version": "0.11.1",
|
|
4
|
+
"description": "Micro-framework de test pour l'écosystème @mostajs/* : zéro dépendance, API minimale (test/expect/run), runner CLI (preuves HTML/JSON/JUnit XML via --report/--json/--junit ; compte rendu de validation CRA lié à la SBOM, CTRF, in-toto test-result via --compte-rendu/--ctrf/--intoto ; mode lecteur --depuis : lit le rapport natif de Java, C#, Python, Go, C++… — JUnit XML, NUnit, TRX, TestNG, Robot Framework, CTest, Cucumber JSON, Behave JSON, Allure 2, CTRF, TAP — et en fait le même compte rendu ; lecteurs réutilisables ./lecteurs ; menu en shell mjs-unit-menu), notions JUnit (échec/erreur, classname, crochets, délai, étiquettes, tests paramétrés), reporters réutilisables (./report), et un resolver ESM qui exécute sous Node les dist à imports sans extension (convention moduleResolution=bundler). Depuis 0.11.0 : le client qatrax (mjs-unit qatrax etat|rapatrier|pris|corrige|pousser, @mostajs/mjs-unit/qatrax), hors du cœur.",
|
|
5
5
|
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
|
7
7
|
"type": "module",
|
|
@@ -32,6 +32,11 @@
|
|
|
32
32
|
"import": "./dist/lecteurs.js",
|
|
33
33
|
"default": "./dist/lecteurs.js"
|
|
34
34
|
},
|
|
35
|
+
"./qatrax": {
|
|
36
|
+
"types": "./dist/qatrax.d.ts",
|
|
37
|
+
"import": "./dist/qatrax.js",
|
|
38
|
+
"default": "./dist/qatrax.js"
|
|
39
|
+
},
|
|
35
40
|
"./register": {
|
|
36
41
|
"default": "./register.mjs"
|
|
37
42
|
},
|
|
@@ -72,7 +77,9 @@
|
|
|
72
77
|
"behave",
|
|
73
78
|
"allure",
|
|
74
79
|
"ctest",
|
|
75
|
-
"junit"
|
|
80
|
+
"junit",
|
|
81
|
+
"qatrax",
|
|
82
|
+
"recette"
|
|
76
83
|
],
|
|
77
84
|
"mostajs": {
|
|
78
85
|
"niveau": "N0",
|