refactor: validate generated evidence artifacts
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import { mkdir, readFile, rm } from "node:fs/promises";
|
||||
import process from "node:process";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -9,14 +9,17 @@ import {
|
||||
} from "../src/features/installed-feature-contracts.ts";
|
||||
import {
|
||||
buildManifestArtifactSchema,
|
||||
jsonSchemaDocumentArtifactSchema,
|
||||
moduleInventoryArtifactSchema,
|
||||
releaseManifestV2ArtifactSchema,
|
||||
runtimeConfigV2ArtifactSchema,
|
||||
} from "../src/contracts/release-artifacts.ts";
|
||||
} from "./contracts/release-artifacts.ts";
|
||||
import { buildContractSet } from "./generate-contract-set.ts";
|
||||
import {
|
||||
assertCiBuildEnvironment,
|
||||
buildDate,
|
||||
} from "./lib/build-environment.ts";
|
||||
import { writeValidatedJsonArtifact } from "./lib/validated-json-artifact.ts";
|
||||
|
||||
assertCiBuildEnvironment(process.env);
|
||||
type ViteManifestEntry = Readonly<{
|
||||
@@ -41,12 +44,15 @@ const moduleInventory = await readFile(
|
||||
"dist/.vite/module-inventory.json",
|
||||
"utf8",
|
||||
);
|
||||
parseModuleInventory(JSON.parse(moduleInventory));
|
||||
const moduleInventoryDocument = moduleInventoryArtifactSchema.parse(
|
||||
JSON.parse(moduleInventory),
|
||||
);
|
||||
const moduleInventoryBytes = `${JSON.stringify(moduleInventoryDocument, null, 2)}\n`;
|
||||
const assetManifestHash = createHash("sha256")
|
||||
.update(viteManifest)
|
||||
.digest("hex");
|
||||
const moduleInventoryHash = createHash("sha256")
|
||||
.update(moduleInventory)
|
||||
.update(moduleInventoryBytes)
|
||||
.digest("hex");
|
||||
const runtimeConfig = runtimeConfigV2ArtifactSchema.parse(
|
||||
JSON.parse(await readFile("dist/config.json", "utf8")),
|
||||
@@ -108,28 +114,37 @@ const releaseManifest = releaseManifestV2ArtifactSchema.parse({
|
||||
|
||||
await mkdir("artifacts/release", { recursive: true });
|
||||
await mkdir("artifacts/quality", { recursive: true });
|
||||
await writeFile(
|
||||
"artifacts/quality/vite-module-inventory.json",
|
||||
moduleInventory,
|
||||
);
|
||||
await writeValidatedJsonArtifact({
|
||||
path: "artifacts/quality/vite-module-inventory.json",
|
||||
schema: moduleInventoryArtifactSchema,
|
||||
value: moduleInventoryDocument,
|
||||
});
|
||||
await rm("dist/.vite/module-inventory.json");
|
||||
await writeFile("dist/config.json", `${JSON.stringify(runtimeConfig, null, 2)}\n`);
|
||||
await writeFile(
|
||||
"dist/release-manifest.json",
|
||||
`${JSON.stringify(releaseManifest, null, 2)}\n`,
|
||||
);
|
||||
await writeFile(
|
||||
"dist/runtime-config.schema.json",
|
||||
`${JSON.stringify(runtimeConfigJsonSchema, null, 2)}\n`,
|
||||
);
|
||||
await writeFile(
|
||||
"artifacts/release/runtime-config.schema.json",
|
||||
`${JSON.stringify(runtimeConfigJsonSchema, null, 2)}\n`,
|
||||
);
|
||||
await writeFile(
|
||||
"artifacts/release/build-manifest.json",
|
||||
`${JSON.stringify(manifest, null, 2)}\n`,
|
||||
);
|
||||
await writeValidatedJsonArtifact({
|
||||
path: "dist/config.json",
|
||||
schema: runtimeConfigV2ArtifactSchema,
|
||||
value: runtimeConfig,
|
||||
});
|
||||
await writeValidatedJsonArtifact({
|
||||
path: "dist/release-manifest.json",
|
||||
schema: releaseManifestV2ArtifactSchema,
|
||||
value: releaseManifest,
|
||||
});
|
||||
await writeValidatedJsonArtifact({
|
||||
path: "dist/runtime-config.schema.json",
|
||||
schema: jsonSchemaDocumentArtifactSchema,
|
||||
value: runtimeConfigJsonSchema,
|
||||
});
|
||||
await writeValidatedJsonArtifact({
|
||||
path: "artifacts/release/runtime-config.schema.json",
|
||||
schema: jsonSchemaDocumentArtifactSchema,
|
||||
value: runtimeConfigJsonSchema,
|
||||
});
|
||||
await writeValidatedJsonArtifact({
|
||||
path: "artifacts/release/build-manifest.json",
|
||||
schema: buildManifestArtifactSchema,
|
||||
value: manifest,
|
||||
});
|
||||
|
||||
function parsePackageMetadata(value: unknown): Readonly<{
|
||||
version: string;
|
||||
@@ -165,23 +180,6 @@ function parseViteManifest(
|
||||
return entries;
|
||||
}
|
||||
|
||||
function parseModuleInventory(value: unknown): void {
|
||||
if (
|
||||
!isRecord(value) ||
|
||||
value.schemaVersion !== 1 ||
|
||||
!Array.isArray(value.chunks) ||
|
||||
value.chunks.some(
|
||||
(chunk) =>
|
||||
!isRecord(chunk) ||
|
||||
typeof chunk.fileName !== "string" ||
|
||||
!Array.isArray(chunk.modules) ||
|
||||
chunk.modules.some((moduleId) => typeof moduleId !== "string"),
|
||||
)
|
||||
) {
|
||||
throw new TypeError("Vite module inventory is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user