flakiness 0.148.0 → 0.149.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.
@@ -1,25 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/cmd-convert.ts
4
+ import { GitWorktree, writeReport } from "@flakiness/sdk";
4
5
  import fs3 from "fs/promises";
5
- import path3 from "path";
6
+ import path2 from "path";
6
7
 
7
8
  // src/junit.ts
8
9
  import { ReportUtils as ReportUtils2 } from "@flakiness/sdk";
9
10
  import { parseXml, XmlElement, XmlText } from "@rgrove/parse-xml";
10
- import assert2 from "assert";
11
+ import assert from "assert";
11
12
  import fs2 from "fs";
12
- import path2 from "path";
13
+ import path from "path";
13
14
 
14
15
  // src/utils.ts
15
16
  import { ReportUtils } from "@flakiness/sdk";
16
- import assert from "assert";
17
- import { spawnSync } from "child_process";
18
17
  import crypto from "crypto";
19
18
  import fs from "fs";
20
19
  import http from "http";
21
20
  import https from "https";
22
- import path, { posix as posixPath, win32 as win32Path } from "path";
23
21
  function sha1File(filePath) {
24
22
  return new Promise((resolve, reject) => {
25
23
  const hash = crypto.createHash("sha1");
@@ -123,51 +121,6 @@ var httpUtils;
123
121
  httpUtils2.postJSON = postJSON;
124
122
  })(httpUtils || (httpUtils = {}));
125
123
  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");
126
- async function saveReportAndAttachments(report, attachments, outputFolder) {
127
- const reportPath = path.join(outputFolder, "report.json");
128
- const attachmentsFolder = path.join(outputFolder, "attachments");
129
- await fs.promises.rm(outputFolder, { recursive: true, force: true });
130
- await fs.promises.mkdir(outputFolder, { recursive: true });
131
- await fs.promises.writeFile(reportPath, JSON.stringify(report), "utf-8");
132
- if (attachments.length)
133
- await fs.promises.mkdir(attachmentsFolder);
134
- const movedAttachments = [];
135
- for (const attachment of attachments) {
136
- const attachmentPath = path.join(attachmentsFolder, attachment.id);
137
- if (attachment.path)
138
- await fs.promises.cp(attachment.path, attachmentPath);
139
- else if (attachment.body)
140
- await fs.promises.writeFile(attachmentPath, attachment.body);
141
- movedAttachments.push({
142
- contentType: attachment.contentType,
143
- id: attachment.id,
144
- path: attachmentPath
145
- });
146
- }
147
- return movedAttachments;
148
- }
149
- function shell(command, args, options) {
150
- try {
151
- const result = spawnSync(command, args, { encoding: "utf-8", ...options });
152
- if (result.status !== 0) {
153
- return void 0;
154
- }
155
- return result.stdout.trim();
156
- } catch (e) {
157
- console.error(e);
158
- return void 0;
159
- }
160
- }
161
- function gitCommitInfo(gitRepo) {
162
- const sha = shell(`git`, ["rev-parse", "HEAD"], {
163
- cwd: gitRepo,
164
- encoding: "utf-8"
165
- });
166
- assert(sha, `FAILED: git rev-parse HEAD @ ${gitRepo}`);
167
- return sha.trim();
168
- }
169
- var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
170
- var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
171
124
 
172
125
  // src/junit.ts
173
126
  function getProperties(element) {
@@ -211,19 +164,21 @@ function extractStdout(testcase, stdio) {
211
164
  }));
212
165
  }
213
166
  async function parseAttachment(value) {
214
- let absolutePath = path2.resolve(process.cwd(), value);
167
+ let absolutePath = path.resolve(process.cwd(), value);
215
168
  if (fs2.existsSync(absolutePath)) {
216
169
  const id = await sha1File(absolutePath);
217
170
  return {
218
171
  contentType: "image/png",
219
172
  path: absolutePath,
220
- id
173
+ id,
174
+ type: "file"
221
175
  };
222
176
  }
223
177
  return {
224
178
  contentType: "text/plain",
225
179
  id: sha1Buffer(value),
226
- body: Buffer.from(value)
180
+ body: Buffer.from(value),
181
+ type: "buffer"
227
182
  };
228
183
  }
