Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ Use this entry point when you need to process or manipulate reports in browser-b
- **`fetchTestDurations()`** - Fetch historical test durations from Flakiness.io and return a report enriched with timings
- **`showReport()`** - Start a local server and open the report in your browser
- **`showReportCommand()`** - Build a shell command for opening the report later with the Flakiness CLI
- **`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)
- **`uploadReport()`** - Upload reports and attachments to Flakiness.io
- **`writeReport()`** - Write reports to disk in the standard Flakiness report format

Expand Down
13 changes: 13 additions & 0 deletions src/_internalUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ export function sha1File(filePath: string): Promise<string> {
});
}

/**
* Whether the current process is running on CI.
*
* Virtually every CI provider (GitHub Actions, GitLab, CircleCI, …) sets the `CI`
* environment variable, usually to `true` or `1`. An explicit `false`/`0`/empty
* value is treated as an opt-out rather than as "on" — `process.env.CI` is a
* non-empty truthy string in those cases too, so a plain truthiness check is wrong.
*/
export function isCI(): boolean {
const ci = (process.env.CI ?? '').toLowerCase();
return ci !== '' && ci !== 'false' && ci !== '0';
}

export function randomUUIDBase62(): string {
const BASE62_CHARSET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
let num = BigInt('0x' + crypto.randomUUID().replace(/-/g, ''));
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ export { fetchTestDurations, type FetchTestDurationsOptions } from './fetchTestD
export { readReport } from './readReport.js';
export { showReport } from './showReport.js';
export { showReportCommand } from './showReportCommand.js';
export { showReportMessage } from './showReportMessage.js';
export { uploadReport } from './uploadReport.js';
export { writeReport } from './writeReport.js';
31 changes: 31 additions & 0 deletions src/showReportMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import path from 'node:path';
import { styleText } from 'node:util';
import { isCI } from './_internalUtils.js';
import { showReportCommand } from './showReportCommand.js';

/**
* Builds the human-facing message that test runners print after writing a report.
*
* In interactive environments this returns instructions for opening the report
* locally with the Flakiness CLI. On CI (the `CI` environment variable is set to
* anything other than `false`/`0`), where launching the local viewer isn't useful,
* it returns a one-liner pointing at the folder the report was written to instead.
*
* @param {string} reportFolder - Absolute or relative path to the report folder.
*
* @returns {string} A ready-to-print message.
*
* @example
* ```typescript
* console.log(showReportMessage('./flakiness-report'));
* // Interactive: "To open last Flakiness report, run:\n\n npx flakiness show"
* // On CI: "Flakiness report written to /abs/path/flakiness-report"
* ```
*/
export function showReportMessage(reportFolder: string): string {
if (isCI())
return `Flakiness report written to ${path.resolve(reportFolder)}`;

const command = showReportCommand(reportFolder);
return `To open last Flakiness report, run:\n\n ${styleText('cyan', command)}`;
}
6 changes: 3 additions & 3 deletions src/uploadReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import assert from 'assert';
import fs from 'fs';
import { URL } from 'url';
import { GithubOIDC } from './githubOIDC.js';
import { compressTextAsync, getJSON, putBuffer, sha1File, sha1Text } from './_internalUtils.js';
import { compressTextAsync, getJSON, isCI, putBuffer, sha1File, sha1Text } from './_internalUtils.js';

type ReportUploaderOptions = {
flakinessEndpoint: string;
Expand Down Expand Up @@ -246,7 +246,7 @@ export async function uploadReport(
if (!flakinessAccessToken && githubOIDC) {
if (!report.flakinessProject) {
const reason = '`flakinessProject` is not configured to upload using Github OIDC.';
if (process.env.CI)
if (isCI())
logger.warn(`[flakiness.io] ⚠ Skipping upload: ${reason}`);
return { status: 'skipped', reason };
}
Expand All @@ -265,7 +265,7 @@ export async function uploadReport(

if (!flakinessAccessToken) {
const reason = 'No FLAKINESS_ACCESS_TOKEN found';
if (process.env.CI)
if (isCI())
logger.warn(`[flakiness.io] ⚠ Skipping upload: ${reason}`);
return { status: 'skipped', reason };
}
Expand Down
Loading