@continuous-excellence/ze-great-dashboard-aws 0.18.4 → 0.20.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/client/.vite/manifest.json +2 -2
- package/client/assets/{index-BCZ7NCP8.css → index-Cuk6kga3.css} +1 -1
- package/client/assets/index-k3N7vI0h.js +3 -0
- package/client/assets/index-k3N7vI0h.js.map +1 -0
- package/client/index.html +2 -2
- package/dist/cli.js +96 -14
- package/dist/index.d.ts +3 -1
- package/dist/index.js +90 -10
- package/dist/lambda.mjs +631 -255
- package/dist/release.d.ts +3 -1
- package/package.json +1 -1
- package/template-ecs.yml +4 -5
- package/template.yml +4 -5
- package/client/assets/index-mtLNXa0q.js +0 -3
- package/client/assets/index-mtLNXa0q.js.map +0 -1
package/client/index.html
CHANGED
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
<title>Trust Dashboard</title>
|
|
12
12
|
|
|
13
13
|
<script type="importmap">{"imports":{"react":"https://esm.sh/react@19.2.8","react/":"https://esm.sh/react@19.2.8/","react-dom":"https://esm.sh/react-dom@19.2.8","react-dom/":"https://esm.sh/react-dom@19.2.8/","scheduler":"https://esm.sh/scheduler@0.27.0","scheduler/":"https://esm.sh/scheduler@0.27.0/","zod":"https://esm.sh/zod@4.4.3","zod/":"https://esm.sh/zod@4.4.3/"}}</script>
|
|
14
|
-
<script type="module" crossorigin src="/__ASSET_PATH__/assets/index-
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/__ASSET_PATH__/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/__ASSET_PATH__/assets/index-k3N7vI0h.js"></script>
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/__ASSET_PATH__/assets/index-Cuk6kga3.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body>
|
|
18
18
|
<div id="root"></div>
|
package/dist/cli.js
CHANGED
|
@@ -157,6 +157,16 @@ var githubActionsSourceSchema = z2.looseObject({
|
|
|
157
157
|
branch: z2.string().min(1).optional(),
|
|
158
158
|
...sourceAuthenticationSchema
|
|
159
159
|
}).superRefine(exactlyOneGithubAuthenticationMode);
|
|
160
|
+
var azureDevOpsSourceSchema = z2.looseObject({
|
|
161
|
+
type: z2.literal("azure-devops"),
|
|
162
|
+
/** Azure DevOps organization name, used as one URL path segment. */
|
|
163
|
+
organization: z2.string().regex(/^[^/\s]+$/, "must be an organization name"),
|
|
164
|
+
project: z2.string().min(1),
|
|
165
|
+
/** The branch whose build health the dashboard represents. */
|
|
166
|
+
branch: z2.string().min(1).optional(),
|
|
167
|
+
/** Azure DevOps Build API access is authenticated with a read-scoped PAT. */
|
|
168
|
+
token_env: z2.string().min(1)
|
|
169
|
+
});
|
|
160
170
|
var sourceSchema = z2.looseObject({ type: z2.string().min(1), ...sourceAuthenticationSchema }).superRefine(exactlyOneGithubAuthenticationMode);
|
|
161
171
|
var boardSchema = z2.object({
|
|
162
172
|
refresh: durationSchema.optional(),
|
|
@@ -192,6 +202,33 @@ var boardConfigSchema = z2.object({
|
|
|
192
202
|
sources: z2.record(z2.string().min(1), sourceSchema).default({}),
|
|
193
203
|
boards: z2.record(z2.string().min(1), boardSchema),
|
|
194
204
|
auth: authSchema.optional()
|
|
205
|
+
}).superRefine((config, ctx) => {
|
|
206
|
+
for (const [sourceName, source] of Object.entries(config.sources)) {
|
|
207
|
+
if (source.type !== "azure-devops") continue;
|
|
208
|
+
const parsedSource = azureDevOpsSourceSchema.safeParse(source);
|
|
209
|
+
if (!parsedSource.success) {
|
|
210
|
+
for (const issue of parsedSource.error.issues) {
|
|
211
|
+
ctx.addIssue({
|
|
212
|
+
code: "custom",
|
|
213
|
+
path: ["sources", sourceName, ...issue.path],
|
|
214
|
+
message: issue.message
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
for (const [boardName, board] of Object.entries(config.boards)) {
|
|
220
|
+
board.panels.forEach((panel, panelIndex) => {
|
|
221
|
+
const source = panel.source ? config.sources[panel.source] : void 0;
|
|
222
|
+
if (panel.type !== "pipeline-status" || source?.type !== "azure-devops") return;
|
|
223
|
+
if (typeof panel.pipeline !== "number" || !Number.isInteger(panel.pipeline) || panel.pipeline <= 0) {
|
|
224
|
+
ctx.addIssue({
|
|
225
|
+
code: "custom",
|
|
226
|
+
path: ["boards", boardName, "panels", panelIndex, "pipeline"],
|
|
227
|
+
message: "Azure DevOps pipeline-status panels require a positive numeric pipeline definition id"
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
195
232
|
});
|
|
196
233
|
|
|
197
234
|
// packages/shared/src/board-config-modeline.ts
|
|
@@ -235,15 +272,13 @@ var clientEnvSchema = z3.object({
|
|
|
235
272
|
proxyPath: z3.string().min(1),
|
|
236
273
|
/** Which board this is, resolved server-side so the client parses no URLs. */
|
|
237
274
|
board: z3.string().min(1),
|
|
238
|
-
/** The client version being served, so two published versions are visibly distinguishable. */
|
|
239
|
-
clientVersion: z3.string().min(1),
|
|
240
275
|
/** Omitted entirely when unauthenticated — presence is what turns auth on. */
|
|
241
276
|
auth: z3.object({
|
|
242
277
|
issuer: z3.string().min(1),
|
|
243
278
|
clientId: z3.string().min(1).optional()
|
|
244
279
|
}).optional()
|
|
245
280
|
});
|
|
246
|
-
var clientIdentitySchema = clientEnvSchema.pick({ assetPath: true
|
|
281
|
+
var clientIdentitySchema = clientEnvSchema.pick({ assetPath: true });
|
|
247
282
|
|
|
248
283
|
// packages/shared/src/envelope.ts
|
|
249
284
|
import { z as z4 } from "zod";
|
|
@@ -318,7 +353,32 @@ var pullRequestHealthSchema = z4.object({
|
|
|
318
353
|
status: pipelineStatusSchema.shape.status,
|
|
319
354
|
summary: z4.string().min(1),
|
|
320
355
|
workflows: z4.array(pullRequestHealthItemSchema),
|
|
321
|
-
pullRequests: z4.array(pullRequestHealthItemSchema)
|
|
356
|
+
pullRequests: z4.array(pullRequestHealthItemSchema),
|
|
357
|
+
/** Missing component reads remain visible even when the evidence we did get is reassuring. */
|
|
358
|
+
incompleteObservations: z4.array(z4.object({ label: z4.string().min(1), message: z4.string().min(1) })).optional(),
|
|
359
|
+
/** The latest component reading, disclosed beside the oldest aggregate evidence. */
|
|
360
|
+
newestObservedAt: z4.iso.datetime().optional()
|
|
361
|
+
});
|
|
362
|
+
var pullRequestCandidateSchema = z4.object({
|
|
363
|
+
number: z4.number().int().positive(),
|
|
364
|
+
branch: z4.string().min(1),
|
|
365
|
+
link: z4.url()
|
|
366
|
+
});
|
|
367
|
+
var pullRequestCandidatesSchema = z4.object({
|
|
368
|
+
type: z4.literal("pull-request-candidates"),
|
|
369
|
+
pullRequests: z4.array(pullRequestCandidateSchema),
|
|
370
|
+
/** GitHub's first page is a deliberate bounded observation, not proof that no later PR exists. */
|
|
371
|
+
truncated: z4.boolean().optional()
|
|
372
|
+
});
|
|
373
|
+
var pullRequestWorkflowObservationSchema = z4.object({
|
|
374
|
+
type: z4.literal("pull-request-workflow"),
|
|
375
|
+
workflow: z4.string().min(1),
|
|
376
|
+
item: pullRequestHealthItemSchema
|
|
377
|
+
});
|
|
378
|
+
var pullRequestBuildObservationSchema = z4.object({
|
|
379
|
+
type: z4.literal("pull-request-build"),
|
|
380
|
+
branch: z4.string().min(1),
|
|
381
|
+
item: pullRequestHealthItemSchema
|
|
322
382
|
});
|
|
323
383
|
var httpValueSchema = z4.object({
|
|
324
384
|
type: z4.literal("http-value"),
|
|
@@ -416,11 +476,25 @@ function credentialEnvironmentNames2(source) {
|
|
|
416
476
|
// packages/aws/src/release.ts
|
|
417
477
|
var CORE_RUNTIME_VERSION = "1.0.0";
|
|
418
478
|
var CANONICAL_ASSET_DOMAIN = "https://public-assets.zegreatrob.com";
|
|
419
|
-
function
|
|
479
|
+
function legacyAssetPath(version, domain = CANONICAL_ASSET_DOMAIN) {
|
|
420
480
|
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(version))
|
|
421
481
|
throw new Error(`Invalid dashboard version: ${version}`);
|
|
422
482
|
return `${domain.replace(/\/+$/, "")}/dashboard/${version}`;
|
|
423
483
|
}
|
|
484
|
+
function normalizeAssetPath(value2) {
|
|
485
|
+
const assetPath = value2.replace(/\/+$/, "");
|
|
486
|
+
let url;
|
|
487
|
+
try {
|
|
488
|
+
url = new URL(assetPath);
|
|
489
|
+
} catch {
|
|
490
|
+
throw new Error("--asset-path must be an absolute HTTP(S) URL");
|
|
491
|
+
}
|
|
492
|
+
if (!["http:", "https:"].includes(url.protocol) || !url.hostname || url.username || url.password || url.search || url.hash)
|
|
493
|
+
throw new Error(
|
|
494
|
+
"--asset-path must be an absolute HTTP(S) URL without credentials, query, or fragment"
|
|
495
|
+
);
|
|
496
|
+
return assetPath;
|
|
497
|
+
}
|
|
424
498
|
async function validateBoardConfig(path, expectedSchemaUrl) {
|
|
425
499
|
const source = await readFile(resolve(path), "utf8");
|
|
426
500
|
const authoredSchemaUrl = readBoardSchemaModeline(source, expectedSchemaUrl);
|
|
@@ -442,10 +516,14 @@ ${stringify(result.data, { sortMapEntries: true })}`;
|
|
|
442
516
|
};
|
|
443
517
|
}
|
|
444
518
|
async function assembleRelease(input) {
|
|
445
|
-
|
|
519
|
+
if (input.assetPath && input.assetDomain)
|
|
520
|
+
throw new Error("--asset-path and --asset-domain cannot be used together");
|
|
521
|
+
const assetPath = normalizeAssetPath(
|
|
522
|
+
input.assetPath ?? legacyAssetPath(input.version, input.assetDomain)
|
|
523
|
+
);
|
|
446
524
|
const board = await validateBoardConfig(
|
|
447
525
|
input.boardConfigPath,
|
|
448
|
-
`${
|
|
526
|
+
`${assetPath}/${boardSchemaFileName}`
|
|
449
527
|
);
|
|
450
528
|
if (board.usesCredentials && !input.secretReference)
|
|
451
529
|
throw new Error(
|
|
@@ -456,7 +534,7 @@ async function assembleRelease(input) {
|
|
|
456
534
|
await writeFile(join(outputDir, "board.yaml"), board.yaml);
|
|
457
535
|
const metadata = {
|
|
458
536
|
dashboardVersion: input.version,
|
|
459
|
-
|
|
537
|
+
assetPath,
|
|
460
538
|
serverRuntimeVersion: CORE_RUNTIME_VERSION,
|
|
461
539
|
supportedProviders: input.providers ?? ["aws-lambda"],
|
|
462
540
|
artifactChecksums: { "board.yaml": board.sha256 },
|
|
@@ -2700,6 +2778,7 @@ async function packageLambda(options) {
|
|
|
2700
2778
|
outputDir: runtimeDir,
|
|
2701
2779
|
version: options.version,
|
|
2702
2780
|
providers: ["aws-lambda"],
|
|
2781
|
+
assetPath: options.assetPath,
|
|
2703
2782
|
assetDomain: options.assetDomain,
|
|
2704
2783
|
secretReference: options.secretReference
|
|
2705
2784
|
});
|
|
@@ -2745,7 +2824,7 @@ async function packageLambda(options) {
|
|
|
2745
2824
|
deploymentTemplate(await cloudFormationTemplate("lambda"), {
|
|
2746
2825
|
ComputeMode: "lambda",
|
|
2747
2826
|
LambdaArtifactKey: packagedRelease.artifactKey,
|
|
2748
|
-
|
|
2827
|
+
AssetPath: packagedRelease.assetPath
|
|
2749
2828
|
})
|
|
2750
2829
|
);
|
|
2751
2830
|
return packagedRelease;
|
|
@@ -2759,6 +2838,7 @@ async function packageEcs(options) {
|
|
|
2759
2838
|
outputDir,
|
|
2760
2839
|
version: options.version,
|
|
2761
2840
|
providers: ["aws-ecs-fargate"],
|
|
2841
|
+
assetPath: options.assetPath,
|
|
2762
2842
|
assetDomain: options.assetDomain,
|
|
2763
2843
|
secretReference: options.secretReference
|
|
2764
2844
|
});
|
|
@@ -2775,7 +2855,7 @@ async function packageEcs(options) {
|
|
|
2775
2855
|
deploymentTemplate(await cloudFormationTemplate("ecs"), {
|
|
2776
2856
|
ComputeMode: "ecs",
|
|
2777
2857
|
Image: imageReference,
|
|
2778
|
-
|
|
2858
|
+
AssetPath: packagedRelease.assetPath
|
|
2779
2859
|
})
|
|
2780
2860
|
);
|
|
2781
2861
|
await writeFile3(
|
|
@@ -2944,10 +3024,8 @@ async function runDoctor(options, dependencies = actualDependencies) {
|
|
|
2944
3024
|
return `${bucket} exists in ${bucketRegion}`;
|
|
2945
3025
|
});
|
|
2946
3026
|
await check("Hosted client", async () => {
|
|
2947
|
-
const baseUrl = parameterData?.definitions.AssetBaseUrl?.Default;
|
|
2948
|
-
if (typeof baseUrl !== "string") throw new Error("template has no AssetBaseUrl default");
|
|
2949
3027
|
if (!dependencies.packageVersion) throw new Error("installed package version is unavailable");
|
|
2950
|
-
const url =
|
|
3028
|
+
const url = `https://public-assets.zegreatrob.com/dashboard/${dependencies.packageVersion}/index.html`;
|
|
2951
3029
|
const response = await dependencies.fetch(url);
|
|
2952
3030
|
if (!response.ok) throw new Error(`${url} returned HTTP ${response.status}`);
|
|
2953
3031
|
return `${url} returned HTTP ${response.status}`;
|
|
@@ -3583,6 +3661,8 @@ ${shellCommand(awsCommand)}`,
|
|
|
3583
3661
|
if (!boardConfig) throw new Error("--board-config is required");
|
|
3584
3662
|
if (!version)
|
|
3585
3663
|
throw new Error("Unable to determine the package version; pass --version explicitly");
|
|
3664
|
+
if (option("--asset-domain"))
|
|
3665
|
+
console.warn("--asset-domain is deprecated; use --asset-path with the complete asset URL");
|
|
3586
3666
|
const outputDir = option("--output", "aws-dashboard-release") ?? "aws-dashboard-release";
|
|
3587
3667
|
const parametersPath = option("--parameters", "aws-dashboard-parameters.json") ?? "aws-dashboard-parameters.json";
|
|
3588
3668
|
const rawParameters = await existingParameters(parametersPath);
|
|
@@ -3597,12 +3677,14 @@ ${shellCommand(awsCommand)}`,
|
|
|
3597
3677
|
boardConfigPath: boardConfig,
|
|
3598
3678
|
outputDir,
|
|
3599
3679
|
version,
|
|
3680
|
+
assetPath: option("--asset-path"),
|
|
3600
3681
|
assetDomain: option("--asset-domain"),
|
|
3601
3682
|
secretReference
|
|
3602
3683
|
}) : await packageEcs({
|
|
3603
3684
|
boardConfigPath: boardConfig,
|
|
3604
3685
|
outputDir,
|
|
3605
3686
|
version,
|
|
3687
|
+
assetPath: option("--asset-path"),
|
|
3606
3688
|
assetDomain: option("--asset-domain"),
|
|
3607
3689
|
secretReference,
|
|
3608
3690
|
imageReference: option("--image")
|
|
@@ -3611,7 +3693,7 @@ ${shellCommand(awsCommand)}`,
|
|
|
3611
3693
|
ComputeMode: mode,
|
|
3612
3694
|
LambdaArtifactKey: metadata.artifactKey,
|
|
3613
3695
|
Image: metadata.image ?? "",
|
|
3614
|
-
|
|
3696
|
+
AssetPath: metadata.assetPath
|
|
3615
3697
|
});
|
|
3616
3698
|
if (mode === "lambda" && !rawParameters.some(({ ParameterKey }) => ParameterKey === "ComputeMode"))
|
|
3617
3699
|
resolvedParameters.splice(
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { type BootstrapAffectedStack, type BootstrapRecoveryCommand, type Bootst
|
|
|
7
7
|
export type ReleaseMetadata = {
|
|
8
8
|
computeMode: ComputeMode;
|
|
9
9
|
dashboardVersion: string;
|
|
10
|
-
|
|
10
|
+
assetPath: string;
|
|
11
11
|
serverRuntimeVersion: string;
|
|
12
12
|
supportedProviders: string[];
|
|
13
13
|
artifactChecksums: Record<string, string>;
|
|
@@ -23,6 +23,8 @@ export type LambdaPackageOptions = {
|
|
|
23
23
|
boardConfigPath: string;
|
|
24
24
|
outputDir: string;
|
|
25
25
|
version: string;
|
|
26
|
+
assetPath?: string;
|
|
27
|
+
/** @deprecated Use assetPath. */
|
|
26
28
|
assetDomain?: string;
|
|
27
29
|
/** ARN of the consumer-owned JSON credential-map secret, never a secret value. */
|
|
28
30
|
secretReference?: string;
|
package/dist/index.js
CHANGED
|
@@ -839,6 +839,16 @@ var githubActionsSourceSchema = z2.looseObject({
|
|
|
839
839
|
branch: z2.string().min(1).optional(),
|
|
840
840
|
...sourceAuthenticationSchema
|
|
841
841
|
}).superRefine(exactlyOneGithubAuthenticationMode);
|
|
842
|
+
var azureDevOpsSourceSchema = z2.looseObject({
|
|
843
|
+
type: z2.literal("azure-devops"),
|
|
844
|
+
/** Azure DevOps organization name, used as one URL path segment. */
|
|
845
|
+
organization: z2.string().regex(/^[^/\s]+$/, "must be an organization name"),
|
|
846
|
+
project: z2.string().min(1),
|
|
847
|
+
/** The branch whose build health the dashboard represents. */
|
|
848
|
+
branch: z2.string().min(1).optional(),
|
|
849
|
+
/** Azure DevOps Build API access is authenticated with a read-scoped PAT. */
|
|
850
|
+
token_env: z2.string().min(1)
|
|
851
|
+
});
|
|
842
852
|
var sourceSchema = z2.looseObject({ type: z2.string().min(1), ...sourceAuthenticationSchema }).superRefine(exactlyOneGithubAuthenticationMode);
|
|
843
853
|
var boardSchema = z2.object({
|
|
844
854
|
refresh: durationSchema.optional(),
|
|
@@ -874,6 +884,33 @@ var boardConfigSchema = z2.object({
|
|
|
874
884
|
sources: z2.record(z2.string().min(1), sourceSchema).default({}),
|
|
875
885
|
boards: z2.record(z2.string().min(1), boardSchema),
|
|
876
886
|
auth: authSchema.optional()
|
|
887
|
+
}).superRefine((config, ctx) => {
|
|
888
|
+
for (const [sourceName, source] of Object.entries(config.sources)) {
|
|
889
|
+
if (source.type !== "azure-devops") continue;
|
|
890
|
+
const parsedSource = azureDevOpsSourceSchema.safeParse(source);
|
|
891
|
+
if (!parsedSource.success) {
|
|
892
|
+
for (const issue of parsedSource.error.issues) {
|
|
893
|
+
ctx.addIssue({
|
|
894
|
+
code: "custom",
|
|
895
|
+
path: ["sources", sourceName, ...issue.path],
|
|
896
|
+
message: issue.message
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
for (const [boardName, board] of Object.entries(config.boards)) {
|
|
902
|
+
board.panels.forEach((panel, panelIndex) => {
|
|
903
|
+
const source = panel.source ? config.sources[panel.source] : void 0;
|
|
904
|
+
if (panel.type !== "pipeline-status" || source?.type !== "azure-devops") return;
|
|
905
|
+
if (typeof panel.pipeline !== "number" || !Number.isInteger(panel.pipeline) || panel.pipeline <= 0) {
|
|
906
|
+
ctx.addIssue({
|
|
907
|
+
code: "custom",
|
|
908
|
+
path: ["boards", boardName, "panels", panelIndex, "pipeline"],
|
|
909
|
+
message: "Azure DevOps pipeline-status panels require a positive numeric pipeline definition id"
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
});
|
|
913
|
+
}
|
|
877
914
|
});
|
|
878
915
|
|
|
879
916
|
// packages/shared/src/board-config-modeline.ts
|
|
@@ -917,15 +954,13 @@ var clientEnvSchema = z3.object({
|
|
|
917
954
|
proxyPath: z3.string().min(1),
|
|
918
955
|
/** Which board this is, resolved server-side so the client parses no URLs. */
|
|
919
956
|
board: z3.string().min(1),
|
|
920
|
-
/** The client version being served, so two published versions are visibly distinguishable. */
|
|
921
|
-
clientVersion: z3.string().min(1),
|
|
922
957
|
/** Omitted entirely when unauthenticated — presence is what turns auth on. */
|
|
923
958
|
auth: z3.object({
|
|
924
959
|
issuer: z3.string().min(1),
|
|
925
960
|
clientId: z3.string().min(1).optional()
|
|
926
961
|
}).optional()
|
|
927
962
|
});
|
|
928
|
-
var clientIdentitySchema = clientEnvSchema.pick({ assetPath: true
|
|
963
|
+
var clientIdentitySchema = clientEnvSchema.pick({ assetPath: true });
|
|
929
964
|
|
|
930
965
|
// packages/shared/src/envelope.ts
|
|
931
966
|
import { z as z4 } from "zod";
|
|
@@ -1000,7 +1035,32 @@ var pullRequestHealthSchema = z4.object({
|
|
|
1000
1035
|
status: pipelineStatusSchema.shape.status,
|
|
1001
1036
|
summary: z4.string().min(1),
|
|
1002
1037
|
workflows: z4.array(pullRequestHealthItemSchema),
|
|
1003
|
-
pullRequests: z4.array(pullRequestHealthItemSchema)
|
|
1038
|
+
pullRequests: z4.array(pullRequestHealthItemSchema),
|
|
1039
|
+
/** Missing component reads remain visible even when the evidence we did get is reassuring. */
|
|
1040
|
+
incompleteObservations: z4.array(z4.object({ label: z4.string().min(1), message: z4.string().min(1) })).optional(),
|
|
1041
|
+
/** The latest component reading, disclosed beside the oldest aggregate evidence. */
|
|
1042
|
+
newestObservedAt: z4.iso.datetime().optional()
|
|
1043
|
+
});
|
|
1044
|
+
var pullRequestCandidateSchema = z4.object({
|
|
1045
|
+
number: z4.number().int().positive(),
|
|
1046
|
+
branch: z4.string().min(1),
|
|
1047
|
+
link: z4.url()
|
|
1048
|
+
});
|
|
1049
|
+
var pullRequestCandidatesSchema = z4.object({
|
|
1050
|
+
type: z4.literal("pull-request-candidates"),
|
|
1051
|
+
pullRequests: z4.array(pullRequestCandidateSchema),
|
|
1052
|
+
/** GitHub's first page is a deliberate bounded observation, not proof that no later PR exists. */
|
|
1053
|
+
truncated: z4.boolean().optional()
|
|
1054
|
+
});
|
|
1055
|
+
var pullRequestWorkflowObservationSchema = z4.object({
|
|
1056
|
+
type: z4.literal("pull-request-workflow"),
|
|
1057
|
+
workflow: z4.string().min(1),
|
|
1058
|
+
item: pullRequestHealthItemSchema
|
|
1059
|
+
});
|
|
1060
|
+
var pullRequestBuildObservationSchema = z4.object({
|
|
1061
|
+
type: z4.literal("pull-request-build"),
|
|
1062
|
+
branch: z4.string().min(1),
|
|
1063
|
+
item: pullRequestHealthItemSchema
|
|
1004
1064
|
});
|
|
1005
1065
|
var httpValueSchema = z4.object({
|
|
1006
1066
|
type: z4.literal("http-value"),
|
|
@@ -1098,11 +1158,25 @@ function credentialEnvironmentNames2(source) {
|
|
|
1098
1158
|
// packages/aws/src/release.ts
|
|
1099
1159
|
var CORE_RUNTIME_VERSION = "1.0.0";
|
|
1100
1160
|
var CANONICAL_ASSET_DOMAIN = "https://public-assets.zegreatrob.com";
|
|
1101
|
-
function
|
|
1161
|
+
function legacyAssetPath(version, domain = CANONICAL_ASSET_DOMAIN) {
|
|
1102
1162
|
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(version))
|
|
1103
1163
|
throw new Error(`Invalid dashboard version: ${version}`);
|
|
1104
1164
|
return `${domain.replace(/\/+$/, "")}/dashboard/${version}`;
|
|
1105
1165
|
}
|
|
1166
|
+
function normalizeAssetPath(value2) {
|
|
1167
|
+
const assetPath = value2.replace(/\/+$/, "");
|
|
1168
|
+
let url;
|
|
1169
|
+
try {
|
|
1170
|
+
url = new URL(assetPath);
|
|
1171
|
+
} catch {
|
|
1172
|
+
throw new Error("--asset-path must be an absolute HTTP(S) URL");
|
|
1173
|
+
}
|
|
1174
|
+
if (!["http:", "https:"].includes(url.protocol) || !url.hostname || url.username || url.password || url.search || url.hash)
|
|
1175
|
+
throw new Error(
|
|
1176
|
+
"--asset-path must be an absolute HTTP(S) URL without credentials, query, or fragment"
|
|
1177
|
+
);
|
|
1178
|
+
return assetPath;
|
|
1179
|
+
}
|
|
1106
1180
|
async function validateBoardConfig(path, expectedSchemaUrl) {
|
|
1107
1181
|
const source = await readFile(resolve(path), "utf8");
|
|
1108
1182
|
const authoredSchemaUrl = readBoardSchemaModeline(source, expectedSchemaUrl);
|
|
@@ -1124,10 +1198,14 @@ ${stringify(result.data, { sortMapEntries: true })}`;
|
|
|
1124
1198
|
};
|
|
1125
1199
|
}
|
|
1126
1200
|
async function assembleRelease(input) {
|
|
1127
|
-
|
|
1201
|
+
if (input.assetPath && input.assetDomain)
|
|
1202
|
+
throw new Error("--asset-path and --asset-domain cannot be used together");
|
|
1203
|
+
const assetPath = normalizeAssetPath(
|
|
1204
|
+
input.assetPath ?? legacyAssetPath(input.version, input.assetDomain)
|
|
1205
|
+
);
|
|
1128
1206
|
const board = await validateBoardConfig(
|
|
1129
1207
|
input.boardConfigPath,
|
|
1130
|
-
`${
|
|
1208
|
+
`${assetPath}/${boardSchemaFileName}`
|
|
1131
1209
|
);
|
|
1132
1210
|
if (board.usesCredentials && !input.secretReference)
|
|
1133
1211
|
throw new Error(
|
|
@@ -1138,7 +1216,7 @@ async function assembleRelease(input) {
|
|
|
1138
1216
|
await writeFile(join(outputDir, "board.yaml"), board.yaml);
|
|
1139
1217
|
const metadata = {
|
|
1140
1218
|
dashboardVersion: input.version,
|
|
1141
|
-
|
|
1219
|
+
assetPath,
|
|
1142
1220
|
serverRuntimeVersion: CORE_RUNTIME_VERSION,
|
|
1143
1221
|
supportedProviders: input.providers ?? ["aws-lambda"],
|
|
1144
1222
|
artifactChecksums: { "board.yaml": board.sha256 },
|
|
@@ -2688,6 +2766,7 @@ async function packageLambda(options) {
|
|
|
2688
2766
|
outputDir: runtimeDir,
|
|
2689
2767
|
version: options.version,
|
|
2690
2768
|
providers: ["aws-lambda"],
|
|
2769
|
+
assetPath: options.assetPath,
|
|
2691
2770
|
assetDomain: options.assetDomain,
|
|
2692
2771
|
secretReference: options.secretReference
|
|
2693
2772
|
});
|
|
@@ -2733,7 +2812,7 @@ async function packageLambda(options) {
|
|
|
2733
2812
|
deploymentTemplate(await cloudFormationTemplate("lambda"), {
|
|
2734
2813
|
ComputeMode: "lambda",
|
|
2735
2814
|
LambdaArtifactKey: packagedRelease.artifactKey,
|
|
2736
|
-
|
|
2815
|
+
AssetPath: packagedRelease.assetPath
|
|
2737
2816
|
})
|
|
2738
2817
|
);
|
|
2739
2818
|
return packagedRelease;
|
|
@@ -2747,6 +2826,7 @@ async function packageEcs(options) {
|
|
|
2747
2826
|
outputDir,
|
|
2748
2827
|
version: options.version,
|
|
2749
2828
|
providers: ["aws-ecs-fargate"],
|
|
2829
|
+
assetPath: options.assetPath,
|
|
2750
2830
|
assetDomain: options.assetDomain,
|
|
2751
2831
|
secretReference: options.secretReference
|
|
2752
2832
|
});
|
|
@@ -2763,7 +2843,7 @@ async function packageEcs(options) {
|
|
|
2763
2843
|
deploymentTemplate(await cloudFormationTemplate("ecs"), {
|
|
2764
2844
|
ComputeMode: "ecs",
|
|
2765
2845
|
Image: imageReference,
|
|
2766
|
-
|
|
2846
|
+
AssetPath: packagedRelease.assetPath
|
|
2767
2847
|
})
|
|
2768
2848
|
);
|
|
2769
2849
|
await writeFile3(
|