@flakiness/sdk 0.129.4 → 0.130.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/lib/cli/cli.js +109 -44
- package/lib/cli/cmd-convert.js +3 -3
- package/lib/cli/cmd-show-report.js +45 -21
- package/lib/junit.js +3 -3
- package/lib/localReportApi.js +207 -5
- package/lib/localReportServer.js +76 -52
- package/lib/playwright-test.js +70 -46
- package/package.json +10 -5
- package/types/tsconfig.tsbuildinfo +1 -1
package/lib/cli/cli.js
CHANGED
|
@@ -737,8 +737,50 @@ var Ranges;
|
|
|
737
737
|
import { TypedHTTP as TypedHTTP4 } from "@flakiness/shared/common/typedHttp.js";
|
|
738
738
|
import assert4 from "assert";
|
|
739
739
|
import { Command, Option } from "commander";
|
|
740
|
-
import
|
|
741
|
-
|
|
740
|
+
import path11 from "path";
|
|
741
|
+
|
|
742
|
+
// ../package.json
|
|
743
|
+
var package_default = {
|
|
744
|
+
name: "flakiness",
|
|
745
|
+
version: "0.130.0",
|
|
746
|
+
private: true,
|
|
747
|
+
scripts: {
|
|
748
|
+
minor: "./version.mjs minor",
|
|
749
|
+
patch: "./version.mjs patch",
|
|
750
|
+
dev: "npx kubik --env-file=.env.dev -w $(find . -name build.mts) ./app.mts ./stripe.mts",
|
|
751
|
+
"dev+billing": "npx kubik --env-file=.env.dev+billing -w $(find . -name build.mts) ./app.mts ./stripe.mts",
|
|
752
|
+
prod: "npx kubik --env-file=.env.prodlocal -w ./server.mts ./web/build.mts ./experimental/build.mts ./landing/build.mts",
|
|
753
|
+
build: "npx kubik $(find . -name build.mts)",
|
|
754
|
+
perf: "node --max-old-space-size=10240 --enable-source-maps --env-file=.env.prodlocal experimental/lib/perf_filter.js"
|
|
755
|
+
},
|
|
756
|
+
engines: {
|
|
757
|
+
node: ">=24"
|
|
758
|
+
},
|
|
759
|
+
author: "Degu Labs, Inc",
|
|
760
|
+
license: "Fair Source 100",
|
|
761
|
+
workspaces: [
|
|
762
|
+
"./report",
|
|
763
|
+
"./sdk",
|
|
764
|
+
"./docs",
|
|
765
|
+
"./landing",
|
|
766
|
+
"./devenv",
|
|
767
|
+
"./database",
|
|
768
|
+
"./server",
|
|
769
|
+
"./shared",
|
|
770
|
+
"./experimental",
|
|
771
|
+
"./e2e",
|
|
772
|
+
"./web"
|
|
773
|
+
],
|
|
774
|
+
devDependencies: {
|
|
775
|
+
"@playwright/test": "^1.54.0",
|
|
776
|
+
"@types/node": "^22.10.2",
|
|
777
|
+
esbuild: "^0.27.0",
|
|
778
|
+
glob: "^10.3.10",
|
|
779
|
+
kubik: "^0.24.0",
|
|
780
|
+
tsx: "^4.19.2",
|
|
781
|
+
typescript: "^5.6.2"
|
|
782
|
+
}
|
|
783
|
+
};
|
|
742
784
|
|
|
743
785
|
// src/flakinessConfig.ts
|
|
744
786
|
import fs2 from "fs";
|
|
@@ -1158,7 +1200,7 @@ import fs5 from "fs/promises";
|
|
|
1158
1200
|
import path5 from "path";
|
|
1159
1201
|
|
|
1160
1202
|
// src/junit.ts
|
|
1161
|
-
import { ReportUtils as ReportUtils2
|
|
1203
|
+
import { ReportUtils as ReportUtils2 } from "@flakiness/report";
|
|
1162
1204
|
import { parseXml, XmlElement, XmlText } from "@rgrove/parse-xml";
|
|
1163
1205
|
import assert2 from "assert";
|
|
1164
1206
|
import fs4 from "fs";
|
|
@@ -1236,7 +1278,7 @@ async function traverseJUnitReport(context, node) {
|
|
|
1236
1278
|
file,
|
|
1237
1279
|
line,
|
|
1238
1280
|
column: 1
|
|
1239
|
-
} :
|
|
1281
|
+
} : void 0,
|
|
1240
1282
|
type: name ? "suite" : file ? "file" : "anonymous suite",
|
|
1241
1283
|
suites: [],
|
|
1242
1284
|
tests: []
|
|
@@ -1298,7 +1340,7 @@ async function traverseJUnitReport(context, node) {
|
|
|
1298
1340
|
file,
|
|
1299
1341
|
line,
|
|
1300
1342
|
column: 1
|
|
1301
|
-
} :
|
|
1343
|
+
} : void 0,
|
|
1302
1344
|
attempts: [{
|
|
1303
1345
|
environmentIdx: currentEnvIndex,
|
|
1304
1346
|
expectedStatus,
|
|
@@ -1549,7 +1591,7 @@ async function cmdLogin(endpoint) {
|
|
|
1549
1591
|
// src/cli/cmd-show-report.ts
|
|
1550
1592
|
import chalk from "chalk";
|
|
1551
1593
|
import open2 from "open";
|
|
1552
|
-
import
|
|
1594
|
+
import path8 from "path";
|
|
1553
1595
|
|
|
1554
1596
|
// src/localReportServer.ts
|
|
1555
1597
|
import { TypedHTTP as TypedHTTP3 } from "@flakiness/shared/common/typedHttp.js";
|
|
@@ -1560,9 +1602,14 @@ import compression from "compression";
|
|
|
1560
1602
|
import debug from "debug";
|
|
1561
1603
|
import express from "express";
|
|
1562
1604
|
import "express-async-errors";
|
|
1563
|
-
import fs8 from "fs";
|
|
1564
1605
|
import http2 from "http";
|
|
1565
1606
|
|
|
1607
|
+
// src/localReportApi.ts
|
|
1608
|
+
import { TypedHTTP as TypedHTTP2 } from "@flakiness/shared/common/typedHttp.js";
|
|
1609
|
+
import fs7 from "fs";
|
|
1610
|
+
import path7 from "path";
|
|
1611
|
+
import { z } from "zod/v4";
|
|
1612
|
+
|
|
1566
1613
|
// src/localGit.ts
|
|
1567
1614
|
import { exec } from "child_process";
|
|
1568
1615
|
import { promisify } from "util";
|
|
@@ -1604,9 +1651,37 @@ async function listLocalCommits(gitRoot, head, count) {
|
|
|
1604
1651
|
}
|
|
1605
1652
|
|
|
1606
1653
|
// src/localReportApi.ts
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1654
|
+
var ReportInfo = class {
|
|
1655
|
+
constructor(_options) {
|
|
1656
|
+
this._options = _options;
|
|
1657
|
+
}
|
|
1658
|
+
report;
|
|
1659
|
+
attachmentIdToPath = /* @__PURE__ */ new Map();
|
|
1660
|
+
commits = [];
|
|
1661
|
+
async refresh() {
|
|
1662
|
+
const report = await fs7.promises.readFile(this._options.reportPath, "utf-8").then((x) => JSON.parse(x)).catch((e) => void 0);
|
|
1663
|
+
if (!report) {
|
|
1664
|
+
this.report = void 0;
|
|
1665
|
+
this.commits = [];
|
|
1666
|
+
this.attachmentIdToPath = /* @__PURE__ */ new Map();
|
|
1667
|
+
return;
|
|
1668
|
+
}
|
|
1669
|
+
if (JSON.stringify(report) === JSON.stringify(this.report))
|
|
1670
|
+
return;
|
|
1671
|
+
this.report = report;
|
|
1672
|
+
this.commits = await listLocalCommits(path7.dirname(this._options.reportPath), report.commitId, 100);
|
|
1673
|
+
const attachmentsDir = this._options.attachmentsFolder;
|
|
1674
|
+
const { attachmentIdToPath, missingAttachments } = await resolveAttachmentPaths(report, attachmentsDir);
|
|
1675
|
+
if (missingAttachments.length) {
|
|
1676
|
+
const first = missingAttachments.slice(0, 3);
|
|
1677
|
+
for (let i = 0; i < 3 && i < missingAttachments.length; ++i)
|
|
1678
|
+
console.warn(`Missing attachment with id ${missingAttachments[i]}`);
|
|
1679
|
+
if (missingAttachments.length > 3)
|
|
1680
|
+
console.warn(`...and ${missingAttachments.length - 3} more missing attachments.`);
|
|
1681
|
+
}
|
|
1682
|
+
this.attachmentIdToPath = attachmentIdToPath;
|
|
1683
|
+
}
|
|
1684
|
+
};
|
|
1610
1685
|
var t = TypedHTTP2.Router.create();
|
|
1611
1686
|
var localReportRouter = {
|
|
1612
1687
|
ping: t.get({
|
|
@@ -1616,7 +1691,7 @@ var localReportRouter = {
|
|
|
1616
1691
|
}),
|
|
1617
1692
|
lastCommits: t.get({
|
|
1618
1693
|
handler: async ({ ctx }) => {
|
|
1619
|
-
return ctx.commits;
|
|
1694
|
+
return ctx.reportInfo.commits;
|
|
1620
1695
|
}
|
|
1621
1696
|
}),
|
|
1622
1697
|
report: {
|
|
@@ -1625,7 +1700,7 @@ var localReportRouter = {
|
|
|
1625
1700
|
attachmentId: z.string().min(1).max(100).transform((id) => id)
|
|
1626
1701
|
}),
|
|
1627
1702
|
handler: async ({ ctx, input }) => {
|
|
1628
|
-
const idx = ctx.attachmentIdToPath.get(input.attachmentId);
|
|
1703
|
+
const idx = ctx.reportInfo.attachmentIdToPath.get(input.attachmentId);
|
|
1629
1704
|
if (!idx)
|
|
1630
1705
|
throw TypedHTTP2.HttpError.withCode("NOT_FOUND");
|
|
1631
1706
|
const buffer = await fs7.promises.readFile(idx.path);
|
|
@@ -1634,7 +1709,8 @@ var localReportRouter = {
|
|
|
1634
1709
|
}),
|
|
1635
1710
|
json: t.get({
|
|
1636
1711
|
handler: async ({ ctx }) => {
|
|
1637
|
-
|
|
1712
|
+
await ctx.reportInfo.refresh();
|
|
1713
|
+
return ctx.reportInfo.report;
|
|
1638
1714
|
}
|
|
1639
1715
|
})
|
|
1640
1716
|
}
|
|
@@ -1649,17 +1725,6 @@ var LocalReportServer = class _LocalReportServer {
|
|
|
1649
1725
|
this._authToken = _authToken;
|
|
1650
1726
|
}
|
|
1651
1727
|
static async create(options) {
|
|
1652
|
-
const report = JSON.parse(await fs8.promises.readFile(options.reportPath, "utf-8"));
|
|
1653
|
-
const attachmentsDir = options.attachmentsFolder;
|
|
1654
|
-
const { attachmentIdToPath, missingAttachments } = await resolveAttachmentPaths(report, attachmentsDir);
|
|
1655
|
-
if (missingAttachments.length) {
|
|
1656
|
-
const first = missingAttachments.slice(0, 3);
|
|
1657
|
-
for (let i = 0; i < 3 && i < missingAttachments.length; ++i)
|
|
1658
|
-
console.warn(`Missing attachment with id ${missingAttachments[i]}`);
|
|
1659
|
-
if (missingAttachments.length > 3)
|
|
1660
|
-
console.warn(`...and ${missingAttachments.length - 3} more missing attachments.`);
|
|
1661
|
-
}
|
|
1662
|
-
const commits = await listLocalCommits(process.cwd(), report.commitId, 100);
|
|
1663
1728
|
const app = express();
|
|
1664
1729
|
app.set("etag", false);
|
|
1665
1730
|
const authToken = randomUUIDBase62();
|
|
@@ -1682,9 +1747,10 @@ var LocalReportServer = class _LocalReportServer {
|
|
|
1682
1747
|
});
|
|
1683
1748
|
next();
|
|
1684
1749
|
});
|
|
1750
|
+
const reportInfo = new ReportInfo(options);
|
|
1685
1751
|
app.use("/" + authToken, createTypedHttpExpressMiddleware({
|
|
1686
1752
|
router: localReportRouter,
|
|
1687
|
-
createRootContext: async ({ req, res, input }) => ({
|
|
1753
|
+
createRootContext: async ({ req, res, input }) => ({ reportInfo })
|
|
1688
1754
|
}));
|
|
1689
1755
|
app.use((err2, req, res, next) => {
|
|
1690
1756
|
if (err2 instanceof TypedHTTP3.HttpError)
|
|
@@ -1718,7 +1784,7 @@ var LocalReportServer = class _LocalReportServer {
|
|
|
1718
1784
|
|
|
1719
1785
|
// src/cli/cmd-show-report.ts
|
|
1720
1786
|
async function cmdShowReport(reportFolder) {
|
|
1721
|
-
const reportPath =
|
|
1787
|
+
const reportPath = path8.join(reportFolder, "report.json");
|
|
1722
1788
|
const session2 = await FlakinessSession.load();
|
|
1723
1789
|
const config = await FlakinessConfig.load();
|
|
1724
1790
|
const projectPublicId = config.projectPublicId();
|
|
@@ -1768,8 +1834,8 @@ async function cmdUnlink() {
|
|
|
1768
1834
|
}
|
|
1769
1835
|
|
|
1770
1836
|
// src/cli/cmd-upload-playwright-json.ts
|
|
1771
|
-
import
|
|
1772
|
-
import
|
|
1837
|
+
import fs9 from "fs/promises";
|
|
1838
|
+
import path9 from "path";
|
|
1773
1839
|
|
|
1774
1840
|
// src/playwrightJSONReport.ts
|
|
1775
1841
|
import { FlakinessReport as FK2 } from "@flakiness/report";
|
|
@@ -1950,7 +2016,7 @@ function parseJSONError(context, error) {
|
|
|
1950
2016
|
// src/reportUploader.ts
|
|
1951
2017
|
import { compressTextAsync, compressTextSync } from "@flakiness/shared/node/compression.js";
|
|
1952
2018
|
import assert3 from "assert";
|
|
1953
|
-
import
|
|
2019
|
+
import fs8 from "fs";
|
|
1954
2020
|
import { URL as URL2 } from "url";
|
|
1955
2021
|
var ReportUploader = class _ReportUploader {
|
|
1956
2022
|
static optionsFromEnv(overrides) {
|
|
@@ -2048,16 +2114,16 @@ var ReportUpload = class {
|
|
|
2048
2114
|
url: uploadUrl,
|
|
2049
2115
|
headers: {
|
|
2050
2116
|
"Content-Type": attachment.contentType,
|
|
2051
|
-
"Content-Length": (await
|
|
2117
|
+
"Content-Length": (await fs8.promises.stat(attachmentPath)).size + ""
|
|
2052
2118
|
},
|
|
2053
2119
|
method: "put"
|
|
2054
2120
|
});
|
|
2055
|
-
|
|
2121
|
+
fs8.createReadStream(attachmentPath).pipe(request);
|
|
2056
2122
|
await responseDataPromise;
|
|
2057
2123
|
}, HTTP_BACKOFF);
|
|
2058
2124
|
return;
|
|
2059
2125
|
}
|
|
2060
|
-
let buffer = attachment.body ? attachment.body : attachment.path ? await
|
|
2126
|
+
let buffer = attachment.body ? attachment.body : attachment.path ? await fs8.promises.readFile(attachment.path) : void 0;
|
|
2061
2127
|
assert3(buffer);
|
|
2062
2128
|
const encoding = compressable ? "br" : void 0;
|
|
2063
2129
|
if (compressable)
|
|
@@ -2082,12 +2148,12 @@ var ReportUpload = class {
|
|
|
2082
2148
|
|
|
2083
2149
|
// src/cli/cmd-upload-playwright-json.ts
|
|
2084
2150
|
async function cmdUploadPlaywrightJson(relativePath, options) {
|
|
2085
|
-
const fullPath =
|
|
2086
|
-
if (!await
|
|
2151
|
+
const fullPath = path9.resolve(relativePath);
|
|
2152
|
+
if (!await fs9.access(fullPath, fs9.constants.F_OK).then(() => true).catch(() => false)) {
|
|
2087
2153
|
console.error(`Error: path ${fullPath} is not accessible`);
|
|
2088
2154
|
process.exit(1);
|
|
2089
2155
|
}
|
|
2090
|
-
const text = await
|
|
2156
|
+
const text = await fs9.readFile(fullPath, "utf-8");
|
|
2091
2157
|
const playwrightJson = JSON.parse(text);
|
|
2092
2158
|
const { attachments, report, unaccessibleAttachmentPaths } = await PlaywrightJSONReport.parse(PlaywrightJSONReport.collectMetadata(), playwrightJson, {
|
|
2093
2159
|
extractAttachments: true
|
|
@@ -2109,20 +2175,20 @@ async function cmdUploadPlaywrightJson(relativePath, options) {
|
|
|
2109
2175
|
|
|
2110
2176
|
// src/cli/cmd-upload.ts
|
|
2111
2177
|
import chalk2 from "chalk";
|
|
2112
|
-
import
|
|
2113
|
-
import
|
|
2178
|
+
import fs10 from "fs/promises";
|
|
2179
|
+
import path10 from "path";
|
|
2114
2180
|
var warn = (txt) => console.warn(chalk2.yellow(`[flakiness.io] WARN: ${txt}`));
|
|
2115
2181
|
var err = (txt) => console.error(chalk2.red(`[flakiness.io] Error: ${txt}`));
|
|
2116
2182
|
var log = (txt) => console.log(`[flakiness.io] ${txt}`);
|
|
2117
2183
|
async function cmdUpload(relativePath, options) {
|
|
2118
|
-
const fullPath =
|
|
2119
|
-
if (!await
|
|
2184
|
+
const fullPath = path10.resolve(relativePath);
|
|
2185
|
+
if (!await fs10.access(fullPath, fs10.constants.F_OK).then(() => true).catch(() => false)) {
|
|
2120
2186
|
err(`Path ${fullPath} is not accessible!`);
|
|
2121
2187
|
process.exit(1);
|
|
2122
2188
|
}
|
|
2123
|
-
const text = await
|
|
2189
|
+
const text = await fs10.readFile(fullPath, "utf-8");
|
|
2124
2190
|
const report = JSON.parse(text);
|
|
2125
|
-
const attachmentsDir = options.attachmentsDir ??
|
|
2191
|
+
const attachmentsDir = options.attachmentsDir ?? path10.dirname(fullPath);
|
|
2126
2192
|
const { attachmentIdToPath, missingAttachments } = await resolveAttachmentPaths(report, attachmentsDir);
|
|
2127
2193
|
if (missingAttachments.length) {
|
|
2128
2194
|
warn(`Missing ${missingAttachments.length} attachments`);
|
|
@@ -2167,8 +2233,7 @@ async function runCommand(callback) {
|
|
|
2167
2233
|
process.exit(1);
|
|
2168
2234
|
}
|
|
2169
2235
|
}
|
|
2170
|
-
var
|
|
2171
|
-
var program = new Command().name("flakiness").description("Flakiness CLI tool").version(PACKAGE_JSON.version);
|
|
2236
|
+
var program = new Command().name("flakiness").description("Flakiness CLI tool").version(package_default.version);
|
|
2172
2237
|
async function ensureAccessToken(options) {
|
|
2173
2238
|
let accessToken = options.accessToken;
|
|
2174
2239
|
if (!accessToken) {
|
|
@@ -2269,7 +2334,7 @@ program.command("upload").description("Upload Flakiness report to the flakiness.
|
|
|
2269
2334
|
});
|
|
2270
2335
|
});
|
|
2271
2336
|
program.command("show-report [report]").description("Show flakiness report").argument("[relative-path]", "Path to the Flakiness report file or folder that contains `report.json`.").action(async (arg) => runCommand(async () => {
|
|
2272
|
-
const dir =
|
|
2337
|
+
const dir = path11.resolve(arg ?? "flakiness-report");
|
|
2273
2338
|
await cmdShowReport(dir);
|
|
2274
2339
|
}));
|
|
2275
2340
|
program.command("convert-junit").description("Convert JUnit XML report(s) to Flakiness report format").argument("<junit-root-dir-path>", "Path to JUnit XML file or directory containing XML files").option("--env-name <name>", "Environment name for the report", "default").option("--commit-id <id>", "Git commit ID (auto-detected if not provided)").action(async (junitPath, options) => {
|
package/lib/cli/cmd-convert.js
CHANGED
|
@@ -5,7 +5,7 @@ import fs3 from "fs/promises";
|
|
|
5
5
|
import path2 from "path";
|
|
6
6
|
|
|
7
7
|
// src/junit.ts
|
|
8
|
-
import { ReportUtils as ReportUtils2
|
|
8
|
+
import { ReportUtils as ReportUtils2 } from "@flakiness/report";
|
|
9
9
|
import { parseXml, XmlElement, XmlText } from "@rgrove/parse-xml";
|
|
10
10
|
import assert2 from "assert";
|
|
11
11
|
import fs2 from "fs";
|
|
@@ -219,7 +219,7 @@ async function traverseJUnitReport(context, node) {
|
|
|
219
219
|
file,
|
|
220
220
|
line,
|
|
221
221
|
column: 1
|
|
222
|
-
} :
|
|
222
|
+
} : void 0,
|
|
223
223
|
type: name ? "suite" : file ? "file" : "anonymous suite",
|
|
224
224
|
suites: [],
|
|
225
225
|
tests: []
|
|
@@ -281,7 +281,7 @@ async function traverseJUnitReport(context, node) {
|
|
|
281
281
|
file,
|
|
282
282
|
line,
|
|
283
283
|
column: 1
|
|
284
|
-
} :
|
|
284
|
+
} : void 0,
|
|
285
285
|
attempts: [{
|
|
286
286
|
environmentIdx: currentEnvIndex,
|
|
287
287
|
expectedStatus,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/cli/cmd-show-report.ts
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import open from "open";
|
|
4
|
-
import
|
|
4
|
+
import path5 from "path";
|
|
5
5
|
|
|
6
6
|
// src/flakinessConfig.ts
|
|
7
7
|
import fs2 from "fs";
|
|
@@ -298,9 +298,14 @@ import compression from "compression";
|
|
|
298
298
|
import debug from "debug";
|
|
299
299
|
import express from "express";
|
|
300
300
|
import "express-async-errors";
|
|
301
|
-
import fs5 from "fs";
|
|
302
301
|
import http2 from "http";
|
|
303
302
|
|
|
303
|
+
// src/localReportApi.ts
|
|
304
|
+
import { TypedHTTP as TypedHTTP2 } from "@flakiness/shared/common/typedHttp.js";
|
|
305
|
+
import fs4 from "fs";
|
|
306
|
+
import path4 from "path";
|
|
307
|
+
import { z } from "zod/v4";
|
|
308
|
+
|
|
304
309
|
// src/localGit.ts
|
|
305
310
|
import { exec } from "child_process";
|
|
306
311
|
import { promisify } from "util";
|
|
@@ -342,9 +347,37 @@ async function listLocalCommits(gitRoot, head, count) {
|
|
|
342
347
|
}
|
|
343
348
|
|
|
344
349
|
// src/localReportApi.ts
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
350
|
+
var ReportInfo = class {
|
|
351
|
+
constructor(_options) {
|
|
352
|
+
this._options = _options;
|
|
353
|
+
}
|
|
354
|
+
report;
|
|
355
|
+
attachmentIdToPath = /* @__PURE__ */ new Map();
|
|
356
|
+
commits = [];
|
|
357
|
+
async refresh() {
|
|
358
|
+
const report = await fs4.promises.readFile(this._options.reportPath, "utf-8").then((x) => JSON.parse(x)).catch((e) => void 0);
|
|
359
|
+
if (!report) {
|
|
360
|
+
this.report = void 0;
|
|
361
|
+
this.commits = [];
|
|
362
|
+
this.attachmentIdToPath = /* @__PURE__ */ new Map();
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
if (JSON.stringify(report) === JSON.stringify(this.report))
|
|
366
|
+
return;
|
|
367
|
+
this.report = report;
|
|
368
|
+
this.commits = await listLocalCommits(path4.dirname(this._options.reportPath), report.commitId, 100);
|
|
369
|
+
const attachmentsDir = this._options.attachmentsFolder;
|
|
370
|
+
const { attachmentIdToPath, missingAttachments } = await resolveAttachmentPaths(report, attachmentsDir);
|
|
371
|
+
if (missingAttachments.length) {
|
|
372
|
+
const first = missingAttachments.slice(0, 3);
|
|
373
|
+
for (let i = 0; i < 3 && i < missingAttachments.length; ++i)
|
|
374
|
+
console.warn(`Missing attachment with id ${missingAttachments[i]}`);
|
|
375
|
+
if (missingAttachments.length > 3)
|
|
376
|
+
console.warn(`...and ${missingAttachments.length - 3} more missing attachments.`);
|
|
377
|
+
}
|
|
378
|
+
this.attachmentIdToPath = attachmentIdToPath;
|
|
379
|
+
}
|
|
380
|
+
};
|
|
348
381
|
var t = TypedHTTP2.Router.create();
|
|
349
382
|
var localReportRouter = {
|
|
350
383
|
ping: t.get({
|
|
@@ -354,7 +387,7 @@ var localReportRouter = {
|
|
|
354
387
|
}),
|
|
355
388
|
lastCommits: t.get({
|
|
356
389
|
handler: async ({ ctx }) => {
|
|
357
|
-
return ctx.commits;
|
|
390
|
+
return ctx.reportInfo.commits;
|
|
358
391
|
}
|
|
359
392
|
}),
|
|
360
393
|
report: {
|
|
@@ -363,7 +396,7 @@ var localReportRouter = {
|
|
|
363
396
|
attachmentId: z.string().min(1).max(100).transform((id) => id)
|
|
364
397
|
}),
|
|
365
398
|
handler: async ({ ctx, input }) => {
|
|
366
|
-
const idx = ctx.attachmentIdToPath.get(input.attachmentId);
|
|
399
|
+
const idx = ctx.reportInfo.attachmentIdToPath.get(input.attachmentId);
|
|
367
400
|
if (!idx)
|
|
368
401
|
throw TypedHTTP2.HttpError.withCode("NOT_FOUND");
|
|
369
402
|
const buffer = await fs4.promises.readFile(idx.path);
|
|
@@ -372,7 +405,8 @@ var localReportRouter = {
|
|
|
372
405
|
}),
|
|
373
406
|
json: t.get({
|
|
374
407
|
handler: async ({ ctx }) => {
|
|
375
|
-
|
|
408
|
+
await ctx.reportInfo.refresh();
|
|
409
|
+
return ctx.reportInfo.report;
|
|
376
410
|
}
|
|
377
411
|
})
|
|
378
412
|
}
|
|
@@ -387,17 +421,6 @@ var LocalReportServer = class _LocalReportServer {
|
|
|
387
421
|
this._authToken = _authToken;
|
|
388
422
|
}
|
|
389
423
|
static async create(options) {
|
|
390
|
-
const report = JSON.parse(await fs5.promises.readFile(options.reportPath, "utf-8"));
|
|
391
|
-
const attachmentsDir = options.attachmentsFolder;
|
|
392
|
-
const { attachmentIdToPath, missingAttachments } = await resolveAttachmentPaths(report, attachmentsDir);
|
|
393
|
-
if (missingAttachments.length) {
|
|
394
|
-
const first = missingAttachments.slice(0, 3);
|
|
395
|
-
for (let i = 0; i < 3 && i < missingAttachments.length; ++i)
|
|
396
|
-
console.warn(`Missing attachment with id ${missingAttachments[i]}`);
|
|
397
|
-
if (missingAttachments.length > 3)
|
|
398
|
-
console.warn(`...and ${missingAttachments.length - 3} more missing attachments.`);
|
|
399
|
-
}
|
|
400
|
-
const commits = await listLocalCommits(process.cwd(), report.commitId, 100);
|
|
401
424
|
const app = express();
|
|
402
425
|
app.set("etag", false);
|
|
403
426
|
const authToken = randomUUIDBase62();
|
|
@@ -420,9 +443,10 @@ var LocalReportServer = class _LocalReportServer {
|
|
|
420
443
|
});
|
|
421
444
|
next();
|
|
422
445
|
});
|
|
446
|
+
const reportInfo = new ReportInfo(options);
|
|
423
447
|
app.use("/" + authToken, createTypedHttpExpressMiddleware({
|
|
424
448
|
router: localReportRouter,
|
|
425
|
-
createRootContext: async ({ req, res, input }) => ({
|
|
449
|
+
createRootContext: async ({ req, res, input }) => ({ reportInfo })
|
|
426
450
|
}));
|
|
427
451
|
app.use((err, req, res, next) => {
|
|
428
452
|
if (err instanceof TypedHTTP3.HttpError)
|
|
@@ -456,7 +480,7 @@ var LocalReportServer = class _LocalReportServer {
|
|
|
456
480
|
|
|
457
481
|
// src/cli/cmd-show-report.ts
|
|
458
482
|
async function cmdShowReport(reportFolder) {
|
|
459
|
-
const reportPath =
|
|
483
|
+
const reportPath = path5.join(reportFolder, "report.json");
|
|
460
484
|
const session = await FlakinessSession.load();
|
|
461
485
|
const config = await FlakinessConfig.load();
|
|
462
486
|
const projectPublicId = config.projectPublicId();
|
package/lib/junit.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/junit.ts
|
|
2
|
-
import { ReportUtils as ReportUtils2
|
|
2
|
+
import { ReportUtils as ReportUtils2 } from "@flakiness/report";
|
|
3
3
|
import { parseXml, XmlElement, XmlText } from "@rgrove/parse-xml";
|
|
4
4
|
import assert from "assert";
|
|
5
5
|
import fs2 from "fs";
|
|
@@ -191,7 +191,7 @@ async function traverseJUnitReport(context, node) {
|
|
|
191
191
|
file,
|
|
192
192
|
line,
|
|
193
193
|
column: 1
|
|
194
|
-
} :
|
|
194
|
+
} : void 0,
|
|
195
195
|
type: name ? "suite" : file ? "file" : "anonymous suite",
|
|
196
196
|
suites: [],
|
|
197
197
|
tests: []
|
|
@@ -253,7 +253,7 @@ async function traverseJUnitReport(context, node) {
|
|
|
253
253
|
file,
|
|
254
254
|
line,
|
|
255
255
|
column: 1
|
|
256
|
-
} :
|
|
256
|
+
} : void 0,
|
|
257
257
|
attempts: [{
|
|
258
258
|
environmentIdx: currentEnvIndex,
|
|
259
259
|
expectedStatus,
|