@mostajs/mjs-unit 0.12.0 → 0.13.0
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 +52 -0
- package/bin/cli.mjs +6 -0
- package/dist/d4.d.ts +44 -0
- package/dist/d4.d.ts.map +1 -0
- package/dist/d4.js +225 -0
- package/dist/d4.js.map +1 -0
- package/llms.txt +53 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -197,6 +197,58 @@ test("T-CMP-1 — crée le compte", async () => { const c = await compte.obtenir
|
|
|
197
197
|
test("T-CMP-2 — une autorisation sur le compte existant", async () => { const c = await compte.obtenir(); /* … */ });
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
+
## Après la suite — D4Q et D4PF (0.13.0)
|
|
201
|
+
|
|
202
|
+
Deux commandes pour ce qui suit une version **intégrée** (suite S1P verte, `main` avancé) ; premier usage : Guerway
|
|
203
|
+
(04/11/2026). L'application décrit ses étapes dans **`d4.config.json`** ; mjs-unit les enchaîne avec les mêmes règles partout.
|
|
204
|
+
|
|
205
|
+
**L'ordre d'une version** : essais rouges → code → suite (`--jobs`, rapport JSON) → intégration S1P
|
|
206
|
+
(`mjs-unit empreinte --verifier`, fusion `--ff-only`) → **`mjs-unit d4q`** → **`mjs-unit d4pf` sur feu vert**.
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
npx mjs-unit d4q # la qualité : ne déploie RIEN (CAPTURES=0 saute une étape marquée « sauterSi »)
|
|
210
|
+
npx mjs-unit d4q ../worktrees/L2-1.4.0 # sur un autre dossier de l'application (un worktree)
|
|
211
|
+
npx mjs-unit d4pf --a-blanc # contrôles, puis les commandes qui seraient lancées ; rien n'est exécuté
|
|
212
|
+
npx mjs-unit d4pf # SEULEMENT sur feu vert explicite pour CETTE version
|
|
213
|
+
npx mjs-unit d4pfq # D4PF puis D4Q (D4Q seulement si D4PF réussit) — sur feu vert ; --a-blanc aussi
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### D4Q — « déploie pour la qualité »
|
|
217
|
+
|
|
218
|
+
Régénère et publie tout ce qui sert à juger la version, dans l'ordre déclaré (chez Guerway : cahier des écrans, feuilles
|
|
219
|
+
de recette par rôle, feuilles de formation, plan Dev+Test, avancement, chiffrage, `mjs-unit qatrax pousser plan,run`).
|
|
220
|
+
|
|
221
|
+
- `exige` : les fichiers sans lesquels D4Q refuse (le rapport de la DERNIÈRE suite : `test-scripts/.out/report.json`) ;
|
|
222
|
+
- chaque étape s'arrête au premier échec, sauf si sa sortie contient son motif `reporterSi` (un quota de service de PDF) :
|
|
223
|
+
elle est alors « reportée » et la suite continue ; `sauterSi: "VAR=valeur"` la saute ;
|
|
224
|
+
- `dossier` : `app` (défaut) ou `racine` (le dossier de `d4.config.json`) ; `lignes` : les dernières lignes montrées.
|
|
225
|
+
|
|
226
|
+
### D4PF — « déploie pour prod et formation »
|
|
227
|
+
|
|
228
|
+
1. contrôles : la branche (`main`), aucun fichier suivi modifié hors `ignorer` (expressions sur `git status --porcelain`) ;
|
|
229
|
+
2. `sauvegardes` : chaque commande écrit sa copie dans `fichier` ; vide ou sans `entete` (ex. `PGDMP`) → arrêt AVANT
|
|
230
|
+
tout déploiement ;
|
|
231
|
+
3. et 4. `deploiements`, dans l'ordre (production, puis formation) ;
|
|
232
|
+
5. `sante` : chaque commande rend le JSON de `/health` ; `ok`, `version` du package.json ET `commit` de `main` exigés ;
|
|
233
|
+
6. `journaux` : les dernières erreurs, pour lecture (des lignes anciennes ne sont pas une erreur de la version).
|
|
234
|
+
|
|
235
|
+
Règles : aucune valeur du `.env` affichée ; ne pas figer la liste des processus du serveur (pas de `pm2 save`) ; le
|
|
236
|
+
`push` et la publication npm restent hors de D4PF. Jetons des commandes : `{racine}`, `{app}`, `{version}`, `{commit}`, `{date}`.
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"app": "mon-api",
|
|
241
|
+
"d4q": { "exige": ["test-scripts/.out/report.json"], "etapes": [
|
|
242
|
+
{ "titre": "feuilles de recette", "commande": "node outils/feuillets.mjs", "reporterSi": "QUOTA_EXCEEDED" },
|
|
243
|
+
{ "titre": "qatrax", "commande": "npx mjs-unit qatrax pousser plan,run" } ] },
|
|
244
|
+
"d4pf": { "branche": "main", "ignorer": [" \\.env\\.example$"],
|
|
245
|
+
"sauvegardes": [{ "nom": "production", "commande": "ssh serveur 'pg_dump -Fc \"$BASE\"'", "fichier": "sauvegardes/avant-{version}-{date}.dump", "entete": "PGDMP" }],
|
|
246
|
+
"deploiements": [{ "nom": "production", "commande": "bash deploy.sh ./prod.conf" }, { "nom": "formation", "commande": "bash deploy.sh ./formation.conf" }],
|
|
247
|
+
"sante": [{ "nom": "production", "commande": "ssh serveur 'curl -s http://127.0.0.1:5400/health'" }],
|
|
248
|
+
"journaux": "ssh serveur 'tail -n 5 logs/err.log'" }
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
200
252
|
## API
|
|
201
253
|
|
|
202
254
|
| Fonction | Rôle |
|
package/bin/cli.mjs
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
* JUnit XML, NUnit 2/3, TRX, TestNG, Robot Framework, CTest, Cucumber JSON, Behave JSON,
|
|
25
25
|
* Allure 2, CTRF, TAP, JSON mjs-unit — reconnus à leur contenu
|
|
26
26
|
* 0.11.0 — LE CLIENT QATRAX : mjs-unit qatrax <etat|rapatrier|pris|corrige|pousser> (voir : mjs-unit qatrax aide)
|
|
27
|
+
* 0.13.0 — mjs-unit d4q [dossier] | d4pf | d4pfq (D4PF puis D4Q) [--config=d4.config.json] [--a-blanc] : feu vert pour d4pf*
|
|
27
28
|
* --depuis=chemin un dossier (tous ses .xml, .json, .tap, .trx ; dans allure-results, les *-container et
|
|
28
29
|
* *-attachment sont écartés) ou un fichier
|
|
29
30
|
* → les mêmes sorties : --compte-rendu, --ctrf, --intoto, --json, --junit, --report
|
|
@@ -31,6 +32,11 @@
|
|
|
31
32
|
* @author Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
|
|
32
33
|
*/
|
|
33
34
|
// 0.11.0 — `mjs-unit qatrax …` : le client qatrax, chargé SEULEMENT pour cette sous-commande (le runner reste sans réseau).
|
|
35
|
+
// 0.13.0 — `mjs-unit d4q` / `mjs-unit d4pf` : ce qui suit une version intégrée, décrit par l'app dans d4.config.json.
|
|
36
|
+
if (process.argv[2] === "d4q" || process.argv[2] === "d4pf" || process.argv[2] === "d4pfq") {
|
|
37
|
+
const d4 = await import("../dist/d4.js");
|
|
38
|
+
process.exit(d4[process.argv[2]](process.argv.slice(3)));
|
|
39
|
+
}
|
|
34
40
|
if (process.argv[2] === "qatrax") {
|
|
35
41
|
const { principal } = await import("../dist/qatrax.js");
|
|
36
42
|
process.exit(await principal(process.argv.slice(3)));
|
package/dist/d4.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export interface Etape {
|
|
2
|
+
titre?: string;
|
|
3
|
+
nom?: string;
|
|
4
|
+
commande: string;
|
|
5
|
+
dossier?: "app" | "racine";
|
|
6
|
+
lignes?: number;
|
|
7
|
+
reporterSi?: string;
|
|
8
|
+
sauterSi?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface Sauvegarde {
|
|
11
|
+
nom: string;
|
|
12
|
+
commande: string;
|
|
13
|
+
fichier: string;
|
|
14
|
+
entete?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface Sante {
|
|
17
|
+
nom: string;
|
|
18
|
+
commande: string;
|
|
19
|
+
champs?: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface ConfigD4 {
|
|
22
|
+
app?: string;
|
|
23
|
+
d4q?: {
|
|
24
|
+
exige?: string[];
|
|
25
|
+
etapes: Etape[];
|
|
26
|
+
};
|
|
27
|
+
d4pf?: {
|
|
28
|
+
branche?: string;
|
|
29
|
+
ignorer?: string[];
|
|
30
|
+
sauvegardes?: Sauvegarde[];
|
|
31
|
+
deploiements?: Etape[];
|
|
32
|
+
sante?: Sante[];
|
|
33
|
+
journaux?: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Remplace les jetons {x} d'une commande. */
|
|
37
|
+
export declare function jetons(texte: string, valeurs: Record<string, string>): string;
|
|
38
|
+
/** D4Q : régénère et publie ce qui sert à juger la version ; ne déploie rien. → code de sortie. */
|
|
39
|
+
export declare function d4q(argv: string[]): number;
|
|
40
|
+
/** D4PF : déploie main sur la production et la formation — SEULEMENT sur feu vert pour CETTE version. → code de sortie. */
|
|
41
|
+
export declare function d4pf(argv: string[]): number;
|
|
42
|
+
/** D4PFQ : D4PF puis D4Q — D4Q seulement si D4PF a réussi. SEULEMENT sur feu vert pour CETTE version. → code de sortie. */
|
|
43
|
+
export declare function d4pfq(argv: string[]): number;
|
|
44
|
+
//# sourceMappingURL=d4.d.ts.map
|
package/dist/d4.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"d4.d.ts","sourceRoot":"","sources":["../src/d4.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,KAAK;IAAG,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;AAC9J,MAAM,WAAW,UAAU;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE;AAC/F,MAAM,WAAW,KAAK;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE;AAC3E,MAAM,WAAW,QAAQ;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,EAAE,KAAK,EAAE,CAAA;KAAE,CAAC;IAC5C,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC;QAAC,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACzI;AAOD,8CAA8C;AAC9C,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAE7E;AAqBD,mGAAmG;AACnG,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CA4B1C;AAQD,2HAA2H;AAC3H,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CA+D3C;AAED,2HAA2H;AAC3H,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAQ5C"}
|
package/dist/d4.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @mostajs/mjs-unit — D4Q et D4PF (0.13.0) : ce qui suit une version INTÉGRÉE (suite S1P verte, main avancé).
|
|
3
|
+
*
|
|
4
|
+
* mjs-unit d4q [dossier-de-l-app] [--config=d4.config.json] « déploie pour la qualité » : ne déploie RIEN ;
|
|
5
|
+
* mjs-unit d4pfq [--config=…] [--a-blanc] D4PF puis D4Q (D4Q seulement si D4PF réussit) : sur FEU VERT ;
|
|
6
|
+
* mjs-unit d4pf [--config=d4.config.json] [--a-blanc] « déploie pour prod et formation » : sur FEU VERT
|
|
7
|
+
* (--a-blanc : contrôles, puis les commandes, sans rien lancer).
|
|
8
|
+
*
|
|
9
|
+
* L'application décrit ses étapes dans `d4.config.json` (cherché dans le dossier courant) ; mjs-unit les enchaîne avec
|
|
10
|
+
* les mêmes règles partout : arrêt au premier échec, une étape « reportée » sur un motif déclaré (quota d'un service
|
|
11
|
+
* de PDF), une étape sautée par variable d'environnement ; pour D4PF : branche et arbre propre exigés, chaque
|
|
12
|
+
* sauvegarde vérifiée (non vide, en-tête attendu) AVANT tout déploiement, santé = version du package.json ET commit.
|
|
13
|
+
* Jetons des commandes : {racine} (dossier de la config), {app}, {version}, {commit}, {date} (AAAAMMJJ-HHMM).
|
|
14
|
+
* Premier usage : Guerway (outils/d4q.sh, outils/d4pf.sh, 04/11/2026).
|
|
15
|
+
* @author Dr Hamid MADANI <drmdh@msn.com> · AGPL-3.0-or-later
|
|
16
|
+
*/
|
|
17
|
+
import { spawnSync } from "node:child_process";
|
|
18
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync, openSync, readSync, closeSync } from "node:fs";
|
|
19
|
+
import { dirname, join, resolve, basename, isAbsolute } from "node:path";
|
|
20
|
+
const BLEU = (s) => `\x1b[0;36m${s}\x1b[0m`;
|
|
21
|
+
const VERT = (s) => `\x1b[0;32m${s}\x1b[0m`;
|
|
22
|
+
const deuxChiffres = (n) => String(n).padStart(2, "0");
|
|
23
|
+
const dateCourte = (d = new Date()) => `${d.getFullYear()}${deuxChiffres(d.getMonth() + 1)}${deuxChiffres(d.getDate())}-${deuxChiffres(d.getHours())}${deuxChiffres(d.getMinutes())}`;
|
|
24
|
+
/** Remplace les jetons {x} d'une commande. */
|
|
25
|
+
export function jetons(texte, valeurs) {
|
|
26
|
+
return texte.replace(/\{(racine|app|version|commit|date)\}/g, (m, k) => (k in valeurs ? valeurs[k] : m));
|
|
27
|
+
}
|
|
28
|
+
function shell(commande, cwd) {
|
|
29
|
+
const r = spawnSync("bash", ["-c", commande], { cwd, encoding: "utf8", env: process.env, maxBuffer: 256 * 1024 * 1024 });
|
|
30
|
+
return { code: r.status ?? 1, sortie: `${r.stdout ?? ""}${r.stderr ?? ""}` };
|
|
31
|
+
}
|
|
32
|
+
const fin = (s, n = 3) => s.trimEnd().split("\n").slice(-n).join("\n");
|
|
33
|
+
function charger(argv) {
|
|
34
|
+
const opt = argv.find((a) => a.startsWith("--config="));
|
|
35
|
+
const fichier = resolve(opt ? opt.slice(9) : "d4.config.json");
|
|
36
|
+
if (!existsSync(fichier))
|
|
37
|
+
throw Object.assign(new Error(`${fichier} introuvable : décrivez les étapes de l'application dans d4.config.json`), { code: 2 });
|
|
38
|
+
const config = JSON.parse(readFileSync(fichier, "utf8"));
|
|
39
|
+
const racine = dirname(fichier);
|
|
40
|
+
const libres = argv.filter((a) => !a.startsWith("--"));
|
|
41
|
+
const app = libres[0] ? resolve(libres[0]) : resolve(racine, config.app || ".");
|
|
42
|
+
if (!existsSync(join(app, "package.json")))
|
|
43
|
+
throw Object.assign(new Error(`${app} : pas de package.json (dossier de l'application attendu)`), { code: 1 });
|
|
44
|
+
const pkg = JSON.parse(readFileSync(join(app, "package.json"), "utf8"));
|
|
45
|
+
return { config, racine, app, version: String(pkg.version), nom: String(pkg.name || basename(app)), libres };
|
|
46
|
+
}
|
|
47
|
+
/** D4Q : régénère et publie ce qui sert à juger la version ; ne déploie rien. → code de sortie. */
|
|
48
|
+
export function d4q(argv) {
|
|
49
|
+
let c;
|
|
50
|
+
try {
|
|
51
|
+
c = charger(argv);
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
console.error(`✗ ${e.message}`);
|
|
55
|
+
return e.code ?? 1;
|
|
56
|
+
}
|
|
57
|
+
const q = c.config.d4q;
|
|
58
|
+
if (!q || !q.etapes?.length) {
|
|
59
|
+
console.error("✗ aucune section d4q (etapes) dans d4.config.json");
|
|
60
|
+
return 2;
|
|
61
|
+
}
|
|
62
|
+
const valeurs = { racine: c.racine, app: c.app, version: c.version, commit: "", date: dateCourte() };
|
|
63
|
+
console.log(`D4Q — ${c.nom} ${c.version} (${c.app})`);
|
|
64
|
+
for (const f of q.exige || [])
|
|
65
|
+
if (!existsSync(join(c.app, f))) {
|
|
66
|
+
console.error(`✗ aucune exécution : ${f} manque — lancer d'abord la suite dans ${c.app}`);
|
|
67
|
+
return 1;
|
|
68
|
+
}
|
|
69
|
+
const n = q.etapes.length;
|
|
70
|
+
const reportees = [];
|
|
71
|
+
if (argv.includes("--a-blanc")) {
|
|
72
|
+
for (const [i, e] of q.etapes.entries())
|
|
73
|
+
console.log(` [${i + 1}/${n}] ${e.titre} : ${jetons(e.commande, valeurs)}`);
|
|
74
|
+
console.log(`\n${VERT("✓ D4Q à blanc — rien n'a été lancé")}`);
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
for (const [i, e] of q.etapes.entries()) {
|
|
78
|
+
const k = i + 1;
|
|
79
|
+
if (e.sauterSi) {
|
|
80
|
+
const [v, val] = e.sauterSi.split("=");
|
|
81
|
+
if (process.env[v] === val) {
|
|
82
|
+
console.log(`\n${BLEU(`[${k}/${n}] ${e.titre} — sautée (${e.sauterSi})`)}`);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
console.log(`\n${BLEU(`[${k}/${n}] ${e.titre}`)}`);
|
|
87
|
+
const r = shell(jetons(e.commande, valeurs), e.dossier === "racine" ? c.racine : c.app);
|
|
88
|
+
if (r.code === 0) {
|
|
89
|
+
if (r.sortie.trim())
|
|
90
|
+
console.log(fin(r.sortie, e.lignes ?? 3));
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (e.reporterSi && r.sortie.includes(e.reporterSi)) {
|
|
94
|
+
console.log(` ⚠ reportée : ${e.reporterSi} (les sources sont à jour ; relancer D4Q plus tard)`);
|
|
95
|
+
reportees.push(k);
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
console.log(fin(r.sortie, 15));
|
|
99
|
+
console.error(`✗ étape ${k} en échec`);
|
|
100
|
+
return 1;
|
|
101
|
+
}
|
|
102
|
+
if (reportees.length)
|
|
103
|
+
console.log(`⚠ étapes reportées : ${reportees.join(", ")} ; relancer D4Q pour les produire.`);
|
|
104
|
+
console.log(`\n${VERT(`✓ D4Q terminé — ${c.nom} ${c.version}`)}`);
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
/** Les premiers octets d'un fichier. */
|
|
108
|
+
function debut(fichier, n) {
|
|
109
|
+
const fd = openSync(fichier, "r");
|
|
110
|
+
const b = Buffer.alloc(n);
|
|
111
|
+
const lus = readSync(fd, b, 0, n, 0);
|
|
112
|
+
closeSync(fd);
|
|
113
|
+
return b.subarray(0, lus).toString("latin1");
|
|
114
|
+
}
|
|
115
|
+
/** D4PF : déploie main sur la production et la formation — SEULEMENT sur feu vert pour CETTE version. → code de sortie. */
|
|
116
|
+
export function d4pf(argv) {
|
|
117
|
+
let c;
|
|
118
|
+
try {
|
|
119
|
+
c = charger(argv);
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
console.error(`✗ ${e.message}`);
|
|
123
|
+
return e.code ?? 1;
|
|
124
|
+
}
|
|
125
|
+
const d = c.config.d4pf;
|
|
126
|
+
if (!d) {
|
|
127
|
+
console.error("✗ aucune section d4pf dans d4.config.json");
|
|
128
|
+
return 2;
|
|
129
|
+
}
|
|
130
|
+
const git = (a) => shell(`git ${a}`, c.app).sortie.trim();
|
|
131
|
+
const commit = git("rev-parse --short HEAD");
|
|
132
|
+
const valeurs = { racine: c.racine, app: c.app, version: c.version, commit, date: dateCourte() };
|
|
133
|
+
const pas = (k, t) => console.log(`\n${BLEU(`[${k}/6] ${t}`)}`);
|
|
134
|
+
console.log(`D4PF — ${c.nom} ${c.version} (${commit})`);
|
|
135
|
+
pas(1, "contrôles");
|
|
136
|
+
const branche = d.branche || "main";
|
|
137
|
+
const courante = git("branch --show-current");
|
|
138
|
+
if (courante !== branche) {
|
|
139
|
+
console.error(`✗ branche courante : ${courante} (${branche} attendu)`);
|
|
140
|
+
return 1;
|
|
141
|
+
}
|
|
142
|
+
const ignorer = (d.ignorer || []).map((x) => new RegExp(x));
|
|
143
|
+
const sale = git("status --porcelain --untracked-files=no").split("\n").filter((l) => l.trim() && !ignorer.some((re) => re.test(l)));
|
|
144
|
+
if (sale.length) {
|
|
145
|
+
console.error(`✗ fichiers suivis modifiés :\n${sale.join("\n")}`);
|
|
146
|
+
return 1;
|
|
147
|
+
}
|
|
148
|
+
console.log(` ✓ ${branche}, arbre propre${ignorer.length ? " (hors fichiers ignorés)" : ""}`);
|
|
149
|
+
// --a-blanc : les contrôles seuls, puis les commandes qui seraient lancées (jetons remplacés) ; rien n'est exécuté.
|
|
150
|
+
if (argv.includes("--a-blanc")) {
|
|
151
|
+
const l = (t, x) => console.log(` ${t} : ${jetons(x, valeurs)}`);
|
|
152
|
+
for (const s of d.sauvegardes || [])
|
|
153
|
+
l(`sauvegarde ${s.nom} → ${jetons(s.fichier, valeurs)}`, s.commande);
|
|
154
|
+
for (const e of d.deploiements || [])
|
|
155
|
+
l(`déploiement ${e.titre || e.nom}`, e.commande);
|
|
156
|
+
for (const s of d.sante || [])
|
|
157
|
+
l(`santé ${s.nom}`, s.commande);
|
|
158
|
+
if (d.journaux)
|
|
159
|
+
l("journaux", d.journaux);
|
|
160
|
+
console.log(`\n${VERT(`✓ D4PF à blanc — rien n'a été sauvegardé ni déployé`)}`);
|
|
161
|
+
return 0;
|
|
162
|
+
}
|
|
163
|
+
pas(2, "sauvegardes");
|
|
164
|
+
for (const s of d.sauvegardes || []) {
|
|
165
|
+
const fichier = jetons(s.fichier, valeurs);
|
|
166
|
+
const chemin = isAbsolute(fichier) ? fichier : join(c.app, fichier);
|
|
167
|
+
mkdirSync(dirname(chemin), { recursive: true });
|
|
168
|
+
const r = spawnSync("bash", ["-c", jetons(s.commande, valeurs)], { cwd: c.app, env: process.env, maxBuffer: 4 * 1024 * 1024 * 1024 });
|
|
169
|
+
writeFileSync(chemin, r.stdout ?? Buffer.alloc(0));
|
|
170
|
+
const taille = existsSync(chemin) ? statSync(chemin).size : 0;
|
|
171
|
+
if (r.status !== 0 || !taille || (s.entete && debut(chemin, s.entete.length) !== s.entete)) {
|
|
172
|
+
console.error(`✗ ${basename(chemin)} : copie vide ou illisible (${s.nom})`);
|
|
173
|
+
return 1;
|
|
174
|
+
}
|
|
175
|
+
console.log(` ✓ ${basename(chemin)} — ${taille} octets`);
|
|
176
|
+
}
|
|
177
|
+
for (const [i, e] of (d.deploiements || []).entries()) {
|
|
178
|
+
pas(3 + Math.min(i, 1), String(e.titre || e.nom));
|
|
179
|
+
const r = shell(jetons(e.commande, valeurs), e.dossier === "racine" ? c.racine : c.app);
|
|
180
|
+
console.log(fin(r.sortie, e.lignes ?? 4));
|
|
181
|
+
if (r.code !== 0) {
|
|
182
|
+
console.error(`✗ déploiement « ${e.titre || e.nom} » en échec`);
|
|
183
|
+
return 1;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
pas(5, "santé");
|
|
187
|
+
let malade = false;
|
|
188
|
+
for (const s of d.sante || []) {
|
|
189
|
+
const r = shell(jetons(s.commande, valeurs), c.app);
|
|
190
|
+
let h = null;
|
|
191
|
+
try {
|
|
192
|
+
h = JSON.parse(r.sortie);
|
|
193
|
+
}
|
|
194
|
+
catch { /* réponse illisible */ }
|
|
195
|
+
const bon = Boolean(h && h.ok && h.version === c.version && String(h.commit).startsWith(commit));
|
|
196
|
+
const plus = (s.champs || []).filter((k) => h?.[k] != null).map((k) => ` · ${k} ${h[k]}`).join("");
|
|
197
|
+
console.log(` ${bon ? "✓" : "✗"} ${s.nom} : ${h ? `${h.version} ${h.commit}${plus}` : "réponse illisible"}`);
|
|
198
|
+
if (!bon)
|
|
199
|
+
malade = true;
|
|
200
|
+
}
|
|
201
|
+
if (malade) {
|
|
202
|
+
console.error("✗ santé : version ou commit inattendu");
|
|
203
|
+
return 1;
|
|
204
|
+
}
|
|
205
|
+
pas(6, "journaux (dernières erreurs)");
|
|
206
|
+
if (d.journaux)
|
|
207
|
+
console.log(fin(shell(jetons(d.journaux, valeurs), c.app).sortie, 40));
|
|
208
|
+
console.log(`\n${VERT(`✓ D4PF terminé — ${c.nom} ${c.version} (${commit})`)}`);
|
|
209
|
+
return 0;
|
|
210
|
+
}
|
|
211
|
+
/** D4PFQ : D4PF puis D4Q — D4Q seulement si D4PF a réussi. SEULEMENT sur feu vert pour CETTE version. → code de sortie. */
|
|
212
|
+
export function d4pfq(argv) {
|
|
213
|
+
const a = d4pf(argv);
|
|
214
|
+
if (a !== 0) {
|
|
215
|
+
console.error("✗ D4PF en échec : D4Q non lancé");
|
|
216
|
+
return a;
|
|
217
|
+
}
|
|
218
|
+
// D4Q porte sur l'application déployée (celle de la config), jamais sur un autre dossier.
|
|
219
|
+
const b = d4q(argv.filter((x) => x.startsWith("--")));
|
|
220
|
+
if (b !== 0)
|
|
221
|
+
return b;
|
|
222
|
+
console.log(VERT(argv.includes("--a-blanc") ? "✓ D4PFQ à blanc — rien n'a été lancé" : "✓ D4PFQ terminé — déployé, puis la qualité"));
|
|
223
|
+
return 0;
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=d4.js.map
|
package/dist/d4.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"d4.js","sourceRoot":"","sources":["../src/d4.ts"],"names":[],"mappings":"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"}
|
package/llms.txt
CHANGED
|
@@ -141,3 +141,56 @@ Le cœur (`.`) n'importe pas ce client.
|
|
|
141
141
|
## CONVENTION (écosystème)
|
|
142
142
|
Tout test ET son runner (`run-tests.sh`) sont versionnés dans `test-scripts/` ; `package.json` `scripts.test`
|
|
143
143
|
pointe sur le runner. Jamais de test jetable.
|
|
144
|
+
|
|
145
|
+
## D4Q et D4PF, après la suite (0.13.0)
|
|
146
|
+
|
|
147
|
+
Deux commandes pour ce qui suit une version **intégrée** (suite S1P verte, `main` avancé) ; premier usage : Guerway
|
|
148
|
+
(04/11/2026). L'application décrit ses étapes dans **`d4.config.json`** ; mjs-unit les enchaîne avec les mêmes règles partout.
|
|
149
|
+
|
|
150
|
+
**L'ordre d'une version** : essais rouges → code → suite (`--jobs`, rapport JSON) → intégration S1P
|
|
151
|
+
(`mjs-unit empreinte --verifier`, fusion `--ff-only`) → **`mjs-unit d4q`** → **`mjs-unit d4pf` sur feu vert**.
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
npx mjs-unit d4q # la qualité : ne déploie RIEN (CAPTURES=0 saute une étape marquée « sauterSi »)
|
|
155
|
+
npx mjs-unit d4q ../worktrees/L2-1.4.0 # sur un autre dossier de l'application (un worktree)
|
|
156
|
+
npx mjs-unit d4pf --a-blanc # contrôles, puis les commandes qui seraient lancées ; rien n'est exécuté
|
|
157
|
+
npx mjs-unit d4pf # SEULEMENT sur feu vert explicite pour CETTE version
|
|
158
|
+
npx mjs-unit d4pfq # D4PF puis D4Q (D4Q seulement si D4PF réussit) — sur feu vert ; --a-blanc aussi
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### D4Q — « déploie pour la qualité »
|
|
162
|
+
|
|
163
|
+
Régénère et publie tout ce qui sert à juger la version, dans l'ordre déclaré (chez Guerway : cahier des écrans, feuilles
|
|
164
|
+
de recette par rôle, feuilles de formation, plan Dev+Test, avancement, chiffrage, `mjs-unit qatrax pousser plan,run`).
|
|
165
|
+
|
|
166
|
+
- `exige` : les fichiers sans lesquels D4Q refuse (le rapport de la DERNIÈRE suite : `test-scripts/.out/report.json`) ;
|
|
167
|
+
- chaque étape s'arrête au premier échec, sauf si sa sortie contient son motif `reporterSi` (un quota de service de PDF) :
|
|
168
|
+
elle est alors « reportée » et la suite continue ; `sauterSi: "VAR=valeur"` la saute ;
|
|
169
|
+
- `dossier` : `app` (défaut) ou `racine` (le dossier de `d4.config.json`) ; `lignes` : les dernières lignes montrées.
|
|
170
|
+
|
|
171
|
+
#### D4PF — « déploie pour prod et formation »
|
|
172
|
+
|
|
173
|
+
1. contrôles : la branche (`main`), aucun fichier suivi modifié hors `ignorer` (expressions sur `git status --porcelain`) ;
|
|
174
|
+
2. `sauvegardes` : chaque commande écrit sa copie dans `fichier` ; vide ou sans `entete` (ex. `PGDMP`) → arrêt AVANT
|
|
175
|
+
tout déploiement ;
|
|
176
|
+
3. et 4. `deploiements`, dans l'ordre (production, puis formation) ;
|
|
177
|
+
5. `sante` : chaque commande rend le JSON de `/health` ; `ok`, `version` du package.json ET `commit` de `main` exigés ;
|
|
178
|
+
6. `journaux` : les dernières erreurs, pour lecture (des lignes anciennes ne sont pas une erreur de la version).
|
|
179
|
+
|
|
180
|
+
Règles : aucune valeur du `.env` affichée ; ne pas figer la liste des processus du serveur (pas de `pm2 save`) ; le
|
|
181
|
+
`push` et la publication npm restent hors de D4PF. Jetons des commandes : `{racine}`, `{app}`, `{version}`, `{commit}`, `{date}`.
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"app": "mon-api",
|
|
186
|
+
"d4q": { "exige": ["test-scripts/.out/report.json"], "etapes": [
|
|
187
|
+
{ "titre": "feuilles de recette", "commande": "node outils/feuillets.mjs", "reporterSi": "QUOTA_EXCEEDED" },
|
|
188
|
+
{ "titre": "qatrax", "commande": "npx mjs-unit qatrax pousser plan,run" } ] },
|
|
189
|
+
"d4pf": { "branche": "main", "ignorer": [" \\.env\\.example$"],
|
|
190
|
+
"sauvegardes": [{ "nom": "production", "commande": "ssh serveur 'pg_dump -Fc \"$BASE\"'", "fichier": "sauvegardes/avant-{version}-{date}.dump", "entete": "PGDMP" }],
|
|
191
|
+
"deploiements": [{ "nom": "production", "commande": "bash deploy.sh ./prod.conf" }, { "nom": "formation", "commande": "bash deploy.sh ./formation.conf" }],
|
|
192
|
+
"sante": [{ "nom": "production", "commande": "ssh serveur 'curl -s http://127.0.0.1:5400/health'" }],
|
|
193
|
+
"journaux": "ssh serveur 'tail -n 5 logs/err.log'" }
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/mjs-unit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
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",
|