@plune-ai/cli 0.30.1 → 0.30.2
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 +1 -1
- package/dist/cli.cjs +37 -19
- package/dist/index.cjs +31 -17
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +31 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -121,7 +121,7 @@ the last resort, used only when `PLUNE_TOKEN` is set nowhere else. Nothing write
|
|
|
121
121
|
| `plune init` | Scaffold `plune.yaml`, a sample dataset, and `.env.example`. Flags: `--yes` (non-interactive), `--force`. |
|
|
122
122
|
| `plune login` | Save a [Plune platform](https://plune.ai/platform) API token so `sync` and `ingest` can reach it. The token is **checked against the API before it is saved**, so a wrong one fails here rather than two commands later. Get one at `https://beta.plune.ai` → Account → API tokens. Flags: `--token <token>` (omit to paste it or pipe it via stdin), `--skip-verify` (save without checking, for offline setup). In CI, skip this step: every platform command reads `PLUNE_TOKEN` from the environment first, and the saved login only when it is not set. |
|
|
123
123
|
| `plune logout` | Remove the saved token. |
|
|
124
|
-
| `plune sync` | Upload the latest local run to the platform. Flags: `--file <path>` to send a specific run JSON, `--fail-on-failures` to read the run's summary back once after the upload and exit with [the gate](#a-release-gate---fail-on-failures)'s code. Each upload carries an `Idempotency-Key` (SHA-256 of the body), so sending the same run again returns the same run rather than creating a second one. Against a platform with `POST /v1/jobs` the upload is also reported as a job (kind `
|
|
124
|
+
| `plune sync` | Upload the latest local run to the platform. Flags: `--file <path>` to send a specific run JSON, `--fail-on-failures` to read the run's summary back once after the upload and exit with [the gate](#a-release-gate---fail-on-failures)'s code. Each upload carries an `Idempotency-Key` (SHA-256 of the body), so sending the same run again returns the same run rather than creating a second one. Against a platform with `POST /v1/jobs` the upload is also reported as a job (kind `sync`, counting the run's rows) that ends completed, or failed with the error text if the sync fails; an older platform without the route is not told, and a job report never fails the sync: when the sync goes through, one the platform did not take is said in one line on stderr. |
|
|
125
125
|
| `plune run import <file>` | Turn a **JUnit XML** or **Playwright JSON** report, or an **Allure `allure-results` folder**, into a run in Plune. Needs no provider key — nothing is generated. Flags: `--format junit\|playwright-json\|allure` (detected from the file when omitted; a folder is Allure), `--name <text>` to call the run something other than the [folder-based default](#what-the-run-is-called), `--key <externalKey>` to land several reports in one run (with `PLUNE_SHARED_RUN=1` — see below), `--create` to offer unmatched tests to the review queue, `--fail-on-missing-attachments` to exit 1 when a file a JUnit report names with `[[ATTACHMENT\|path]]`, or an Allure result names as a `source`, is not there (the results are sent either way), `--upload-concurrency <n>` for files uploaded at once ([1 to 32, default 16](#many-screenshots-upload-concurrency-and-retries)), `--fail-on-failures` to exit with [the gate](#a-release-gate---fail-on-failures)'s code on the summary the platform froze when this import finished the run. |
|
|
126
126
|
| `plune run start` | Open a platform run — or join the one already carrying `--key` — and print its id. Flags: `--key <externalKey>` (generated when absent), `--name <text>` to call the run something other than the [default](#what-the-run-is-called), `--json` for one machine-readable line. |
|
|
127
127
|
| `plune run finish <id>` | Close a platform run. This is what the reporter tells you to do for a run it had to leave open. Flags: `--terminate` to record it as cut short, `--reason <text>`, `--fail-on-failures` to exit with [the gate](#a-release-gate---fail-on-failures)'s code on the summary the platform froze. |
|
package/dist/cli.cjs
CHANGED
|
@@ -4376,10 +4376,11 @@ async function handleSync(deps = {}) {
|
|
|
4376
4376
|
const idempotencyKey = (0, import_node_crypto4.createHash)("sha256").update(payload).digest("hex");
|
|
4377
4377
|
const bearer = token;
|
|
4378
4378
|
const job = new JobReporter(doFetch, apiUrl, bearer);
|
|
4379
|
-
await job.open(path9.basename(deps.file !== void 0 ? path9.resolve(cwd, deps.file) : cwd));
|
|
4379
|
+
await job.open(path9.basename(deps.file !== void 0 ? path9.resolve(cwd, deps.file) : cwd), run.summary.total);
|
|
4380
4380
|
try {
|
|
4381
4381
|
const result = await upload();
|
|
4382
4382
|
await job.finish({ ok: true });
|
|
4383
|
+
if (job.problem !== void 0) result.jobProblem = job.problem;
|
|
4383
4384
|
return result;
|
|
4384
4385
|
} catch (err) {
|
|
4385
4386
|
await job.finish({ ok: false, reason: err instanceof Error ? err.message : "Sync failed." });
|
|
@@ -4408,7 +4409,7 @@ async function handleSync(deps = {}) {
|
|
|
4408
4409
|
const body = await res.json().catch(() => ({}));
|
|
4409
4410
|
const id = typeof body.id === "string" ? body.id : "";
|
|
4410
4411
|
const result = { id, url: `${endpoint}/${id}` };
|
|
4411
|
-
await job.
|
|
4412
|
+
await job.uploaded(id || void 0);
|
|
4412
4413
|
if (deps.failOnFailures === true) {
|
|
4413
4414
|
result.gate = gateExit(await readVerdict(doFetch, `${endpoint}/${id}/summary`, bearer));
|
|
4414
4415
|
}
|
|
@@ -4435,7 +4436,7 @@ function reportSyncFailure(err, write) {
|
|
|
4435
4436
|
}
|
|
4436
4437
|
return null;
|
|
4437
4438
|
}
|
|
4438
|
-
var import_node_crypto4, fs8, path9, NotLoggedInError, TokenRejectedError, SyncFileError, SyncNetworkError, SyncHttpError, JOB_KIND, JOB_TIMEOUT_MS, JobReporter;
|
|
4439
|
+
var import_node_crypto4, fs8, path9, NotLoggedInError, TokenRejectedError, SyncFileError, SyncNetworkError, SyncHttpError, JOB_KIND, JOB_TIMEOUT_MS, JOB_SUBJECT_NAME_MAX, JOB_REASON_MAX, JobReporter;
|
|
4439
4440
|
var init_sync = __esm({
|
|
4440
4441
|
"src/cli/commands/sync.ts"() {
|
|
4441
4442
|
"use strict";
|
|
@@ -4483,8 +4484,10 @@ var init_sync = __esm({
|
|
|
4483
4484
|
}
|
|
4484
4485
|
status;
|
|
4485
4486
|
};
|
|
4486
|
-
JOB_KIND = "
|
|
4487
|
+
JOB_KIND = "sync";
|
|
4487
4488
|
JOB_TIMEOUT_MS = 5e3;
|
|
4489
|
+
JOB_SUBJECT_NAME_MAX = 200;
|
|
4490
|
+
JOB_REASON_MAX = 2e3;
|
|
4488
4491
|
JobReporter = class {
|
|
4489
4492
|
constructor(doFetch, base, token) {
|
|
4490
4493
|
this.doFetch = doFetch;
|
|
@@ -4495,32 +4498,43 @@ var init_sync = __esm({
|
|
|
4495
4498
|
base;
|
|
4496
4499
|
token;
|
|
4497
4500
|
id;
|
|
4498
|
-
|
|
4501
|
+
/** The run's rows, the job's `total`; `null` while there are none to count. */
|
|
4502
|
+
size = null;
|
|
4503
|
+
/** The first report the platform did not take, for the CLI to say once. */
|
|
4504
|
+
problem;
|
|
4505
|
+
async send(method, route, body) {
|
|
4499
4506
|
try {
|
|
4500
|
-
const res = await this.doFetch(
|
|
4507
|
+
const res = await this.doFetch(`${this.base}/v1/jobs${route}`, {
|
|
4501
4508
|
method,
|
|
4502
4509
|
headers: { "content-type": "application/json", authorization: `Bearer ${this.token}` },
|
|
4503
4510
|
body: JSON.stringify(body),
|
|
4504
4511
|
signal: AbortSignal.timeout(JOB_TIMEOUT_MS)
|
|
4505
4512
|
});
|
|
4506
4513
|
const json = await res.json().catch(() => void 0);
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4514
|
+
if (res.ok) return json ?? {};
|
|
4515
|
+
if (route === "" && (res.status === 404 || res.status === 405)) return void 0;
|
|
4516
|
+
this.problem ??= `HTTP ${res.status}${typeof json?.error === "string" ? ` \u2014 ${json.error}` : ""}`;
|
|
4517
|
+
} catch (err) {
|
|
4518
|
+
this.problem ??= err instanceof Error ? err.message : String(err);
|
|
4510
4519
|
}
|
|
4520
|
+
return void 0;
|
|
4511
4521
|
}
|
|
4512
|
-
async open(subjectName) {
|
|
4513
|
-
|
|
4522
|
+
async open(subjectName, rows) {
|
|
4523
|
+
this.size = Number.isInteger(rows) && rows > 0 ? rows : null;
|
|
4524
|
+
const name = subjectName.trim().slice(0, JOB_SUBJECT_NAME_MAX);
|
|
4525
|
+
const body = await this.send("POST", "", {
|
|
4514
4526
|
kind: JOB_KIND,
|
|
4515
|
-
subjectName,
|
|
4516
|
-
progress: 0
|
|
4527
|
+
...name !== "" ? { subjectName: name } : {},
|
|
4528
|
+
...this.size !== null ? { progress: { done: 0, total: this.size } } : {}
|
|
4517
4529
|
});
|
|
4518
4530
|
if (typeof body?.id === "string") this.id = body.id;
|
|
4519
4531
|
}
|
|
4520
|
-
|
|
4532
|
+
/** The upload is in: every row of the run is on the platform. */
|
|
4533
|
+
async uploaded(cursor) {
|
|
4521
4534
|
if (this.id === void 0) return;
|
|
4522
|
-
await this.send("PATCH",
|
|
4523
|
-
|
|
4535
|
+
await this.send("PATCH", `/${encodeURIComponent(this.id)}/progress`, {
|
|
4536
|
+
done: this.size,
|
|
4537
|
+
total: this.size,
|
|
4524
4538
|
...cursor !== void 0 ? { cursor } : {}
|
|
4525
4539
|
});
|
|
4526
4540
|
}
|
|
@@ -4530,8 +4544,8 @@ var init_sync = __esm({
|
|
|
4530
4544
|
this.id = void 0;
|
|
4531
4545
|
await this.send(
|
|
4532
4546
|
"PATCH",
|
|
4533
|
-
|
|
4534
|
-
outcome.ok ? {
|
|
4547
|
+
`/${encodeURIComponent(id)}/state`,
|
|
4548
|
+
outcome.ok ? { state: "completed" } : { state: "failed", reason: outcome.reason.slice(0, JOB_REASON_MAX) }
|
|
4535
4549
|
);
|
|
4536
4550
|
}
|
|
4537
4551
|
};
|
|
@@ -7665,13 +7679,17 @@ ${missed.map((m) => ` - ${m}`).join("\n")}
|
|
|
7665
7679
|
const { handleSync: handleSync2, reportSyncFailure: reportSyncFailure2 } = await Promise.resolve().then(() => (init_sync(), sync_exports));
|
|
7666
7680
|
const cwd = globals.config !== void 0 ? (0, import_node_path6.dirname)((0, import_node_path6.resolve)(globals.config)) : process.cwd();
|
|
7667
7681
|
try {
|
|
7668
|
-
const { id, url, gate } = await handleSync2({
|
|
7682
|
+
const { id, url, gate, jobProblem } = await handleSync2({
|
|
7669
7683
|
cwd,
|
|
7670
7684
|
...options.file !== void 0 ? { file: options.file } : {},
|
|
7671
7685
|
...options.failOnFailures ? { failOnFailures: true } : {}
|
|
7672
7686
|
});
|
|
7673
7687
|
process.stdout.write(`Synced run ${id} \u2192 ${url}
|
|
7674
7688
|
`);
|
|
7689
|
+
if (jobProblem !== void 0) {
|
|
7690
|
+
process.stderr.write(`plune: could not report this sync to the job queue (${jobProblem}) \u2014 the run is uploaded.
|
|
7691
|
+
`);
|
|
7692
|
+
}
|
|
7675
7693
|
if (gate !== void 0) {
|
|
7676
7694
|
process.stdout.write(`${gate.line}
|
|
7677
7695
|
`);
|
package/dist/index.cjs
CHANGED
|
@@ -1892,8 +1892,10 @@ var SyncHttpError = class extends Error {
|
|
|
1892
1892
|
}
|
|
1893
1893
|
status;
|
|
1894
1894
|
};
|
|
1895
|
-
var JOB_KIND = "
|
|
1895
|
+
var JOB_KIND = "sync";
|
|
1896
1896
|
var JOB_TIMEOUT_MS = 5e3;
|
|
1897
|
+
var JOB_SUBJECT_NAME_MAX = 200;
|
|
1898
|
+
var JOB_REASON_MAX = 2e3;
|
|
1897
1899
|
var JobReporter = class {
|
|
1898
1900
|
constructor(doFetch, base, token) {
|
|
1899
1901
|
this.doFetch = doFetch;
|
|
@@ -1904,32 +1906,43 @@ var JobReporter = class {
|
|
|
1904
1906
|
base;
|
|
1905
1907
|
token;
|
|
1906
1908
|
id;
|
|
1907
|
-
|
|
1909
|
+
/** The run's rows, the job's `total`; `null` while there are none to count. */
|
|
1910
|
+
size = null;
|
|
1911
|
+
/** The first report the platform did not take, for the CLI to say once. */
|
|
1912
|
+
problem;
|
|
1913
|
+
async send(method, route, body) {
|
|
1908
1914
|
try {
|
|
1909
|
-
const res = await this.doFetch(
|
|
1915
|
+
const res = await this.doFetch(`${this.base}/v1/jobs${route}`, {
|
|
1910
1916
|
method,
|
|
1911
1917
|
headers: { "content-type": "application/json", authorization: `Bearer ${this.token}` },
|
|
1912
1918
|
body: JSON.stringify(body),
|
|
1913
1919
|
signal: AbortSignal.timeout(JOB_TIMEOUT_MS)
|
|
1914
1920
|
});
|
|
1915
1921
|
const json = await res.json().catch(() => void 0);
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1922
|
+
if (res.ok) return json ?? {};
|
|
1923
|
+
if (route === "" && (res.status === 404 || res.status === 405)) return void 0;
|
|
1924
|
+
this.problem ??= `HTTP ${res.status}${typeof json?.error === "string" ? ` \u2014 ${json.error}` : ""}`;
|
|
1925
|
+
} catch (err) {
|
|
1926
|
+
this.problem ??= err instanceof Error ? err.message : String(err);
|
|
1919
1927
|
}
|
|
1928
|
+
return void 0;
|
|
1920
1929
|
}
|
|
1921
|
-
async open(subjectName) {
|
|
1922
|
-
|
|
1930
|
+
async open(subjectName, rows) {
|
|
1931
|
+
this.size = Number.isInteger(rows) && rows > 0 ? rows : null;
|
|
1932
|
+
const name = subjectName.trim().slice(0, JOB_SUBJECT_NAME_MAX);
|
|
1933
|
+
const body = await this.send("POST", "", {
|
|
1923
1934
|
kind: JOB_KIND,
|
|
1924
|
-
subjectName,
|
|
1925
|
-
progress: 0
|
|
1935
|
+
...name !== "" ? { subjectName: name } : {},
|
|
1936
|
+
...this.size !== null ? { progress: { done: 0, total: this.size } } : {}
|
|
1926
1937
|
});
|
|
1927
1938
|
if (typeof body?.id === "string") this.id = body.id;
|
|
1928
1939
|
}
|
|
1929
|
-
|
|
1940
|
+
/** The upload is in: every row of the run is on the platform. */
|
|
1941
|
+
async uploaded(cursor) {
|
|
1930
1942
|
if (this.id === void 0) return;
|
|
1931
|
-
await this.send("PATCH",
|
|
1932
|
-
|
|
1943
|
+
await this.send("PATCH", `/${encodeURIComponent(this.id)}/progress`, {
|
|
1944
|
+
done: this.size,
|
|
1945
|
+
total: this.size,
|
|
1933
1946
|
...cursor !== void 0 ? { cursor } : {}
|
|
1934
1947
|
});
|
|
1935
1948
|
}
|
|
@@ -1939,8 +1952,8 @@ var JobReporter = class {
|
|
|
1939
1952
|
this.id = void 0;
|
|
1940
1953
|
await this.send(
|
|
1941
1954
|
"PATCH",
|
|
1942
|
-
|
|
1943
|
-
outcome.ok ? {
|
|
1955
|
+
`/${encodeURIComponent(id)}/state`,
|
|
1956
|
+
outcome.ok ? { state: "completed" } : { state: "failed", reason: outcome.reason.slice(0, JOB_REASON_MAX) }
|
|
1944
1957
|
);
|
|
1945
1958
|
}
|
|
1946
1959
|
};
|
|
@@ -1986,10 +1999,11 @@ async function handleSync(deps = {}) {
|
|
|
1986
1999
|
const idempotencyKey = (0, import_node_crypto2.createHash)("sha256").update(payload).digest("hex");
|
|
1987
2000
|
const bearer = token;
|
|
1988
2001
|
const job = new JobReporter(doFetch, apiUrl, bearer);
|
|
1989
|
-
await job.open(path5.basename(deps.file !== void 0 ? path5.resolve(cwd, deps.file) : cwd));
|
|
2002
|
+
await job.open(path5.basename(deps.file !== void 0 ? path5.resolve(cwd, deps.file) : cwd), run.summary.total);
|
|
1990
2003
|
try {
|
|
1991
2004
|
const result = await upload();
|
|
1992
2005
|
await job.finish({ ok: true });
|
|
2006
|
+
if (job.problem !== void 0) result.jobProblem = job.problem;
|
|
1993
2007
|
return result;
|
|
1994
2008
|
} catch (err) {
|
|
1995
2009
|
await job.finish({ ok: false, reason: err instanceof Error ? err.message : "Sync failed." });
|
|
@@ -2018,7 +2032,7 @@ async function handleSync(deps = {}) {
|
|
|
2018
2032
|
const body = await res.json().catch(() => ({}));
|
|
2019
2033
|
const id = typeof body.id === "string" ? body.id : "";
|
|
2020
2034
|
const result = { id, url: `${endpoint}/${id}` };
|
|
2021
|
-
await job.
|
|
2035
|
+
await job.uploaded(id || void 0);
|
|
2022
2036
|
if (deps.failOnFailures === true) {
|
|
2023
2037
|
result.gate = gateExit(await readVerdict(doFetch, `${endpoint}/${id}/summary`, bearer));
|
|
2024
2038
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -364,6 +364,8 @@ interface SyncResult {
|
|
|
364
364
|
code: number;
|
|
365
365
|
line: string;
|
|
366
366
|
};
|
|
367
|
+
/** Why the platform's job queue did not take this sync's report: the first refusal or error. The upload went in. */
|
|
368
|
+
jobProblem?: string;
|
|
367
369
|
}
|
|
368
370
|
/**
|
|
369
371
|
* Upload the latest (or `--file`) local run to `POST {apiUrl}/v1/runs` with the stored Bearer token.
|
package/dist/index.d.ts
CHANGED
|
@@ -364,6 +364,8 @@ interface SyncResult {
|
|
|
364
364
|
code: number;
|
|
365
365
|
line: string;
|
|
366
366
|
};
|
|
367
|
+
/** Why the platform's job queue did not take this sync's report: the first refusal or error. The upload went in. */
|
|
368
|
+
jobProblem?: string;
|
|
367
369
|
}
|
|
368
370
|
/**
|
|
369
371
|
* Upload the latest (or `--file`) local run to `POST {apiUrl}/v1/runs` with the stored Bearer token.
|
package/dist/index.js
CHANGED
|
@@ -1832,8 +1832,10 @@ var SyncHttpError = class extends Error {
|
|
|
1832
1832
|
}
|
|
1833
1833
|
status;
|
|
1834
1834
|
};
|
|
1835
|
-
var JOB_KIND = "
|
|
1835
|
+
var JOB_KIND = "sync";
|
|
1836
1836
|
var JOB_TIMEOUT_MS = 5e3;
|
|
1837
|
+
var JOB_SUBJECT_NAME_MAX = 200;
|
|
1838
|
+
var JOB_REASON_MAX = 2e3;
|
|
1837
1839
|
var JobReporter = class {
|
|
1838
1840
|
constructor(doFetch, base, token) {
|
|
1839
1841
|
this.doFetch = doFetch;
|
|
@@ -1844,32 +1846,43 @@ var JobReporter = class {
|
|
|
1844
1846
|
base;
|
|
1845
1847
|
token;
|
|
1846
1848
|
id;
|
|
1847
|
-
|
|
1849
|
+
/** The run's rows, the job's `total`; `null` while there are none to count. */
|
|
1850
|
+
size = null;
|
|
1851
|
+
/** The first report the platform did not take, for the CLI to say once. */
|
|
1852
|
+
problem;
|
|
1853
|
+
async send(method, route, body) {
|
|
1848
1854
|
try {
|
|
1849
|
-
const res = await this.doFetch(
|
|
1855
|
+
const res = await this.doFetch(`${this.base}/v1/jobs${route}`, {
|
|
1850
1856
|
method,
|
|
1851
1857
|
headers: { "content-type": "application/json", authorization: `Bearer ${this.token}` },
|
|
1852
1858
|
body: JSON.stringify(body),
|
|
1853
1859
|
signal: AbortSignal.timeout(JOB_TIMEOUT_MS)
|
|
1854
1860
|
});
|
|
1855
1861
|
const json = await res.json().catch(() => void 0);
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1862
|
+
if (res.ok) return json ?? {};
|
|
1863
|
+
if (route === "" && (res.status === 404 || res.status === 405)) return void 0;
|
|
1864
|
+
this.problem ??= `HTTP ${res.status}${typeof json?.error === "string" ? ` \u2014 ${json.error}` : ""}`;
|
|
1865
|
+
} catch (err) {
|
|
1866
|
+
this.problem ??= err instanceof Error ? err.message : String(err);
|
|
1859
1867
|
}
|
|
1868
|
+
return void 0;
|
|
1860
1869
|
}
|
|
1861
|
-
async open(subjectName) {
|
|
1862
|
-
|
|
1870
|
+
async open(subjectName, rows) {
|
|
1871
|
+
this.size = Number.isInteger(rows) && rows > 0 ? rows : null;
|
|
1872
|
+
const name = subjectName.trim().slice(0, JOB_SUBJECT_NAME_MAX);
|
|
1873
|
+
const body = await this.send("POST", "", {
|
|
1863
1874
|
kind: JOB_KIND,
|
|
1864
|
-
subjectName,
|
|
1865
|
-
progress: 0
|
|
1875
|
+
...name !== "" ? { subjectName: name } : {},
|
|
1876
|
+
...this.size !== null ? { progress: { done: 0, total: this.size } } : {}
|
|
1866
1877
|
});
|
|
1867
1878
|
if (typeof body?.id === "string") this.id = body.id;
|
|
1868
1879
|
}
|
|
1869
|
-
|
|
1880
|
+
/** The upload is in: every row of the run is on the platform. */
|
|
1881
|
+
async uploaded(cursor) {
|
|
1870
1882
|
if (this.id === void 0) return;
|
|
1871
|
-
await this.send("PATCH",
|
|
1872
|
-
|
|
1883
|
+
await this.send("PATCH", `/${encodeURIComponent(this.id)}/progress`, {
|
|
1884
|
+
done: this.size,
|
|
1885
|
+
total: this.size,
|
|
1873
1886
|
...cursor !== void 0 ? { cursor } : {}
|
|
1874
1887
|
});
|
|
1875
1888
|
}
|
|
@@ -1879,8 +1892,8 @@ var JobReporter = class {
|
|
|
1879
1892
|
this.id = void 0;
|
|
1880
1893
|
await this.send(
|
|
1881
1894
|
"PATCH",
|
|
1882
|
-
|
|
1883
|
-
outcome.ok ? {
|
|
1895
|
+
`/${encodeURIComponent(id)}/state`,
|
|
1896
|
+
outcome.ok ? { state: "completed" } : { state: "failed", reason: outcome.reason.slice(0, JOB_REASON_MAX) }
|
|
1884
1897
|
);
|
|
1885
1898
|
}
|
|
1886
1899
|
};
|
|
@@ -1926,10 +1939,11 @@ async function handleSync(deps = {}) {
|
|
|
1926
1939
|
const idempotencyKey = createHash2("sha256").update(payload).digest("hex");
|
|
1927
1940
|
const bearer = token;
|
|
1928
1941
|
const job = new JobReporter(doFetch, apiUrl, bearer);
|
|
1929
|
-
await job.open(path5.basename(deps.file !== void 0 ? path5.resolve(cwd, deps.file) : cwd));
|
|
1942
|
+
await job.open(path5.basename(deps.file !== void 0 ? path5.resolve(cwd, deps.file) : cwd), run.summary.total);
|
|
1930
1943
|
try {
|
|
1931
1944
|
const result = await upload();
|
|
1932
1945
|
await job.finish({ ok: true });
|
|
1946
|
+
if (job.problem !== void 0) result.jobProblem = job.problem;
|
|
1933
1947
|
return result;
|
|
1934
1948
|
} catch (err) {
|
|
1935
1949
|
await job.finish({ ok: false, reason: err instanceof Error ? err.message : "Sync failed." });
|
|
@@ -1958,7 +1972,7 @@ async function handleSync(deps = {}) {
|
|
|
1958
1972
|
const body = await res.json().catch(() => ({}));
|
|
1959
1973
|
const id = typeof body.id === "string" ? body.id : "";
|
|
1960
1974
|
const result = { id, url: `${endpoint}/${id}` };
|
|
1961
|
-
await job.
|
|
1975
|
+
await job.uploaded(id || void 0);
|
|
1962
1976
|
if (deps.failOnFailures === true) {
|
|
1963
1977
|
result.gate = gateExit(await readVerdict(doFetch, `${endpoint}/${id}/summary`, bearer));
|
|
1964
1978
|
}
|
package/package.json
CHANGED