@glubean/cli 0.7.0 → 0.8.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/dist/commands/load.d.ts +54 -0
- package/dist/commands/load.d.ts.map +1 -0
- package/dist/commands/load.js +270 -0
- package/dist/commands/load.js.map +1 -0
- package/dist/commands/run.d.ts +7 -2
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +14 -29
- package/dist/commands/run.js.map +1 -1
- package/dist/lib/config.d.ts +2 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +3 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +11 -0
- package/dist/main.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { LoadArtifact } from "@glubean/sdk/load";
|
|
2
|
+
/** A filesystem-safe result filename for a runner id. */
|
|
3
|
+
export declare function loadResultFileName(runnerId: string): string;
|
|
4
|
+
/** One plan's run outcome. */
|
|
5
|
+
export interface LoadRunOutcome {
|
|
6
|
+
file: string;
|
|
7
|
+
runnerId: string;
|
|
8
|
+
artifact: LoadArtifact;
|
|
9
|
+
}
|
|
10
|
+
/** A per-file failure (e.g. an unimportable load file). */
|
|
11
|
+
export interface LoadFileError {
|
|
12
|
+
file: string;
|
|
13
|
+
message: string;
|
|
14
|
+
}
|
|
15
|
+
/** Result of running a set of load files — completed outcomes + per-file errors. */
|
|
16
|
+
export interface RunLoadFilesResult {
|
|
17
|
+
outcomes: LoadRunOutcome[];
|
|
18
|
+
errors: LoadFileError[];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Run each load file's plans in a CHILD PROCESS (`runLoadFileInSubprocess`) so the
|
|
22
|
+
* harness and the user file co-resolve one `@glubean/sdk`, and collect the
|
|
23
|
+
* artifacts. A single file's import failure (or a crash) is recorded as a per-file
|
|
24
|
+
* error and the rest still run — completed artifacts are never discarded because a
|
|
25
|
+
* LATER file is broken. The raw `{ vars, secrets }` flow to the child, which
|
|
26
|
+
* applies the process.env fallback. Free of fs writes / process exit / printing.
|
|
27
|
+
*/
|
|
28
|
+
export declare function runLoadFiles(files: string[], opts: {
|
|
29
|
+
vars: Record<string, string>;
|
|
30
|
+
secrets: Record<string, string>;
|
|
31
|
+
/** Project root the child runs in — drives runner resolution + bare imports. */
|
|
32
|
+
cwd: string;
|
|
33
|
+
}): Promise<RunLoadFilesResult>;
|
|
34
|
+
/** Write each outcome's artifact to `<glubeanDir>/<runnerId>.load.result.json`,
|
|
35
|
+
* disambiguating ids that sanitize to the same filename so no artifact is lost. */
|
|
36
|
+
export declare function writeLoadResults(outcomes: LoadRunOutcome[], glubeanDir: string): Promise<string[]>;
|
|
37
|
+
/** Print a one-plan summary line block. The top `iterations` line is the
|
|
38
|
+
* end-to-end (whole-transaction) view; when a scenario calls
|
|
39
|
+
* `ctx.report.primaryComplete()` the artifact also carries a primary/end-to-end
|
|
40
|
+
* phase split, surfaced as an extra line so an async-job run shows submit latency
|
|
41
|
+
* vs full latency. (Exported for display tests.) */
|
|
42
|
+
export declare function printOutcome(o: LoadRunOutcome): void;
|
|
43
|
+
/** Options for the `load` command. */
|
|
44
|
+
export interface LoadCommandOptions {
|
|
45
|
+
/** Env file basename (default: the active env, else `.env`). */
|
|
46
|
+
envFile?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* `glubean load [target]` — discover + run load plans under `target` (a file,
|
|
50
|
+
* directory, or glob; defaults to the cwd), write results, and exit non-zero if
|
|
51
|
+
* any plan fails.
|
|
52
|
+
*/
|
|
53
|
+
export declare function loadCommand(target: string | undefined, options?: LoadCommandOptions): Promise<void>;
|
|
54
|
+
//# sourceMappingURL=load.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/commands/load.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA0BtD,yDAAyD;AACzD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED,8BAA8B;AAC9B,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,2DAA2D;AAC3D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oFAAoF;AACpF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,EAAE;IACJ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;CACb,GACA,OAAO,CAAC,kBAAkB,CAAC,CAa7B;AAED;oFACoF;AACpF,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,cAAc,EAAE,EAC1B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC,CAsBnB;AA2CD;;;;qDAIqD;AACrD,wBAAgB,YAAY,CAAC,CAAC,EAAE,cAAc,GAAG,IAAI,CAkFpD;AAED,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CA8Df"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `glubean load [target]` — run performance plans (M4-c).
|
|
3
|
+
*
|
|
4
|
+
* Discovers `loadRunner()` exports in `.load.ts` files, runs each through the
|
|
5
|
+
* closed-model orchestrator (`@glubean/runner` `runLoad`) IN A CHILD PROCESS,
|
|
6
|
+
* writes each finalized `LoadArtifact` to `.glubean/<runnerId>.load.result.json`,
|
|
7
|
+
* prints a per-plan summary, and exits non-zero if any plan's `summary.pass` is
|
|
8
|
+
* false (a crash or a breached threshold). This is the dedicated load path —
|
|
9
|
+
* separate from `glubean run` (the per-test ProjectRunner), since load's
|
|
10
|
+
* execution model differs.
|
|
11
|
+
*
|
|
12
|
+
* Each `.load.ts` runs via `runLoadFileInSubprocess`, which spawns the
|
|
13
|
+
* project-local runner harness (as `glubean run` does) so the harness and the
|
|
14
|
+
* user file co-resolve one `@glubean/sdk` — no split-brain when a globally
|
|
15
|
+
* installed CLI runs against a project with its own non-deduped sdk.
|
|
16
|
+
*/
|
|
17
|
+
import { resolve, dirname } from "node:path";
|
|
18
|
+
import { stat, readdir, writeFile, mkdir } from "node:fs/promises";
|
|
19
|
+
import { existsSync } from "node:fs";
|
|
20
|
+
import { glob } from "node:fs/promises";
|
|
21
|
+
import { loadProjectEnv, runLoadFileInSubprocess } from "@glubean/runner";
|
|
22
|
+
import { resolveEnvFileName } from "../lib/active_env.js";
|
|
23
|
+
import { findProjectConfig } from "./run.js";
|
|
24
|
+
const colors = {
|
|
25
|
+
reset: "\x1b[0m",
|
|
26
|
+
bold: "\x1b[1m",
|
|
27
|
+
dim: "\x1b[2m",
|
|
28
|
+
green: "\x1b[32m",
|
|
29
|
+
red: "\x1b[31m",
|
|
30
|
+
yellow: "\x1b[33m",
|
|
31
|
+
blue: "\x1b[34m",
|
|
32
|
+
cyan: "\x1b[36m",
|
|
33
|
+
};
|
|
34
|
+
// Mirror the run command's skip list (+ .glubean output) so a compiled `build/`
|
|
35
|
+
// dir isn't walked — otherwise a built `.load.js` could double-run a plan.
|
|
36
|
+
const SKIP_DIRS = new Set(["node_modules", ".git", "dist", "build", ".glubean"]);
|
|
37
|
+
// Directory/glob discovery matches SOURCE `.load.ts` only (like `glubean run`'s
|
|
38
|
+
// `.ts`-only discovery), so a compiled `.load.js`/`.mjs` alongside it isn't run
|
|
39
|
+
// twice. An explicit file target still runs whatever the user named.
|
|
40
|
+
function isLoadSourceFile(name) {
|
|
41
|
+
return name.endsWith(".load.ts");
|
|
42
|
+
}
|
|
43
|
+
/** A filesystem-safe result filename for a runner id. */
|
|
44
|
+
export function loadResultFileName(runnerId) {
|
|
45
|
+
const safe = runnerId.replace(/[^a-zA-Z0-9._-]/g, "_").replace(/^_+|_+$/g, "");
|
|
46
|
+
return `${safe || "load"}.load.result.json`;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Run each load file's plans in a CHILD PROCESS (`runLoadFileInSubprocess`) so the
|
|
50
|
+
* harness and the user file co-resolve one `@glubean/sdk`, and collect the
|
|
51
|
+
* artifacts. A single file's import failure (or a crash) is recorded as a per-file
|
|
52
|
+
* error and the rest still run — completed artifacts are never discarded because a
|
|
53
|
+
* LATER file is broken. The raw `{ vars, secrets }` flow to the child, which
|
|
54
|
+
* applies the process.env fallback. Free of fs writes / process exit / printing.
|
|
55
|
+
*/
|
|
56
|
+
export async function runLoadFiles(files, opts) {
|
|
57
|
+
const outcomes = [];
|
|
58
|
+
const errors = [];
|
|
59
|
+
for (const file of files) {
|
|
60
|
+
const res = await runLoadFileInSubprocess(file, {
|
|
61
|
+
vars: opts.vars,
|
|
62
|
+
secrets: opts.secrets,
|
|
63
|
+
cwd: opts.cwd,
|
|
64
|
+
});
|
|
65
|
+
for (const o of res.outcomes)
|
|
66
|
+
outcomes.push({ file, runnerId: o.runnerId, artifact: o.artifact });
|
|
67
|
+
for (const e of res.errors)
|
|
68
|
+
errors.push({ file, message: e.message });
|
|
69
|
+
}
|
|
70
|
+
return { outcomes, errors };
|
|
71
|
+
}
|
|
72
|
+
/** Write each outcome's artifact to `<glubeanDir>/<runnerId>.load.result.json`,
|
|
73
|
+
* disambiguating ids that sanitize to the same filename so no artifact is lost. */
|
|
74
|
+
export async function writeLoadResults(outcomes, glubeanDir) {
|
|
75
|
+
await mkdir(glubeanDir, { recursive: true });
|
|
76
|
+
// Track collisions case-INSENSITIVELY: on macOS/Windows, "Checkout" and
|
|
77
|
+
// "checkout" are the same directory entry, so an exact-string check would let
|
|
78
|
+
// the second overwrite the first.
|
|
79
|
+
const used = new Set();
|
|
80
|
+
const written = [];
|
|
81
|
+
for (const o of outcomes) {
|
|
82
|
+
let name = loadResultFileName(o.runnerId);
|
|
83
|
+
if (used.has(name.toLowerCase())) {
|
|
84
|
+
// Ids collapsed to the same filename — append `-N` so both survive.
|
|
85
|
+
const base = name.replace(/\.load\.result\.json$/, "");
|
|
86
|
+
let n = 2;
|
|
87
|
+
while (used.has(`${base}-${n}.load.result.json`.toLowerCase()))
|
|
88
|
+
n += 1;
|
|
89
|
+
name = `${base}-${n}.load.result.json`;
|
|
90
|
+
}
|
|
91
|
+
used.add(name.toLowerCase());
|
|
92
|
+
const path = resolve(glubeanDir, name);
|
|
93
|
+
await writeFile(path, JSON.stringify(o.artifact, null, 2), "utf-8");
|
|
94
|
+
written.push(path);
|
|
95
|
+
}
|
|
96
|
+
return written;
|
|
97
|
+
}
|
|
98
|
+
/** Recursively collect `.load.ts` files under a directory. */
|
|
99
|
+
async function walkLoadFiles(dir, out) {
|
|
100
|
+
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
101
|
+
if (entry.isDirectory()) {
|
|
102
|
+
if (!SKIP_DIRS.has(entry.name))
|
|
103
|
+
await walkLoadFiles(resolve(dir, entry.name), out);
|
|
104
|
+
}
|
|
105
|
+
else if (entry.isFile() && isLoadSourceFile(entry.name)) {
|
|
106
|
+
out.push(resolve(dir, entry.name));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** Resolve a file / directory / glob target to a sorted, deduped `.load.ts` list. */
|
|
111
|
+
async function resolveLoadFiles(target) {
|
|
112
|
+
const abs = resolve(target);
|
|
113
|
+
try {
|
|
114
|
+
const s = await stat(abs);
|
|
115
|
+
if (s.isFile())
|
|
116
|
+
return [abs];
|
|
117
|
+
if (s.isDirectory()) {
|
|
118
|
+
const files = [];
|
|
119
|
+
await walkLoadFiles(abs, files);
|
|
120
|
+
files.sort();
|
|
121
|
+
return files;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// not a path — try glob below
|
|
126
|
+
}
|
|
127
|
+
const files = [];
|
|
128
|
+
for await (const entry of glob(target, { cwd: process.cwd() })) {
|
|
129
|
+
const full = resolve(process.cwd(), entry);
|
|
130
|
+
if (!isLoadSourceFile(full))
|
|
131
|
+
continue;
|
|
132
|
+
const s = await stat(full).catch(() => null);
|
|
133
|
+
if (s?.isFile())
|
|
134
|
+
files.push(full);
|
|
135
|
+
}
|
|
136
|
+
files.sort();
|
|
137
|
+
return [...new Set(files)];
|
|
138
|
+
}
|
|
139
|
+
function pct(fraction) {
|
|
140
|
+
return `${(fraction * 100).toFixed(2)}%`;
|
|
141
|
+
}
|
|
142
|
+
/** Print a one-plan summary line block. The top `iterations` line is the
|
|
143
|
+
* end-to-end (whole-transaction) view; when a scenario calls
|
|
144
|
+
* `ctx.report.primaryComplete()` the artifact also carries a primary/end-to-end
|
|
145
|
+
* phase split, surfaced as an extra line so an async-job run shows submit latency
|
|
146
|
+
* vs full latency. (Exported for display tests.) */
|
|
147
|
+
export function printOutcome(o) {
|
|
148
|
+
const s = o.artifact.summary;
|
|
149
|
+
const verdict = s.pass
|
|
150
|
+
? `${colors.green}PASS${colors.reset}`
|
|
151
|
+
: `${colors.red}FAIL${colors.reset}`;
|
|
152
|
+
console.log(`${colors.bold}${o.runnerId}${colors.reset} ${verdict}`);
|
|
153
|
+
console.log(`${colors.dim} iterations ${s.totalIterations} (ok ${s.successfulIterations}, failed ${s.failedIterations})` +
|
|
154
|
+
` errorRate ${pct(s.errorRate)} p95 ${Math.round(s.latency.p95)}ms` +
|
|
155
|
+
` throughput ${s.throughputPerSec.toFixed(1)}/s${colors.reset}`);
|
|
156
|
+
// Phase split (M5): the line above is end-to-end; show the primary phase (up to
|
|
157
|
+
// the primaryComplete boundary). `completed/started` indicates primary coverage —
|
|
158
|
+
// when fewer iterations complete primary than started, some failed before the
|
|
159
|
+
// boundary (a branch/error path); precise boundary coverage lands with M6.
|
|
160
|
+
if (s.primary) {
|
|
161
|
+
console.log(`${colors.dim} primary (to boundary) p95 ${Math.round(s.primary.latency.p95)}ms` +
|
|
162
|
+
` throughput ${s.primary.throughputPerSec.toFixed(1)}/s` +
|
|
163
|
+
` completed ${s.primary.completed}/${s.primary.started}${colors.reset}`);
|
|
164
|
+
if (s.primary.completed < s.primary.started) {
|
|
165
|
+
console.log(`${colors.yellow} ⚠ ${s.primary.started - s.primary.completed} iteration(s) did not reach the primary boundary` +
|
|
166
|
+
` (failed before it, or a branch skipped it)${colors.reset}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Continuation / producer-release subsystem (M6): present once any iteration engaged
|
|
170
|
+
// release (released / rejected / duplicate / still pending). Show the slot model, how
|
|
171
|
+
// many slots were released, the backlog peak + back-pressure, then surface rejections,
|
|
172
|
+
// drain-timeout aborts, and coverage gaps as warnings.
|
|
173
|
+
const c = s.continuation;
|
|
174
|
+
if (c) {
|
|
175
|
+
console.log(`${colors.dim} continuation (${o.artifact.runtime.slotModel}) released ${c.releasedProducerSlots}` +
|
|
176
|
+
` backlog max ${c.maxBacklog}` +
|
|
177
|
+
(c.backpressureMs ? ` backpressure p95 ${Math.round(c.backpressureMs.p95)}ms` : "") +
|
|
178
|
+
`${colors.reset}`);
|
|
179
|
+
if (c.rejectedReleaseSignals > 0) {
|
|
180
|
+
console.log(`${colors.yellow} ⚠ ${c.rejectedReleaseSignals} release(s) rejected (backlog full, drain bound, or run deadline)${colors.reset}`);
|
|
181
|
+
}
|
|
182
|
+
if (c.abortedByDrainTimeout > 0) {
|
|
183
|
+
console.log(`${colors.yellow} ⚠ ${c.abortedByDrainTimeout} continuation(s) aborted by the drain timeout` +
|
|
184
|
+
` (still in flight at finalize)${colors.reset}`);
|
|
185
|
+
}
|
|
186
|
+
if (c.duplicateReleaseSignals > 0) {
|
|
187
|
+
console.log(`${colors.yellow} ⚠ ${c.duplicateReleaseSignals} duplicate release signal(s)` +
|
|
188
|
+
` (one producer-release boundary per iteration)${colors.reset}`);
|
|
189
|
+
}
|
|
190
|
+
// Coverage gaps: only SOME iterations reached a primary boundary (a branch/error path
|
|
191
|
+
// skipped it), so the producer-release stats above reflect just that subset — warn,
|
|
192
|
+
// since `releaseCoverage` alone can read 100% while boundary coverage is partial.
|
|
193
|
+
if (c.primaryBoundaryCoverage < 1) {
|
|
194
|
+
console.log(`${colors.yellow} ⚠ only ${pct(c.primaryBoundaryCoverage)} of iterations reached a primary boundary` +
|
|
195
|
+
` — producer-release stats cover that subset${colors.reset}`);
|
|
196
|
+
}
|
|
197
|
+
if (c.releaseCoverage < 1) {
|
|
198
|
+
console.log(`${colors.dim} release coverage ${pct(c.releaseCoverage)} of primary boundaries${colors.reset}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
for (const t of s.thresholds) {
|
|
202
|
+
const mark = t.pass ? `${colors.green}✓${colors.reset}` : `${colors.red}✗${colors.reset}`;
|
|
203
|
+
const where = t.target ? `${t.scope}[${t.target}]` : t.scope;
|
|
204
|
+
console.log(`${colors.dim} ${mark} ${where}.${t.metric} ${t.expression} (actual ${t.actual})${colors.reset}`);
|
|
205
|
+
}
|
|
206
|
+
// Non-fatal run-shape advisories (M6-d), e.g. a long tail poll that held the producer
|
|
207
|
+
// slot with no release.
|
|
208
|
+
for (const a of s.advisories ?? []) {
|
|
209
|
+
console.log(`${colors.yellow} ⓘ ${a}${colors.reset}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* `glubean load [target]` — discover + run load plans under `target` (a file,
|
|
214
|
+
* directory, or glob; defaults to the cwd), write results, and exit non-zero if
|
|
215
|
+
* any plan fails.
|
|
216
|
+
*/
|
|
217
|
+
export async function loadCommand(target, options = {}) {
|
|
218
|
+
console.log(`\n${colors.bold}${colors.blue}⚡ Glubean Load${colors.reset}\n`);
|
|
219
|
+
const files = await resolveLoadFiles(target ?? process.cwd());
|
|
220
|
+
if (files.length === 0) {
|
|
221
|
+
console.log(`${colors.yellow}No .load.ts files found${target ? ` for "${target}"` : ` in ${process.cwd()}`}.${colors.reset}`);
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
// Derive the project root from the discovered file (not the shell cwd) so a
|
|
225
|
+
// targeted run outside cwd uses the load file's project for runner resolution /
|
|
226
|
+
// env / `.glubean` output.
|
|
227
|
+
const { rootDir } = await findProjectConfig(dirname(files[0]));
|
|
228
|
+
// An EXPLICIT --env-file that's missing is an error (mirrors `glubean run`) —
|
|
229
|
+
// silently running with empty env could send load to the wrong target / run
|
|
230
|
+
// without credentials. Validate the env file up front so a missing one fails
|
|
231
|
+
// fast. A resolved default/active env file may be absent.
|
|
232
|
+
const userSpecifiedEnvFile = options.envFile !== undefined;
|
|
233
|
+
const envFileName = userSpecifiedEnvFile ? options.envFile : await resolveEnvFileName(rootDir);
|
|
234
|
+
if (userSpecifiedEnvFile && !existsSync(resolve(rootDir, envFileName))) {
|
|
235
|
+
console.log(`${colors.red}Error: env file '${envFileName}' not found in ${rootDir}${colors.reset}`);
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
// Plugin bootstrap happens INSIDE each subprocess (the harness registers
|
|
239
|
+
// matchers / protocol adapters before importing the load file), so the CLI no
|
|
240
|
+
// longer bootstraps here.
|
|
241
|
+
const { vars, secrets } = await loadProjectEnv(rootDir, envFileName);
|
|
242
|
+
// A single file's import failure (or crash) is collected (not thrown) so
|
|
243
|
+
// earlier/later files still produce + persist results. Pass the raw resolved
|
|
244
|
+
// env — the child re-applies the process.env fallback (a Proxy can't cross the
|
|
245
|
+
// process boundary), so shell/CI-supplied vars/secrets still resolve.
|
|
246
|
+
const { outcomes, errors } = await runLoadFiles(files, { vars, secrets, cwd: rootDir });
|
|
247
|
+
// Persist every completed artifact FIRST — a later broken file must not discard
|
|
248
|
+
// an expensive successful plan's result.
|
|
249
|
+
const written = await writeLoadResults(outcomes, resolve(rootDir, ".glubean"));
|
|
250
|
+
console.log();
|
|
251
|
+
let anyFail = false;
|
|
252
|
+
for (const o of outcomes) {
|
|
253
|
+
printOutcome(o);
|
|
254
|
+
if (!o.artifact.summary.pass)
|
|
255
|
+
anyFail = true;
|
|
256
|
+
}
|
|
257
|
+
for (const e of errors) {
|
|
258
|
+
console.log(`${colors.red}✗ ${e.message}${colors.reset}`);
|
|
259
|
+
}
|
|
260
|
+
if (written.length > 0) {
|
|
261
|
+
console.log(`\n${colors.dim}Wrote ${written.length} result file(s) to .glubean/${colors.reset}`);
|
|
262
|
+
}
|
|
263
|
+
if (outcomes.length === 0 && errors.length === 0) {
|
|
264
|
+
console.log(`${colors.yellow}No loadRunner() exports found in ${files.length} file(s).${colors.reset}`);
|
|
265
|
+
}
|
|
266
|
+
// Fail if any plan failed, any file errored, or nothing ran at all.
|
|
267
|
+
if (anyFail || errors.length > 0 || outcomes.length === 0)
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/commands/load.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/run.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { GlubeanFileKind } from "@glubean/scanner";
|
|
1
2
|
interface RunOptions {
|
|
2
3
|
filter?: string;
|
|
3
4
|
pick?: string;
|
|
@@ -108,6 +109,10 @@ interface RunOptions {
|
|
|
108
109
|
*/
|
|
109
110
|
thresholds?: import("@glubean/sdk").ThresholdConfig;
|
|
110
111
|
}
|
|
112
|
+
export declare function findProjectConfig(startDir: string): Promise<{
|
|
113
|
+
rootDir: string;
|
|
114
|
+
configPath?: string;
|
|
115
|
+
}>;
|
|
111
116
|
/**
|
|
112
117
|
* Map a file path to its Glubean kind by extension.
|
|
113
118
|
* - `.test.ts` → "test"
|
|
@@ -120,7 +125,7 @@ interface RunOptions {
|
|
|
120
125
|
* Returns undefined for non-Glubean files. The suite.kinds filter in
|
|
121
126
|
* resolveTestFiles uses this to keep only files whose kind matches.
|
|
122
127
|
*/
|
|
123
|
-
export type GlubeanFileKind
|
|
128
|
+
export type { GlubeanFileKind };
|
|
124
129
|
export declare function classifyGlubeanFile(filePath: string): GlubeanFileKind | undefined;
|
|
125
130
|
/**
|
|
126
131
|
* Per-suite resolution helper exposed for main.ts. Resolves a suite's
|
|
@@ -174,6 +179,7 @@ export declare function discoverTests(filePath: string): Promise<DiscoveredTest[
|
|
|
174
179
|
export declare const __testing: {
|
|
175
180
|
matchesTags: (testItem: DiscoveredTest, tags: string[], mode?: "or" | "and" | undefined) => boolean;
|
|
176
181
|
matchesExcludeTags: (testItem: DiscoveredTest, excludeTags: string[]) => boolean;
|
|
182
|
+
isGlubeanTestFile: (name: string) => boolean;
|
|
177
183
|
};
|
|
178
184
|
declare function matchesTags(testItem: DiscoveredTest, tags: string[], mode?: "or" | "and"): boolean;
|
|
179
185
|
/**
|
|
@@ -183,5 +189,4 @@ declare function matchesTags(testItem: DiscoveredTest, tags: string[], mode?: "o
|
|
|
183
189
|
*/
|
|
184
190
|
declare function matchesExcludeTags(testItem: DiscoveredTest, excludeTags: string[]): boolean;
|
|
185
191
|
export declare function runCommand(target: string | string[], options?: RunOptions): Promise<void>;
|
|
186
|
-
export {};
|
|
187
192
|
//# sourceMappingURL=run.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAuBxD,UAAU,UAAU;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,IAAI,GAAG,KAAK,CAAC;IACvB,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,4EAA4E;IAC5E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC;IACrE;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,OAAO,oBAAoB,EAAE,eAAe,CAAC;IAC/D;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,cAAc,EAAE,eAAe,CAAC;CACrD;AAuCD,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAoBnD;AA+ED;;;;;;;;;;;GAWG;AACH,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAGjF;AA+DD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,MAAM,EAAE,CAAC,CA+BnB;AAED,UAAU,kBAAkB;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;CACrC;AAED,UAAU,cAAc;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,kBAAkB,CAAC;CAC1B;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAoM/E;AAUD,eAAO,MAAM,SAAS;;;8BAIM,MAAM;CACjC,CAAC;AAEF,iBAAS,WAAW,CAClB,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,GAAE,IAAI,GAAG,KAAY,GACxB,OAAO,CAKT;AAED;;;;GAIG;AACH,iBAAS,kBAAkB,CACzB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,MAAM,EAAE,GACpB,OAAO,CAKT;AA6DD,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,OAAO,GAAE,UAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAqvDf"}
|
package/dist/commands/run.js
CHANGED
|
@@ -9,7 +9,7 @@ import { shouldSkipTest } from "../lib/skip.js";
|
|
|
9
9
|
import { CLI_VERSION } from "../version.js";
|
|
10
10
|
import { redactMetadataForUpload } from "../lib/redact-metadata.js";
|
|
11
11
|
import { extractContractCases, extractFromSource } from "@glubean/scanner/static";
|
|
12
|
-
import { extractContractFromFile, findTemplateMatch, loadProjectOverlays, matchesTemplateFilter, } from "@glubean/scanner";
|
|
12
|
+
import { buildSuffixes, classifyByStem, extractContractFromFile, findTemplateMatch, GLUBEAN_KINDS, loadProjectOverlays, matchesTemplateFilter, } from "@glubean/scanner";
|
|
13
13
|
import { applyEnvTemplating } from "@glubean/runner";
|
|
14
14
|
// ANSI color codes for pretty output
|
|
15
15
|
const colors = {
|
|
@@ -28,7 +28,7 @@ const CLOUD_MEMORY_LIMITS = {
|
|
|
28
28
|
pro: 700,
|
|
29
29
|
};
|
|
30
30
|
const MEMORY_WARNING_THRESHOLD_MB = CLOUD_MEMORY_LIMITS.free * 0.67;
|
|
31
|
-
async function findProjectConfig(startDir) {
|
|
31
|
+
export async function findProjectConfig(startDir) {
|
|
32
32
|
let dir = startDir;
|
|
33
33
|
while (dir !== "/") {
|
|
34
34
|
try {
|
|
@@ -77,13 +77,12 @@ function isGlob(target) {
|
|
|
77
77
|
// calls execute and register overlays before discovery runs (attachment-
|
|
78
78
|
// model §7.4). `discoverTests()` is responsible for distinguishing
|
|
79
79
|
// bootstrap-only files from runnable-emitting ones.
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
];
|
|
80
|
+
// CLI target resolution for `glubean run` recognizes only `.ts` files across the
|
|
81
|
+
// test-runner kinds (including bootstrap), derived from the canonical kind
|
|
82
|
+
// registry (scanner/kinds.ts). `load` is EXCLUDED here: load plans run through
|
|
83
|
+
// the dedicated `glubean load` command + the closed-model orchestrator, not the
|
|
84
|
+
// per-test ProjectRunner, so `glubean run ./dir` must not sweep in `.load.ts`.
|
|
85
|
+
const TEST_FILE_SUFFIXES = GLUBEAN_KINDS.filter((k) => k.kind !== "load").flatMap((k) => buildSuffixes(k.stems, [".ts"]));
|
|
87
86
|
function isGlubeanTestFile(name) {
|
|
88
87
|
return TEST_FILE_SUFFIXES.some((suffix) => name.endsWith(suffix));
|
|
89
88
|
}
|
|
@@ -93,17 +92,9 @@ function isGlubeanTestFile(name) {
|
|
|
93
92
|
// the static test path — a `.workflow.` substring would mis-route it into
|
|
94
93
|
// contract extraction (which ignores `test()` exports), silently dropping its
|
|
95
94
|
// tests (codex 0.6 P2).
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
".contract.mjs",
|
|
100
|
-
".workflow.ts",
|
|
101
|
-
".workflow.js",
|
|
102
|
-
".workflow.mjs",
|
|
103
|
-
".flow.ts",
|
|
104
|
-
".flow.js",
|
|
105
|
-
".flow.mjs",
|
|
106
|
-
];
|
|
95
|
+
// Contract/workflow/flow artifact files (NOT bootstrap), all extensions —
|
|
96
|
+
// derived from the canonical kind registry (scanner/kinds.ts).
|
|
97
|
+
const RUNTIME_ARTIFACT_SUFFIXES = GLUBEAN_KINDS.filter((k) => k.runtimeArtifact && k.kind !== "bootstrap").flatMap((k) => buildSuffixes(k.stems));
|
|
107
98
|
function isRuntimeExtractableArtifact(name) {
|
|
108
99
|
return RUNTIME_ARTIFACT_SUFFIXES.some((suffix) => name.endsWith(suffix));
|
|
109
100
|
}
|
|
@@ -125,15 +116,8 @@ async function walkTestFiles(dir, result) {
|
|
|
125
116
|
}
|
|
126
117
|
}
|
|
127
118
|
export function classifyGlubeanFile(filePath) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
if (filePath.endsWith(".contract.ts"))
|
|
131
|
-
return "contract";
|
|
132
|
-
if (filePath.endsWith(".workflow.ts") || filePath.endsWith(".flow.ts"))
|
|
133
|
-
return "flow";
|
|
134
|
-
if (filePath.endsWith(".bootstrap.ts"))
|
|
135
|
-
return "bootstrap";
|
|
136
|
-
return undefined;
|
|
119
|
+
// `.ts`-only classification, by stem, from the canonical kind registry.
|
|
120
|
+
return classifyByStem(filePath, [".ts"]);
|
|
137
121
|
}
|
|
138
122
|
async function resolveSingleTarget(target) {
|
|
139
123
|
const abs = resolve(target);
|
|
@@ -450,6 +434,7 @@ function matchesFilter(testItem, filter) {
|
|
|
450
434
|
export const __testing = {
|
|
451
435
|
matchesTags: (...args) => matchesTags(...args),
|
|
452
436
|
matchesExcludeTags: (...args) => matchesExcludeTags(...args),
|
|
437
|
+
isGlubeanTestFile: (name) => isGlubeanTestFile(name),
|
|
453
438
|
};
|
|
454
439
|
function matchesTags(testItem, tags, mode = "or") {
|
|
455
440
|
if (!testItem.meta.tags?.length)
|