flakiness 0.158.0 → 0.160.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 +0 -1
- package/lib/cli/cli.js +85 -222
- package/lib/junit.js +7 -130
- package/package.json +9 -6
- package/types/tsconfig.tsbuildinfo +1 -1
package/lib/junit.js
CHANGED
|
@@ -1,121 +1,10 @@
|
|
|
1
1
|
// src/junit.ts
|
|
2
|
-
import { ReportUtils
|
|
2
|
+
import { ReportUtils } from "@flakiness/sdk";
|
|
3
3
|
import { parseXml, XmlElement, XmlText } from "@rgrove/parse-xml";
|
|
4
4
|
import assert from "assert";
|
|
5
|
-
import fs2 from "fs";
|
|
6
|
-
import path from "path";
|
|
7
|
-
|
|
8
|
-
// src/utils.ts
|
|
9
|
-
import { ReportUtils } from "@flakiness/sdk";
|
|
10
|
-
import crypto from "crypto";
|
|
11
5
|
import fs from "fs";
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
function sha1File(filePath) {
|
|
15
|
-
return new Promise((resolve, reject) => {
|
|
16
|
-
const hash = crypto.createHash("sha1");
|
|
17
|
-
const stream = fs.createReadStream(filePath);
|
|
18
|
-
stream.on("data", (chunk) => {
|
|
19
|
-
hash.update(chunk);
|
|
20
|
-
});
|
|
21
|
-
stream.on("end", () => {
|
|
22
|
-
resolve(hash.digest("hex"));
|
|
23
|
-
});
|
|
24
|
-
stream.on("error", (err) => {
|
|
25
|
-
reject(err);
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
var FLAKINESS_DBG = !!process.env.FLAKINESS_DBG;
|
|
30
|
-
function errorText(error) {
|
|
31
|
-
return FLAKINESS_DBG ? error.stack : error.message;
|
|
32
|
-
}
|
|
33
|
-
function sha1Buffer(data) {
|
|
34
|
-
const hash = crypto.createHash("sha1");
|
|
35
|
-
hash.update(data);
|
|
36
|
-
return hash.digest("hex");
|
|
37
|
-
}
|
|
38
|
-
async function retryWithBackoff(job, backoff = []) {
|
|
39
|
-
for (const timeout of backoff) {
|
|
40
|
-
try {
|
|
41
|
-
return await job();
|
|
42
|
-
} catch (e) {
|
|
43
|
-
if (e instanceof AggregateError)
|
|
44
|
-
console.error(`[flakiness.io err]`, errorText(e.errors[0]));
|
|
45
|
-
else if (e instanceof Error)
|
|
46
|
-
console.error(`[flakiness.io err]`, errorText(e));
|
|
47
|
-
else
|
|
48
|
-
console.error(`[flakiness.io err]`, e);
|
|
49
|
-
await new Promise((x) => setTimeout(x, timeout));
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return await job();
|
|
53
|
-
}
|
|
54
|
-
var httpUtils;
|
|
55
|
-
((httpUtils2) => {
|
|
56
|
-
function createRequest({ url, method = "get", headers = {} }) {
|
|
57
|
-
let resolve;
|
|
58
|
-
let reject;
|
|
59
|
-
const responseDataPromise = new Promise((a, b) => {
|
|
60
|
-
resolve = a;
|
|
61
|
-
reject = b;
|
|
62
|
-
});
|
|
63
|
-
const protocol = url.startsWith("https") ? https : http;
|
|
64
|
-
headers = Object.fromEntries(Object.entries(headers).filter(([key, value]) => value !== void 0));
|
|
65
|
-
const request = protocol.request(url, { method, headers }, (res) => {
|
|
66
|
-
const chunks = [];
|
|
67
|
-
res.on("data", (chunk) => chunks.push(chunk));
|
|
68
|
-
res.on("end", () => {
|
|
69
|
-
if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300)
|
|
70
|
-
resolve(Buffer.concat(chunks));
|
|
71
|
-
else
|
|
72
|
-
reject(new Error(`Request to ${url} failed with ${res.statusCode}`));
|
|
73
|
-
});
|
|
74
|
-
res.on("error", (error) => reject(error));
|
|
75
|
-
});
|
|
76
|
-
request.on("error", reject);
|
|
77
|
-
return { request, responseDataPromise };
|
|
78
|
-
}
|
|
79
|
-
httpUtils2.createRequest = createRequest;
|
|
80
|
-
async function getBuffer(url, backoff) {
|
|
81
|
-
return await retryWithBackoff(async () => {
|
|
82
|
-
const { request, responseDataPromise } = createRequest({ url });
|
|
83
|
-
request.end();
|
|
84
|
-
return await responseDataPromise;
|
|
85
|
-
}, backoff);
|
|
86
|
-
}
|
|
87
|
-
httpUtils2.getBuffer = getBuffer;
|
|
88
|
-
async function getText(url, backoff) {
|
|
89
|
-
const buffer = await getBuffer(url, backoff);
|
|
90
|
-
return buffer.toString("utf-8");
|
|
91
|
-
}
|
|
92
|
-
httpUtils2.getText = getText;
|
|
93
|
-
async function getJSON(url) {
|
|
94
|
-
return JSON.parse(await getText(url));
|
|
95
|
-
}
|
|
96
|
-
httpUtils2.getJSON = getJSON;
|
|
97
|
-
async function postText(url, text, backoff) {
|
|
98
|
-
const headers = {
|
|
99
|
-
"Content-Type": "application/json",
|
|
100
|
-
"Content-Length": Buffer.byteLength(text) + ""
|
|
101
|
-
};
|
|
102
|
-
return await retryWithBackoff(async () => {
|
|
103
|
-
const { request, responseDataPromise } = createRequest({ url, headers, method: "post" });
|
|
104
|
-
request.write(text);
|
|
105
|
-
request.end();
|
|
106
|
-
return await responseDataPromise;
|
|
107
|
-
}, backoff);
|
|
108
|
-
}
|
|
109
|
-
httpUtils2.postText = postText;
|
|
110
|
-
async function postJSON(url, json, backoff) {
|
|
111
|
-
const buffer = await postText(url, JSON.stringify(json), backoff);
|
|
112
|
-
return JSON.parse(buffer.toString("utf-8"));
|
|
113
|
-
}
|
|
114
|
-
httpUtils2.postJSON = postJSON;
|
|
115
|
-
})(httpUtils || (httpUtils = {}));
|
|
116
|
-
var ansiRegex = new RegExp("[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))", "g");
|
|
117
|
-
|
|
118
|
-
// src/junit.ts
|
|
6
|
+
import mime from "mime";
|
|
7
|
+
import path from "path";
|
|
119
8
|
function getProperties(element) {
|
|
120
9
|
const propertiesNodes = element.children.filter((node) => node instanceof XmlElement).filter((node) => node.name === "properties");
|
|
121
10
|
if (!propertiesNodes.length)
|
|
@@ -158,21 +47,9 @@ function extractStdout(testcase, stdio) {
|
|
|
158
47
|
}
|
|
159
48
|
async function parseAttachment(value) {
|
|
160
49
|
let absolutePath = path.resolve(process.cwd(), value);
|
|
161
|
-
if (
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
contentType: "image/png",
|
|
165
|
-
path: absolutePath,
|
|
166
|
-
id,
|
|
167
|
-
type: "file"
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
return {
|
|
171
|
-
contentType: "text/plain",
|
|
172
|
-
id: sha1Buffer(value),
|
|
173
|
-
body: Buffer.from(value),
|
|
174
|
-
type: "buffer"
|
|
175
|
-
};
|
|
50
|
+
if (fs.existsSync(absolutePath))
|
|
51
|
+
return ReportUtils.createFileAttachment(mime.getType(absolutePath) ?? "image/png", absolutePath);
|
|
52
|
+
return ReportUtils.createDataAttachment("text/plain", Buffer.from(value));
|
|
176
53
|
}
|
|
177
54
|
async function traverseJUnitReport(context, node) {
|
|
178
55
|
const element = node;
|
|
@@ -301,7 +178,7 @@ async function parseJUnit(xmls, options) {
|
|
|
301
178
|
await traverseJUnitReport(context, element);
|
|
302
179
|
}
|
|
303
180
|
return {
|
|
304
|
-
report:
|
|
181
|
+
report: ReportUtils.normalizeReport(report),
|
|
305
182
|
attachments: Array.from(context.attachments.values())
|
|
306
183
|
};
|
|
307
184
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "flakiness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.160.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"bin": {
|
|
6
6
|
"flakiness": "./lib/cli/cli.js"
|
|
@@ -20,16 +20,19 @@
|
|
|
20
20
|
"license": "Fair Source 100",
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@playwright/test": "^1.57.0",
|
|
23
|
+
"@types/debug": "^4.1.12",
|
|
23
24
|
"@types/express": "^4.17.20",
|
|
24
|
-
"@flakiness/server": "0.
|
|
25
|
-
"@flakiness/shared": "0.
|
|
25
|
+
"@flakiness/server": "0.160.0",
|
|
26
|
+
"@flakiness/shared": "0.160.0"
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
28
|
-
"@flakiness/
|
|
29
|
+
"@flakiness/flakiness-report": "^0.22.0",
|
|
30
|
+
"@flakiness/sdk": "^1.0.1",
|
|
29
31
|
"@rgrove/parse-xml": "^4.2.0",
|
|
30
32
|
"chalk": "^5.6.2",
|
|
31
|
-
"commander": "^
|
|
32
|
-
"debug": "^4.3
|
|
33
|
+
"commander": "^14.0.0",
|
|
34
|
+
"debug": "^4.4.3",
|
|
35
|
+
"mime": "^4.1.0",
|
|
33
36
|
"open": "^10.2.0",
|
|
34
37
|
"ora": "^8.2.0"
|
|
35
38
|
},
|