@flakiness/sdk 0.149.0 → 0.150.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.
Files changed (57) hide show
  1. package/README.md +9 -4
  2. package/lib/_internalUtils.js +2 -68
  3. package/lib/browser.js +2 -149
  4. package/lib/ciUtils.js +0 -1
  5. package/lib/createEnvironment.js +1 -105
  6. package/lib/createTestStepSnippets.js +1 -19
  7. package/lib/flakinessProjectConfig.js +6 -317
  8. package/lib/gitWorktree.js +8 -112
  9. package/lib/index.js +9 -1244
  10. package/lib/normalizeReport.js +2 -3
  11. package/lib/reportUtils.js +9 -384
  12. package/lib/reportUtilsBrowser.js +3 -132
  13. package/lib/showReport.js +3 -612
  14. package/lib/staticServer.js +7 -8
  15. package/lib/stripAnsi.js +1 -2
  16. package/lib/systemUtilizationSampler.js +2 -3
  17. package/lib/uploadReport.js +33 -148
  18. package/lib/visitTests.js +0 -1
  19. package/lib/writeReport.js +0 -1
  20. package/package.json +14 -5
  21. package/types/src/_internalUtils.d.ts +13 -0
  22. package/types/src/_internalUtils.d.ts.map +1 -0
  23. package/types/src/browser.d.ts +3 -0
  24. package/types/src/browser.d.ts.map +1 -0
  25. package/types/src/ciUtils.d.ts +33 -0
  26. package/types/src/ciUtils.d.ts.map +1 -0
  27. package/types/src/createEnvironment.d.ts +40 -0
  28. package/types/src/createEnvironment.d.ts.map +1 -0
  29. package/types/src/createTestStepSnippets.d.ts +30 -0
  30. package/types/src/createTestStepSnippets.d.ts.map +1 -0
  31. package/types/src/flakinessProjectConfig.d.ts +103 -0
  32. package/types/src/flakinessProjectConfig.d.ts.map +1 -0
  33. package/types/src/gitWorktree.d.ts +139 -0
  34. package/types/src/gitWorktree.d.ts.map +1 -0
  35. package/types/src/index.d.ts +10 -0
  36. package/types/src/index.d.ts.map +1 -0
  37. package/types/src/normalizeReport.d.ts +26 -0
  38. package/types/src/normalizeReport.d.ts.map +1 -0
  39. package/types/src/reportUtils.d.ts +7 -0
  40. package/types/src/reportUtils.d.ts.map +1 -0
  41. package/types/src/reportUtilsBrowser.d.ts +4 -0
  42. package/types/src/reportUtilsBrowser.d.ts.map +1 -0
  43. package/types/src/showReport.d.ts +18 -0
  44. package/types/src/showReport.d.ts.map +1 -0
  45. package/types/src/staticServer.d.ts +16 -0
  46. package/types/src/staticServer.d.ts.map +1 -0
  47. package/types/src/stripAnsi.d.ts +19 -0
  48. package/types/src/stripAnsi.d.ts.map +1 -0
  49. package/types/src/systemUtilizationSampler.d.ts +43 -0
  50. package/types/src/systemUtilizationSampler.d.ts.map +1 -0
  51. package/types/src/uploadReport.d.ts +196 -0
  52. package/types/src/uploadReport.d.ts.map +1 -0
  53. package/types/src/visitTests.d.ts +28 -0
  54. package/types/src/visitTests.d.ts.map +1 -0
  55. package/types/src/writeReport.d.ts +45 -0
  56. package/types/src/writeReport.d.ts.map +1 -0
  57. package/types/tsconfig.tsbuildinfo +0 -1
@@ -1,129 +1,7 @@
1
- // src/uploadReport.ts
2
1
  import assert from "assert";
3
- import fs2 from "fs";
4
- import { URL } from "url";
5
-
6
- // src/_internalUtils.ts
7
- import crypto from "crypto";
8
2
  import fs from "fs";
