@flakiness/sdk 3.4.0 → 3.5.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 CHANGED
@@ -105,6 +105,7 @@ Use this entry point when you need to process or manipulate reports in browser-b
105
105
  - **`fetchTestDurations()`** - Fetch historical test durations from Flakiness.io and return a report enriched with timings
106
106
  - **`showReport()`** - Start a local server and open the report in your browser
107
107
  - **`showReportCommand()`** - Build a shell command for opening the report later with the Flakiness CLI
108
+ - **`showReportMessage()`** - Build the message a runner prints after writing a report (CI-aware: a one-liner with the report path on CI, open-in-CLI instructions otherwise)
108
109
  - **`uploadReport()`** - Upload reports and attachments to Flakiness.io
109
110
  - **`writeReport()`** - Write reports to disk in the standard Flakiness report format
110
111
 
package/lib/index.js CHANGED
@@ -218,6 +218,10 @@ function sha1File(filePath) {
218
218
  });
219
219
  });
220
220
  }
221
+ function isCI() {
222
+ const ci = (process.env.CI ?? "").toLowerCase();
223
+ return ci !== "" && ci !== "false" && ci !== "0";
224
+ }
221
225
  function randomUUIDBase62() {
222
226
  const BASE62_CHARSET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
223
227
  let num = BigInt("0x" + crypto.randomUUID().replace(/-/g, ""));
@@ -924,7 +928,7 @@ async function uploadReport(report, attachments, options) {
924
928
  if (!flakinessAccessToken && githubOIDC) {
925
929
  if (!report.flakinessProject) {
926
930
  const reason = "`flakinessProject` is not configured to upload using Github OIDC.";
927
- if (process.env.CI)
931
+ if (isCI())
928
932
  logger.warn(`[flakiness.io] \u26A0 Skipping upload: ${reason}`);
929
933
  return { status: "skipped", reason };
930
934
  }
@@ -942,7 +946,7 @@ async function uploadReport(report, attachments, options) {
942
946
  }
943
947
  if (!flakinessAccessToken) {
944
948
  const reason = "No FLAKINESS_ACCESS_TOKEN found";
945
- if (process.env.CI)
949
+ if (isCI())
946
950
  logger.warn(`[flakiness.io] \u26A0 Skipping upload: ${reason}`);
947
951
  return { status: "skipped", reason };
948
952
  }
@@ -1497,12 +1501,24 @@ function quoteShellArgument(argument) {
1497
1501
  return JSON.stringify(argument);
1498
1502
  }
1499
1503
 
1504
+ // src/showReportMessage.ts
1505
+ import path4 from "node:path";
1506
+ import { styleText as styleText2 } from "node:util";
1507
+ function showReportMessage(reportFolder) {
1508
+ if (isCI())
1509
+ return `Flakiness report written to ${path4.resolve(reportFolder)}`;
1510
+ const command = showReportCommand(reportFolder);
1511
+ return `To open last Flakiness report, run:
1512
+
1513
+ ${styleText2("cyan", command)}`;
1514
+ }
1515
+
1500
1516
  // src/writeReport.ts
1501
1517
  import fs8 from "fs";
1502
- import path4 from "path";
1518
+ import path5 from "path";
1503
1519
  async function writeReport(report, attachments, outputFolder) {
1504
- const reportPath = path4.join(outputFolder, "report.json");
1505
- const attachmentsFolder = path4.join(outputFolder, "attachments");
1520
+ const reportPath = path5.join(outputFolder, "report.json");
1521
+ const attachmentsFolder = path5.join(outputFolder, "attachments");
1506
1522
  await fs8.promises.rm(outputFolder, { recursive: true, force: true });
1507
1523
  await fs8.promises.mkdir(outputFolder, { recursive: true });
1508
1524
  await fs8.promises.writeFile(reportPath, JSON.stringify(report), "utf-8");
@@ -1510,7 +1526,7 @@ async function writeReport(report, attachments, outputFolder) {
1510
1526
  await fs8.promises.mkdir(attachmentsFolder);
1511
1527
  const movedAttachments = [];
1512
1528
  for (const attachment of attachments) {
1513
- const attachmentPath = path4.join(attachmentsFolder, attachment.id);
1529
+ const attachmentPath = path5.join(attachmentsFolder, attachment.id);
1514
1530
  if (attachment.type === "file")
1515
1531
  await fs8.promises.cp(attachment.path, attachmentPath);
1516
1532
  else if (attachment.type === "buffer")
@@ -1535,6 +1551,7 @@ export {
1535
1551
  readReport,
1536
1552
  showReport,
1537
1553
  showReportCommand,
1554
+ showReportMessage,
1538
1555
  uploadReport,
1539
1556
  writeReport
1540
1557
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flakiness/sdk",
3
- "version": "3.4.0",
3
+ "version": "3.5.0",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,5 +11,14 @@ export declare function putBuffer(input: RequestInfo | URL, body: Buffer, header
11
11
  export declare function shell(command: string, args?: string[], options?: SpawnSyncOptionsWithStringEncoding): string | undefined;
12
12
  export declare function sha1Text(data: crypto.BinaryLike): string;
13
13
  export declare function sha1File(filePath: string): Promise<string>;
14
+ /**
15
+ * Whether the current process is running on CI.
16
+ *
17
+ * Virtually every CI provider (GitHub Actions, GitLab, CircleCI, …) sets the `CI`
18
+ * environment variable, usually to `true` or `1`. An explicit `false`/`0`/empty
19
+ * value is treated as an opt-out rather than as "on" — `process.env.CI` is a
20
+ * non-empty truthy string in those cases too, so a plain truthiness check is wrong.
21
+ */
22
+ export declare function isCI(): boolean;
14
23
  export declare function randomUUIDBase62(): string;
15
24
  //# sourceMappingURL=_internalUtils.d.ts.map
@@ -1 +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;AAM5B,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,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CASnG;AAED,eAAO,MAAM,YAAY,UAAqC,CAAC;AAY/D,wBAAsB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,EAAE,OAAO,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,CAK3H;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAU9I;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"}
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;AAM5B,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,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CASnG;AAED,eAAO,MAAM,YAAY,UAAqC,CAAC;AAY/D,wBAAsB,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,EAAE,OAAO,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,CAK3H;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAU9I;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;;;;;;;GAOG;AACH,wBAAgB,IAAI,IAAI,OAAO,CAG9B;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAczC"}
@@ -8,6 +8,7 @@ export { fetchTestDurations, type FetchTestDurationsOptions } from './fetchTestD
8
8
  export { readReport } from './readReport.js';
9
9
  export { showReport } from './showReport.js';
10
10
  export { showReportCommand } from './showReportCommand.js';
11
+ export { showReportMessage } from './showReportMessage.js';
11
12
  export { uploadReport } from './uploadReport.js';
12
13
  export { writeReport } from './writeReport.js';
13
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAGhD,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAGhD,OAAO,EAAE,kBAAkB,EAAE,KAAK,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Builds the human-facing message that test runners print after writing a report.
3
+ *
4
+ * In interactive environments this returns instructions for opening the report
5
+ * locally with the Flakiness CLI. On CI (the `CI` environment variable is set to
6
+ * anything other than `false`/`0`), where launching the local viewer isn't useful,
7
+ * it returns a one-liner pointing at the folder the report was written to instead.
8
+ *
9
+ * @param {string} reportFolder - Absolute or relative path to the report folder.
10
+ *
11
+ * @returns {string} A ready-to-print message.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * console.log(showReportMessage('./flakiness-report'));
16
+ * // Interactive: "To open last Flakiness report, run:\n\n npx flakiness show"
17
+ * // On CI: "Flakiness report written to /abs/path/flakiness-report"
18
+ * ```
19
+ */
20
+ export declare function showReportMessage(reportFolder: string): string;
21
+ //# sourceMappingURL=showReportMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"showReportMessage.d.ts","sourceRoot":"","sources":["../../src/showReportMessage.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAM9D"}