@continuous-excellence/ze-great-dashboard-aws 0.31.55 → 0.31.57

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 (4) hide show
  1. package/dist/cli.js +336 -211
  2. package/dist/index.js +336 -211
  3. package/dist/lambda.mjs +255 -106
  4. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1259,6 +1259,12 @@ var testCountSchema = z4.discriminatedUnion("status", [
1259
1259
  type: z4.literal("test-count"),
1260
1260
  status: z4.literal("reported"),
1261
1261
  total: z4.number().int().nonnegative(),
1262
+ /** Public identity for browser-local comparisons, never observation time. */
1263
+ run: z4.object({
1264
+ id: z4.string().min(1),
1265
+ attempt: z4.number().int().positive(),
1266
+ updatedAt: z4.iso.datetime()
1267
+ }).optional(),
1262
1268
  passed: z4.number().int().nonnegative().optional(),
1263
1269
  failed: z4.number().int().nonnegative().optional(),
1264
1270
  skipped: z4.number().int().nonnegative().optional()
@@ -1351,8 +1357,29 @@ var securityDetailsResponseSchema = z5.strictObject({
1351
1357
  ])
1352
1358
  });
1353
1359
 
1360
+ // packages/shared/src/test-history.ts
1361
+ import { z as z6 } from "zod";
1362
+ var testHistorySampleSchema = z6.object({
1363
+ id: z6.string().min(1),
1364
+ attempt: z6.number().int().positive(),
1365
+ updatedAt: z6.iso.datetime(),
1366
+ total: z6.number().int().nonnegative()
1367
+ });
1368
+ var testHistorySchema = z6.object({
1369
+ inspectedAt: z6.iso.datetime(),
1370
+ inspectedRuns: z6.number().int().min(0).max(8),
1371
+ complete: z6.boolean(),
1372
+ samples: z6.array(testHistorySampleSchema).max(8),
1373
+ retryAt: z6.iso.datetime().optional()
1374
+ });
1375
+ function retryAfterTime(value2, now) {
1376
+ if (!value2) return void 0;
1377
+ const at = /^\d+$/.test(value2) ? now + Number(value2) * 1e3 : Date.parse(value2);
1378
+ return Number.isFinite(at) && at > now ? at : void 0;
1379
+ }
1380
+
1354
1381
  // packages/server/src/adapters/github-actions.ts
1355
- import { z as z7 } from "zod";
1382
+ import { z as z9 } from "zod";
1356
1383
 
1357
1384
  // packages/server/src/credentials.ts
1358
1385
  function environmentCredentials(env = process.env) {
@@ -1533,6 +1560,9 @@ function base64url(value2) {
1533
1560
  return Buffer.from(value2).toString("base64url");
1534
1561
  }
1535
1562
 
1563
+ // packages/server/src/adapters/github-test-evidence.ts
1564
+ import { z as z8 } from "zod";
1565
+
1536
1566
  // node_modules/fflate/esm/browser.js
1537
1567
  var u82 = Uint8Array;
1538
1568
  var u162 = Uint16Array;
@@ -1972,10 +2002,10 @@ function strFromU8(dat, latin1) {
1972
2002
  return s;
1973
2003
  }
1974
2004
  }
