@plune-ai/cli 0.10.0 → 0.11.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 +8 -0
- package/dist/cli.cjs +48 -35
- package/dist/reporter-core.cjs +18 -7
- package/dist/reporter-core.js +18 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -158,6 +158,14 @@ job closes the run instead of the explicit `finish`.
|
|
|
158
158
|
`plune run exec` sets it for you — anything reporting inside it, this command included, joins
|
|
159
159
|
without closing.
|
|
160
160
|
|
|
161
|
+
### What the run is called
|
|
162
|
+
|
|
163
|
+
A run nobody named is called after the directory, the minute it started and where it ran —
|
|
164
|
+
`plune · 2026-09-15 15:26 · ci` — so a row in the list reads without being opened. The clock is the
|
|
165
|
+
reporting machine's own; `ci` comes from the `CI` variable every hosted runner sets. To call it
|
|
166
|
+
something else, set `PLUNE_RUN_TITLE`; `PLUNE_ENV` and `PLUNE_LABELS` mark where it ran and how, and
|
|
167
|
+
those stay marks rather than becoming part of the name.
|
|
168
|
+
|
|
161
169
|
## Optional: keep a history
|
|
162
170
|
|
|
163
171
|
Everything above works with no account, no network, and no token — that does not change. `run`,
|
package/dist/cli.cjs
CHANGED
|
@@ -2210,7 +2210,7 @@ function createClient(opts) {
|
|
|
2210
2210
|
const wait = opts.wait ?? sleep;
|
|
2211
2211
|
const base = opts.apiUrl.replace(/\/+$/, "");
|
|
2212
2212
|
const scrub = (text2) => opts.token === "" ? text2 : text2.split(opts.token).join("***");
|
|
2213
|
-
async function send(method,
|
|
2213
|
+
async function send(method, path13, body) {
|
|
2214
2214
|
let last = {
|
|
2215
2215
|
kind: "unavailable",
|
|
2216
2216
|
status: null,
|
|
@@ -2219,7 +2219,7 @@ function createClient(opts) {
|
|
|
2219
2219
|
for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt += 1) {
|
|
2220
2220
|
let res;
|
|
2221
2221
|
try {
|
|
2222
|
-
res = await doFetch(`${base}${
|
|
2222
|
+
res = await doFetch(`${base}${path13}`, {
|
|
2223
2223
|
method,
|
|
2224
2224
|
headers: { "content-type": "application/json", authorization: `Bearer ${opts.token}` },
|
|
2225
2225
|
// A DELETE carries none. Sending `"undefined"` as a body is what a naive
|
|
@@ -2247,8 +2247,8 @@ function createClient(opts) {
|
|
|
2247
2247
|
return { ok: false, ...last };
|
|
2248
2248
|
}
|
|
2249
2249
|
return {
|
|
2250
|
-
post: (
|
|
2251
|
-
del: (
|
|
2250
|
+
post: (path13, body) => send("POST", path13, body),
|
|
2251
|
+
del: (path13) => send("DELETE", path13)
|
|
2252
2252
|
};
|
|
2253
2253
|
}
|
|
2254
2254
|
var RETRY_DELAYS_MS, sleep;
|
|
@@ -2313,18 +2313,25 @@ function readEnv(env = process.env) {
|
|
|
2313
2313
|
ignored: UNSUPPORTED_VARS.filter((name) => value(env, name) !== void 0)
|
|
2314
2314
|
};
|
|
2315
2315
|
}
|
|
2316
|
-
|
|
2316
|
+
function defaultRunTitle(env = process.env, now = /* @__PURE__ */ new Date(), cwd = process.cwd()) {
|
|
2317
|
+
const two = (n) => String(n).padStart(2, "0");
|
|
2318
|
+
const stamp = `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())} ${two(now.getHours())}:${two(now.getMinutes())}`;
|
|
2319
|
+
const where = flag(env, "CI") || flag(env, "GITHUB_ACTIONS") ? "ci" : "local";
|
|
2320
|
+
return `${path6.basename(cwd)} \xB7 ${stamp} \xB7 ${where}`;
|
|
2321
|
+
}
|
|
2322
|
+
var path6, UNSUPPORTED_VARS;
|
|
2317
2323
|
var init_env2 = __esm({
|
|
2318
2324
|
"src/reporter-core/env.ts"() {
|
|
2319
2325
|
"use strict";
|
|
2320
2326
|
init_cjs_shims();
|
|
2327
|
+
path6 = __toESM(require("path"), 1);
|
|
2321
2328
|
UNSUPPORTED_VARS = ["PLUNE_GROUP"];
|
|
2322
2329
|
}
|
|
2323
2330
|
});
|
|
2324
2331
|
|
|
2325
2332
|
// src/reporter-core/fallback.ts
|
|
2326
2333
|
function appendBatch(file, batch) {
|
|
2327
|
-
fs6.mkdirSync(
|
|
2334
|
+
fs6.mkdirSync(path7.dirname(file), { recursive: true });
|
|
2328
2335
|
const line = {
|
|
2329
2336
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2330
2337
|
runId: batch.runId,
|
|
@@ -2334,14 +2341,14 @@ function appendBatch(file, batch) {
|
|
|
2334
2341
|
fs6.appendFileSync(file, `${JSON.stringify(line)}
|
|
2335
2342
|
`, "utf8");
|
|
2336
2343
|
}
|
|
2337
|
-
var fs6,
|
|
2344
|
+
var fs6, path7, DEFAULT_FALLBACK_PATH;
|
|
2338
2345
|
var init_fallback = __esm({
|
|
2339
2346
|
"src/reporter-core/fallback.ts"() {
|
|
2340
2347
|
"use strict";
|
|
2341
2348
|
init_cjs_shims();
|
|
2342
2349
|
fs6 = __toESM(require("fs"), 1);
|
|
2343
|
-
|
|
2344
|
-
DEFAULT_FALLBACK_PATH =
|
|
2350
|
+
path7 = __toESM(require("path"), 1);
|
|
2351
|
+
DEFAULT_FALLBACK_PATH = path7.join(".plune", "pending-results.jsonl");
|
|
2345
2352
|
}
|
|
2346
2353
|
});
|
|
2347
2354
|
|
|
@@ -2468,6 +2475,10 @@ async function startRun(passed, declared) {
|
|
|
2468
2475
|
...externalKey !== null ? { externalKey } : {},
|
|
2469
2476
|
...cfg.meta !== void 0 ? { meta: cfg.meta } : {},
|
|
2470
2477
|
...configuration !== void 0 ? { configuration } : {},
|
|
2478
|
+
// Named even when nobody named it — the list has to read without opening a row. Only what
|
|
2479
|
+
// the caller DESCRIBED goes to `warnIfDropped` below: a title this side invented is not one
|
|
2480
|
+
// a person will miss, and a deployment older than the field must not be nagged on every run.
|
|
2481
|
+
title: defaultRunTitle(),
|
|
2471
2482
|
...described
|
|
2472
2483
|
});
|
|
2473
2484
|
if (start.ok) {
|
|
@@ -2689,7 +2700,9 @@ async function handleRunStart(options = {}) {
|
|
|
2689
2700
|
const out = await client.post("/v1/runs", {
|
|
2690
2701
|
schemaVersion: 2,
|
|
2691
2702
|
kind: options.kind ?? "automated",
|
|
2692
|
-
externalKey
|
|
2703
|
+
externalKey,
|
|
2704
|
+
// The same name the reporter would give it; `PLUNE_RUN_TITLE` replaces it, as everywhere.
|
|
2705
|
+
title: env.config.title ?? defaultRunTitle()
|
|
2693
2706
|
});
|
|
2694
2707
|
if (!out.ok) throw new RunCommandError(`Could not start the run \u2014 ${out.detail || out.kind}.`);
|
|
2695
2708
|
const result = {
|
|
@@ -3351,7 +3364,7 @@ function isRunResult(v) {
|
|
|
3351
3364
|
}
|
|
3352
3365
|
function handleReport(opts = {}) {
|
|
3353
3366
|
const cwd = opts.cwd ?? process.cwd();
|
|
3354
|
-
const file =
|
|
3367
|
+
const file = path8.join(cwd, ".plune", "last-run.json");
|
|
3355
3368
|
let raw;
|
|
3356
3369
|
try {
|
|
3357
3370
|
raw = fs9.readFileSync(file, "utf8");
|
|
@@ -3369,13 +3382,13 @@ function handleReport(opts = {}) {
|
|
|
3369
3382
|
}
|
|
3370
3383
|
return parsed;
|
|
3371
3384
|
}
|
|
3372
|
-
var fs9,
|
|
3385
|
+
var fs9, path8, ReportNotFoundError;
|
|
3373
3386
|
var init_report = __esm({
|
|
3374
3387
|
"src/cli/commands/report.ts"() {
|
|
3375
3388
|
"use strict";
|
|
3376
3389
|
init_cjs_shims();
|
|
3377
3390
|
fs9 = __toESM(require("fs"), 1);
|
|
3378
|
-
|
|
3391
|
+
path8 = __toESM(require("path"), 1);
|
|
3379
3392
|
ReportNotFoundError = class extends Error {
|
|
3380
3393
|
code = "NO_SAVED_RUN";
|
|
3381
3394
|
constructor(message) {
|
|
@@ -3599,7 +3612,7 @@ async function runInitWizard(cwd) {
|
|
|
3599
3612
|
process.exit(1);
|
|
3600
3613
|
return;
|
|
3601
3614
|
}
|
|
3602
|
-
const outputPath =
|
|
3615
|
+
const outputPath = path9.join(cwd, "plune.yaml");
|
|
3603
3616
|
if (fs11.existsSync(outputPath)) {
|
|
3604
3617
|
const overwrite = await clack.confirm({
|
|
3605
3618
|
message: "plune.yaml already exists. Overwrite?"
|
|
@@ -3643,14 +3656,14 @@ async function runInitWizard(cwd) {
|
|
|
3643
3656
|
spin.stop("plune.yaml created!");
|
|
3644
3657
|
clack.outro("plune.yaml is ready.");
|
|
3645
3658
|
}
|
|
3646
|
-
var clack, fs11,
|
|
3659
|
+
var clack, fs11, path9, import_yaml2;
|
|
3647
3660
|
var init_wizard = __esm({
|
|
3648
3661
|
"src/config/init/wizard.ts"() {
|
|
3649
3662
|
"use strict";
|
|
3650
3663
|
init_cjs_shims();
|
|
3651
3664
|
clack = __toESM(require("@clack/prompts"), 1);
|
|
3652
3665
|
fs11 = __toESM(require("fs"), 1);
|
|
3653
|
-
|
|
3666
|
+
path9 = __toESM(require("path"), 1);
|
|
3654
3667
|
import_yaml2 = require("yaml");
|
|
3655
3668
|
init_errors();
|
|
3656
3669
|
}
|
|
@@ -3658,21 +3671,21 @@ var init_wizard = __esm({
|
|
|
3658
3671
|
|
|
3659
3672
|
// src/cli/templates/index.ts
|
|
3660
3673
|
function writeTemplateFile(cwd, rel, content, force) {
|
|
3661
|
-
const target =
|
|
3674
|
+
const target = path10.join(cwd, rel);
|
|
3662
3675
|
if (!force && fs12.existsSync(target)) {
|
|
3663
3676
|
return "skipped";
|
|
3664
3677
|
}
|
|
3665
|
-
fs12.mkdirSync(
|
|
3678
|
+
fs12.mkdirSync(path10.dirname(target), { recursive: true });
|
|
3666
3679
|
fs12.writeFileSync(target, content, "utf8");
|
|
3667
3680
|
return "written";
|
|
3668
3681
|
}
|
|
3669
|
-
var fs12,
|
|
3682
|
+
var fs12, path10, ENV_EXAMPLE_TPL, EXAMPLE_JSONL_TPL, PLUNE_YAML_TPL;
|
|
3670
3683
|
var init_templates = __esm({
|
|
3671
3684
|
"src/cli/templates/index.ts"() {
|
|
3672
3685
|
"use strict";
|
|
3673
3686
|
init_cjs_shims();
|
|
3674
3687
|
fs12 = __toESM(require("fs"), 1);
|
|
3675
|
-
|
|
3688
|
+
path10 = __toESM(require("path"), 1);
|
|
3676
3689
|
ENV_EXAMPLE_TPL = `# Copy this file to .env and replace the placeholders with your real keys.
|
|
3677
3690
|
# .env is gitignored; .env.example is safe to commit.
|
|
3678
3691
|
# Plune reads whichever key matches your configured provider.
|
|
@@ -3928,7 +3941,7 @@ __export(sync_exports, {
|
|
|
3928
3941
|
reportSyncFailure: () => reportSyncFailure
|
|
3929
3942
|
});
|
|
3930
3943
|
function readRun(cwd, file) {
|
|
3931
|
-
const target = file !== void 0 ?
|
|
3944
|
+
const target = file !== void 0 ? path11.resolve(cwd, file) : path11.join(cwd, ".plune", "last-run.json");
|
|
3932
3945
|
let raw;
|
|
3933
3946
|
try {
|
|
3934
3947
|
raw = fs13.readFileSync(target, "utf8");
|
|
@@ -3995,13 +4008,13 @@ function reportSyncFailure(err, write) {
|
|
|
3995
4008
|
}
|
|
3996
4009
|
return null;
|
|
3997
4010
|
}
|
|
3998
|
-
var fs13,
|
|
4011
|
+
var fs13, path11, NotLoggedInError, TokenRejectedError2, SyncFileError, SyncNetworkError, SyncHttpError;
|
|
3999
4012
|
var init_sync = __esm({
|
|
4000
4013
|
"src/cli/commands/sync.ts"() {
|
|
4001
4014
|
"use strict";
|
|
4002
4015
|
init_cjs_shims();
|
|
4003
4016
|
fs13 = __toESM(require("fs"), 1);
|
|
4004
|
-
|
|
4017
|
+
path11 = __toESM(require("path"), 1);
|
|
4005
4018
|
init_run_result_schema();
|
|
4006
4019
|
init_api_url();
|
|
4007
4020
|
init_credentials();
|
|
@@ -4051,9 +4064,9 @@ async function findLatestCairnRun(runsDir = "runs") {
|
|
|
4051
4064
|
let newest;
|
|
4052
4065
|
for (const entry of entries) {
|
|
4053
4066
|
if (!entry.isDirectory()) continue;
|
|
4054
|
-
const dir =
|
|
4067
|
+
const dir = path12.join(runsDir, entry.name);
|
|
4055
4068
|
try {
|
|
4056
|
-
const report = await fs14.lstat(
|
|
4069
|
+
const report = await fs14.lstat(path12.join(dir, "report.json"));
|
|
4057
4070
|
if (!report.isFile()) continue;
|
|
4058
4071
|
if (newest === void 0 || report.mtimeMs > newest.at) {
|
|
4059
4072
|
newest = { dir, at: report.mtimeMs };
|
|
@@ -4072,7 +4085,7 @@ async function readJson(file) {
|
|
|
4072
4085
|
}
|
|
4073
4086
|
}
|
|
4074
4087
|
async function defaultReadEvidence(dir) {
|
|
4075
|
-
const raw = await readJson(
|
|
4088
|
+
const raw = await readJson(path12.join(dir, "api-evidence.json"));
|
|
4076
4089
|
if (!Array.isArray(raw)) return void 0;
|
|
4077
4090
|
return raw.map((r) => {
|
|
4078
4091
|
const rec = asRecord(r);
|
|
@@ -4114,7 +4127,7 @@ function casesFromApi(report, verdicts) {
|
|
|
4114
4127
|
});
|
|
4115
4128
|
}
|
|
4116
4129
|
async function readCairnRun(dir, deps = {}) {
|
|
4117
|
-
const raw = await readJson(
|
|
4130
|
+
const raw = await readJson(path12.join(dir, "report.json"));
|
|
4118
4131
|
if (raw === void 0) throw new CairnRunNotFoundError(dir);
|
|
4119
4132
|
const report = asRecord(raw);
|
|
4120
4133
|
if (report["schemaVersion"] !== SUPPORTED_ARTIFACT_VERSION) {
|
|
@@ -4144,20 +4157,20 @@ async function readCairnRun(dir, deps = {}) {
|
|
|
4144
4157
|
return {
|
|
4145
4158
|
schemaVersion: INGEST_SCHEMA_VERSION,
|
|
4146
4159
|
run: {
|
|
4147
|
-
runId: str(report["runId"],
|
|
4160
|
+
runId: str(report["runId"], path12.basename(dir)),
|
|
4148
4161
|
mode,
|
|
4149
4162
|
target: str(report["url"], "unknown")
|
|
4150
4163
|
},
|
|
4151
4164
|
cases
|
|
4152
4165
|
};
|
|
4153
4166
|
}
|
|
4154
|
-
var fs14,
|
|
4167
|
+
var fs14, path12, SUPPORTED_ARTIFACT_VERSION, INGEST_SCHEMA_VERSION, NoCairnRunsError, CairnRunNotFoundError, CairnRunVersionError, CairnRunPartialError, CairnEvidenceAmbiguousError, asRecord, str;
|
|
4155
4168
|
var init_cairn_artifact = __esm({
|
|
4156
4169
|
"src/cli/commands/cairn-artifact.ts"() {
|
|
4157
4170
|
"use strict";
|
|
4158
4171
|
init_cjs_shims();
|
|
4159
4172
|
fs14 = __toESM(require("fs/promises"), 1);
|
|
4160
|
-
|
|
4173
|
+
path12 = __toESM(require("path"), 1);
|
|
4161
4174
|
SUPPORTED_ARTIFACT_VERSION = 1;
|
|
4162
4175
|
INGEST_SCHEMA_VERSION = 1;
|
|
4163
4176
|
NoCairnRunsError = class extends Error {
|
|
@@ -4613,10 +4626,10 @@ function createProgram() {
|
|
|
4613
4626
|
const { handleLogin: handleLogin2, reportLoginFailure: reportLoginFailure2 } = await Promise.resolve().then(() => (init_login(), login_exports));
|
|
4614
4627
|
try {
|
|
4615
4628
|
const token = options.token ?? await readTokenFromStdin();
|
|
4616
|
-
const { path:
|
|
4629
|
+
const { path: path13, verified } = await handleLogin2({ token, skipVerify: options.skipVerify });
|
|
4617
4630
|
process.stdout.write(
|
|
4618
|
-
verified ? `Logged in. Token checked against the API and saved to ${
|
|
4619
|
-
` : `Token saved to ${
|
|
4631
|
+
verified ? `Logged in. Token checked against the API and saved to ${path13}
|
|
4632
|
+
` : `Token saved to ${path13} WITHOUT being checked (--skip-verify).
|
|
4620
4633
|
`
|
|
4621
4634
|
);
|
|
4622
4635
|
} catch (err) {
|
|
@@ -4633,9 +4646,9 @@ function createProgram() {
|
|
|
4633
4646
|
const verbose = command.optsWithGlobals().verbose === true;
|
|
4634
4647
|
const { handleLogout: handleLogout2 } = await Promise.resolve().then(() => (init_logout(), logout_exports));
|
|
4635
4648
|
try {
|
|
4636
|
-
const { removed, path:
|
|
4649
|
+
const { removed, path: path13 } = handleLogout2();
|
|
4637
4650
|
process.stdout.write(
|
|
4638
|
-
removed ? `Logged out. Removed ${
|
|
4651
|
+
removed ? `Logged out. Removed ${path13}
|
|
4639
4652
|
` : "Not logged in \u2014 nothing to remove.\n"
|
|
4640
4653
|
);
|
|
4641
4654
|
} catch (err) {
|
package/dist/reporter-core.cjs
CHANGED
|
@@ -97,7 +97,7 @@ function createClient(opts) {
|
|
|
97
97
|
const wait = opts.wait ?? sleep;
|
|
98
98
|
const base = opts.apiUrl.replace(/\/+$/, "");
|
|
99
99
|
const scrub = (text) => opts.token === "" ? text : text.split(opts.token).join("***");
|
|
100
|
-
async function send(method,
|
|
100
|
+
async function send(method, path3, body) {
|
|
101
101
|
let last = {
|
|
102
102
|
kind: "unavailable",
|
|
103
103
|
status: null,
|
|
@@ -106,7 +106,7 @@ function createClient(opts) {
|
|
|
106
106
|
for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt += 1) {
|
|
107
107
|
let res;
|
|
108
108
|
try {
|
|
109
|
-
res = await doFetch(`${base}${
|
|
109
|
+
res = await doFetch(`${base}${path3}`, {
|
|
110
110
|
method,
|
|
111
111
|
headers: { "content-type": "application/json", authorization: `Bearer ${opts.token}` },
|
|
112
112
|
// A DELETE carries none. Sending `"undefined"` as a body is what a naive
|
|
@@ -134,12 +134,13 @@ function createClient(opts) {
|
|
|
134
134
|
return { ok: false, ...last };
|
|
135
135
|
}
|
|
136
136
|
return {
|
|
137
|
-
post: (
|
|
138
|
-
del: (
|
|
137
|
+
post: (path3, body) => send("POST", path3, body),
|
|
138
|
+
del: (path3) => send("DELETE", path3)
|
|
139
139
|
};
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// src/reporter-core/env.ts
|
|
143
|
+
var path = __toESM(require("path"), 1);
|
|
143
144
|
var UNSUPPORTED_VARS = ["PLUNE_GROUP"];
|
|
144
145
|
function value(env, name) {
|
|
145
146
|
const raw = env[name]?.trim();
|
|
@@ -192,13 +193,19 @@ function readEnv(env = process.env) {
|
|
|
192
193
|
ignored: UNSUPPORTED_VARS.filter((name) => value(env, name) !== void 0)
|
|
193
194
|
};
|
|
194
195
|
}
|
|
196
|
+
function defaultRunTitle(env = process.env, now = /* @__PURE__ */ new Date(), cwd = process.cwd()) {
|
|
197
|
+
const two = (n) => String(n).padStart(2, "0");
|
|
198
|
+
const stamp = `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())} ${two(now.getHours())}:${two(now.getMinutes())}`;
|
|
199
|
+
const where = flag(env, "CI") || flag(env, "GITHUB_ACTIONS") ? "ci" : "local";
|
|
200
|
+
return `${path.basename(cwd)} \xB7 ${stamp} \xB7 ${where}`;
|
|
201
|
+
}
|
|
195
202
|
|
|
196
203
|
// src/reporter-core/fallback.ts
|
|
197
204
|
var fs = __toESM(require("fs"), 1);
|
|
198
|
-
var
|
|
199
|
-
var DEFAULT_FALLBACK_PATH =
|
|
205
|
+
var path2 = __toESM(require("path"), 1);
|
|
206
|
+
var DEFAULT_FALLBACK_PATH = path2.join(".plune", "pending-results.jsonl");
|
|
200
207
|
function appendBatch(file, batch) {
|
|
201
|
-
fs.mkdirSync(
|
|
208
|
+
fs.mkdirSync(path2.dirname(file), { recursive: true });
|
|
202
209
|
const line = {
|
|
203
210
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
204
211
|
runId: batch.runId,
|
|
@@ -339,6 +346,10 @@ async function startRun(passed, declared) {
|
|
|
339
346
|
...externalKey !== null ? { externalKey } : {},
|
|
340
347
|
...cfg.meta !== void 0 ? { meta: cfg.meta } : {},
|
|
341
348
|
...configuration !== void 0 ? { configuration } : {},
|
|
349
|
+
// Named even when nobody named it — the list has to read without opening a row. Only what
|
|
350
|
+
// the caller DESCRIBED goes to `warnIfDropped` below: a title this side invented is not one
|
|
351
|
+
// a person will miss, and a deployment older than the field must not be nagged on every run.
|
|
352
|
+
title: defaultRunTitle(),
|
|
342
353
|
...described
|
|
343
354
|
});
|
|
344
355
|
if (start.ok) {
|
package/dist/reporter-core.js
CHANGED
|
@@ -54,7 +54,7 @@ function createClient(opts) {
|
|
|
54
54
|
const wait = opts.wait ?? sleep;
|
|
55
55
|
const base = opts.apiUrl.replace(/\/+$/, "");
|
|
56
56
|
const scrub = (text) => opts.token === "" ? text : text.split(opts.token).join("***");
|
|
57
|
-
async function send(method,
|
|
57
|
+
async function send(method, path3, body) {
|
|
58
58
|
let last = {
|
|
59
59
|
kind: "unavailable",
|
|
60
60
|
status: null,
|
|
@@ -63,7 +63,7 @@ function createClient(opts) {
|
|
|
63
63
|
for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt += 1) {
|
|
64
64
|
let res;
|
|
65
65
|
try {
|
|
66
|
-
res = await doFetch(`${base}${
|
|
66
|
+
res = await doFetch(`${base}${path3}`, {
|
|
67
67
|
method,
|
|
68
68
|
headers: { "content-type": "application/json", authorization: `Bearer ${opts.token}` },
|
|
69
69
|
// A DELETE carries none. Sending `"undefined"` as a body is what a naive
|
|
@@ -91,12 +91,13 @@ function createClient(opts) {
|
|
|
91
91
|
return { ok: false, ...last };
|
|
92
92
|
}
|
|
93
93
|
return {
|
|
94
|
-
post: (
|
|
95
|
-
del: (
|
|
94
|
+
post: (path3, body) => send("POST", path3, body),
|
|
95
|
+
del: (path3) => send("DELETE", path3)
|
|
96
96
|
};
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
// src/reporter-core/env.ts
|
|
100
|
+
import * as path from "path";
|
|
100
101
|
var UNSUPPORTED_VARS = ["PLUNE_GROUP"];
|
|
101
102
|
function value(env, name) {
|
|
102
103
|
const raw = env[name]?.trim();
|
|
@@ -149,13 +150,19 @@ function readEnv(env = process.env) {
|
|
|
149
150
|
ignored: UNSUPPORTED_VARS.filter((name) => value(env, name) !== void 0)
|
|
150
151
|
};
|
|
151
152
|
}
|
|
153
|
+
function defaultRunTitle(env = process.env, now = /* @__PURE__ */ new Date(), cwd = process.cwd()) {
|
|
154
|
+
const two = (n) => String(n).padStart(2, "0");
|
|
155
|
+
const stamp = `${now.getFullYear()}-${two(now.getMonth() + 1)}-${two(now.getDate())} ${two(now.getHours())}:${two(now.getMinutes())}`;
|
|
156
|
+
const where = flag(env, "CI") || flag(env, "GITHUB_ACTIONS") ? "ci" : "local";
|
|
157
|
+
return `${path.basename(cwd)} \xB7 ${stamp} \xB7 ${where}`;
|
|
158
|
+
}
|
|
152
159
|
|
|
153
160
|
// src/reporter-core/fallback.ts
|
|
154
161
|
import * as fs from "fs";
|
|
155
|
-
import * as
|
|
156
|
-
var DEFAULT_FALLBACK_PATH =
|
|
162
|
+
import * as path2 from "path";
|
|
163
|
+
var DEFAULT_FALLBACK_PATH = path2.join(".plune", "pending-results.jsonl");
|
|
157
164
|
function appendBatch(file, batch) {
|
|
158
|
-
fs.mkdirSync(
|
|
165
|
+
fs.mkdirSync(path2.dirname(file), { recursive: true });
|
|
159
166
|
const line = {
|
|
160
167
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
161
168
|
runId: batch.runId,
|
|
@@ -296,6 +303,10 @@ async function startRun(passed, declared) {
|
|
|
296
303
|
...externalKey !== null ? { externalKey } : {},
|
|
297
304
|
...cfg.meta !== void 0 ? { meta: cfg.meta } : {},
|
|
298
305
|
...configuration !== void 0 ? { configuration } : {},
|
|
306
|
+
// Named even when nobody named it — the list has to read without opening a row. Only what
|
|
307
|
+
// the caller DESCRIBED goes to `warnIfDropped` below: a title this side invented is not one
|
|
308
|
+
// a person will miss, and a deployment older than the field must not be nagged on every run.
|
|
309
|
+
title: defaultRunTitle(),
|
|
299
310
|
...described
|
|
300
311
|
});
|
|
301
312
|
if (start.ok) {
|
package/package.json
CHANGED