229
184
  async function traverseJUnitReport(context, node) {
@@ -264,7 +219,7 @@ async function traverseJUnitReport(context, node) {
264
219
  currentEnvIndex = report.environments.push(currentEnv) - 1;
265
220
  }
266
221
  } else if (element.name === "testcase") {
267
- assert2(currentSuite);
222
+ assert(currentSuite);
268
223
  const file = element.attributes["file"];
269
224
  const name = element.attributes["name"];
270
225
  const line = parseInt(element.attributes["line"], 10);
@@ -284,7 +239,7 @@ async function traverseJUnitReport(context, node) {
284
239
  id: attachment.id,
285
240
  contentType: attachment.contentType,
286
241
  //TODO: better default names for attachments?
287
- name: attachment.path ? path2.basename(attachment.path) : `attachment`
242
+ name: attachment.type === "file" ? path.basename(attachment.path) : `attachment`
288
243
  });
289
244
  } else {
290
245
  annotations.push({
@@ -359,7 +314,7 @@ async function parseJUnit(xmls, options) {
359
314
 
360
315
  // src/cli/cmd-convert.ts
361
316
  async function cmdConvert(junitPath, options) {
362
- const fullPath = path3.resolve(junitPath);
317
+ const fullPath = path2.resolve(junitPath);
363
318
  if (!await fs3.access(fullPath, fs3.constants.F_OK).then(() => true).catch(() => false)) {
364
319
  console.error(`Error: path ${fullPath} is not accessible`);
365
320
  process.exit(1);
@@ -389,7 +344,8 @@ async function cmdConvert(junitPath, options) {
389
344
  commitId = options.commitId;
390
345
  } else {
391
346
  try {
392
- commitId = gitCommitInfo(process.cwd());
347
+ const worktree = GitWorktree.create(process.cwd());
348
+ commitId = worktree.headCommitId();
393
349
  } catch (e) {
394
350
  console.error("Failed to get git commit info. Please provide --commit-id option.");
395
351
  process.exit(1);
@@ -401,13 +357,13 @@ async function cmdConvert(junitPath, options) {
401
357
  runStartTimestamp: Date.now(),
402
358
  runDuration: 0
403
359
  });
404
- await saveReportAndAttachments(report, attachments, options.outputDir);
360
+ await writeReport(report, attachments, options.outputDir);
405
361
  console.log(`\u2713 Saved to ${options.outputDir}`);
406
362
  }
407
363
  async function findXmlFiles(dir, result = []) {
408
364
  const entries = await fs3.readdir(dir, { withFileTypes: true });
409
365
  for (const entry of entries) {
410
- const fullPath = path3.join(dir, entry.name);
366
+ const fullPath = path2.join(dir, entry.name);
411
367
  if (entry.isFile() && entry.name.toLowerCase().endsWith(".xml"))
412
368
  result.push(fullPath);
413
369
  else if (entry.isDirectory())
@@ -103,8 +103,6 @@ var httpUtils;
103
103
  httpUtils2.postJSON = postJSON;
104
104
  })(httpUtils || (httpUtils = {}));
105
105
  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");
106
- var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
107
- var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
108
106
 
109
107
  // src/serverapi.ts
110
108
  function createServerAPI(endpoint, options) {
@@ -93,8 +93,6 @@ var httpUtils;
93
93
  httpUtils2.postJSON = postJSON;
94
94
  })(httpUtils || (httpUtils = {}));
95
95
  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");
96
- var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
97
- var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
98
96
 
99
97
  // src/serverapi.ts
100
98
  function createServerAPI(endpoint, options) {
@@ -96,8 +96,6 @@ var httpUtils;
96
96
  httpUtils2.postJSON = postJSON;
97
97
  })(httpUtils || (httpUtils = {}));
98
98
  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");
99
- var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
100
- var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
101
99
 
102
100
  // src/serverapi.ts
103
101
  function createServerAPI(endpoint, options) {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/cmd-upload.ts
4
- import { ReportUploader } from "@flakiness/sdk";
4
+ import { uploadReport } from "@flakiness/sdk";
5
5
  import chalk from "chalk";
6
6
  import fs2 from "fs/promises";
7
7
  import path2 from "path";
@@ -11,7 +11,7 @@ import { ReportUtils } from "@flakiness/sdk";
11
11
  import fs from "fs";
12
12
  import http from "http";
13
13
  import https from "https";
14
- import path, { posix as posixPath, win32 as win32Path } from "path";
14
+ import path from "path";
15
15
  var FLAKINESS_DBG = !!process.env.FLAKINESS_DBG;
16
16
  function errorText(error) {
17
17
  return FLAKINESS_DBG ? error.stack : error.message;
@@ -110,7 +110,8 @@ async function resolveAttachmentPaths(report, attachmentsDir) {
110
110
  attachmentIdToPath.set(attachment.id, {
111
111
  contentType: attachment.contentType,
112
112
  id: attachment.id,
113
- path: attachmentPath
113
+ path: attachmentPath,
114
+ type: "file"
114
115
  });
115
116
  }
116
117
  }
@@ -129,18 +130,11 @@ async function listFilesRecursively(dir, result = []) {
129
130
  }
130
131
  return result;
131
132
  }
132
- var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
133
- var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
134
133
 
135
134
  // src/cli/cmd-upload.ts
136
135
  var warn = (txt) => console.warn(chalk.yellow(`[flakiness.io] WARN: ${txt}`));
137
136
  var err = (txt) => console.error(chalk.red(`[flakiness.io] Error: ${txt}`));
138
- var log = (txt) => console.log(`[flakiness.io] ${txt}`);
139
137
  async function cmdUpload(relativePaths, options) {
140
- const uploader = new ReportUploader({
141
- flakinessAccessToken: options.accessToken,
142
- flakinessEndpoint: options.endpoint
143
- });
144
138
  for (const relativePath of relativePaths) {
145
139
  const fullPath = path2.resolve(relativePath);
146
140
  if (!await fs2.access(fullPath, fs2.constants.F_OK).then(() => true).catch(() => false)) {
@@ -154,13 +148,10 @@ async function cmdUpload(relativePaths, options) {
154
148
  if (missingAttachments.length) {
155
149
  warn(`Missing ${missingAttachments.length} attachments`);
156
150
  }
157
- const upload = uploader.createUpload(report, Array.from(attachmentIdToPath.values()));
158
- const uploadResult = await upload.upload();
159
- if (!uploadResult.success) {
160
- err(`Failed to upload to ${options.endpoint}: ${uploadResult.message}`);
161
- } else {
162
- log(`\u2713 Uploaded ${uploadResult.reportUrl ?? uploadResult.message ?? ""}`);
163
- }
151
+ await uploadReport(report, Array.from(attachmentIdToPath.values()), {
152
+ flakinessAccessToken: options.accessToken,
153
+ flakinessEndpoint: options.endpoint
154
+ });
164
155
  }
165
156
  }
166
157
  export {
@@ -95,8 +95,6 @@ var httpUtils;
95
95
  httpUtils2.postJSON = postJSON;
96
96
  })(httpUtils || (httpUtils = {}));
97
97
  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");
98
- var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
99
- var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
100
98
 
101
99
  // src/serverapi.ts
102
100
  function createServerAPI(endpoint, options) {
@@ -93,8 +93,6 @@ var httpUtils;
93
93
  httpUtils2.postJSON = postJSON;
94
94
  })(httpUtils || (httpUtils = {}));
95
95
  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");
96
- var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
97
- var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
98
96
 
99
97
  // src/serverapi.ts
100
98
  function createServerAPI(endpoint, options) {
package/lib/junit.js CHANGED
@@ -114,8 +114,6 @@ var httpUtils;
114
114
  httpUtils2.postJSON = postJSON;
115
115
  })(httpUtils || (httpUtils = {}));
116
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
- var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
118
- var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
119
117
 
120
118
  // src/junit.ts
121
119
  function getProperties(element) {
@@ -165,13 +163,15 @@ async function parseAttachment(value) {
165
163
  return {
166
164
  contentType: "image/png",
167
165
  path: absolutePath,
168
- id
166
+ id,
167
+ type: "file"
169
168
  };
170
169
  }
171
170
  return {
172
171
  contentType: "text/plain",
173
172
  id: sha1Buffer(value),
174
- body: Buffer.from(value)
173
+ body: Buffer.from(value),
174
+ type: "buffer"
175
175
  };
176
176
  }
177
177
  async function traverseJUnitReport(context, node) {
@@ -232,7 +232,7 @@ async function traverseJUnitReport(context, node) {
232
232
  id: attachment.id,
233
233
  contentType: attachment.contentType,
234
234
  //TODO: better default names for attachments?
235
- name: attachment.path ? path.basename(attachment.path) : `attachment`
235
+ name: attachment.type === "file" ? path.basename(attachment.path) : `attachment`
236
236
  });
237
237
  } else {
238
238
  annotations.push({
package/lib/serverapi.js CHANGED
@@ -88,8 +88,6 @@ var httpUtils;
88
88
  httpUtils2.postJSON = postJSON;
89
89
  })(httpUtils || (httpUtils = {}));
90
90
  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");
91
- var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
92
- var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
93
91
 
94
92
  // src/serverapi.ts
95
93
  function createServerAPI(endpoint, options) {
package/lib/utils.js CHANGED
@@ -1,13 +1,11 @@
1
1
  // src/utils.ts
2
2
  import { ReportUtils } from "@flakiness/sdk";
3
- import assert from "assert";
4
3
  import { spawnSync } from "child_process";
5
4
  import crypto from "crypto";
6
5
  import fs from "fs";
7
6
  import http from "http";
8
7
  import https from "https";
9
- import os from "os";
10
- import path, { posix as posixPath, win32 as win32Path } from "path";
8
+ import path from "path";
11
9
  async function existsAsync(aPath) {
12
10
  return fs.promises.stat(aPath).then(() => true).catch((e) => false);
13
11
  }
@@ -123,29 +121,6 @@ var ansiRegex = new RegExp("[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:
123
121
  function stripAnsi(str) {
124
122
  return str.replace(ansiRegex, "");
125
123
  }
126
- async function saveReportAndAttachments(report, attachments, outputFolder) {
127
- const reportPath = path.join(outputFolder, "report.json");
128
- const attachmentsFolder = path.join(outputFolder, "attachments");
129
- await fs.promises.rm(outputFolder, { recursive: true, force: true });
130
- await fs.promises.mkdir(outputFolder, { recursive: true });
131
- await fs.promises.writeFile(reportPath, JSON.stringify(report), "utf-8");
132
- if (attachments.length)
133
- await fs.promises.mkdir(attachmentsFolder);
134
- const movedAttachments = [];
135
- for (const attachment of attachments) {
136
- const attachmentPath = path.join(attachmentsFolder, attachment.id);
137
- if (attachment.path)
138
- await fs.promises.cp(attachment.path, attachmentPath);
139
- else if (attachment.body)
140
- await fs.promises.writeFile(attachmentPath, attachment.body);
141
- movedAttachments.push({
142
- contentType: attachment.contentType,
143
- id: attachment.id,
144
- path: attachmentPath
145
- });
146
- }
147
- return movedAttachments;
148
- }
149
124
  function shell(command, args, options) {
150
125
  try {
151
126
  const result = spawnSync(command, args, { encoding: "utf-8", ...options });
@@ -158,58 +133,9 @@ function shell(command, args, options) {
158
133
  return void 0;
159
134
  }
160
135
  }
161
- function readLinuxOSRelease() {
162
- const osReleaseText = fs.readFileSync("/etc/os-release", "utf-8");
163
- return new Map(osReleaseText.toLowerCase().split("\n").filter((line) => line.includes("=")).map((line) => {
164
- line = line.trim();
165
- let [key, value] = line.split("=");
166
- if (value.startsWith('"') && value.endsWith('"'))
167
- value = value.substring(1, value.length - 1);
168
- return [key, value];
169
- }));
170
- }
171
- function osLinuxInfo() {
172
- const arch = shell(`uname`, [`-m`]);
173
- const osReleaseMap = readLinuxOSRelease();
174
- const name = osReleaseMap.get("name") ?? shell(`uname`);
175
- const version = osReleaseMap.get("version_id");
176
- return { name, arch, version };
177
- }
178
- function osDarwinInfo() {
179
- const name = "macos";
180
- const arch = shell(`uname`, [`-m`]);
181
- const version = shell(`sw_vers`, [`-productVersion`]);
182
- return { name, arch, version };
183
- }
184
- function osWinInfo() {
185
- const name = "win";
186
- const arch = process.arch;
187
- const version = os.release();
188
- return { name, arch, version };
189
- }
190
- function getOSInfo() {
191
- if (process.platform === "darwin")
192
- return osDarwinInfo();
193
- if (process.platform === "win32")
194
- return osWinInfo();
195
- return osLinuxInfo();
196
- }
197
- function inferRunUrl() {
198
- if (process.env.GITHUB_REPOSITORY && process.env.GITHUB_RUN_ID)
199
- return `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`;
200
- return void 0;
201
- }
202
136
  function parseStringDate(dateString) {
203
137
  return +new Date(dateString);
204
138
  }
205
- function gitCommitInfo(gitRepo) {
206
- const sha = shell(`git`, ["rev-parse", "HEAD"], {
207
- cwd: gitRepo,
208
- encoding: "utf-8"
209
- });
210
- assert(sha, `FAILED: git rev-parse HEAD @ ${gitRepo}`);
211
- return sha.trim();
212
- }
213
139
  async function resolveAttachmentPaths(report, attachmentsDir) {
214
140
  const attachmentFiles = await listFilesRecursively(attachmentsDir);
215
141
  const filenameToPath = new Map(attachmentFiles.map((file) => [path.basename(file), file]));
@@ -225,7 +151,8 @@ async function resolveAttachmentPaths(report, attachmentsDir) {
225
151
  attachmentIdToPath.set(attachment.id, {
226
152
  contentType: attachment.contentType,
227
153
  id: attachment.id,
228
- path: attachmentPath
154
+ path: attachmentPath,
155
+ type: "file"
229
156
  });
230
157
  }
231
158
  }
@@ -244,128 +171,14 @@ async function listFilesRecursively(dir, result = []) {
244
171
  }
245
172
  return result;
246
173
  }
247
- function computeGitRoot(somePathInsideGitRepo) {
248
- const root = shell(`git`, ["rev-parse", "--show-toplevel"], {
249
- cwd: somePathInsideGitRepo,
250
- encoding: "utf-8"
251
- });
252
- assert(root, `FAILED: git rev-parse --show-toplevel HEAD @ ${somePathInsideGitRepo}`);
253
- return normalizePath(root);
254
- }
255
- var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
256
- var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
257
- function normalizePath(aPath) {
258
- if (IS_WIN32_PATH.test(aPath)) {
259
- aPath = aPath.split(win32Path.sep).join(posixPath.sep);
260
- }
261
- if (IS_ALMOST_POSIX_PATH.test(aPath))
262
- return "/" + aPath[0] + aPath.substring(2);
263
- return aPath;
264
- }
265
- function getCallerLocation(gitRoot, offset = 0) {
266
- const err = new Error();
267
- const stack = err.stack?.split("\n");
268
- const caller = stack?.[2 + offset]?.trim();
269
- const match = caller?.match(/\((.*):(\d+):(\d+)\)$/);
270
- if (!match) return void 0;
271
- const [, filePath, line, column] = match;
272
- return {
273
- file: gitFilePath(gitRoot, normalizePath(filePath)),
274
- line: Number(line),
275
- column: Number(column)
276
- };
277
- }
278
- function parseStackLocations() {
279
- const err = new Error();
280
- const stack = err.stack?.split("\n").slice(2);
281
- if (!stack)
282
- return [];
283
- const result = [];
284
- for (const caller of stack) {
285
- const match = caller.trim().match(/\((.*):(\d+):(\d+)\)$/);
286
- if (!match)
287
- continue;
288
- const [, file, line, column] = match;
289
- result.push({ file, line, column });
290
- }
291
- return result;
292
- }
293
- function gitFilePath(gitRoot, absolutePath) {
294
- return posixPath.relative(gitRoot, absolutePath);
295
- }
296
- function parseDurationMS(value) {
297
- if (isNaN(value))
298
- throw new Error("Duration cannot be NaN");
299
- if (value < 0)
300
- throw new Error(`Duration cannot be less than 0, found ${value}`);
301
- return value | 0;
302
- }
303
- function createEnvironment(options) {
304
- const osInfo = getOSInfo();
305
- return {
306
- name: options.name,
307
- systemData: {
308
- osArch: osInfo.arch,
309
- osName: osInfo.name,
310
- osVersion: osInfo.version
311
- },
312
- userSuppliedData: {
313
- ...extractEnvConfiguration(),
314
- ...options.userSuppliedData ?? {}
315
- }
316
- };
317
- }
318
- function createEnvironments(projects) {
319
- const envConfiguration = extractEnvConfiguration();
320
- const osInfo = getOSInfo();
321
- let uniqueNames = /* @__PURE__ */ new Set();
322
- const result = /* @__PURE__ */ new Map();
323
- for (const project of projects) {
324
- let defaultName = project.name;
325
- if (!defaultName.trim())
326
- defaultName = "anonymous";
327
- let name = defaultName;
328
- for (let i = 2; uniqueNames.has(name); ++i)
329
- name = `${defaultName}-${i}`;
330
- uniqueNames.add(defaultName);
331
- result.set(project, {
332
- name,
333
- systemData: {
334
- osArch: osInfo.arch,
335
- osName: osInfo.name,
336
- osVersion: osInfo.version
337
- },
338
- userSuppliedData: {
339
- ...envConfiguration,
340
- ...project.metadata
341
- },
342
- opaqueData: {
343
- project
344
- }
345
- });
346
- }
347
- return result;
348
- }
349
174
  export {
350
- computeGitRoot,
351
- createEnvironment,
352
- createEnvironments,
353
175
  errorText,
354
176
  existsAsync,
355
177
  extractEnvConfiguration,
356
- getCallerLocation,
357
- getOSInfo,
358
- gitCommitInfo,
359
- gitFilePath,
360
178
  httpUtils,
361
- inferRunUrl,
362
- normalizePath,
363
- parseDurationMS,
364
- parseStackLocations,
365
179
  parseStringDate,
366
180
  resolveAttachmentPaths,
367
181
  retryWithBackoff,
368
- saveReportAndAttachments,
369
182
  sha1Buffer,
370
183
  sha1File,
371
184
  shell,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flakiness",
3
- "version": "0.148.0",
3
+ "version": "0.149.0",
4
4
  "private": false,
5
5
  "bin": {
6
6
  "flakiness": "./lib/cli/cli.js"
@@ -32,12 +32,12 @@
32
32
  "author": "Degu Labs, Inc",
33
33
  "license": "Fair Source 100",
34
34
  "devDependencies": {
35
- "@flakiness/server": "0.148.0",
35
+ "@flakiness/server": "0.149.0",
36
36
  "@playwright/test": "^1.57.0"
37
37
  },
38
38
  "dependencies": {
39
- "@flakiness/sdk": "0.148.0",
40
- "@flakiness/shared": "0.148.0",
39
+ "@flakiness/sdk": "0.149.0",
40
+ "@flakiness/shared": "0.149.0",
41
41
  "@rgrove/parse-xml": "^4.2.0",
42
42
  "chalk": "^5.6.2",
43
43
  "commander": "^13.1.0",