1975
- var z64hs = function(d, b, l, z11, sc, su, off) {
2005
+ var z64hs = function(d, b, l, z13, sc, su, off) {
1976
2006
  var nsc = sc == 4294967295, nsu = su == 4294967295, noff = off == 4294967295, e = b + l;
1977
2007
  var nf = nsc + nsu + noff;
1978
- if (z11 && nf) {
2008
+ if (z13 && nf) {
1979
2009
  for (; b + 4 < e; b += 4 + b2(d, b + 2)) {
1980
2010
  if (b2(d, b) == 1) {
1981
2011
  return [
@@ -1986,7 +2016,7 @@ var z64hs = function(d, b, l, z11, sc, su, off) {
1986
2016
  ];
1987
2017
  }
1988
2018
  }
1989
- if (z11 < 2)
2019
+ if (z13 < 2)
1990
2020
  err2(13);
1991
2021
  }
1992
2022
  return [sc, su, off, 0];
@@ -2150,18 +2180,18 @@ var Unzip = /* @__PURE__ */ (function() {
2150
2180
  })();
2151
2181
 
2152
2182
  // packages/server/src/workflow-artifact-summary.ts
2153
- import { z as z6 } from "zod";
2183
+ import { z as z7 } from "zod";
2154
2184
  var maxArtifactBytes = 64 * 1024;
2155
- var testResultsSummarySchema = z6.object({
2156
- schemaVersion: z6.literal(1),
2157
- runId: z6.number().int().positive(),
2158
- runAttempt: z6.number().int().positive(),
2159
- headSha: z6.string().min(1),
2160
- total: z6.number().int().nonnegative(),
2161
- passed: z6.number().int().nonnegative().optional(),
2162
- failed: z6.number().int().nonnegative().optional(),
2163
- skipped: z6.number().int().nonnegative().optional(),
2164
- metadata: z6.record(z6.string(), z6.unknown()).optional()
2185
+ var testResultsSummarySchema = z7.object({
2186
+ schemaVersion: z7.literal(1),
2187
+ runId: z7.number().int().positive(),
2188
+ runAttempt: z7.number().int().positive(),
2189
+ headSha: z7.string().min(1),
2190
+ total: z7.number().int().nonnegative(),
2191
+ passed: z7.number().int().nonnegative().optional(),
2192
+ failed: z7.number().int().nonnegative().optional(),
2193
+ skipped: z7.number().int().nonnegative().optional(),
2194
+ metadata: z7.record(z7.string(), z7.unknown()).optional()
2165
2195
  }).superRefine((summary, ctx) => {
2166
2196
  const outcomeTotal = (summary.passed ?? 0) + (summary.failed ?? 0) + (summary.skipped ?? 0);
2167
2197
  for (const key of ["passed", "failed", "skipped"]) {
@@ -2237,71 +2267,165 @@ function concat(chunks, length) {
2237
2267
  return result;
2238
2268
  }
2239
2269
 
2270
+ // packages/server/src/adapters/github-test-evidence.ts
2271
+ var artifactsSchema = z8.object({
2272
+ artifacts: z8.array(
2273
+ z8.object({ id: z8.number().int().positive(), name: z8.string().min(1), expired: z8.boolean() })
2274
+ )
2275
+ });
2276
+ function testArtifactHttpFailure(response) {
2277
+ const retry = retryAfterTime(response.headers.get("retry-after"), Date.now());
2278
+ return {
2279
+ kind: "failed",
2280
+ observedAt: observedAt(response.headers.get("date")),
2281
+ errorKind: upstreamErrorKind(response.status),
2282
+ httpStatus: response.status,
2283
+ ...retry === void 0 ? {} : { retryAt: new Date(retry).toISOString() }
2284
+ };
2285
+ }
2286
+ async function inspectGithubTestArtifact(args, selected, config) {
2287
+ const { run } = selected;
2288
+ let at = selected.observedAt;
2289
+ const failed = (errorKind3) => ({
2290
+ kind: "failed",
2291
+ observedAt: at,
2292
+ errorKind: errorKind3
2293
+ });
2294
+ const get = (url) => args.githubClient.get({
2295
+ source: args.source,
2296
+ fetcher: args.fetcher,
2297
+ url,
2298
+ requestHeaders: new Headers()
2299
+ });
2300
+ const observe = (response) => {
2301
+ const value2 = observedAt(response.headers.get("date"));
2302
+ if (Date.parse(value2) < Date.parse(at)) at = value2;
2303
+ };
2304
+ try {
2305
+ if (!run.id) return failed("upstream-error");
2306
+ if (run.status !== "completed") return { kind: "pending", observedAt: at };
2307
+ const url = new URL(
2308
+ `https://api.github.com/repos/${args.source.repo}/actions/runs/${run.id}/artifacts`
2309
+ );
2310
+ url.searchParams.set("name", config.artifact);
2311
+ url.searchParams.set("per_page", "100");
2312
+ const artifacts = await get(url.toString());
2313
+ if (!artifacts.ok) return testArtifactHttpFailure(artifacts);
2314
+ observe(artifacts);
2315
+ const matches = artifactsSchema.parse(await artifacts.json()).artifacts.filter((item) => item.name === config.artifact);
2316
+ if (!matches.length) return { kind: "absent", observedAt: at };
2317
+ const [artifact] = matches;
2318
+ if (matches.length !== 1 || !artifact) return failed("upstream-error");
2319
+ if (artifact.expired) return { kind: "expired", observedAt: at };
2320
+ const archive = await get(
2321
+ `https://api.github.com/repos/${args.source.repo}/actions/artifacts/${artifact.id}/zip`
2322
+ );
2323
+ if (!archive.ok) return testArtifactHttpFailure(archive);
2324
+ observe(archive);
2325
+ const summary = testResultsSummarySchema.parse(
2326
+ JSON.parse(await readTestResultsArtifact(archive, config.entry))
2327
+ );
2328
+ if (summary.runId !== run.id || summary.runAttempt !== run.run_attempt || summary.headSha !== run.head_sha)
2329
+ return failed("upstream-error");
2330
+ const updatedAt = z8.iso.datetime().safeParse(run.updated_at);
2331
+ const tests = {
2332
+ type: "test-count",
2333
+ status: "reported",
2334
+ total: summary.total,
2335
+ ...updatedAt.success ? { run: { id: String(run.id), attempt: summary.runAttempt, updatedAt: updatedAt.data } } : {},
2336
+ ...summary.passed === void 0 ? {} : { passed: summary.passed },
2337
+ ...summary.failed === void 0 ? {} : { failed: summary.failed },
2338
+ ...summary.skipped === void 0 ? {} : { skipped: summary.skipped }
2339
+ };
2340
+ return { kind: "reported", observedAt: at, tests };
2341
+ } catch (error) {
2342
+ return failed(error instanceof GithubAuthenticationError ? "unauthorized" : "upstream-error");
2343
+ }
2344
+ }
2345
+ function currentTestEvidence(inspection) {
2346
+ const { observedAt: at } = inspection;
2347
+ switch (inspection.kind) {
2348
+ case "reported":
2349
+ return { state: "ok", observedAt: at, signal: inspection.tests };
2350
+ case "pending":
2351
+ return { state: "ok", observedAt: at, signal: { type: "test-count", status: "pending" } };
2352
+ case "absent":
2353
+ return { state: "ok", observedAt: at, signal: { type: "test-count", status: "not-reported" } };
2354
+ case "expired":
2355
+ return {
2356
+ state: "error",
2357
+ observedAt: at,
2358
+ error: { kind: "upstream-error", message: publicErrorMessage("upstream-error") }
2359
+ };
2360
+ case "failed":
2361
+ return {
2362
+ state: "error",
2363
+ observedAt: at,
2364
+ error: { kind: inspection.errorKind, message: publicErrorMessage(inspection.errorKind) }
2365
+ };
2366
+ }
2367
+ }
2368
+
2240
2369
  // packages/server/src/adapters/github-actions.ts
2241
- var pipelinePanelSchema = z7.object({
2370
+ var pipelinePanelSchema = z9.object({
2242
2371
  test_results: testResultsArtifactSchema.optional(),
2243
- id: z7.string().min(1),
2244
- type: z7.literal("pipeline-status"),
2245
- source: z7.string().min(1),
2372
+ id: z9.string().min(1),
2373
+ type: z9.literal("pipeline-status"),
2374
+ source: z9.string().min(1),
2246
2375
  /** GitHub accepts a workflow filename or numeric workflow id in this URL segment. */
2247
- pipeline: z7.string().min(1)
2376
+ pipeline: z9.string().min(1)
2248
2377
  });
2249
- var pullRequestHealthPanelSchema = z7.object({
2250
- id: z7.string().min(1),
2251
- type: z7.literal("pull-request-health"),
2252
- source: z7.string().min(1),
2253
- base_branch: z7.string().min(1),
2254
- update_workflows: z7.array(
2255
- z7.object({
2256
- workflow: z7.string().min(1),
2257
- branch_prefixes: z7.array(z7.string().min(1)).min(1)
2378
+ var pullRequestHealthPanelSchema = z9.object({
2379
+ id: z9.string().min(1),
2380
+ type: z9.literal("pull-request-health"),
2381
+ source: z9.string().min(1),
2382
+ base_branch: z9.string().min(1),
2383
+ update_workflows: z9.array(
2384
+ z9.object({
2385
+ workflow: z9.string().min(1),
2386
+ branch_prefixes: z9.array(z9.string().min(1)).min(1)
2258
2387
  })
2259
2388
  ).min(1),
2260
- build_workflow: z7.string().min(1),
2389
+ build_workflow: z9.string().min(1),
2261
2390
  build_events: githubActionsBuildEventsSchema.optional()
2262
2391
  });
2263
- var runSchema = z7.object({
2264
- id: z7.number().int().positive().optional(),
2265
- run_attempt: z7.number().int().positive().optional(),
2266
- head_sha: z7.string().min(1).optional(),
2267
- status: z7.string(),
2268
- conclusion: z7.string().nullable(),
2269
- name: z7.string().min(1),
2270
- html_url: z7.url(),
2392
+ var runSchema = z9.object({
2393
+ id: z9.number().int().positive().optional(),
2394
+ run_attempt: z9.number().int().positive().optional(),
2395
+ head_sha: z9.string().min(1).optional(),
2396
+ status: z9.string(),
2397
+ conclusion: z9.string().nullable(),
2398
+ name: z9.string().min(1),
2399
+ html_url: z9.url(),
2271
2400
  /** The GitHub Actions trigger that started this run. */
2272
- event: z7.string().min(1).optional(),
2401
+ event: z9.string().min(1).optional(),
2273
2402
  /** The branch that produced this run; absent for some event types. */
2274
- head_branch: z7.string().min(1).nullable().optional(),
2403
+ head_branch: z9.string().min(1).nullable().optional(),
2275
2404
  // Timestamp quality should only remove timing advice, never make an otherwise useful run unreadable.
2276
- run_started_at: z7.string().nullable().optional(),
2277
- updated_at: z7.string().optional(),
2278
- created_at: z7.string().optional()
2405
+ run_started_at: z9.string().nullable().optional(),
2406
+ updated_at: z9.string().optional(),
2407
+ created_at: z9.string().optional()
2279
2408
  });
2280
- var artifactsSchema = z7.object({
2281
- artifacts: z7.array(
2282
- z7.object({ id: z7.number().int().positive(), name: z7.string().min(1), expired: z7.boolean() })
2283
- )
2284
- });
2285
- var runsSchema = z7.object({ workflow_runs: z7.array(runSchema) });
2286
- var jobsSchema = z7.object({
2287
- jobs: z7.array(
2288
- z7.object({
2289
- name: z7.string().min(1),
2290
- status: z7.string(),
2291
- steps: z7.array(z7.object({ name: z7.string().min(1), status: z7.string() })).optional()
2409
+ var runsSchema = z9.object({ workflow_runs: z9.array(runSchema) });
2410
+ var jobsSchema = z9.object({
2411
+ jobs: z9.array(
2412
+ z9.object({
2413
+ name: z9.string().min(1),
2414
+ status: z9.string(),
2415
+ steps: z9.array(z9.object({ name: z9.string().min(1), status: z9.string() })).optional()
2292
2416
  })
2293
2417
  )
2294
2418
  });
2295
- var pullRequestsSchema = z7.array(
2296
- z7.object({
2297
- number: z7.number().int().positive(),
2298
- html_url: z7.url(),
2299
- head: z7.object({ ref: z7.string().min(1) }),
2300
- base: z7.object({ ref: z7.string().min(1) })
2419
+ var pullRequestsSchema = z9.array(
2420
+ z9.object({
2421
+ number: z9.number().int().positive(),
2422
+ html_url: z9.url(),
2423
+ head: z9.object({ ref: z9.string().min(1) }),
2424
+ base: z9.object({ ref: z9.string().min(1) })
2301
2425
  })
2302
2426
  );
2303
2427
  function permittedGithubActionsCalls(panel, source, _credentials) {
2304
- const { panel: parsedPanel, source: parsedSource } = z7.object({ panel: pipelinePanelSchema, source: githubActionsSourceSchema }).parse({ panel, source });
2428
+ const { panel: parsedPanel, source: parsedSource } = z9.object({ panel: pipelinePanelSchema, source: githubActionsSourceSchema }).parse({ panel, source });
2305
2429
  const url = new URL(
2306
2430
  `https://api.github.com/repos/${parsedSource.repo}/actions/workflows/${encodeURIComponent(parsedPanel.pipeline)}/runs`
2307
2431
  );
@@ -2310,7 +2434,7 @@ function permittedGithubActionsCalls(panel, source, _credentials) {
2310
2434
  return [{ url: url.toString(), headers: new Headers() }];
2311
2435
  }
2312
2436
  function testCountCapabilities(panel, source) {
2313
- return z7.object({ panel: testCountPanelSchema, source: githubActionsSourceSchema }).parse({ panel, source });
2437
+ return z9.object({ panel: testCountPanelSchema, source: githubActionsSourceSchema }).parse({ panel, source });
2314
2438
  }
2315
2439
  async function fetchGithubActionsTestCount(args) {
2316
2440
  const { panel, source } = testCountCapabilities(args.panel, args.source);
@@ -2328,13 +2452,15 @@ async function fetchGithubActionsTestCount(args) {
2328
2452
  return testCountEnvelope(
2329
2453
  noRunEnvelope(panel.id, source, panel.pipeline, selected.response.headers.get("date"))
2330
2454
  );
2331
- const evidence = await readGithubRunTestEvidence(
2332
- { ...args, source, githubClient },
2333
- {
2334
- run: selected.run,
2335
- observedAt: selected.observedAt
2336
- },
2337
- panel.test_results
2455
+ const evidence = currentTestEvidence(
2456
+ await inspectGithubTestArtifact(
2457
+ { ...args, source, githubClient },
2458
+ {
2459
+ run: selected.run,
2460
+ observedAt: selected.observedAt
2461
+ },
2462
+ panel.test_results
2463
+ )
2338
2464
  );
2339
2465
  return testCountEnvelope({ ...evidence, panelId: panel.id, link: selected.run.html_url });
2340
2466
  } catch (error) {
@@ -2348,82 +2474,8 @@ async function fetchGithubActionsTestCount(args) {
2348
2474
  );
2349
2475
  }
2350
2476
  }
2351
- async function readGithubRunTestEvidence(args, selected, artifactConfig) {
2352
- const { run, observedAt: runObservedAt } = selected;
2353
- const { source, githubClient } = args;
2354
- const noValidators = new Headers();
2355
- let failureObservedAt = runObservedAt;
2356
- const evidenceError = (kind, at = failureObservedAt) => ({
2357
- state: "error",
2358
- observedAt: at,
2359
- error: { kind, message: publicErrorMessage(kind) }
2360
- });
2361
- const failedResponse = (response) => evidenceError(errorKind(response.status), observedAt2(response.headers.get("date")));
2362
- try {
2363
- if (!run.id) return evidenceError("upstream-error");
2364
- if (run.status !== "completed")
2365
- return {
2366
- state: "ok",
2367
- observedAt: runObservedAt,
2368
- signal: { type: "test-count", status: "pending" }
2369
- };
2370
- const artifactsResponse = await githubFetch(
2371
- githubArtifactsCall(source, run.id, artifactConfig),
2372
- {
2373
- ...args,
2374
- source,
2375
- requestHeaders: noValidators,
2376
- githubClient
2377
- }
2378
- );
2379
- if (!artifactsResponse.ok) return failedResponse(artifactsResponse);
2380
- const artifactObservedAt = observedAt2(artifactsResponse.headers.get("date"));
2381
- failureObservedAt = oldestObservation(runObservedAt, artifactObservedAt);
2382
- const artifacts = artifactsSchema.parse(await artifactsResponse.json()).artifacts;
2383
- const matches = artifacts.filter((artifact2) => artifact2.name === artifactConfig.artifact);
2384
- if (matches.length === 0)
2385
- return {
2386
- state: "ok",
2387
- observedAt: oldestObservation(runObservedAt, artifactObservedAt),
2388
- signal: { type: "test-count", status: "not-reported" }
2389
- };
2390
- const [artifact] = matches;
2391
- if (matches.length !== 1 || !artifact || artifact.expired)
2392
- return evidenceError("upstream-error");
2393
- const archiveResponse = await githubFetch(githubArtifactDownloadCall(source, artifact.id), {
2394
- ...args,
2395
- source,
2396
- requestHeaders: noValidators,
2397
- githubClient
2398
- });
2399
- if (!archiveResponse.ok) return failedResponse(archiveResponse);
2400
- const archiveObservedAt = observedAt2(archiveResponse.headers.get("date"));
2401
- failureObservedAt = oldestObservation(runObservedAt, artifactObservedAt, archiveObservedAt);
2402
- const summary = testResultsSummarySchema.parse(
2403
- JSON.parse(await readTestResultsArtifact(archiveResponse, artifactConfig.entry))
2404
- );
2405
- if (summary.runId !== run.id || summary.runAttempt !== run.run_attempt || summary.headSha !== run.head_sha)
2406
- throw new Error("Test-results manifest does not belong to the selected workflow run.");
2407
- return {
2408
- state: "ok",
2409
- observedAt: oldestObservation(runObservedAt, artifactObservedAt, archiveObservedAt),
2410
- signal: {
2411
- type: "test-count",
2412
- status: "reported",
2413
- total: summary.total,
2414
- ...summary.passed === void 0 ? {} : { passed: summary.passed },
2415
- ...summary.failed === void 0 ? {} : { failed: summary.failed },
2416
- ...summary.skipped === void 0 ? {} : { skipped: summary.skipped }
2417
- }
2418
- };
2419
- } catch (error) {
2420
- return evidenceError(
2421
- error instanceof GithubAuthenticationError ? "unauthorized" : "upstream-error"
2422
- );
2423
- }
2424
- }
2425
2477
  function pullRequestHealthCapabilities(panel) {
2426
- const { panel: parsed } = z7.object({ panel: pullRequestHealthPanelSchema }).parse({ panel });
2478
+ const { panel: parsed } = z9.object({ panel: pullRequestHealthPanelSchema }).parse({ panel });
2427
2479
  return {
2428
2480
  panel: parsed,
2429
2481
  configuredUpdateWorkflow(workflow) {
@@ -2525,10 +2577,12 @@ async function fetchGithubActionsPipeline(args) {
2525
2577
  if (activity) signal.activity = activity;
2526
2578
  }
2527
2579
  if (parsedPanel.test_results) {
2528
- signal.testResults = await readGithubRunTestEvidence(
2529
- { ...args, source: parsedSource, githubClient },
2530
- { run, observedAt: selected.observedAt },
2531
- parsedPanel.test_results
2580
+ signal.testResults = currentTestEvidence(
2581
+ await inspectGithubTestArtifact(
2582
+ { ...args, source: parsedSource, githubClient },
2583
+ { run, observedAt: selected.observedAt },
2584
+ parsedPanel.test_results
2585
+ )
2532
2586
  );
2533
2587
  }
2534
2588
  const envelope = {
@@ -2647,18 +2701,6 @@ function githubJobsCall(source, runId) {
2647
2701
  url.searchParams.set("per_page", "100");
2648
2702
  return { url: url.toString(), headers: new Headers() };
2649
2703
  }
2650
- function githubArtifactsCall(source, runId, testResults) {
2651
- const url = new URL(`https://api.github.com/repos/${source.repo}/actions/runs/${runId}/artifacts`);
2652
- url.searchParams.set("name", testResults.artifact);
2653
- url.searchParams.set("per_page", "100");
2654
- return { url: url.toString(), headers: new Headers() };
2655
- }
2656
- function githubArtifactDownloadCall(source, artifactId) {
2657
- return {
2658
- url: `https://api.github.com/repos/${source.repo}/actions/artifacts/${artifactId}/zip`,
2659
- headers: new Headers()
2660
- };
2661
- }
2662
2704
  function noRunEnvelope(panelId, source, pipeline, date) {
2663
2705
  return {
2664
2706
  panelId,
@@ -2697,7 +2739,7 @@ function completedRunDuration(run) {
2697
2739
  return Number.isFinite(durationMs) && durationMs >= 0 ? { durationMs } : {};
2698
2740
  }
2699
2741
  function timestamp(value2) {
2700
- if (!value2 || !z7.iso.datetime().safeParse(value2).success) return void 0;
2742
+ if (!value2 || !z9.iso.datetime().safeParse(value2).success) return void 0;
2701
2743
  return Number.isFinite(new Date(value2).valueOf()) ? value2 : void 0;
2702
2744
  }
2703
2745
  function normalizeStatus(status, conclusion) {
@@ -2714,7 +2756,7 @@ function errorEnvelope(panelId, kind, error, link, observedAt4 = (/* @__PURE__ *
2714
2756
  return upstreamErrorEnvelope({ panelId, kind, error, link, upstreamDate: observedAt4 });
2715
2757
  }
2716
2758
  function sourceLink(panel, source) {
2717
- const parsedPanel = z7.object({ pipeline: z7.string().min(1) }).parse(panel);
2759
+ const parsedPanel = z9.object({ pipeline: z9.string().min(1) }).parse(panel);
2718
2760
  const parsedSource = githubActionsSourceSchema.parse(source);
2719
2761
  return sourceLinkForWorkflow(parsedSource, parsedPanel.pipeline);
2720
2762
  }
@@ -2724,6 +2766,81 @@ function sourceLinkForWorkflow(source, pipeline) {
2724
2766
  function observedAt2(value2) {
2725
2767
  return observedAt(value2);
2726
2768
  }
2769
+ async function fetchGithubTestHistory(args) {
2770
+ const source = githubActionsSourceSchema.parse(args.source);
2771
+ const fetcher = (input, init) => args.fetcher(input, { ...init, ...args.signal ? { signal: args.signal } : {} });
2772
+ const artifact = testResultsArtifactSchema.parse(args.panel.test_results);
2773
+ const workflow = z9.string().min(1).parse(args.panel.pipeline);
2774
+ const now = Date.now();
2775
+ const cutoff = now - 14 * 864e5;
2776
+ const history = {
2777
+ inspectedAt: new Date(now).toISOString(),
2778
+ inspectedRuns: 0,
2779
+ complete: true,
2780
+ samples: []
2781
+ };
2782
+ let stop = false;
2783
+ const recordFailure = (failure2) => {
2784
+ history.complete = false;
2785
+ if (failure2.errorKind === "unauthorized" || failure2.httpStatus === 429) stop = true;
2786
+ if (failure2.retryAt && (!history.retryAt || Date.parse(failure2.retryAt) > Date.parse(history.retryAt)))
2787
+ history.retryAt = failure2.retryAt;
2788
+ };
2789
+ try {
2790
+ const call = githubRunsCall(
2791
+ source,
2792
+ workflow,
2793
+ source.branch,
2794
+ void 0,
2795
+ 8,
2796
+ new Date(cutoff).toISOString()
2797
+ );
2798
+ const url = new URL(call.url);
2799
+ url.searchParams.set("status", "completed");
2800
+ const response = await githubFetch(
2801
+ { ...call, url: url.toString() },
2802
+ { ...args, fetcher, source, requestHeaders: new Headers() }
2803
+ );
2804
+ if (!response.ok) recordFailure(testArtifactHttpFailure(response));
2805
+ else {
2806
+ const runs = runsSchema.parse(await response.json()).workflow_runs.slice(0, 8);
2807
+ for (const run of runs) {
2808
+ if (stop || args.signal?.aborted) {
2809
+ history.complete = false;
2810
+ break;
2811
+ }
2812
+ if (run.status !== "completed") continue;
2813
+ if (run.updated_at && Date.parse(run.updated_at) < cutoff) continue;
2814
+ history.inspectedRuns++;
2815
+ const inspection = await inspectGithubTestArtifact(
2816
+ { ...args, fetcher, source },
2817
+ { run, observedAt: observedAt2(response.headers.get("date")) },
2818
+ artifact
2819
+ );
2820
+ switch (inspection.kind) {
2821
+ case "failed":
2822
+ recordFailure(inspection);
2823
+ break;
2824
+ case "reported": {
2825
+ const { run: identity, total } = inspection.tests;
2826
+ if (identity) history.samples.push({ ...identity, total });
2827
+ else history.complete = false;
2828
+ break;
2829
+ }
2830
+ case "absent":
2831
+ case "expired":
2832
+ break;
2833
+ case "pending":
2834
+ history.complete = false;
2835
+ break;
2836
+ }
2837
+ }
2838
+ }
2839
+ } catch {
2840
+ history.complete = false;
2841
+ }
2842
+ return Response.json(history, { headers: { "cache-control": "no-store" } });
2843
+ }
2727
2844
 
2728
2845
  // packages/server/src/configuration-error.ts
2729
2846
  var ConfigurationError = class extends Error {
@@ -2777,37 +2894,37 @@ function correctiveConstraint(issue) {
2777
2894
 
2778
2895
  // packages/server/src/adapters/azure-devops.ts
2779
2896
  import { readFile } from "node:fs/promises";
2780
- import { z as z8 } from "zod";
2781
- var pipelinePanelSchema2 = z8.object({
2782
- id: z8.string().min(1),
2783
- type: z8.literal("pipeline-status"),
2784
- source: z8.string().min(1),
2785
- pipeline: z8.number().int().positive()
2897
+ import { z as z10 } from "zod";
2898
+ var pipelinePanelSchema2 = z10.object({
2899
+ id: z10.string().min(1),
2900
+ type: z10.literal("pipeline-status"),
2901
+ source: z10.string().min(1),
2902
+ pipeline: z10.number().int().positive()
2786
2903
  });
2787
- var buildSchema = z8.object({
2788
- id: z8.number().int().positive(),
2789
- buildNumber: z8.string().min(1),
2790
- status: z8.string().nullable().optional(),
2791
- result: z8.string().nullable().optional(),
2792
- sourceBranch: z8.string().min(1).nullable().optional(),
2793
- startTime: z8.string().nullable().optional(),
2794
- finishTime: z8.string().nullable().optional(),
2795
- lastChangedDate: z8.string().nullable().optional()
2904
+ var buildSchema = z10.object({
2905
+ id: z10.number().int().positive(),
2906
+ buildNumber: z10.string().min(1),
2907
+ status: z10.string().nullable().optional(),
2908
+ result: z10.string().nullable().optional(),
2909
+ sourceBranch: z10.string().min(1).nullable().optional(),
2910
+ startTime: z10.string().nullable().optional(),
2911
+ finishTime: z10.string().nullable().optional(),
2912
+ lastChangedDate: z10.string().nullable().optional()
2796
2913
  });
2797
- var buildsSchema = z8.object({ value: z8.array(buildSchema) });
2798
- var timelineSchema = z8.object({
2799
- records: z8.array(
2800
- z8.object({
2801
- id: z8.string().min(1),
2802
- parentId: z8.string().min(1).nullable().optional(),
2803
- type: z8.string().min(1),
2804
- name: z8.string().min(1),
2805
- state: z8.string().nullable().optional()
2914
+ var buildsSchema = z10.object({ value: z10.array(buildSchema) });
2915
+ var timelineSchema = z10.object({
2916
+ records: z10.array(
2917
+ z10.object({
2918
+ id: z10.string().min(1),
2919
+ parentId: z10.string().min(1).nullable().optional(),
2920
+ type: z10.string().min(1),
2921
+ name: z10.string().min(1),
2922
+ state: z10.string().nullable().optional()
2806
2923
  })
2807
2924
  )
2808
2925
  });
2809
2926
  function permittedAzureDevOpsCalls(panel, source) {
2810
- const { panel: parsedPanel, source: parsedSource } = z8.object({ panel: pipelinePanelSchema2, source: azureDevOpsSourceSchema }).parse({ panel, source });
2927
+ const { panel: parsedPanel, source: parsedSource } = z10.object({ panel: pipelinePanelSchema2, source: azureDevOpsSourceSchema }).parse({ panel, source });
2811
2928
  return [buildsCall(parsedPanel.pipeline, parsedSource)];
2812
2929
  }
2813
2930
  async function fetchAzureDevOpsPipeline(args) {
@@ -2920,9 +3037,9 @@ async function fetchAzureDevOpsPipeline(args) {
2920
3037
  };
2921
3038
  }
2922
3039
  }
2923
- var delegatedTokenFileSchema = z8.object({
2924
- accessToken: z8.string().min(1),
2925
- expiresAt: z8.string().min(1)
3040
+ var delegatedTokenFileSchema = z10.object({
3041
+ accessToken: z10.string().min(1),
3042
+ expiresAt: z10.string().min(1)
2926
3043
  });
2927
3044
  async function azureDevOpsAuthorization(source, credentials) {
2928
3045
  if (source.token_env) {
@@ -3003,7 +3120,7 @@ function completedBuildDuration(build) {
3003
3120
  return Number.isFinite(durationMs) && durationMs >= 0 ? { durationMs } : {};
3004
3121
  }
3005
3122
  function timestamp2(value2) {
3006
- if (!value2 || !z8.iso.datetime().safeParse(value2).success) return void 0;
3123
+ if (!value2 || !z10.iso.datetime().safeParse(value2).success) return void 0;
3007
3124
  return Number.isFinite(new Date(value2).valueOf()) ? value2 : void 0;
3008
3125
  }
3009
3126
  function copyValidators(requestHeaders, upstreamHeaders) {
@@ -3029,23 +3146,23 @@ function observedAt3(value2) {
3029
3146
  }
3030
3147
 
3031
3148
  // packages/server/src/adapters/gitlab-ci.ts
3032
- import { z as z9 } from "zod";
3033
- var pipelinePanelSchema3 = z9.object({
3034
- id: z9.string().min(1),
3035
- type: z9.literal("pipeline-status"),
3036
- source: z9.string().min(1)
3149
+ import { z as z11 } from "zod";
3150
+ var pipelinePanelSchema3 = z11.object({
3151
+ id: z11.string().min(1),
3152
+ type: z11.literal("pipeline-status"),
3153
+ source: z11.string().min(1)
3037
3154
  });
3038
- var pipelineSchema = z9.object({
3039
- id: z9.number().int().positive(),
3040
- name: z9.string().min(1).nullable().optional(),
3041
- status: z9.string(),
3042
- ref: z9.string().min(1).nullable().optional(),
3043
- created_at: z9.string().nullable().optional(),
3044
- updated_at: z9.string().nullable().optional(),
3045
- web_url: z9.url()
3155
+ var pipelineSchema = z11.object({
3156
+ id: z11.number().int().positive(),
3157
+ name: z11.string().min(1).nullable().optional(),
3158
+ status: z11.string(),
3159
+ ref: z11.string().min(1).nullable().optional(),
3160
+ created_at: z11.string().nullable().optional(),
3161
+ updated_at: z11.string().nullable().optional(),
3162
+ web_url: z11.url()
3046
3163
  });
3047
3164
  function permittedGitlabCiCalls(panel, source) {
3048
- const { source: parsedSource } = z9.object({ panel: pipelinePanelSchema3, source: gitlabCiSourceSchema }).parse({ panel, source });
3165
+ const { source: parsedSource } = z11.object({ panel: pipelinePanelSchema3, source: gitlabCiSourceSchema }).parse({ panel, source });
3049
3166
  return [pipelinesCall(parsedSource)];
3050
3167
  }
3051
3168
  async function fetchGitlabCiPipeline(args) {
@@ -3084,7 +3201,7 @@ async function fetchGitlabCiPipeline(args) {
3084
3201
  );
3085
3202
  }
3086
3203
  try {
3087
- const pipeline = z9.array(pipelineSchema).parse(await upstream.json())[0];
3204
+ const pipeline = z11.array(pipelineSchema).parse(await upstream.json())[0];
3088
3205
  if (!pipeline) {
3089
3206
  const detail = source.branch ? `No pipelines found for ref "${source.branch}". Check the source's branch setting.` : "No pipelines found.";
3090
3207
  return failure(
@@ -3150,7 +3267,7 @@ function normalizeStatus3(status) {
3150
3267
  return "unknown";
3151
3268
  }
3152
3269
  function timestamp3(value2) {
3153
- if (!value2 || !z9.iso.datetime().safeParse(value2).success) return void 0;
3270
+ if (!value2 || !z11.iso.datetime().safeParse(value2).success) return void 0;
3154
3271
  return Number.isFinite(new Date(value2).valueOf()) ? value2 : void 0;
3155
3272
  }
3156
3273
  function failure(panelId, kind, error, link, date, failure2) {
@@ -3163,10 +3280,10 @@ function failure(panelId, kind, error, link, date, failure2) {
3163
3280
  }
3164
3281
 
3165
3282
  // packages/server/src/adapters/http-value.ts
3166
- import { z as z10 } from "zod";
3283
+ import { z as z12 } from "zod";
3167
3284
  function permittedHttpValueCalls(panel) {
3168
3285
  const grouped = httpValueGroupedPanelSchema.safeParse(panel);
3169
- const urls = grouped.success ? grouped.data.facts.map((fact) => fact.url) : [z10.object({ panel: httpValueScalarPanelSchema }).parse({ panel }).panel.url];
3286
+ const urls = grouped.success ? grouped.data.facts.map((fact) => fact.url) : [z12.object({ panel: httpValueScalarPanelSchema }).parse({ panel }).panel.url];
3170
3287
  return urls.map(permittedCall);
3171
3288
  }
3172
3289
  async function fetchHttpValue(args) {
@@ -3265,6 +3382,9 @@ function readPanelAdapter(panel, source) {
3265
3382
  if (panel.type === "pipeline-status" && source?.type === "github-actions") {
3266
3383
  permittedGithubActionsCalls(panel, source);
3267
3384
  return {
3385
+ ...panel.test_results ? {
3386
+ testHistory: ({ source: _source, ...args }) => fetchGithubTestHistory({ ...args, source })
3387
+ } : {},
3268
3388
  destination: () => "https://api.github.com",
3269
3389
  fetch: ({ source: _configuredSource, ...args }) => fetchGithubActionsPipeline({ ...args, source })
3270
3390
  };
@@ -3272,6 +3392,9 @@ function readPanelAdapter(panel, source) {
3272
3392
  if (panel.type === "test-count" && source?.type === "github-actions") {
3273
3393
  testCountCapabilities(panel, source);
3274
3394
  return {
3395
+ ...panel.test_results ? {
3396
+ testHistory: ({ source: _source, ...args }) => fetchGithubTestHistory({ ...args, source })
3397
+ } : {},
3275
3398
  destination: () => "https://api.github.com",
3276
3399
  fetch: ({ source: _configuredSource, ...args }) => fetchGithubActionsTestCount({ ...args, source })
3277
3400
  };
@@ -3350,7 +3473,9 @@ function derive(config, rejectUnsupported) {
3350
3473
  return allowed;
3351
3474
  }
3352
3475
  function panelCapability(panel, source) {
3353
- if (readPanelAdapter(panel, source)) return { kind: "server", operations: ["read"] };
3476
+ const adapter = readPanelAdapter(panel, source);
3477
+ if (adapter)
3478
+ return { kind: "server", operations: adapter.testHistory ? ["read", "test-history"] : ["read"] };
3354
3479
  if (panel.type === "pull-request-health" && source?.type === "github-actions") {
3355
3480
  pullRequestHealthCapabilities(panel);
3356
3481
  return {