@flakiness/sdk 1.1.0 → 2.1.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 +26 -2
- package/lib/index.js +34 -169
- package/package.json +1 -1
- package/types/src/index.d.ts +0 -1
- package/types/src/index.d.ts.map +1 -1
- package/types/src/showReport.d.ts +6 -1
- package/types/src/showReport.d.ts.map +1 -1
- package/types/src/uploadReport.d.ts +16 -3
- package/types/src/uploadReport.d.ts.map +1 -1
- package/types/src/flakinessProjectConfig.d.ts +0 -103
- package/types/src/flakinessProjectConfig.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -96,6 +96,30 @@ Use this entry point when you need to process or manipulate reports in browser-b
|
|
|
96
96
|
- **`uploadReport()`** - Upload reports and attachments to Flakiness.io
|
|
97
97
|
- **`writeReport()`** - Write reports to disk in the standard Flakiness report format
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
## Uploading Reports
|
|
100
|
+
|
|
101
|
+
`uploadReport()` authenticates using one of the following methods (in order of priority):
|
|
102
|
+
|
|
103
|
+
1. **Access token** — pass `flakinessAccessToken` option or set the `FLAKINESS_ACCESS_TOKEN` environment variable.
|
|
104
|
+
2. **GitHub Actions OIDC** — when running inside GitHub Actions, `uploadReport` can authenticate automatically without an access token. This works when both conditions are met:
|
|
105
|
+
- The report has `flakinessProject` set to a flakiness project identifier (e.g. `"org/proj"`).
|
|
106
|
+
- The flakiness project is bound to the GitHub repository that runs the action.
|
|
107
|
+
|
|
108
|
+
Your GitHub Actions workflow must grant the `id-token: write` permission:
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
permissions:
|
|
112
|
+
id-token: write
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
const report: FlakinessReport.Report = {
|
|
117
|
+
flakinessProject: 'my-org/my-project',
|
|
118
|
+
// ... rest of the report
|
|
119
|
+
};
|
|
120
|
+
// No access token needed — OIDC authentication is used automatically.
|
|
121
|
+
await uploadReport(report, attachments);
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
If neither method is available, the upload is skipped with a `'skipped'` status.
|
|
101
125
|
|
package/lib/index.js
CHANGED
|
@@ -1069,7 +1069,17 @@ var ReportUpload = class {
|
|
|
1069
1069
|
}));
|
|
1070
1070
|
}
|
|
1071
1071
|
async upload() {
|
|
1072
|
-
const
|
|
1072
|
+
const [orgSlug, projectSlug] = this._report.flakinessProject ? this._report.flakinessProject.split("/") : [];
|
|
1073
|
+
const response = await this._api("/api/upload/start", this._options.flakinessAccessToken, {
|
|
1074
|
+
// When bearer token is a Device OAuth token with a user session, upload/start
|
|
1075
|
+
// endpoint requires passing explicit orgSlug / projectSlug.
|
|
1076
|
+
// This is NOT required and is ignored for automation-scoped tokens,
|
|
1077
|
+
// like Github OIDC of `FLAKINESS_ACCESS_TOKEN`.
|
|
1078
|
+
// Since this SDK is also used to power Flakiness CLI, we pass these here
|
|
1079
|
+
// unconditionally.
|
|
1080
|
+
orgSlug,
|
|
1081
|
+
projectSlug
|
|
1082
|
+
});
|
|
1073
1083
|
if (response?.error || !response.result)
|
|
1074
1084
|
return { success: false, message: response.error };
|
|
1075
1085
|
const webUrl = new URL2(response.result.webUrl, this._options.flakinessEndpoint).toString();
|
|
@@ -1231,151 +1241,11 @@ async function listFilesRecursively(dir, result = []) {
|
|
|
1231
1241
|
import chalk from "chalk";
|
|
1232
1242
|
import open from "open";
|
|
1233
1243
|
|
|
1234
|
-
// src/flakinessProjectConfig.ts
|
|
1235
|
-
import fs6 from "fs";
|
|
1236
|
-
import path2 from "path";
|
|
1237
|
-
function createConfigPath(dir) {
|
|
1238
|
-
return path2.join(dir, ".flakiness", "config.json");
|
|
1239
|
-
}
|
|
1240
|
-
var gConfigPath;
|
|
1241
|
-
function ensureConfigPath() {
|
|
1242
|
-
if (!gConfigPath)
|
|
1243
|
-
gConfigPath = computeConfigPath();
|
|
1244
|
-
return gConfigPath;
|
|
1245
|
-
}
|
|
1246
|
-
function computeConfigPath() {
|
|
1247
|
-
for (let p = process.cwd(); p !== path2.resolve(p, ".."); p = path2.resolve(p, "..")) {
|
|
1248
|
-
const configPath = createConfigPath(p);
|
|
1249
|
-
if (fs6.existsSync(configPath))
|
|
1250
|
-
return configPath;
|
|
1251
|
-
}
|
|
1252
|
-
try {
|
|
1253
|
-
const worktree = GitWorktree.create(process.cwd());
|
|
1254
|
-
return createConfigPath(worktree.rootPath());
|
|
1255
|
-
} catch (e) {
|
|
1256
|
-
return createConfigPath(process.cwd());
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
var FlakinessProjectConfig = class _FlakinessProjectConfig {
|
|
1260
|
-
constructor(_configPath, _config) {
|
|
1261
|
-
this._configPath = _configPath;
|
|
1262
|
-
this._config = _config;
|
|
1263
|
-
}
|
|
1264
|
-
/**
|
|
1265
|
-
* Loads the Flakiness project configuration from disk.
|
|
1266
|
-
*
|
|
1267
|
-
* Searches for an existing `.flakiness/config.json` file starting from the current working
|
|
1268
|
-
* directory and walking up the directory tree. If no config exists, it determines the
|
|
1269
|
-
* appropriate location (git root or current directory) for future saves.
|
|
1270
|
-
*
|
|
1271
|
-
* @returns {Promise<FlakinessProjectConfig>} Promise that resolves to a FlakinessProjectConfig
|
|
1272
|
-
* instance. If no config file exists, returns an instance with default/empty values.
|
|
1273
|
-
*
|
|
1274
|
-
* @example
|
|
1275
|
-
* ```typescript
|
|
1276
|
-
* const config = await FlakinessProjectConfig.load();
|
|
1277
|
-
* const projectId = config.projectPublicId();
|
|
1278
|
-
* ```
|
|
1279
|
-
*/
|
|
1280
|
-
static async load() {
|
|
1281
|
-
const configPath = ensureConfigPath();
|
|
1282
|
-
const data = await fs6.promises.readFile(configPath, "utf-8").catch((e) => void 0);
|
|
1283
|
-
const json = data ? JSON.parse(data) : {};
|
|
1284
|
-
return new _FlakinessProjectConfig(configPath, json);
|
|
1285
|
-
}
|
|
1286
|
-
/**
|
|
1287
|
-
* Creates a new empty Flakiness project configuration.
|
|
1288
|
-
*
|
|
1289
|
-
* Creates a configuration instance with no values set. Use this when you want to build
|
|
1290
|
-
* a configuration from scratch. Call `save()` to persist it to disk.
|
|
1291
|
-
*
|
|
1292
|
-
* @returns {FlakinessProjectConfig} A new empty configuration instance.
|
|
1293
|
-
*
|
|
1294
|
-
* @example
|
|
1295
|
-
* ```typescript
|
|
1296
|
-
* const config = FlakinessProjectConfig.createEmpty();
|
|
1297
|
-
* config.setProjectPublicId('my-project-id');
|
|
1298
|
-
* await config.save();
|
|
1299
|
-
* ```
|
|
1300
|
-
*/
|
|
1301
|
-
static createEmpty() {
|
|
1302
|
-
return new _FlakinessProjectConfig(ensureConfigPath(), {});
|
|
1303
|
-
}
|
|
1304
|
-
/**
|
|
1305
|
-
* Returns the absolute path to the configuration file.
|
|
1306
|
-
*
|
|
1307
|
-
* @returns {string} Absolute path to `.flakiness/config.json`.
|
|
1308
|
-
*/
|
|
1309
|
-
path() {
|
|
1310
|
-
return this._configPath;
|
|
1311
|
-
}
|
|
1312
|
-
/**
|
|
1313
|
-
* Returns the project's public ID, if configured.
|
|
1314
|
-
*
|
|
1315
|
-
* The project public ID is used to associate reports with a specific Flakiness.io project.
|
|
1316
|
-
*
|
|
1317
|
-
* @returns {string | undefined} Project public ID, or `undefined` if not set.
|
|
1318
|
-
*/
|
|
1319
|
-
projectPublicId() {
|
|
1320
|
-
return this._config.projectPublicId;
|
|
1321
|
-
}
|
|
1322
|
-
/**
|
|
1323
|
-
* Returns the report viewer URL, either custom or default.
|
|
1324
|
-
*
|
|
1325
|
-
* @returns {string} Custom report viewer URL if configured, otherwise the default
|
|
1326
|
-
* `https://report.flakiness.io`.
|
|
1327
|
-
*/
|
|
1328
|
-
reportViewerUrl() {
|
|
1329
|
-
return this._config.customReportViewerUrl ?? "https://report.flakiness.io";
|
|
1330
|
-
}
|
|
1331
|
-
/**
|
|
1332
|
-
* Sets or clears the custom report viewer URL.
|
|
1333
|
-
*
|
|
1334
|
-
* @param {string | undefined} url - Custom report viewer URL to use, or `undefined` to
|
|
1335
|
-
* clear and use the default URL.
|
|
1336
|
-
*/
|
|
1337
|
-
setCustomReportViewerUrl(url) {
|
|
1338
|
-
if (url)
|
|
1339
|
-
this._config.customReportViewerUrl = url;
|
|
1340
|
-
else
|
|
1341
|
-
delete this._config.customReportViewerUrl;
|
|
1342
|
-
}
|
|
1343
|
-
/**
|
|
1344
|
-
* Sets the project's public ID.
|
|
1345
|
-
*
|
|
1346
|
-
* @param {string | undefined} projectId - Project public ID to set, or `undefined` to clear.
|
|
1347
|
-
*/
|
|
1348
|
-
setProjectPublicId(projectId) {
|
|
1349
|
-
this._config.projectPublicId = projectId;
|
|
1350
|
-
}
|
|
1351
|
-
/**
|
|
1352
|
-
* Saves the configuration to disk.
|
|
1353
|
-
*
|
|
1354
|
-
* Writes the current configuration values to `.flakiness/config.json`. Creates the
|
|
1355
|
-
* `.flakiness` directory if it doesn't exist.
|
|
1356
|
-
*
|
|
1357
|
-
* @returns {Promise<void>} Promise that resolves when the file has been written.
|
|
1358
|
-
*
|
|
1359
|
-
* @throws {Error} Throws if unable to create directories or write the file.
|
|
1360
|
-
*
|
|
1361
|
-
* @example
|
|
1362
|
-
* ```typescript
|
|
1363
|
-
* const config = await FlakinessProjectConfig.load();
|
|
1364
|
-
* config.setProjectPublicId('my-project');
|
|
1365
|
-
* await config.save();
|
|
1366
|
-
* ```
|
|
1367
|
-
*/
|
|
1368
|
-
async save() {
|
|
1369
|
-
await fs6.promises.mkdir(path2.dirname(this._configPath), { recursive: true });
|
|
1370
|
-
await fs6.promises.writeFile(this._configPath, JSON.stringify(this._config, null, 2));
|
|
1371
|
-
}
|
|
1372
|
-
};
|
|
1373
|
-
|
|
1374
1244
|
// src/staticServer.ts
|
|
1375
1245
|
import debug2 from "debug";
|
|
1376
|
-
import * as
|
|
1246
|
+
import * as fs6 from "fs";
|
|
1377
1247
|
import * as http from "http";
|
|
1378
|
-
import * as
|
|
1248
|
+
import * as path2 from "path";
|
|
1379
1249
|
var log2 = debug2("fk:static_server");
|
|
1380
1250
|
var StaticServer = class {
|
|
1381
1251
|
_server;
|
|
@@ -1396,7 +1266,7 @@ var StaticServer = class {
|
|
|
1396
1266
|
};
|
|
1397
1267
|
constructor(pathPrefix, folderPath, cors = []) {
|
|
1398
1268
|
this._pathPrefix = "/" + pathPrefix.replace(/^\//, "").replace(/\/$/, "");
|
|
1399
|
-
this._absoluteFolderPath =
|
|
1269
|
+
this._absoluteFolderPath = path2.resolve(folderPath);
|
|
1400
1270
|
this._cors = cors;
|
|
1401
1271
|
this._server = http.createServer((req, res) => this._handleRequest(req, res));
|
|
1402
1272
|
}
|
|
@@ -1493,22 +1363,22 @@ var StaticServer = class {
|
|
|
1493
1363
|
return;
|
|
1494
1364
|
}
|
|
1495
1365
|
const relativePath = url.slice(this._pathPrefix.length);
|
|
1496
|
-
const safeSuffix =
|
|
1497
|
-
const filePath =
|
|
1366
|
+
const safeSuffix = path2.normalize(decodeURIComponent(relativePath)).replace(/^(\.\.[\/\\])+/, "");
|
|
1367
|
+
const filePath = path2.join(this._absoluteFolderPath, safeSuffix);
|
|
1498
1368
|
if (!filePath.startsWith(this._absoluteFolderPath)) {
|
|
1499
1369
|
this._errorResponse(req, res, 403, "Forbidden");
|
|
1500
1370
|
return;
|
|
1501
1371
|
}
|
|
1502
|
-
|
|
1372
|
+
fs6.stat(filePath, (err, stats) => {
|
|
1503
1373
|
if (err || !stats.isFile()) {
|
|
1504
1374
|
this._errorResponse(req, res, 404, "File Not Found");
|
|
1505
1375
|
return;
|
|
1506
1376
|
}
|
|
1507
|
-
const ext =
|
|
1377
|
+
const ext = path2.extname(filePath).toLowerCase();
|
|
1508
1378
|
const contentType = this._mimeTypes[ext] || "application/octet-stream";
|
|
1509
1379
|
res.writeHead(200, { "Content-Type": contentType });
|
|
1510
1380
|
log2(`[200] ${req.method} ${req.url} -> ${filePath}`);
|
|
1511
|
-
const readStream =
|
|
1381
|
+
const readStream = fs6.createReadStream(filePath);
|
|
1512
1382
|
readStream.pipe(res);
|
|
1513
1383
|
readStream.on("error", (err2) => {
|
|
1514
1384
|
log2("Stream error: %o", err2);
|
|
@@ -1519,22 +1389,18 @@ var StaticServer = class {
|
|
|
1519
1389
|
};
|
|
1520
1390
|
|
|
1521
1391
|
// src/showReport.ts
|
|
1522
|
-
async function showReport(reportFolder) {
|
|
1523
|
-
const
|
|
1524
|
-
const projectPublicId = config.projectPublicId();
|
|
1525
|
-
const reportViewerEndpoint = config.reportViewerUrl();
|
|
1392
|
+
async function showReport(reportFolder, options) {
|
|
1393
|
+
const reportViewerUrl = options?.reportViewerUrl ?? "https://report.flakiness.io";
|
|
1526
1394
|
const token = randomUUIDBase62();
|
|
1527
1395
|
const server = new StaticServer(token, reportFolder, [
|
|
1528
|
-
|
|
1396
|
+
reportViewerUrl,
|
|
1529
1397
|
// trace.playwright.dev is used to load & display Playwright Test traces.
|
|
1530
1398
|
"https://trace.playwright.dev"
|
|
1531
1399
|
]);
|
|
1532
1400
|
await server.start(9373, "127.0.0.1");
|
|
1533
|
-
const url = new URL(
|
|
1401
|
+
const url = new URL(reportViewerUrl);
|
|
1534
1402
|
url.searchParams.set("port", String(server.port()));
|
|
1535
1403
|
url.searchParams.set("token", token);
|
|
1536
|
-
if (projectPublicId)
|
|
1537
|
-
url.searchParams.set("ppid", projectPublicId);
|
|
1538
1404
|
console.log(chalk.cyan(`
|
|
1539
1405
|
Serving Flakiness report at ${url.toString()}
|
|
1540
1406
|
Press Ctrl+C to quit.`));
|
|
@@ -1544,23 +1410,23 @@ async function showReport(reportFolder) {
|
|
|
1544
1410
|
}
|
|
1545
1411
|
|
|
1546
1412
|
// src/writeReport.ts
|
|
1547
|
-
import
|
|
1548
|
-
import
|
|
1413
|
+
import fs7 from "fs";
|
|
1414
|
+
import path3 from "path";
|
|
1549
1415
|
async function writeReport(report, attachments, outputFolder) {
|
|
1550
|
-
const reportPath =
|
|
1551
|
-
const attachmentsFolder =
|
|
1552
|
-
await
|
|
1553
|
-
await
|
|
1554
|
-
await
|
|
1416
|
+
const reportPath = path3.join(outputFolder, "report.json");
|
|
1417
|
+
const attachmentsFolder = path3.join(outputFolder, "attachments");
|
|
1418
|
+
await fs7.promises.rm(outputFolder, { recursive: true, force: true });
|
|
1419
|
+
await fs7.promises.mkdir(outputFolder, { recursive: true });
|
|
1420
|
+
await fs7.promises.writeFile(reportPath, JSON.stringify(report), "utf-8");
|
|
1555
1421
|
if (attachments.length)
|
|
1556
|
-
await
|
|
1422
|
+
await fs7.promises.mkdir(attachmentsFolder);
|
|
1557
1423
|
const movedAttachments = [];
|
|
1558
1424
|
for (const attachment of attachments) {
|
|
1559
|
-
const attachmentPath =
|
|
1425
|
+
const attachmentPath = path3.join(attachmentsFolder, attachment.id);
|
|
1560
1426
|
if (attachment.type === "file")
|
|
1561
|
-
await
|
|
1427
|
+
await fs7.promises.cp(attachment.path, attachmentPath);
|
|
1562
1428
|
else if (attachment.type === "buffer")
|
|
1563
|
-
await
|
|
1429
|
+
await fs7.promises.writeFile(attachmentPath, attachment.body);
|
|
1564
1430
|
movedAttachments.push({
|
|
1565
1431
|
type: "file",
|
|
1566
1432
|
contentType: attachment.contentType,
|
|
@@ -1573,7 +1439,6 @@ async function writeReport(report, attachments, outputFolder) {
|
|
|
1573
1439
|
export {
|
|
1574
1440
|
CIUtils,
|
|
1575
1441
|
CPUUtilization,
|
|
1576
|
-
FlakinessProjectConfig,
|
|
1577
1442
|
GitWorktree,
|
|
1578
1443
|
RAMUtilization,
|
|
1579
1444
|
reportUtils_exports as ReportUtils,
|
package/package.json
CHANGED
package/types/src/index.d.ts
CHANGED
|
@@ -7,5 +7,4 @@ export { readReport } from './readReport.js';
|
|
|
7
7
|
export { showReport } from './showReport.js';
|
|
8
8
|
export { uploadReport } from './uploadReport.js';
|
|
9
9
|
export { writeReport } from './writeReport.js';
|
|
10
|
-
export { FlakinessProjectConfig } from './flakinessProjectConfig.js';
|
|
11
10
|
//# sourceMappingURL=index.d.ts.map
|
package/types/src/index.d.ts.map
CHANGED
|
@@ -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,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,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,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAGhD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -8,11 +8,16 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @param {string} reportFolder - Absolute or relative path to the folder containing
|
|
10
10
|
* the Flakiness report.
|
|
11
|
+
* @param {object} [options] - Optional configuration.
|
|
12
|
+
* @param {string} [options.reportViewerUrl] - Custom report viewer URL. Defaults to
|
|
13
|
+
* `https://report.flakiness.io`.
|
|
11
14
|
*
|
|
12
15
|
* @example
|
|
13
16
|
* ```typescript
|
|
14
17
|
* await showReport('./flakiness-report');
|
|
15
18
|
* ```
|
|
16
19
|
*/
|
|
17
|
-
export declare function showReport(reportFolder: string
|
|
20
|
+
export declare function showReport(reportFolder: string, options?: {
|
|
21
|
+
reportViewerUrl?: string;
|
|
22
|
+
}): Promise<void>;
|
|
18
23
|
//# sourceMappingURL=showReport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"showReport.d.ts","sourceRoot":"","sources":["../../src/showReport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"showReport.d.ts","sourceRoot":"","sources":["../../src/showReport.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAC/D,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,iBAmBA"}
|
|
@@ -131,8 +131,10 @@ export type UploadOptions = {
|
|
|
131
131
|
* Access token for authenticating with the Flakiness.io platform.
|
|
132
132
|
*
|
|
133
133
|
* Defaults to the `FLAKINESS_ACCESS_TOKEN` environment variable. If no token is provided
|
|
134
|
-
* through this option or the environment variable, the
|
|
135
|
-
*
|
|
134
|
+
* through this option or the environment variable, the function will attempt to authenticate
|
|
135
|
+
* via GitHub Actions OIDC when running in GitHub Actions (requires `report.flakinessProject`
|
|
136
|
+
* to be set and the project to be bound to the repository). If no authentication method
|
|
137
|
+
* is available, the upload will be skipped with a 'skipped' status.
|
|
136
138
|
*
|
|
137
139
|
* @example 'flakiness-io-1234567890abcdef...'
|
|
138
140
|
*/
|
|
@@ -163,12 +165,23 @@ export type UploadOptions = {
|
|
|
163
165
|
* Uploads a Flakiness report and its attachments to the Flakiness.io platform.
|
|
164
166
|
*
|
|
165
167
|
* This function handles the complete upload process including:
|
|
166
|
-
* - Authentication using access tokens
|
|
168
|
+
* - Authentication using access tokens or GitHub Actions OIDC
|
|
167
169
|
* - Report compression and upload
|
|
168
170
|
* - Attachment upload with automatic compression for text-based content
|
|
169
171
|
* - Error handling and retry logic with exponential backoff
|
|
170
172
|
* - Comprehensive logging of the upload process
|
|
171
173
|
*
|
|
174
|
+
* ## Authentication
|
|
175
|
+
*
|
|
176
|
+
* The function authenticates using one of the following methods (in priority order):
|
|
177
|
+
* 1. **Access token** — provided via `flakinessAccessToken` option or `FLAKINESS_ACCESS_TOKEN` env var.
|
|
178
|
+
* 2. **GitHub Actions OIDC** — when running in GitHub Actions with no access token, the function
|
|
179
|
+
* automatically authenticates via OIDC. This requires:
|
|
180
|
+
* - `report.flakinessProject` to be set to a project identifier (e.g. `"org/proj"`).
|
|
181
|
+
* - The flakiness project to be bound to the GitHub repository running the action.
|
|
182
|
+
* - The workflow to have `id-token: write` permission.
|
|
183
|
+
* 3. If neither is available, the upload is skipped.
|
|
184
|
+
*
|
|
172
185
|
* The function operates in "safe mode" by default, meaning it won't throw errors on upload
|
|
173
186
|
* failures unless explicitly configured to do so.
|
|
174
187
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uploadReport.d.ts","sourceRoot":"","sources":["../../src/uploadReport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAY9D;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,iEAAiE;IACjE,IAAI,EAAE,QAAQ,CAAC;IACf,4EAA4E;IAC5E,EAAE,EAAE,eAAe,CAAC,YAAY,CAAC;IACjC,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,EAAE,EAAE,eAAe,CAAC,YAAY,CAAC;IACjC,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;CACd,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,cAAc,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAOzG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAOrG;AAED,KAAK,YAAY,GACb;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC,UAAU,MAAM;IACd,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B
|
|
1
|
+
{"version":3,"file":"uploadReport.d.ts","sourceRoot":"","sources":["../../src/uploadReport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAY9D;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,iEAAiE;IACjE,IAAI,EAAE,QAAQ,CAAC;IACf,4EAA4E;IAC5E,EAAE,EAAE,eAAe,CAAC,YAAY,CAAC;IACjC,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;CACd,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,EAAE,EAAE,eAAe,CAAC,YAAY,CAAC;IACjC,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;CACd,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,cAAc,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAOzG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAOrG;AAED,KAAK,YAAY,GACb;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAExC,UAAU,MAAM;IACd,GAAG,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;;;;;;;;OAUG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,eAAe,CAAC,MAAM,EAC9B,WAAW,EAAE,UAAU,EAAE,EACzB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,YAAY,CAAC,CAqDvB"}
|
|
@@ -1,103 +0,0 @@
|
|
|
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
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|