@flakiness/sdk 0.146.0 → 0.147.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/LICENSE CHANGED
@@ -1,45 +1,21 @@
1
- Fair Source License, version 0.9
2
-
3
- Copyright (C) 2023 Degu Labs, Inc.
4
-
5
- Licensor: Degu Labs, Inc
6
-
7
- Software: @flakiness/playwright-report
8
-
9
- Use Limitation: 100 users. Executing the software, modifying the code, or
10
- accessing a running copy of the software constitutes “use.”
11
-
12
- License Grant. Licensor hereby grants to each recipient of the
13
- Software ("you") a non-exclusive, non-transferable, royalty-free and
14
- fully-paid-up license, under all of the Licensor’s copyright and
15
- patent rights, to use, copy, distribute, prepare derivative works of,
16
- publicly perform and display the Software, subject to the Use
17
- Limitation and the conditions set forth below.
18
-
19
- Use Limitation. The license granted above allows use by up to the
20
- number of users per entity set forth above (the "Use Limitation"). For
21
- determining the number of users, "you" includes all affiliates,
22
- meaning legal entities controlling, controlled by, or under common
23
- control with you. If you exceed the Use Limitation, your use is
24
- subject to payment of Licensor’s then-current list price for licenses.
25
-
26
- Conditions. Redistribution in source code or other forms must include
27
- a copy of this license document to be provided in a reasonable
28
- manner. Any redistribution of the Software is only allowed subject to
29
- this license.
30
-
31
- Trademarks. This license does not grant you any right in the
32
- trademarks, service marks, brand names or logos of Licensor.
33
-
34
- DISCLAIMER. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OR
35
- CONDITION, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES
36
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
37
- NONINFRINGEMENT. LICENSORS HEREBY DISCLAIM ALL LIABILITY, WHETHER IN
38
- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
39
- CONNECTION WITH THE SOFTWARE.
40
-
41
- Termination. If you violate the terms of this license, your rights
42
- will terminate automatically and will not be reinstated without the
43
- prior written consent of Licensor. Any such termination will not
44
- affect the right of others who may have received copies of the
45
- Software from you.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Degu Labs, Inc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,30 +1,5 @@
1
1
  # Flakiness SDK
2
2
 
3
- The package consists of:
4
- - A CLI to interact with flakiness.io service
5
- - A set of reporters for popular test runners to generate & upload Flakiness
6
- report.
3
+ The package provides a set of tools to create Flakiness Reports in Node.js.
7
4
 