9
- import http from "http";
10
- import https from "https";
11
- import util from "util";
12
- import zlib from "zlib";
13
- var asyncBrotliCompress = util.promisify(zlib.brotliCompress);
14
- async function compressTextAsync(text) {
15
- return asyncBrotliCompress(text, {
16
- chunkSize: 32 * 1024,
17
- params: {
18
- [zlib.constants.BROTLI_PARAM_QUALITY]: 6,
19
- [zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT
20
- }
21
- });
22
- }
23
- var FLAKINESS_DBG = !!process.env.FLAKINESS_DBG;
24
- function errorText(error) {
25
- return FLAKINESS_DBG ? error.stack : error.message;
26
- }
27
- async function retryWithBackoff(job, backoff = []) {
28
- for (const timeout of backoff) {
29
- try {
30
- return await job();
31
- } catch (e) {
32
- if (e instanceof AggregateError)
33
- console.error(`[flakiness.io err]`, errorText(e.errors[0]));
34
- else if (e instanceof Error)
35
- console.error(`[flakiness.io err]`, errorText(e));
36
- else
37
- console.error(`[flakiness.io err]`, e);
38
- await new Promise((x) => setTimeout(x, timeout));
39
- }
40
- }
41
- return await job();
42
- }
43
- var httpUtils;
44
- ((httpUtils2) => {
45
- function createRequest({ url, method = "get", headers = {} }) {
46
- let resolve;
47
- let reject;
48
- const responseDataPromise = new Promise((a, b) => {
49
- resolve = a;
50
- reject = b;
51
- });
52
- const protocol = url.startsWith("https") ? https : http;
53
- headers = Object.fromEntries(Object.entries(headers).filter(([key, value]) => value !== void 0));
54
- const request = protocol.request(url, { method, headers }, (res) => {
55
- const chunks = [];
56
- res.on("data", (chunk) => chunks.push(chunk));
57
- res.on("end", () => {
58
- if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300)
59
- resolve(Buffer.concat(chunks));
60
- else
61
- reject(new Error(`Request to ${url} failed with ${res.statusCode}`));
62
- });
63
- res.on("error", (error) => reject(error));
64
- });
65
- request.on("error", reject);
66
- return { request, responseDataPromise };
67
- }
68
- httpUtils2.createRequest = createRequest;
69
- async function getBuffer(url, backoff) {
70
- return await retryWithBackoff(async () => {
71
- const { request, responseDataPromise } = createRequest({ url });
72
- request.end();
73
- return await responseDataPromise;
74
- }, backoff);
75
- }
76
- httpUtils2.getBuffer = getBuffer;
77
- async function getText(url, backoff) {
78
- const buffer = await getBuffer(url, backoff);
79
- return buffer.toString("utf-8");
80
- }
81
- httpUtils2.getText = getText;
82
- async function getJSON(url) {
83
- return JSON.parse(await getText(url));
84
- }
85
- httpUtils2.getJSON = getJSON;
86
- async function postText(url, text, backoff) {
87
- const headers = {
88
- "Content-Type": "application/json",
89
- "Content-Length": Buffer.byteLength(text) + ""
90
- };
91
- return await retryWithBackoff(async () => {
92
- const { request, responseDataPromise } = createRequest({ url, headers, method: "post" });
93
- request.write(text);
94
- request.end();
95
- return await responseDataPromise;
96
- }, backoff);
97
- }
98
- httpUtils2.postText = postText;
99
- async function postJSON(url, json, backoff) {
100
- const buffer = await postText(url, JSON.stringify(json), backoff);
101
- return JSON.parse(buffer.toString("utf-8"));
102
- }
103
- httpUtils2.postJSON = postJSON;
104
- })(httpUtils || (httpUtils = {}));
105
- function sha1Text(data) {
106
- const hash = crypto.createHash("sha1");
107
- hash.update(data);
108
- return hash.digest("hex");
109
- }
110
- function sha1File(filePath) {
111
- return new Promise((resolve, reject) => {
112
- const hash = crypto.createHash("sha1");
113
- const stream = fs.createReadStream(filePath);
114
- stream.on("data", (chunk) => {
115
- hash.update(chunk);
116
- });
117
- stream.on("end", () => {
118
- resolve(hash.digest("hex"));
119
- });
120
- stream.on("error", (err) => {
121
- reject(err);
122
- });
123
- });
124
- }
125
-
126
- // src/uploadReport.ts
3
+ import { URL } from "url";
4
+ import { compressTextAsync, retryWithBackoff, sha1File, sha1Text } from "./_internalUtils.js";
127
5
  async function createFileAttachment(contentType, filePath) {
128
6
  return {
129
7
  type: "file",
@@ -170,8 +48,8 @@ async function uploadReport(report, attachments, options) {
170
48
  return { status: "failed", error: errorMessage };
171
49
  }
172
50
  }
173
- var HTTP_BACKOFF = [100, 500, 1e3, 1e3, 1e3, 1e3];
174
- var ReportUpload = class {
51
+ const HTTP_BACKOFF = [100, 500, 1e3, 1e3, 1e3, 1e3];
52
+ class ReportUpload {
175
53
  _report;
176
54
  _attachments;
177
55
  _options;
@@ -232,14 +110,15 @@ var ReportUpload = class {
232
110
  "Content-Encoding": "br"
233
111
  };
234
112
  await retryWithBackoff(async () => {
235
- const { request, responseDataPromise } = httpUtils.createRequest({
236
- url: uploadUrl,
113
+ const response = await fetch(uploadUrl, {
114
+ method: "PUT",
237
115
  headers,
238
- method: "put"
116
+ body: Buffer.from(compressed)
239
117
  });
240
- request.write(compressed);
241
- request.end();
242
- await responseDataPromise;
118
+ if (!response.ok) {
119
+ throw new Error(`Request to ${uploadUrl} failed with ${response.status}`);
120
+ }
121
+ await response.arrayBuffer();
243
122
  }, HTTP_BACKOFF);
244
123
  }
245
124
  async _uploadAttachment(attachment, uploadUrl) {
@@ -247,41 +126,47 @@ var ReportUpload = class {
247
126
  const compressable = mimeType.startsWith("text/") || mimeType.endsWith("+json") || mimeType.endsWith("+text") || mimeType.endsWith("+xml");
248
127
  if (!compressable && attachment.type === "file") {
249
128
  await retryWithBackoff(async () => {
250
- const { request, responseDataPromise } = httpUtils.createRequest({
251
- url: uploadUrl,
129
+ const fileBuffer = await fs.promises.readFile(attachment.path);
130
+ const response = await fetch(uploadUrl, {
131
+ method: "PUT",
252
132
  headers: {
253
133
  "Content-Type": attachment.contentType,
254
- "Content-Length": (await fs2.promises.stat(attachment.path)).size + ""
134
+ "Content-Length": fileBuffer.length + ""
255
135
  },
256
- method: "put"
136
+ body: new Uint8Array(fileBuffer)
257
137
  });
258
- fs2.createReadStream(attachment.path).pipe(request);
259
- await responseDataPromise;
138
+ if (!response.ok) {
139
+ throw new Error(`Request to ${uploadUrl} failed with ${response.status}`);
140
+ }
141
+ await response.arrayBuffer();
260
142
  }, HTTP_BACKOFF);
261
143
  return;
262
144
  }
263
- let buffer = attachment.type === "buffer" ? attachment.body : await fs2.promises.readFile(attachment.path);
145
+ let buffer = attachment.type === "buffer" ? attachment.body : await fs.promises.readFile(attachment.path);
264
146
  assert(buffer);
265
147
  const encoding = compressable ? "br" : void 0;
266
148
  if (compressable)
267
149
  buffer = await compressTextAsync(buffer);
268
150
  const headers = {
269
151
  "Content-Type": attachment.contentType,
270
- "Content-Length": Buffer.byteLength(buffer) + "",
271
- "Content-Encoding": encoding
152
+ "Content-Length": Buffer.byteLength(buffer) + ""
272
153
  };
154
+ if (encoding) {
155
+ headers["Content-Encoding"] = encoding;
156
+ }
273
157
  await retryWithBackoff(async () => {
274
- const { request, responseDataPromise } = httpUtils.createRequest({
275
- url: uploadUrl,
158
+ const response = await fetch(uploadUrl, {
159
+ method: "PUT",
276
160
  headers,
277
- method: "put"
161
+ body: new Uint8Array(buffer)
278
162
  });
279
- request.write(buffer);
280
- request.end();
281
- await responseDataPromise;
163
+ if (!response.ok) {
164
+ throw new Error(`Request to ${uploadUrl} failed with ${response.status}`);
165
+ }
166
+ await response.arrayBuffer();
282
167
  }, HTTP_BACKOFF);
283
168
  }
284
- };
169
+ }
285
170
  export {
286
171
  createDataAttachment,
287
172
  createFileAttachment,
package/lib/visitTests.js CHANGED
@@ -1,4 +1,3 @@
1
- // src/visitTests.ts
2
1
  function visitTests(report, testVisitor) {
3
2
  function visitSuite(suite, parents) {
4
3
  parents.push(suite);
@@ -1,4 +1,3 @@
1
- // src/writeReport.ts
2
1
  import fs from "fs";
3
2
  import path from "path";
4
3
  async function writeReport(report, attachments, outputFolder) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flakiness/sdk",
3
- "version": "0.149.0",
3
+ "version": "0.150.0",
4
4
  "private": false,
5
5
  "exports": {
6
6
  ".": {
@@ -17,18 +17,27 @@
17
17
  "type": "module",
18
18
  "description": "",
19
19
  "types": "./types/index.d.ts",
20
- "scripts": {},
20
+ "scripts": {
21
+ "minor": "./version.mjs minor",
22
+ "patch": "./version.mjs patch"
23
+ },
21
24
  "keywords": [],
22
25
  "author": "Degu Labs, Inc",
23
- "license": "Fair Source 100",
26
+ "license": "MIT",
24
27
  "devDependencies": {
25
- "@types/babel__code-frame": "^7.0.6"
28
+ "@types/babel__code-frame": "^7.0.6",
29
+ "@types/debug": "^4.1.12",
30
+ "@types/node": "^25.0.3",
31
+ "esbuild": "^0.27.0",
32
+ "kubik": "^0.24.0",
33
+ "tsx": "^4.21.0",
34
+ "typescript": "^5.6.2"
26
35
  },
27
36
  "dependencies": {
28
37
  "@babel/code-frame": "^7.26.2",
29
38
  "@flakiness/flakiness-report": "^0.16.0",
30
39
  "chalk": "^5.6.2",
31
- "debug": "^4.3.7",
40
+ "debug": "^4.4.3",
32
41
  "open": "^10.2.0",
33
42
  "stable-hash": "^0.0.6"
34
43
  }
@@ -0,0 +1,13 @@
1
+ import { SpawnSyncOptionsWithStringEncoding } from 'child_process';
2
+ import crypto from 'crypto';
3
+ export declare function compressTextAsync(text: string | Buffer): Promise<Buffer>;
4
+ export type Brand<T, Brand extends string> = T & {
5
+ readonly [B in Brand as `__${B}_brand`]: never;
6
+ };
7
+ export declare function errorText(error: Error): string | undefined;
8
+ export declare function retryWithBackoff<T>(job: () => Promise<T>, backoff?: number[]): Promise<T>;
9
+ export declare function shell(command: string, args?: string[], options?: SpawnSyncOptionsWithStringEncoding): string | undefined;
10
+ export declare function sha1Text(data: crypto.BinaryLike): string;
11
+ export declare function sha1File(filePath: string): Promise<string>;
12
+ export declare function randomUUIDBase62(): string;
13
+ //# sourceMappingURL=_internalUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_internalUtils.d.ts","sourceRoot":"","sources":["../../src/_internalUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,kCAAkC,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,MAAM,MAAM,QAAQ,CAAC;AAQ5B,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAQ5E;AAED,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,KAAK,SAAS,MAAM,IAAI,CAAC,GAAG;IAC/C,QAAQ,EAAE,CAAC,IAAI,KAAK,IAAI,KAAK,CAAC,QAAQ,GAAG,KAAK;CAC/C,CAAC;AAGF,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,sBAErC;AAED,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAenG;AAED,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,kCAAkC,sBAWnG;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,UAI/C;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAc1D;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAczC"}
@@ -0,0 +1,3 @@
1
+ export { FlakinessReport } from '@flakiness/flakiness-report';
2
+ export * as ReportUtils from './reportUtilsBrowser.js';
3
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * A collection of utilities to extract information about continuous integration providers.
3
+ *
4
+ * This namespace provides functions to automatically detect and extract useful information
5
+ * from various CI/CD environments, including GitHub Actions, Azure DevOps, Jenkins, and others.
6
+ */
7
+ export declare namespace CIUtils {
8
+ /**
9
+ * Automatically extracts the run URL for common continuous integration providers.
10
+ *
11
+ * This function attempts to detect the current CI environment and construct the appropriate
12
+ * URL that links to the specific build/run where tests are being executed.
13
+ *
14
+ * Supported CI providers (checked in order):
15
+ * - GitHub Actions
16
+ * - Azure DevOps
17
+ * - GitLab CI (via `CI_JOB_URL` environment variable)
18
+ * - Jenkins (via `BUILD_URL` environment variable)
19
+ *
20
+ * @returns {string | undefined} The constructed CI run URL, or `undefined` if no supported
21
+ * CI environment is detected or required environment variables are missing.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const report: FlakinessReport.Report = {
26
+ * // ... other report properties
27
+ * url: CIUtils.runUrl(),
28
+ * };
29
+ * ```
30
+ */
31
+ function runUrl(): string | undefined;
32
+ }
33
+ //# sourceMappingURL=ciUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ciUtils.d.ts","sourceRoot":"","sources":["../../src/ciUtils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,yBAAiB,OAAO,CAAC;IACvB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,SAAgB,MAAM,IAAI,MAAM,GAAG,SAAS,CAE3C;CACF"}
@@ -0,0 +1,40 @@
1
+ import { FlakinessReport } from '@flakiness/flakiness-report';
2
+ /**
3
+ * Creates a Flakiness environment object with system information and user data.
4
+ *
5
+ * Automatically detects operating system details (name, architecture, version) and merges
6
+ * environment variables prefixed with `FK_ENV_` into the user-supplied data. This function
7
+ * is essential for creating environment metadata that helps identify test execution contexts
8
+ * in Flakiness reports.
9
+ *
10
+ * @param {Object} options - Configuration object for the environment.
11
+ * @param {string} options.name - Human-readable name for the environment (e.g., 'CI', 'Local Dev', 'Staging').
12
+ * @param {Record<string, string>} [options.userSuppliedData] - Additional key-value pairs to include
13
+ * in the environment data. These are merged with `FK_ENV_*` environment variables.
14
+ * @param {any} [options.opaqueData] - Optional opaque data object that will be stored with the
15
+ * environment but not used for environment deduplication.
16
+ *
17
+ * @returns {FlakinessReport.Environment} Environment object containing:
18
+ * - `name` - The provided environment name
19
+ * - `systemData` - Automatically detected OS information (arch, name, version)
20
+ * - `userSuppliedData` - Merged data from `FK_ENV_*` variables and `userSuppliedData` option
21
+ * - `opaqueData` - The provided opaque data, if any
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Basic usage
26
+ * const env = createEnvironment({ name: 'CI' });
27
+ *
28
+ * // With custom data
29
+ * const env = createEnvironment({
30
+ * name: 'Staging',
31
+ * userSuppliedData: { region: 'us-east-1', instance: 'large' }
32
+ * });
33
+ * ```
34
+ */
35
+ export declare function createEnvironment(options: {
36
+ name: string;
37
+ userSuppliedData?: Record<string, string>;
38
+ opaqueData?: any;
39
+ }): FlakinessReport.Environment;
40
+ //# sourceMappingURL=createEnvironment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createEnvironment.d.ts","sourceRoot":"","sources":["../../src/createEnvironment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAwD9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,UAAU,CAAC,EAAE,GAAG,CAAC;CAClB,GAAG,eAAe,CAAC,WAAW,CAe9B"}
@@ -0,0 +1,30 @@
1
+ import { FlakinessReport } from '@flakiness/flakiness-report';
2
+ import { GitWorktree } from './gitWorktree.js';
3
+ /**
4
+ * Generates code snippets for test steps and attaches them to the report in-place.
5
+ *
6
+ * This function reads source files from the git worktree and creates highlighted code snippets
7
+ * for each test step that has a location. The snippets include 3 lines of context (1 before,
8
+ * the line itself, 1 after) with syntax highlighting and a visual indicator pointing to the
9
+ * exact column position.
10
+ *
11
+ * The snippets are attached directly to the `step.snippet` property of each test step in the
12
+ * report object. Steps without locations or with invalid file paths are silently skipped.
13
+ *
14
+ * @param {GitWorktree} worktree - Git worktree instance used to resolve file paths from
15
+ * git-relative paths to absolute paths for reading source files.
16
+ *
17
+ * @param {FlakinessReport.Report} report - Flakiness report to process. The report is modified
18
+ * in-place by adding `snippet` properties to test steps.
19
+ *
20
+ * @returns {void} This function modifies the report in-place and does not return a value.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * const worktree = GitWorktree.create(process.cwd());
25
+ * createTestStepSnippetsInplace(worktree, report);
26
+ * // Report steps now have .snippet properties with highlighted code
27
+ * ```
28
+ */
29
+ export declare function createTestStepSnippetsInplace(worktree: GitWorktree, report: FlakinessReport.Report): void;
30
+ //# sourceMappingURL=createTestStepSnippets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createTestStepSnippets.d.ts","sourceRoot":"","sources":["../../src/createTestStepSnippets.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,CAAC,MAAM,QA4ClG"}
@@ -0,0 +1,103 @@
1
+ type JSONConfig = {
2
+ projectPublicId?: string;
3
+ customReportViewerUrl?: string;
4
+ };
5
+ /**
6
+ * Manages Flakiness project configuration stored in `.flakiness/config.json`.
7
+ *
8
+ * The configuration file is automatically located by searching upward from the current working
9
+ * directory for an existing `.flakiness` folder, or by placing it at the git repository root
10
+ * if no existing config is found.
11
+ */
12
+ export declare class FlakinessProjectConfig {
13
+ private _configPath;
14
+ private _config;
15
+ /**
16
+ * Loads the Flakiness project configuration from disk.
17
+ *
18
+ * Searches for an existing `.flakiness/config.json` file starting from the current working
19
+ * directory and walking up the directory tree. If no config exists, it determines the
20
+ * appropriate location (git root or current directory) for future saves.
21
+ *
22
+ * @returns {Promise<FlakinessProjectConfig>} Promise that resolves to a FlakinessProjectConfig
23
+ * instance. If no config file exists, returns an instance with default/empty values.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const config = await FlakinessProjectConfig.load();
28
+ * const projectId = config.projectPublicId();
29
+ * ```
30
+ */
31
+ static load(): Promise<FlakinessProjectConfig>;
32
+ /**
33
+ * Creates a new empty Flakiness project configuration.
34
+ *
35
+ * Creates a configuration instance with no values set. Use this when you want to build
36
+ * a configuration from scratch. Call `save()` to persist it to disk.
37
+ *
38
+ * @returns {FlakinessProjectConfig} A new empty configuration instance.
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const config = FlakinessProjectConfig.createEmpty();
43
+ * config.setProjectPublicId('my-project-id');
44
+ * await config.save();
45
+ * ```
46
+ */
47
+ static createEmpty(): FlakinessProjectConfig;
48
+ constructor(_configPath: string, _config: JSONConfig);
49
+ /**
50
+ * Returns the absolute path to the configuration file.
51
+ *
52
+ * @returns {string} Absolute path to `.flakiness/config.json`.
53
+ */
54
+ path(): string;
55
+ /**
56
+ * Returns the project's public ID, if configured.
57
+ *
58
+ * The project public ID is used to associate reports with a specific Flakiness.io project.
59
+ *
60
+ * @returns {string | undefined} Project public ID, or `undefined` if not set.
61
+ */
62
+ projectPublicId(): string | undefined;
63
+ /**
64
+ * Returns the report viewer URL, either custom or default.
65
+ *
66
+ * @returns {string} Custom report viewer URL if configured, otherwise the default
67
+ * `https://report.flakiness.io`.
68
+ */
69
+ reportViewerUrl(): string;
70
+ /**
71
+ * Sets or clears the custom report viewer URL.
72
+ *
73
+ * @param {string | undefined} url - Custom report viewer URL to use, or `undefined` to
74
+ * clear and use the default URL.
75
+ */
76
+ setCustomReportViewerUrl(url: string | undefined): void;
77
+ /**
78
+ * Sets the project's public ID.
79
+ *
80
+ * @param {string | undefined} projectId - Project public ID to set, or `undefined` to clear.
81
+ */
82
+ setProjectPublicId(projectId: string | undefined): void;
83
+ /**
84
+ * Saves the configuration to disk.
85
+ *
86
+ * Writes the current configuration values to `.flakiness/config.json`. Creates the
87
+ * `.flakiness` directory if it doesn't exist.
88
+ *
89
+ * @returns {Promise<void>} Promise that resolves when the file has been written.
90
+ *
91
+ * @throws {Error} Throws if unable to create directories or write the file.
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * const config = await FlakinessProjectConfig.load();
96
+ * config.setProjectPublicId('my-project');
97
+ * await config.save();
98
+ * ```
99
+ */
100
+ save(): Promise<void>;
101
+ }
102
+ export {};
103
+ //# sourceMappingURL=flakinessProjectConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flakinessProjectConfig.d.ts","sourceRoot":"","sources":["../../src/flakinessProjectConfig.ts"],"names":[],"mappings":"AAmCA,KAAK,UAAU,GAAG;IAChB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAA;AAED;;;;;;GAMG;AACH,qBAAa,sBAAsB;IA4C/B,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,OAAO;IA5CjB;;;;;;;;;;;;;;;OAeG;WACU,IAAI,IAAI,OAAO,CAAC,sBAAsB,CAAC;IAOpD;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,WAAW;gBAKR,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,UAAU;IAG7B;;;;OAIG;IACH,IAAI;IAIJ;;;;;;OAMG;IACH,eAAe;IAIf;;;;;OAKG;IACH,eAAe;IAIf;;;;;OAKG;IACH,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAC,SAAS;IAO9C;;;;OAIG;IACH,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAC,SAAS;IAI9C;;;;;;;;;;;;;;;;OAgBG;IACG,IAAI;CAIX"}
@@ -0,0 +1,139 @@
1
+ import { FlakinessReport } from '@flakiness/flakiness-report';
2
+ /**
3
+ * Represents a git commit with its metadata.
4
+ *
5
+ * This type is returned by `GitWorktree.listCommits()` and contains all the information
6
+ * needed to identify and reference a commit in a git repository.
7
+ */
8
+ export type GitCommit = {
9
+ /** Full commit hash (SHA-1, 40 characters) */
10
+ commitId: FlakinessReport.CommitId;
11
+ /** Commit timestamp in milliseconds since Unix epoch */
12
+ timestamp: FlakinessReport.UnixTimestampMS;
13
+ /** Commit message (subject line only) */
14
+ message: string;
15
+ /** Author name, if available */
16
+ author?: string;
17
+ /** Array of parent commit IDs (empty for initial commit, typically one for normal commits, multiple for merges) */
18
+ parents: FlakinessReport.CommitId[];
19
+ };
20
+ /**
21
+ * Utilities for working with git repositories and converting between git-relative paths
22
+ * and absolute native paths. Essential for creating Flakiness Reports where all paths
23
+ * must be relative to the git root.
24
+ */
25
+ export declare class GitWorktree {
26
+ private _gitRoot;
27
+ /**
28
+ * Creates a GitWorktree instance from any path inside a git repository.
29
+ *
30
+ * @param {string} somePathInsideGitRepo - Any path (file or directory) within a git repository.
31
+ * Can be absolute or relative. The function will locate the git root directory.
32
+ *
33
+ * @returns {GitWorktree} A new GitWorktree instance bound to the discovered git root.
34
+ *
35
+ * @throws {Error} Throws if the path is not inside a git repository or if git commands fail.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const worktree = GitWorktree.create('./src/my-test.ts');
40
+ * const gitRoot = worktree.rootPath();
41
+ * ```
42
+ */
43
+ static create(somePathInsideGitRepo: string): GitWorktree;
44
+ private _posixGitRoot;
45
+ constructor(_gitRoot: string);
46
+ /**
47
+ * Returns the native absolute path of the git repository root directory.
48
+ *
49
+ * @returns {string} Native absolute path to the git root. Format matches the current platform
50
+ * (Windows or POSIX).
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * const root = worktree.rootPath();
55
+ * // On Windows: 'D:\project'
56
+ * // On Unix: '/project'
57
+ * ```
58
+ */
59
+ rootPath(): string;
60
+ /**
61
+ * Returns the commit ID (SHA-1 hash) of the current HEAD commit.
62
+ *
63
+ * @returns {FlakinessReport.CommitId} Full 40-character commit hash of the HEAD commit.
64
+ *
65
+ * @throws {Error} Throws if git command fails or repository is in an invalid state.
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * const commitId = worktree.headCommitId();
70
+ * // Returns: 'a1b2c3d4e5f6...' (40-character SHA-1)
71
+ * ```
72
+ */
73
+ headCommitId(): FlakinessReport.CommitId;
74
+ /**
75
+ * Converts a native absolute path to a git-relative POSIX path.
76
+ *
77
+ * Takes any absolute path (Windows or POSIX format) and converts it to a POSIX path
78
+ * relative to the git repository root. This is essential for Flakiness reports where
79
+ * all file paths must be git-relative and use POSIX separators.
80
+ *
81
+ * @param {string} absolutePath - Native absolute path to convert. Can be in Windows format
82
+ * (e.g., `D:\project\src\test.ts`) or POSIX format (e.g., `/project/src/test.ts`).
83
+ *
84
+ * @returns {FlakinessReport.GitFilePath} POSIX path relative to git root (e.g., `src/test.ts`).
85
+ * Returns an empty string if the path is the git root itself.
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const gitPath = worktree.gitPath('/Users/project/src/test.ts');
90
+ * // Returns: 'src/test.ts'
91
+ * ```
92
+ */
93
+ gitPath(absolutePath: string): FlakinessReport.GitFilePath;
94
+ /**
95
+ * Converts a git-relative POSIX path to a native absolute path.
96
+ *
97
+ * Takes a POSIX path relative to the git root and converts it to the native absolute path
98
+ * format for the current platform (Windows or POSIX). This is the inverse of `gitPath()`.
99
+ *
100
+ * @param {FlakinessReport.GitFilePath} relativePath - POSIX path relative to git root
101
+ * (e.g., `src/test.ts`).
102
+ *
103
+ * @returns {string} Native absolute path. On Windows, returns Windows format (e.g., `D:\project\src\test.ts`).
104
+ * On POSIX systems, returns POSIX format (e.g., `/project/src/test.ts`).
105
+ *
106
+ * @example
107
+ * ```typescript
108
+ * const absolutePath = worktree.absolutePath('src/test.ts');
109
+ * // On Windows: 'D:\project\src\test.ts'
110
+ * // On Unix: '/project/src/test.ts'
111
+ * ```
112
+ */
113
+ absolutePath(relativePath: FlakinessReport.GitFilePath): string;
114
+ /**
115
+ * Lists recent commits from the repository.
116
+ *
117
+ * Retrieves commit information including commit ID, timestamp, author, message, and parent commits.
118
+ * Note: CI environments often have shallow checkouts with limited history, which may affect
119
+ * the number of commits returned.
120
+ *
121
+ * @param {number} count - Maximum number of commits to retrieve, starting from HEAD.
122
+ *
123
+ * @returns {Promise<GitCommit[]>} Promise that resolves to an array of commit objects, ordered
124
+ * from most recent to oldest. Each commit includes:
125
+ * - `commitId` - Full commit hash
126
+ * - `timestamp` - Commit timestamp in milliseconds since Unix epoch
127
+ * - `message` - Commit message (subject line)
128
+ * - `author` - Author name
129
+ * - `parents` - Array of parent commit IDs
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * const commits = await worktree.listCommits(10);
134
+ * console.log(`Latest commit: ${commits[0].message}`);
135
+ * ```
136
+ */
137
+ listCommits(count: number): Promise<GitCommit[]>;
138
+ }
139
+ //# sourceMappingURL=gitWorktree.d.ts.map