@continuous-excellence/ze-great-dashboard-aws 0.21.0 → 0.22.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/dist/lambda.mjs +271 -70
- package/package.json +1 -1
package/dist/lambda.mjs
CHANGED
|
@@ -66462,6 +66462,20 @@ var Hono2 = class extends Hono {
|
|
|
66462
66462
|
var import_yaml = __toESM(require_dist(), 1);
|
|
66463
66463
|
|
|
66464
66464
|
// packages/server/src/upstream.ts
|
|
66465
|
+
function publicErrorMessage(kind) {
|
|
66466
|
+
switch (kind) {
|
|
66467
|
+
case "unreachable":
|
|
66468
|
+
return "The source could not be reached. Check its address and network connectivity.";
|
|
66469
|
+
case "unauthorized":
|
|
66470
|
+
return "The dashboard is not authorized to read this source. Check the configured access.";
|
|
66471
|
+
case "not-found":
|
|
66472
|
+
return "The configured source was not found. Check the board configuration.";
|
|
66473
|
+
case "no-runs":
|
|
66474
|
+
return "No matching workflow runs were found. Check the configured workflow and branch.";
|
|
66475
|
+
case "upstream-error":
|
|
66476
|
+
return "The source returned an unreadable response. Check the source service and configuration.";
|
|
66477
|
+
}
|
|
66478
|
+
}
|
|
66465
66479
|
function forwardValidators(requestHeaders, upstreamHeaders) {
|
|
66466
66480
|
for (const name of ["if-none-match", "if-modified-since"]) {
|
|
66467
66481
|
const value = requestHeaders.get(name);
|
|
@@ -66477,13 +66491,26 @@ function upstreamErrorEnvelope(args) {
|
|
|
66477
66491
|
panelId: args.panelId,
|
|
66478
66492
|
state: "error",
|
|
66479
66493
|
observedAt: observedAt(args.upstreamDate),
|
|
66480
|
-
link: args.link,
|
|
66494
|
+
link: publicLink(args.link),
|
|
66481
66495
|
error: {
|
|
66482
66496
|
kind: args.kind,
|
|
66483
|
-
|
|
66497
|
+
// Raw failures regularly contain URLs, query values, response fragments, or credentials.
|
|
66498
|
+
// The specific evidence stays server-side; the browser gets this fixed actionable vocabulary.
|
|
66499
|
+
message: publicErrorMessage(args.kind)
|
|
66484
66500
|
}
|
|
66485
66501
|
};
|
|
66486
66502
|
}
|
|
66503
|
+
function publicLink(value) {
|
|
66504
|
+
if (!value) return null;
|
|
66505
|
+
try {
|
|
66506
|
+
const url2 = new URL(value);
|
|
66507
|
+
url2.search = "";
|
|
66508
|
+
url2.hash = "";
|
|
66509
|
+
return url2.toString();
|
|
66510
|
+
} catch {
|
|
66511
|
+
return null;
|
|
66512
|
+
}
|
|
66513
|
+
}
|
|
66487
66514
|
function upstreamErrorResponse(envelope) {
|
|
66488
66515
|
return new Response(JSON.stringify(envelope), { status: 200 });
|
|
66489
66516
|
}
|
|
@@ -66494,10 +66521,15 @@ function upstreamErrorKind(status) {
|
|
|
66494
66521
|
}
|
|
66495
66522
|
async function adapterRouteResponse(result) {
|
|
66496
66523
|
const headers = passthroughHeaders(result.response.headers);
|
|
66497
|
-
if (result.response.status === 304)
|
|
66524
|
+
if (result.response.status === 304)
|
|
66525
|
+
return { response: new Response(null, { status: 304, headers }) };
|
|
66498
66526
|
const envelope = result.envelope ?? JSON.parse(await result.response.text());
|
|
66499
66527
|
headers.set("content-type", "application/json; charset=utf-8");
|
|
66500
|
-
return new Response(JSON.stringify(envelope), { status: 200, headers });
|
|
66528
|
+
return { response: new Response(JSON.stringify(envelope), { status: 200, headers }), envelope };
|
|
66529
|
+
}
|
|
66530
|
+
function safeNetworkCode(error52) {
|
|
66531
|
+
const code = error52 && typeof error52 === "object" ? error52.code : void 0;
|
|
66532
|
+
return code === "ECONNREFUSED" || code === "ENOTFOUND" || code === "ETIMEDOUT" || code === "EAI_AGAIN" ? code : void 0;
|
|
66501
66533
|
}
|
|
66502
66534
|
function passthroughHeaders(upstream) {
|
|
66503
66535
|
const headers = new Headers();
|
|
@@ -66555,7 +66587,8 @@ async function fetchAzureDevOpsPipeline(args) {
|
|
|
66555
66587
|
`Credential ${source.token_env} is not available.`,
|
|
66556
66588
|
sourceLink(panel.pipeline, source)
|
|
66557
66589
|
)
|
|
66558
|
-
)
|
|
66590
|
+
),
|
|
66591
|
+
failure: { kind: "unauthorized" }
|
|
66559
66592
|
};
|
|
66560
66593
|
}
|
|
66561
66594
|
const call = buildsCall(panel.pipeline, source);
|
|
@@ -66568,7 +66601,11 @@ async function fetchAzureDevOpsPipeline(args) {
|
|
|
66568
66601
|
return {
|
|
66569
66602
|
response: errorResponse(
|
|
66570
66603
|
errorEnvelope(panel.id, "unreachable", error52, sourceLink(panel.pipeline, source))
|
|
66571
|
-
)
|
|
66604
|
+
),
|
|
66605
|
+
failure: {
|
|
66606
|
+
kind: "unreachable",
|
|
66607
|
+
...safeNetworkCode(error52) ? { networkCode: safeNetworkCode(error52) } : {}
|
|
66608
|
+
}
|
|
66572
66609
|
};
|
|
66573
66610
|
}
|
|
66574
66611
|
if (upstream.status === 304) return { response: upstream };
|
|
@@ -66582,7 +66619,8 @@ async function fetchAzureDevOpsPipeline(args) {
|
|
|
66582
66619
|
sourceLink(panel.pipeline, source),
|
|
66583
66620
|
observedAt2(upstream.headers.get("date"))
|
|
66584
66621
|
)
|
|
66585
|
-
)
|
|
66622
|
+
),
|
|
66623
|
+
failure: { kind: errorKind(upstream.status), upstreamStatus: upstream.status }
|
|
66586
66624
|
};
|
|
66587
66625
|
}
|
|
66588
66626
|
try {
|
|
@@ -66597,7 +66635,8 @@ async function fetchAzureDevOpsPipeline(args) {
|
|
|
66597
66635
|
sourceLink(panel.pipeline, source),
|
|
66598
66636
|
observedAt2(upstream.headers.get("date"))
|
|
66599
66637
|
)
|
|
66600
|
-
)
|
|
66638
|
+
),
|
|
66639
|
+
failure: { kind: "no-runs", upstreamStatus: upstream.status }
|
|
66601
66640
|
};
|
|
66602
66641
|
}
|
|
66603
66642
|
const signal = {
|
|
@@ -66640,7 +66679,8 @@ async function fetchAzureDevOpsPipeline(args) {
|
|
|
66640
66679
|
sourceLink(panel.pipeline, source),
|
|
66641
66680
|
observedAt2(upstream.headers.get("date"))
|
|
66642
66681
|
)
|
|
66643
|
-
)
|
|
66682
|
+
),
|
|
66683
|
+
failure: { kind: "upstream-error", upstreamStatus: upstream.status }
|
|
66644
66684
|
};
|
|
66645
66685
|
}
|
|
66646
66686
|
}
|
|
@@ -67068,7 +67108,11 @@ async function githubObservation(args, source, call, normalize) {
|
|
|
67068
67108
|
)
|
|
67069
67109
|
),
|
|
67070
67110
|
{ status: 200 }
|
|
67071
|
-
)
|
|
67111
|
+
),
|
|
67112
|
+
failure: {
|
|
67113
|
+
kind: error52 instanceof GithubAuthenticationError ? "unauthorized" : "unreachable",
|
|
67114
|
+
...safeNetworkCode(error52) ? { networkCode: safeNetworkCode(error52) } : {}
|
|
67115
|
+
}
|
|
67072
67116
|
};
|
|
67073
67117
|
}
|
|
67074
67118
|
if (upstream.status === 304) return { response: upstream };
|
|
@@ -67085,7 +67129,8 @@ async function githubObservation(args, source, call, normalize) {
|
|
|
67085
67129
|
)
|
|
67086
67130
|
),
|
|
67087
67131
|
{ status: 200 }
|
|
67088
|
-
)
|
|
67132
|
+
),
|
|
67133
|
+
failure: { kind: errorKind2(upstream.status), upstreamStatus: upstream.status }
|
|
67089
67134
|
};
|
|
67090
67135
|
try {
|
|
67091
67136
|
return {
|
|
@@ -67105,7 +67150,8 @@ async function githubObservation(args, source, call, normalize) {
|
|
|
67105
67150
|
)
|
|
67106
67151
|
),
|
|
67107
67152
|
{ status: 200 }
|
|
67108
|
-
)
|
|
67153
|
+
),
|
|
67154
|
+
failure: { kind: "upstream-error", upstreamStatus: upstream.status }
|
|
67109
67155
|
};
|
|
67110
67156
|
}
|
|
67111
67157
|
}
|
|
@@ -67161,7 +67207,11 @@ async function fetchGithubActionsPipeline(args) {
|
|
|
67161
67207
|
)
|
|
67162
67208
|
),
|
|
67163
67209
|
{ status: 200 }
|
|
67164
|
-
)
|
|
67210
|
+
),
|
|
67211
|
+
failure: {
|
|
67212
|
+
kind: error52 instanceof GithubAuthenticationError ? "unauthorized" : "unreachable",
|
|
67213
|
+
...safeNetworkCode(error52) ? { networkCode: safeNetworkCode(error52) } : {}
|
|
67214
|
+
}
|
|
67165
67215
|
};
|
|
67166
67216
|
}
|
|
67167
67217
|
if (upstream.status === 304) return { response: upstream };
|
|
@@ -67178,7 +67228,8 @@ async function fetchGithubActionsPipeline(args) {
|
|
|
67178
67228
|
)
|
|
67179
67229
|
),
|
|
67180
67230
|
{ status: 200 }
|
|
67181
|
-
)
|
|
67231
|
+
),
|
|
67232
|
+
failure: { kind: errorKind2(upstream.status), upstreamStatus: upstream.status }
|
|
67182
67233
|
};
|
|
67183
67234
|
}
|
|
67184
67235
|
try {
|
|
@@ -67197,7 +67248,8 @@ async function fetchGithubActionsPipeline(args) {
|
|
|
67197
67248
|
)
|
|
67198
67249
|
),
|
|
67199
67250
|
{ status: 200 }
|
|
67200
|
-
)
|
|
67251
|
+
),
|
|
67252
|
+
failure: { kind: "no-runs", upstreamStatus: upstream.status }
|
|
67201
67253
|
};
|
|
67202
67254
|
}
|
|
67203
67255
|
const signal = {
|
|
@@ -67242,7 +67294,8 @@ async function fetchGithubActionsPipeline(args) {
|
|
|
67242
67294
|
)
|
|
67243
67295
|
),
|
|
67244
67296
|
{ status: 200 }
|
|
67245
|
-
)
|
|
67297
|
+
),
|
|
67298
|
+
failure: { kind: "upstream-error", upstreamStatus: upstream.status }
|
|
67246
67299
|
};
|
|
67247
67300
|
}
|
|
67248
67301
|
}
|
|
@@ -67334,7 +67387,13 @@ async function fetchHttpValue(args) {
|
|
|
67334
67387
|
try {
|
|
67335
67388
|
upstream = await args.fetcher(call.url, { headers: call.headers });
|
|
67336
67389
|
} catch (error52) {
|
|
67337
|
-
return {
|
|
67390
|
+
return {
|
|
67391
|
+
response: errorResponse2("unreachable", error52, panel),
|
|
67392
|
+
failure: {
|
|
67393
|
+
kind: "unreachable",
|
|
67394
|
+
...safeNetworkCode(error52) ? { networkCode: safeNetworkCode(error52) } : {}
|
|
67395
|
+
}
|
|
67396
|
+
};
|
|
67338
67397
|
}
|
|
67339
67398
|
if (upstream.status === 304) return { response: upstream };
|
|
67340
67399
|
if (!upstream.ok) {
|
|
@@ -67344,7 +67403,8 @@ async function fetchHttpValue(args) {
|
|
|
67344
67403
|
`${upstream.status} ${upstream.statusText}`,
|
|
67345
67404
|
panel,
|
|
67346
67405
|
upstream
|
|
67347
|
-
)
|
|
67406
|
+
),
|
|
67407
|
+
failure: { kind: upstreamErrorKind(upstream.status), upstreamStatus: upstream.status }
|
|
67348
67408
|
};
|
|
67349
67409
|
}
|
|
67350
67410
|
try {
|
|
@@ -67356,14 +67416,15 @@ async function fetchHttpValue(args) {
|
|
|
67356
67416
|
panelId: panel.id,
|
|
67357
67417
|
state: "ok",
|
|
67358
67418
|
observedAt: observedAt(upstream.headers.get("date")),
|
|
67359
|
-
link: panel.link ?? panel.url,
|
|
67419
|
+
link: publicLink(panel.link ?? panel.url),
|
|
67360
67420
|
signal
|
|
67361
67421
|
},
|
|
67362
67422
|
response: upstream
|
|
67363
67423
|
};
|
|
67364
67424
|
} catch (error52) {
|
|
67365
67425
|
return {
|
|
67366
|
-
response: errorResponse2("upstream-error", error52, panel, upstream)
|
|
67426
|
+
response: errorResponse2("upstream-error", error52, panel, upstream),
|
|
67427
|
+
failure: { kind: "upstream-error", upstreamStatus: upstream.status }
|
|
67367
67428
|
};
|
|
67368
67429
|
}
|
|
67369
67430
|
}
|
|
@@ -67434,6 +67495,24 @@ function callsFor(panel, source) {
|
|
|
67434
67495
|
return void 0;
|
|
67435
67496
|
}
|
|
67436
67497
|
|
|
67498
|
+
// packages/server/src/logger.ts
|
|
67499
|
+
var consoleLogger = {
|
|
67500
|
+
log(event) {
|
|
67501
|
+
console.log(JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), ...event }));
|
|
67502
|
+
}
|
|
67503
|
+
};
|
|
67504
|
+
function requestId() {
|
|
67505
|
+
return crypto.randomUUID();
|
|
67506
|
+
}
|
|
67507
|
+
function destinationOrigin(value) {
|
|
67508
|
+
if (!value) return void 0;
|
|
67509
|
+
try {
|
|
67510
|
+
return new URL(value).origin;
|
|
67511
|
+
} catch {
|
|
67512
|
+
return void 0;
|
|
67513
|
+
}
|
|
67514
|
+
}
|
|
67515
|
+
|
|
67437
67516
|
// packages/server/src/template.ts
|
|
67438
67517
|
var ASSET_PATH_SENTINEL = "/__ASSET_PATH__";
|
|
67439
67518
|
var TemplateFetchError = class extends Error {
|
|
@@ -67517,9 +67596,28 @@ function createApp(deps) {
|
|
|
67517
67596
|
const allowlist = deps.boardConfig ? deriveAllowlist(deps.boardConfig) : /* @__PURE__ */ new Map();
|
|
67518
67597
|
const credentials = deps.credentials ?? environmentCredentials();
|
|
67519
67598
|
const githubClient = createGithubClient(credentials);
|
|
67599
|
+
const logger2 = deps.logger ?? consoleLogger;
|
|
67520
67600
|
const app = new Hono2();
|
|
67601
|
+
app.use("/api/*", async (c5, next) => {
|
|
67602
|
+
const id = requestId();
|
|
67603
|
+
c5.set("dashboardRequestId", id);
|
|
67604
|
+
await next();
|
|
67605
|
+
c5.header("x-dashboard-request-id", id);
|
|
67606
|
+
});
|
|
67607
|
+
app.onError((_error, c5) => {
|
|
67608
|
+
const id = c5.get("dashboardRequestId");
|
|
67609
|
+
logger2.log({
|
|
67610
|
+
event: "server.unhandled_exception",
|
|
67611
|
+
...id ? { requestId: id } : {},
|
|
67612
|
+
operation: "route-handler"
|
|
67613
|
+
});
|
|
67614
|
+
return c5.json(
|
|
67615
|
+
{ error: "The dashboard could not complete this request." },
|
|
67616
|
+
500,
|
|
67617
|
+
id ? { "x-dashboard-request-id": id } : void 0
|
|
67618
|
+
);
|
|
67619
|
+
});
|
|
67521
67620
|
app.get("/health", (c5) => c5.json({ status: "ok" }));
|
|
67522
|
-
app.use("/api/*", async (_c5, next) => next());
|
|
67523
67621
|
app.get(`${config2.proxyPath}/client`, (c5) => {
|
|
67524
67622
|
const identity = { assetPath: config2.assetPath };
|
|
67525
67623
|
return c5.json(identity, 200, { "cache-control": "no-store" });
|
|
@@ -67580,48 +67678,82 @@ ${(0, import_yaml.stringify)(outputConfig, { sortMapEntries: true })}`,
|
|
|
67580
67678
|
const panel = board?.panels.find((candidate) => candidate.id === panelId);
|
|
67581
67679
|
const source = panel?.source ? deps.boardConfig?.sources[panel.source] : void 0;
|
|
67582
67680
|
if (!panel || panel.type !== "http-value" && !source || !permitsPanelOperation(allowlist, boardName, panelId, "read"))
|
|
67583
|
-
return c5
|
|
67681
|
+
return rejected(c5, { boardId: boardName, panelId, operation: "read" });
|
|
67584
67682
|
if (panel.type === "pipeline-status" && source?.type === "github-actions" && source) {
|
|
67585
|
-
const result =
|
|
67683
|
+
const result = fetchGithubActionsPipeline({
|
|
67586
67684
|
panel,
|
|
67587
67685
|
source,
|
|
67588
67686
|
requestHeaders: c5.req.raw.headers,
|
|
67589
67687
|
fetcher: deps.fetcher ?? globalThis.fetch,
|
|
67590
67688
|
githubClient
|
|
67591
67689
|
});
|
|
67592
|
-
return
|
|
67690
|
+
return observation(c5, result, {
|
|
67691
|
+
boardId: boardName,
|
|
67692
|
+
panelId,
|
|
67693
|
+
operation: "read",
|
|
67694
|
+
sourceName: panel.source,
|
|
67695
|
+
sourceType: source.type,
|
|
67696
|
+
destination: "https://api.github.com"
|
|
67697
|
+
});
|
|
67593
67698
|
}
|
|
67594
67699
|
if (panel.type === "pipeline-status" && source?.type === "azure-devops" && source) {
|
|
67595
|
-
const result =
|
|
67700
|
+
const result = fetchAzureDevOpsPipeline({
|
|
67596
67701
|
panel,
|
|
67597
67702
|
source,
|
|
67598
67703
|
requestHeaders: c5.req.raw.headers,
|
|
67599
67704
|
fetcher: deps.fetcher ?? globalThis.fetch,
|
|
67600
67705
|
credentials
|
|
67601
67706
|
});
|
|
67602
|
-
return
|
|
67707
|
+
return observation(c5, result, {
|
|
67708
|
+
boardId: boardName,
|
|
67709
|
+
panelId,
|
|
67710
|
+
operation: "read",
|
|
67711
|
+
sourceName: panel.source,
|
|
67712
|
+
sourceType: source.type,
|
|
67713
|
+
destination: "https://dev.azure.com"
|
|
67714
|
+
});
|
|
67603
67715
|
}
|
|
67604
|
-
if (panel.type === "pull-request-health")
|
|
67716
|
+
if (panel.type === "pull-request-health")
|
|
67717
|
+
return rejected(c5, { boardId: boardName, panelId, operation: "read" });
|
|
67605
67718
|
if (panel.type === "http-value") {
|
|
67606
|
-
const result =
|
|
67719
|
+
const result = fetchHttpValue({
|
|
67607
67720
|
panel,
|
|
67608
67721
|
requestHeaders: c5.req.raw.headers,
|
|
67609
67722
|
fetcher: deps.fetcher ?? globalThis.fetch
|
|
67610
67723
|
});
|
|
67611
|
-
return
|
|
67724
|
+
return observation(c5, result, {
|
|
67725
|
+
boardId: boardName,
|
|
67726
|
+
panelId,
|
|
67727
|
+
operation: "read",
|
|
67728
|
+
destination: panel.url
|
|
67729
|
+
});
|
|
67612
67730
|
}
|
|
67613
67731
|
return c5.notFound();
|
|
67614
67732
|
});
|
|
67615
67733
|
app.get("/api/panel/:board/:panelId/pull-requests", async (c5) => {
|
|
67616
67734
|
const resolved = pullRequestPanel(c5.req.param("board"), c5.req.param("panelId"), "pull-requests");
|
|
67617
|
-
if (!resolved)
|
|
67618
|
-
|
|
67619
|
-
|
|
67735
|
+
if (!resolved)
|
|
67736
|
+
return rejected(c5, {
|
|
67737
|
+
boardId: c5.req.param("board"),
|
|
67738
|
+
panelId: c5.req.param("panelId"),
|
|
67739
|
+
operation: "pull-requests"
|
|
67740
|
+
});
|
|
67741
|
+
return observation(
|
|
67742
|
+
c5,
|
|
67743
|
+
fetchGithubActionsPullRequestCandidates({
|
|
67620
67744
|
...resolved,
|
|
67621
67745
|
requestHeaders: c5.req.raw.headers,
|
|
67622
67746
|
fetcher: deps.fetcher ?? globalThis.fetch,
|
|
67623
67747
|
githubClient
|
|
67624
|
-
})
|
|
67748
|
+
}),
|
|
67749
|
+
{
|
|
67750
|
+
boardId: c5.req.param("board"),
|
|
67751
|
+
panelId: c5.req.param("panelId"),
|
|
67752
|
+
operation: "pull-requests",
|
|
67753
|
+
sourceName: resolved.panel.source,
|
|
67754
|
+
sourceType: resolved.source.type,
|
|
67755
|
+
destination: "https://api.github.com"
|
|
67756
|
+
}
|
|
67625
67757
|
);
|
|
67626
67758
|
});
|
|
67627
67759
|
app.get("/api/panel/:board/:panelId/update-workflow/:workflow", async (c5) => {
|
|
@@ -67631,15 +67763,29 @@ ${(0, import_yaml.stringify)(outputConfig, { sortMapEntries: true })}`,
|
|
|
67631
67763
|
"update-workflow"
|
|
67632
67764
|
);
|
|
67633
67765
|
const workflow = c5.req.param("workflow");
|
|
67634
|
-
if (!resolved?.capabilities.configuredUpdateWorkflow(workflow))
|
|
67635
|
-
|
|
67636
|
-
|
|
67766
|
+
if (!resolved?.capabilities.configuredUpdateWorkflow(workflow))
|
|
67767
|
+
return rejected(c5, {
|
|
67768
|
+
boardId: c5.req.param("board"),
|
|
67769
|
+
panelId: c5.req.param("panelId"),
|
|
67770
|
+
operation: "update-workflow"
|
|
67771
|
+
});
|
|
67772
|
+
return observation(
|
|
67773
|
+
c5,
|
|
67774
|
+
fetchGithubActionsUpdateWorkflow({
|
|
67637
67775
|
...resolved,
|
|
67638
67776
|
workflow,
|
|
67639
67777
|
requestHeaders: c5.req.raw.headers,
|
|
67640
67778
|
fetcher: deps.fetcher ?? globalThis.fetch,
|
|
67641
67779
|
githubClient
|
|
67642
|
-
})
|
|
67780
|
+
}),
|
|
67781
|
+
{
|
|
67782
|
+
boardId: c5.req.param("board"),
|
|
67783
|
+
panelId: c5.req.param("panelId"),
|
|
67784
|
+
operation: "update-workflow",
|
|
67785
|
+
sourceName: resolved.panel.source,
|
|
67786
|
+
sourceType: resolved.source.type,
|
|
67787
|
+
destination: "https://api.github.com"
|
|
67788
|
+
}
|
|
67643
67789
|
);
|
|
67644
67790
|
});
|
|
67645
67791
|
app.get("/api/panel/:board/:panelId/pull-request-build", async (c5) => {
|
|
@@ -67650,15 +67796,28 @@ ${(0, import_yaml.stringify)(outputConfig, { sortMapEntries: true })}`,
|
|
|
67650
67796
|
);
|
|
67651
67797
|
const branch = c5.req.query("branch");
|
|
67652
67798
|
if (!resolved || !branch || !resolved.capabilities.permitsBuildBranch(branch))
|
|
67653
|
-
return c5
|
|
67654
|
-
|
|
67655
|
-
|
|
67799
|
+
return rejected(c5, {
|
|
67800
|
+
boardId: c5.req.param("board"),
|
|
67801
|
+
panelId: c5.req.param("panelId"),
|
|
67802
|
+
operation: "pull-request-build"
|
|
67803
|
+
});
|
|
67804
|
+
return observation(
|
|
67805
|
+
c5,
|
|
67806
|
+
fetchGithubActionsPullRequestBuild({
|
|
67656
67807
|
...resolved,
|
|
67657
67808
|
branch,
|
|
67658
67809
|
requestHeaders: c5.req.raw.headers,
|
|
67659
67810
|
fetcher: deps.fetcher ?? globalThis.fetch,
|
|
67660
67811
|
githubClient
|
|
67661
|
-
})
|
|
67812
|
+
}),
|
|
67813
|
+
{
|
|
67814
|
+
boardId: c5.req.param("board"),
|
|
67815
|
+
panelId: c5.req.param("panelId"),
|
|
67816
|
+
operation: "pull-request-build",
|
|
67817
|
+
sourceName: resolved.panel.source,
|
|
67818
|
+
sourceType: resolved.source.type,
|
|
67819
|
+
destination: "https://api.github.com"
|
|
67820
|
+
}
|
|
67662
67821
|
);
|
|
67663
67822
|
});
|
|
67664
67823
|
function pullRequestPanel(boardName, panelId, operation2) {
|
|
@@ -67670,6 +67829,38 @@ ${(0, import_yaml.stringify)(outputConfig, { sortMapEntries: true })}`,
|
|
|
67670
67829
|
if (!capabilities) return void 0;
|
|
67671
67830
|
return panel?.type === "pull-request-health" && source?.type === "github-actions" && permitsPanelOperation(allowlist, boardName, panelId, operation2) ? { panel, source, capabilities } : void 0;
|
|
67672
67831
|
}
|
|
67832
|
+
function rejected(c5, context) {
|
|
67833
|
+
logger2.log({
|
|
67834
|
+
event: "api.operation_rejected",
|
|
67835
|
+
requestId: c5.get("dashboardRequestId"),
|
|
67836
|
+
boardId: context.boardId,
|
|
67837
|
+
panelId: context.panelId,
|
|
67838
|
+
operation: context.operation
|
|
67839
|
+
});
|
|
67840
|
+
return c5.notFound();
|
|
67841
|
+
}
|
|
67842
|
+
async function observation(c5, result, context) {
|
|
67843
|
+
const started = performance.now();
|
|
67844
|
+
const resolved = await result;
|
|
67845
|
+
const adapted = await adapterRouteResponse(resolved);
|
|
67846
|
+
if (adapted.envelope?.state === "error") {
|
|
67847
|
+
logger2.log({
|
|
67848
|
+
event: "panel.observation_failed",
|
|
67849
|
+
requestId: c5.get("dashboardRequestId"),
|
|
67850
|
+
boardId: context.boardId,
|
|
67851
|
+
panelId: context.panelId,
|
|
67852
|
+
operation: context.operation,
|
|
67853
|
+
errorKind: adapted.envelope.error.kind,
|
|
67854
|
+
elapsedMs: Math.round(performance.now() - started),
|
|
67855
|
+
...context.sourceName ? { sourceName: context.sourceName } : {},
|
|
67856
|
+
...context.sourceType ? { sourceType: context.sourceType } : {},
|
|
67857
|
+
...destinationOrigin(context.destination) ? { destinationOrigin: destinationOrigin(context.destination) } : {},
|
|
67858
|
+
...resolved.failure?.upstreamStatus ? { upstreamStatus: resolved.failure.upstreamStatus } : {},
|
|
67859
|
+
...resolved.failure?.networkCode ? { networkCode: resolved.failure.networkCode } : {}
|
|
67860
|
+
});
|
|
67861
|
+
}
|
|
67862
|
+
return adapted.response;
|
|
67863
|
+
}
|
|
67673
67864
|
async function renderEntrypoint(_request, board) {
|
|
67674
67865
|
const template = await templates.get(config2.assetPath);
|
|
67675
67866
|
const env2 = {
|
|
@@ -67777,28 +67968,35 @@ function isLocalHost(host) {
|
|
|
67777
67968
|
|
|
67778
67969
|
// packages/server/src/startup.ts
|
|
67779
67970
|
async function startup(options = {}) {
|
|
67780
|
-
const
|
|
67781
|
-
|
|
67782
|
-
|
|
67783
|
-
|
|
67784
|
-
|
|
67785
|
-
|
|
67786
|
-
fetcher,
|
|
67787
|
-
|
|
67788
|
-
|
|
67789
|
-
|
|
67790
|
-
|
|
67791
|
-
|
|
67792
|
-
|
|
67793
|
-
|
|
67794
|
-
|
|
67795
|
-
credentialNames
|
|
67796
|
-
|
|
67797
|
-
|
|
67798
|
-
|
|
67799
|
-
|
|
67800
|
-
|
|
67801
|
-
|
|
67971
|
+
const logger2 = options.logger ?? consoleLogger;
|
|
67972
|
+
logger2.log({ event: "server.starting" });
|
|
67973
|
+
try {
|
|
67974
|
+
const config2 = loadConfig2();
|
|
67975
|
+
const fetcher = options.fetcher ?? globalThis.fetch;
|
|
67976
|
+
const [, boardConfig] = await Promise.all([
|
|
67977
|
+
waitForTemplate(config2, fetcher),
|
|
67978
|
+
loadBoardConfig(
|
|
67979
|
+
config2.boardConfigUrl,
|
|
67980
|
+
fetcher,
|
|
67981
|
+
config2.assetPath.includes("__ASSET_PATH__") ? void 0 : schemaUrlForAssetPath(config2.assetPath)
|
|
67982
|
+
)
|
|
67983
|
+
]);
|
|
67984
|
+
const board = selectBoard(config2.board, boardConfig);
|
|
67985
|
+
const resolvedConfig = { ...config2, board };
|
|
67986
|
+
const credentialNames = Object.values(boardConfig.sources).flatMap(credentialEnvironmentNames);
|
|
67987
|
+
const credentials = await createCredentialResolver({
|
|
67988
|
+
secretReference: config2.secretReference,
|
|
67989
|
+
credentialNames
|
|
67990
|
+
});
|
|
67991
|
+
warnAboutMissingAuth(resolvedConfig, logger2);
|
|
67992
|
+
return {
|
|
67993
|
+
app: createApp({ config: resolvedConfig, fetcher, boardConfig, credentials, logger: logger2 }),
|
|
67994
|
+
config: resolvedConfig
|
|
67995
|
+
};
|
|
67996
|
+
} catch (error52) {
|
|
67997
|
+
logger2.log({ event: "server.startup_failed", category: startupFailureCategory(error52) });
|
|
67998
|
+
throw error52;
|
|
67999
|
+
}
|
|
67802
68000
|
}
|
|
67803
68001
|
function selectBoard(requested, config2) {
|
|
67804
68002
|
if (requested) {
|
|
@@ -67833,14 +68031,17 @@ async function waitForTemplate(config2, fetcher) {
|
|
|
67833
68031
|
}
|
|
67834
68032
|
}
|
|
67835
68033
|
var RETRY_INTERVAL_MILLIS = 250;
|
|
67836
|
-
function warnAboutMissingAuth(config2) {
|
|
68034
|
+
function warnAboutMissingAuth(config2, logger2) {
|
|
67837
68035
|
if (isLocalHost(config2.host)) return;
|
|
67838
|
-
|
|
67839
|
-
|
|
67840
|
-
|
|
67841
|
-
|
|
67842
|
-
|
|
67843
|
-
);
|
|
68036
|
+
logger2.log({ event: "server.no_auth_warning", host: config2.host, port: config2.port });
|
|
68037
|
+
}
|
|
68038
|
+
function startupFailureCategory(error52) {
|
|
68039
|
+
const message = error52 instanceof Error ? error52.message : "";
|
|
68040
|
+
if (message.includes("server configuration")) return "configuration";
|
|
68041
|
+
if (message.includes("ASSET_PATH") || message.includes("<head>")) return "template";
|
|
68042
|
+
if (message.includes("board") || message.includes("Board")) return "board-config";
|
|
68043
|
+
if (message.includes("credential") || message.includes("secret")) return "credentials";
|
|
68044
|
+
return "unknown";
|
|
67844
68045
|
}
|
|
67845
68046
|
|
|
67846
68047
|
// packages/server/src/lambda.ts
|
package/package.json
CHANGED