8
- ## Getting Started
9
-
10
- To start using reporter with Playwright Test:
11
-
12
- 1. Install this package:
13
- ```bash
14
- npm i @flakiness/sdk@latest
15
- ```
16
- 2. Add flakiness.io to the `playwright.config.ts` file:
17
- ```ts
18
- import { defineConfig } from '@playwright/test';
19
-
20
- export default defineConfig({
21
- reporter: [
22
- ['list'],
23
- ['@flakiness/sdk/playwright-test', {
24
- endpoint: 'https://flakiness.io', // custom endpoint
25
- token: '...', // Flakiness access token
26
- collectBrowserVersion: true, // collect browser versions
27
- }]
28
- ],
29
- });
30
- ```
5
+ Read docs at https://flakiness.io/docs/integrations/custom/
@@ -0,0 +1,127 @@
1
+ // src/browser/index.ts
2
+ import { FlakinessReport } from "@flakiness/flakiness-report";
3
+
4
+ // src/reportUtils.ts
5
+ import { Multimap } from "@flakiness/shared/common/multimap.js";
6
+ import { xxHash, xxHashObject } from "@flakiness/shared/common/utils.js";
7
+ var ReportUtils;
8
+ ((ReportUtils2) => {
9
+ function visitTests(report, testVisitor) {
10
+ function visitSuite(suite, parents) {
11
+ parents.push(suite);
12
+ for (const test of suite.tests ?? [])
13
+ testVisitor(test, parents);
14
+ for (const childSuite of suite.suites ?? [])
15
+ visitSuite(childSuite, parents);
16
+ parents.pop();
17
+ }
18
+ for (const test of report.tests ?? [])
19
+ testVisitor(test, []);
20
+ for (const suite of report.suites)
21
+ visitSuite(suite, []);
22
+ }
23
+ ReportUtils2.visitTests = visitTests;
24
+ function normalizeReport(report) {
25
+ const gEnvs = /* @__PURE__ */ new Map();
26
+ const gSuites = /* @__PURE__ */ new Map();
27
+ const gTests = new Multimap();
28
+ const gSuiteIds = /* @__PURE__ */ new Map();
29
+ const gTestIds = /* @__PURE__ */ new Map();
30
+ const gEnvIds = /* @__PURE__ */ new Map();
31
+ const gSuiteChildren = new Multimap();
32
+ const gSuiteTests = new Multimap();
33
+ for (const env of report.environments) {
34
+ const envId = computeEnvId(env);
35
+ gEnvs.set(envId, env);
36
+ gEnvIds.set(env, envId);
37
+ }
38
+ const usedEnvIds = /* @__PURE__ */ new Set();
39
+ function visitTests2(tests, suiteId) {
40
+ for (const test of tests ?? []) {
41
+ const testId = computeTestId(test, suiteId);
42
+ gTests.set(testId, test);
43
+ gTestIds.set(test, testId);
44
+ gSuiteTests.set(suiteId, test);
45
+ for (const attempt of test.attempts) {
46
+ const env = report.environments[attempt.environmentIdx];
47
+ const envId = gEnvIds.get(env);
48
+ usedEnvIds.add(envId);
49
+ }
50
+ }
51
+ }
52
+ function visitSuite(suite, parentSuiteId) {
53
+ const suiteId = computeSuiteId(suite, parentSuiteId);
54
+ gSuites.set(suiteId, suite);
55
+ gSuiteIds.set(suite, suiteId);
56
+ for (const childSuite of suite.suites ?? []) {
57
+ visitSuite(childSuite, suiteId);
58
+ gSuiteChildren.set(suiteId, childSuite);
59
+ }
60
+ visitTests2(suite.tests ?? [], suiteId);
61
+ }
62
+ function transformTests(tests) {
63
+ const testIds = new Set(tests.map((test) => gTestIds.get(test)));
64
+ return [...testIds].map((testId) => {
65
+ const tests2 = gTests.getAll(testId);
66
+ const tags = tests2.map((test) => test.tags ?? []).flat();
67
+ return {
68
+ location: tests2[0].location,
69
+ title: tests2[0].title,
70
+ tags: tags.length ? tags : void 0,
71
+ attempts: tests2.map((t) => t.attempts).flat().map((attempt) => ({
72
+ ...attempt,
73
+ environmentIdx: envIdToIndex.get(gEnvIds.get(report.environments[attempt.environmentIdx]))
74
+ }))
75
+ };
76
+ });
77
+ }
78
+ function transformSuites(suites) {
79
+ const suiteIds = new Set(suites.map((suite) => gSuiteIds.get(suite)));
80
+ return [...suiteIds].map((suiteId) => {
81
+ const suite = gSuites.get(suiteId);
82
+ return {
83
+ location: suite.location,
84
+ title: suite.title,
85
+ type: suite.type,
86
+ suites: transformSuites(gSuiteChildren.getAll(suiteId)),
87
+ tests: transformTests(gSuiteTests.getAll(suiteId))
88
+ };
89
+ });
90
+ }
91
+ visitTests2(report.tests ?? [], "suiteless");
92
+ for (const suite of report.suites)
93
+ visitSuite(suite);
94
+ const newEnvironments = [...usedEnvIds];
95
+ const envIdToIndex = new Map(newEnvironments.map((envId, index) => [envId, index]));
96
+ return {
97
+ ...report,
98
+ environments: newEnvironments.map((envId) => gEnvs.get(envId)),
99
+ suites: transformSuites(report.suites),
100
+ tests: transformTests(report.tests ?? [])
101
+ };
102
+ }
103
+ ReportUtils2.normalizeReport = normalizeReport;
104
+ function computeEnvId(env) {
105
+ return xxHashObject(env);
106
+ }
107
+ function computeSuiteId(suite, parentSuiteId) {
108
+ return xxHash([
109
+ parentSuiteId ?? "",
110
+ suite.type,
111
+ suite.location?.file ?? "",
112
+ suite.title
113
+ ]);
114
+ }
115
+ function computeTestId(test, suiteId) {
116
+ return xxHash([
117
+ suiteId,
118
+ test.location?.file ?? "",
119
+ test.title
120
+ ]);
121
+ }
122
+ })(ReportUtils || (ReportUtils = {}));
123
+ export {
124
+ FlakinessReport,
125
+ ReportUtils
126
+ };
127
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,78 @@
1
+ // src/createEnvironment.ts
2
+ import { spawnSync } from "child_process";
3
+ import fs from "fs";
4
+ import os from "os";
5
+ function shell(command, args, options) {
6
+ try {
7
+ const result = spawnSync(command, args, { encoding: "utf-8", ...options });
8
+ if (result.status !== 0) {
9
+ return void 0;
10
+ }
11
+ return result.stdout.trim();
12
+ } catch (e) {
13
+ console.error(e);
14
+ return void 0;
15
+ }
16
+ }
17
+ function readLinuxOSRelease() {
18
+ const osReleaseText = fs.readFileSync("/etc/os-release", "utf-8");
19
+ return new Map(osReleaseText.toLowerCase().split("\n").filter((line) => line.includes("=")).map((line) => {
20
+ line = line.trim();
21
+ let [key, value] = line.split("=");
22
+ if (value.startsWith('"') && value.endsWith('"'))
23
+ value = value.substring(1, value.length - 1);
24
+ return [key, value];
25
+ }));
26
+ }
27
+ function osLinuxInfo() {
28
+ const arch = shell(`uname`, [`-m`]);
29
+ const osReleaseMap = readLinuxOSRelease();
30
+ const name = osReleaseMap.get("name") ?? shell(`uname`);
31
+ const version = osReleaseMap.get("version_id");
32
+ return { name, arch, version };
33
+ }
34
+ function osDarwinInfo() {
35
+ const name = "macos";
36
+ const arch = shell(`uname`, [`-m`]);
37
+ const version = shell(`sw_vers`, [`-productVersion`]);
38
+ return { name, arch, version };
39
+ }
40
+ function osWinInfo() {
41
+ const name = "win";
42
+ const arch = process.arch;
43
+ const version = os.release();
44
+ return { name, arch, version };
45
+ }
46
+ function getOSInfo() {
47
+ if (process.platform === "darwin")
48
+ return osDarwinInfo();
49
+ if (process.platform === "win32")
50
+ return osWinInfo();
51
+ return osLinuxInfo();
52
+ }
53
+ function extractEnvConfiguration() {
54
+ const ENV_PREFIX = "FK_ENV_";
55
+ return Object.fromEntries(
56
+ Object.entries(process.env).filter(([key]) => key.toUpperCase().startsWith(ENV_PREFIX.toUpperCase())).map(([key, value]) => [key.substring(ENV_PREFIX.length).toLowerCase(), (value ?? "").trim().toLowerCase()])
57
+ );
58
+ }
59
+ function createEnvironment(options) {
60
+ const osInfo = getOSInfo();
61
+ return {
62
+ name: options.name,
63
+ systemData: {
64
+ osArch: osInfo.arch,
65
+ osName: osInfo.name,
66
+ osVersion: osInfo.version
67
+ },
68
+ userSuppliedData: {
69
+ ...extractEnvConfiguration(),
70
+ ...options.userSuppliedData ?? {}
71
+ },
72
+ opaqueData: options.opaqueData
73
+ };
74
+ }
75
+ export {
76
+ createEnvironment
77
+ };
78
+ //# sourceMappingURL=createEnvironment.js.map
@@ -1,11 +1,149 @@
1
1
  // src/createTestStepSnippets.ts
2
2
  import { codeFrameColumns } from "@babel/code-frame";
3
3
  import fs from "fs";
4
- function createTestStepSnippets(filepathToSteps) {
5
- for (const [filepath, steps] of filepathToSteps) {
4
+ import { posix as posixPath } from "path";
5
+
6
+ // src/reportUtils.ts
7
+ import { Multimap } from "@flakiness/shared/common/multimap.js";
8
+ import { xxHash, xxHashObject } from "@flakiness/shared/common/utils.js";
9
+ var ReportUtils;
10
+ ((ReportUtils2) => {
11
+ function visitTests(report, testVisitor) {
12
+ function visitSuite(suite, parents) {
13
+ parents.push(suite);
14
+ for (const test of suite.tests ?? [])
15
+ testVisitor(test, parents);
16
+ for (const childSuite of suite.suites ?? [])
17
+ visitSuite(childSuite, parents);
18
+ parents.pop();
19
+ }
20
+ for (const test of report.tests ?? [])
21
+ testVisitor(test, []);
22
+ for (const suite of report.suites)
23
+ visitSuite(suite, []);
24
+ }
25
+ ReportUtils2.visitTests = visitTests;
26
+ function normalizeReport(report) {
27
+ const gEnvs = /* @__PURE__ */ new Map();
28
+ const gSuites = /* @__PURE__ */ new Map();
29
+ const gTests = new Multimap();
30
+ const gSuiteIds = /* @__PURE__ */ new Map();
31
+ const gTestIds = /* @__PURE__ */ new Map();
32
+ const gEnvIds = /* @__PURE__ */ new Map();
33
+ const gSuiteChildren = new Multimap();
34
+ const gSuiteTests = new Multimap();
35
+ for (const env of report.environments) {
36
+ const envId = computeEnvId(env);
37
+ gEnvs.set(envId, env);
38
+ gEnvIds.set(env, envId);
39
+ }
40
+ const usedEnvIds = /* @__PURE__ */ new Set();
41
+ function visitTests2(tests, suiteId) {
42
+ for (const test of tests ?? []) {
43
+ const testId = computeTestId(test, suiteId);
44
+ gTests.set(testId, test);
45
+ gTestIds.set(test, testId);
46
+ gSuiteTests.set(suiteId, test);
47
+ for (const attempt of test.attempts) {
48
+ const env = report.environments[attempt.environmentIdx];
49
+ const envId = gEnvIds.get(env);
50
+ usedEnvIds.add(envId);
51
+ }
52
+ }
53
+ }
54
+ function visitSuite(suite, parentSuiteId) {
55
+ const suiteId = computeSuiteId(suite, parentSuiteId);
56
+ gSuites.set(suiteId, suite);
57
+ gSuiteIds.set(suite, suiteId);
58
+ for (const childSuite of suite.suites ?? []) {
59
+ visitSuite(childSuite, suiteId);
60
+ gSuiteChildren.set(suiteId, childSuite);
61
+ }
62
+ visitTests2(suite.tests ?? [], suiteId);
63
+ }
64
+ function transformTests(tests) {
65
+ const testIds = new Set(tests.map((test) => gTestIds.get(test)));
66
+ return [...testIds].map((testId) => {
67
+ const tests2 = gTests.getAll(testId);
68
+ const tags = tests2.map((test) => test.tags ?? []).flat();
69
+ return {
70
+ location: tests2[0].location,
71
+ title: tests2[0].title,
72
+ tags: tags.length ? tags : void 0,
73
+ attempts: tests2.map((t) => t.attempts).flat().map((attempt) => ({
74
+ ...attempt,
75
+ environmentIdx: envIdToIndex.get(gEnvIds.get(report.environments[attempt.environmentIdx]))
76
+ }))
77
+ };
78
+ });
79
+ }
80
+ function transformSuites(suites) {
81
+ const suiteIds = new Set(suites.map((suite) => gSuiteIds.get(suite)));
82
+ return [...suiteIds].map((suiteId) => {
83
+ const suite = gSuites.get(suiteId);
84
+ return {
85
+ location: suite.location,
86
+ title: suite.title,
87
+ type: suite.type,
88
+ suites: transformSuites(gSuiteChildren.getAll(suiteId)),
89
+ tests: transformTests(gSuiteTests.getAll(suiteId))
90
+ };
91
+ });
92
+ }
93
+ visitTests2(report.tests ?? [], "suiteless");
94
+ for (const suite of report.suites)
95
+ visitSuite(suite);
96
+ const newEnvironments = [...usedEnvIds];
97
+ const envIdToIndex = new Map(newEnvironments.map((envId, index) => [envId, index]));
98
+ return {
99
+ ...report,
100
+ environments: newEnvironments.map((envId) => gEnvs.get(envId)),
101
+ suites: transformSuites(report.suites),
102
+ tests: transformTests(report.tests ?? [])
103
+ };
104
+ }
105
+ ReportUtils2.normalizeReport = normalizeReport;
106
+ function computeEnvId(env) {
107
+ return xxHashObject(env);
108
+ }
109
+ function computeSuiteId(suite, parentSuiteId) {
110
+ return xxHash([
111
+ parentSuiteId ?? "",
112
+ suite.type,
113
+ suite.location?.file ?? "",
114
+ suite.title
115
+ ]);
116
+ }
117
+ function computeTestId(test, suiteId) {
118
+ return xxHash([
119
+ suiteId,
120
+ test.location?.file ?? "",
121
+ test.title
122
+ ]);
123
+ }
124
+ })(ReportUtils || (ReportUtils = {}));
125
+
126
+ // src/createTestStepSnippets.ts
127
+ function createTestStepSnippetsInplace(report, gitRoot) {
128
+ const allSteps = /* @__PURE__ */ new Map();
129
+ ReportUtils.visitTests(report, (test) => {
130
+ for (const attempt of test.attempts) {
131
+ for (const step of attempt.steps ?? []) {
132
+ if (!step.location)
133
+ continue;
134
+ let fileSteps = allSteps.get(step.location.file);
135
+ if (!fileSteps) {
136
+ fileSteps = /* @__PURE__ */ new Set();
137
+ allSteps.set(step.location.file, fileSteps);
138
+ }
139
+ fileSteps.add(step);
140
+ }
141
+ }
142
+ });
143
+ for (const [gitFilePath, steps] of allSteps) {
6
144
  let source;
7
145
  try {
8
- source = fs.readFileSync(filepath, "utf-8");
146
+ source = fs.readFileSync(posixPath.join(gitRoot, gitFilePath), "utf-8");
9
147
  } catch (e) {
10
148
  continue;
11
149
  }
@@ -27,6 +165,6 @@ function createTestStepSnippets(filepathToSteps) {
27
165
  }
28
166
  }
29
167
  export {
30
- createTestStepSnippets
168
+ createTestStepSnippetsInplace
31
169
  };
32
170
  //# sourceMappingURL=createTestStepSnippets.js.map
@@ -1,96 +1,26 @@
1
1
  // src/flakinessProjectConfig.ts
2
2
  import fs from "fs";
3
- import path2 from "path";
3
+ import path from "path";
4
4
 
5
- // src/utils.ts
6
- import { ReportUtils } from "@flakiness/report";
5
+ // src/git.ts
7
6
  import assert from "assert";
8
- import { spawnSync } from "child_process";
9
- import http from "http";
10
- import https from "https";
11
- import path, { posix as posixPath, win32 as win32Path } from "path";
12
- var FLAKINESS_DBG = !!process.env.FLAKINESS_DBG;
13
- function errorText(error) {
14
- return FLAKINESS_DBG ? error.stack : error.message;
15
- }
16
- async function retryWithBackoff(job, backoff = []) {
17
- for (const timeout of backoff) {
18
- try {
19
- return await job();
20
- } catch (e) {
21
- if (e instanceof AggregateError)
22
- console.error(`[flakiness.io err]`, errorText(e.errors[0]));
23
- else if (e instanceof Error)
24
- console.error(`[flakiness.io err]`, errorText(e));
25
- else
26
- console.error(`[flakiness.io err]`, e);
27
- await new Promise((x) => setTimeout(x, timeout));
28
- }
7
+
8
+ // src/pathutils.ts
9
+ import { posix as posixPath, win32 as win32Path } from "path";
10
+ var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
11
+ var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
12
+ function normalizePath(aPath) {
13
+ if (IS_WIN32_PATH.test(aPath)) {
14
+ aPath = aPath.split(win32Path.sep).join(posixPath.sep);
29
15
  }
30
- return await job();
16
+ if (IS_ALMOST_POSIX_PATH.test(aPath))
17
+ return "/" + aPath[0] + aPath.substring(2);
18
+ return aPath;
31
19
  }
32
- var httpUtils;
33
- ((httpUtils2) => {
34
- function createRequest({ url, method = "get", headers = {} }) {
35
- let resolve;
36
- let reject;
37
- const responseDataPromise = new Promise((a, b) => {
38
- resolve = a;
39
- reject = b;
40
- });
41
- const protocol = url.startsWith("https") ? https : http;
42
- headers = Object.fromEntries(Object.entries(headers).filter(([key, value]) => value !== void 0));
43
- const request = protocol.request(url, { method, headers }, (res) => {
44
- const chunks = [];
45
- res.on("data", (chunk) => chunks.push(chunk));
46
- res.on("end", () => {
47
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300)
48
- resolve(Buffer.concat(chunks));
49
- else
50
- reject(new Error(`Request to ${url} failed with ${res.statusCode}`));
51
- });
52
- res.on("error", (error) => reject(error));
53
- });
54
- request.on("error", reject);
55
- return { request, responseDataPromise };
56
- }
57
- httpUtils2.createRequest = createRequest;
58
- async function getBuffer(url, backoff) {
59
- return await retryWithBackoff(async () => {
60
- const { request, responseDataPromise } = createRequest({ url });
61
- request.end();
62
- return await responseDataPromise;
63
- }, backoff);
64
- }
65
- httpUtils2.getBuffer = getBuffer;
66
- async function getText(url, backoff) {
67
- const buffer = await getBuffer(url, backoff);
68
- return buffer.toString("utf-8");
69
- }
70
- httpUtils2.getText = getText;
71
- async function getJSON(url) {
72
- return JSON.parse(await getText(url));
73
- }
74
- httpUtils2.getJSON = getJSON;
75
- async function postText(url, text, backoff) {
76
- const headers = {
77
- "Content-Type": "application/json",
78
- "Content-Length": Buffer.byteLength(text) + ""
79
- };
80
- return await retryWithBackoff(async () => {
81
- const { request, responseDataPromise } = createRequest({ url, headers, method: "post" });
82
- request.write(text);
83
- request.end();
84
- return await responseDataPromise;
85
- }, backoff);
86
- }
87
- httpUtils2.postText = postText;
88
- async function postJSON(url, json, backoff) {
89
- const buffer = await postText(url, JSON.stringify(json), backoff);
90
- return JSON.parse(buffer.toString("utf-8"));
91
- }
92
- httpUtils2.postJSON = postJSON;
93
- })(httpUtils || (httpUtils = {}));
20
+
21
+ // src/utils.ts
22
+ import { spawnSync } from "child_process";
23
+ var FLAKINESS_DBG = !!process.env.FLAKINESS_DBG;
94
24
  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");
95
25
  function shell(command, args, options) {
96
26
  try {
@@ -104,6 +34,8 @@ function shell(command, args, options) {
104
34
  return void 0;
105
35
  }
106
36
  }
37
+
38
+ // src/git.ts
107
39
  function computeGitRoot(somePathInsideGitRepo) {
108
40
  const root = shell(`git`, ["rev-parse", "--show-toplevel"], {
109
41
  cwd: somePathInsideGitRepo,
@@ -112,20 +44,10 @@ function computeGitRoot(somePathInsideGitRepo) {
112
44
  assert(root, `FAILED: git rev-parse --show-toplevel HEAD @ ${somePathInsideGitRepo}`);
113
45
  return normalizePath(root);
114
46
  }
115
- var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
116
- var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
117
- function normalizePath(aPath) {
118
- if (IS_WIN32_PATH.test(aPath)) {
119
- aPath = aPath.split(win32Path.sep).join(posixPath.sep);
120
- }
121
- if (IS_ALMOST_POSIX_PATH.test(aPath))
122
- return "/" + aPath[0] + aPath.substring(2);
123
- return aPath;
124
- }
125
47
 
126
48
  // src/flakinessProjectConfig.ts
127
49
  function createConfigPath(dir) {
128
- return path2.join(dir, ".flakiness", "config.json");
50
+ return path.join(dir, ".flakiness", "config.json");
129
51
  }
130
52
  var gConfigPath;
131
53
  function ensureConfigPath() {
@@ -134,7 +56,7 @@ function ensureConfigPath() {
134
56
  return gConfigPath;
135
57
  }
136
58
  function computeConfigPath() {
137
- for (let p = process.cwd(); p !== path2.resolve(p, ".."); p = path2.resolve(p, "..")) {
59
+ for (let p = process.cwd(); p !== path.resolve(p, ".."); p = path.resolve(p, "..")) {
138
60
  const configPath = createConfigPath(p);
139
61
  if (fs.existsSync(configPath))
140
62
  return configPath;
@@ -173,7 +95,7 @@ var FlakinessProjectConfig = class _FlakinessProjectConfig {
173
95
  this._config.projectPublicId = projectId;
174
96
  }
175
97
  async save() {
176
- await fs.promises.mkdir(path2.dirname(this._configPath), { recursive: true });
98
+ await fs.promises.mkdir(path.dirname(this._configPath), { recursive: true });
177
99
  await fs.promises.writeFile(this._configPath, JSON.stringify(this._config, null, 2));
178
100
  }
179
101
  };
package/lib/git.js ADDED
@@ -0,0 +1,55 @@
1
+ // src/git.ts
2
+ import assert from "assert";
3
+
4
+ // src/pathutils.ts
5
+ import { posix as posixPath, win32 as win32Path } from "path";
6
+ var IS_WIN32_PATH = new RegExp("^[a-zA-Z]:\\\\", "i");
7
+ var IS_ALMOST_POSIX_PATH = new RegExp("^[a-zA-Z]:/", "i");
8
+ function normalizePath(aPath) {
9
+ if (IS_WIN32_PATH.test(aPath)) {
10
+ aPath = aPath.split(win32Path.sep).join(posixPath.sep);
11
+ }
12
+ if (IS_ALMOST_POSIX_PATH.test(aPath))
13
+ return "/" + aPath[0] + aPath.substring(2);
14
+ return aPath;
15
+ }
16
+
17
+ // src/utils.ts
18
+ import { spawnSync } from "child_process";
19
+ var FLAKINESS_DBG = !!process.env.FLAKINESS_DBG;
20
+ 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");
21
+ function shell(command, args, options) {
22
+ try {
23
+ const result = spawnSync(command, args, { encoding: "utf-8", ...options });
24
+ if (result.status !== 0) {
25
+ return void 0;
26
+ }
27
+ return result.stdout.trim();
28
+ } catch (e) {
29
+ console.error(e);
30
+ return void 0;
31
+ }
32
+ }
33
+
34
+ // src/git.ts
35
+ function gitCommitInfo(gitRepo) {
36
+ const sha = shell(`git`, ["rev-parse", "HEAD"], {
37
+ cwd: gitRepo,
38
+ encoding: "utf-8"
39
+ });
40
+ assert(sha, `FAILED: git rev-parse HEAD @ ${gitRepo}`);
41
+ return sha.trim();
42
+ }
43
+ function computeGitRoot(somePathInsideGitRepo) {
44
+ const root = shell(`git`, ["rev-parse", "--show-toplevel"], {
45
+ cwd: somePathInsideGitRepo,
46
+ encoding: "utf-8"
47
+ });
48
+ assert(root, `FAILED: git rev-parse --show-toplevel HEAD @ ${somePathInsideGitRepo}`);
49
+ return normalizePath(root);
50
+ }
51
+ export {
52
+ computeGitRoot,
53
+ gitCommitInfo
54
+ };
55
+ //# sourceMappingURL=git.js.map