#!/usr/bin/env node import fs from 'node:fs/promises' import path from 'node:path' import { fileURLToPath } from 'node:url' const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) const repoRoot = path.resolve(__dirname, '..') const sourcePath = path.join( repoRoot, 'docs/generated/higher_dimensional_training_maps/phase6c_dedicated_family_package_validation_report.json', ) const outputPath = path.join( repoRoot, 'website/src/shared/generated/windows-package-validation-summary.json', ) const FAMILY_LABELS = { magic120cell: 'Magic120Cell dedicated-family training map', magiccube5d: 'MagicCube5D dedicated-family training map', } function parseJson(content, label) { try { return JSON.parse(content) } catch (error) { throw new Error(`${label} is not valid JSON: ${error instanceof Error ? error.message : String(error)}`) } } function assertString(value, label) { if (typeof value !== 'string' || value.trim().length === 0) { throw new Error(`${label} must be a non-empty string.`) } return value } function assertBoolean(value, label) { if (typeof value !== 'boolean') { throw new Error(`${label} must be a boolean.`) } return value } function normalizePrePackageEditorBuild(value) { if (value == null) { return null } if (typeof value !== 'object') { throw new Error('prePackageEditorBuild must be an object when present.') } const lane = assertString(value.lane, 'prePackageEditorBuild.lane') const performed = assertBoolean(value.performed, 'prePackageEditorBuild.performed') if (value.result !== 'passed' && value.result !== 'not-run') { throw new Error('prePackageEditorBuild.result must be "passed" or "not-run".') } return { lane, performed, result: value.result, } } function normalizeSmokeResult(value, label) { if (value === 'passed' || value === 'failed') { return value } throw new Error(`${label} must be "passed" or "failed".`) } function buildFallbackLabel(mapUrl) { const mapName = mapUrl.split('/').pop() || mapUrl return `${mapName} packaged smoke map` } function buildSummary(report) { const generatedAtUtc = assertString(report.generatedAtUtc, 'generatedAtUtc') const configuration = assertString(report.configuration, 'configuration') const skipBuild = assertBoolean(report.skipBuild, 'skipBuild') const prePackageEditorBuild = normalizePrePackageEditorBuild(report.prePackageEditorBuild) const result = normalizeSmokeResult(report.result, 'result') const validatedEntries = Array.isArray(report.authoringManifest?.validatedEntries) ? report.authoringManifest.validatedEntries : [] const mapKindByUrl = new Map( validatedEntries .filter((entry) => typeof entry?.mapAssetPath === 'string' && typeof entry?.mapKind === 'string') .map((entry) => [entry.mapAssetPath, entry.mapKind]), ) const smokeReports = Array.isArray(report.smokeReports) ? report.smokeReports : [] const smokeMaps = smokeReports.map((smokeReport, index) => { const mapUrl = assertString(smokeReport.mapUrl, `smokeReports[${index}].mapUrl`) const mapKind = mapKindByUrl.get(mapUrl) const label = (mapKind && FAMILY_LABELS[mapKind]) || buildFallbackLabel(mapUrl) return { map_url: mapUrl, label, result: normalizeSmokeResult(smokeReport.result, `smokeReports[${index}].result`), } }) return { lane: 'Windows Unreal packaged validation', result, generated_at: generatedAtUtc, configuration, skip_build: skipBuild, pre_package_editor_build: prePackageEditorBuild, smoke_map_count: smokeMaps.length, smoke_maps: smokeMaps, } } async function main() { const checkOnly = process.argv.includes('--check') const sourceContent = await fs.readFile(sourcePath, 'utf8') const summary = buildSummary(parseJson(sourceContent, sourcePath)) const serialized = `${JSON.stringify(summary, null, 2)}\n` if (checkOnly) { let existing = null try { existing = await fs.readFile(outputPath, 'utf8') } catch (error) { if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') { console.error(`Generated summary missing: ${outputPath}`) process.exit(1) } throw error } if (existing !== serialized) { console.error('Generated web package-validation summary is stale.') console.error(`Refresh with: node ${path.relative(repoRoot, __filename)}`) process.exit(1) } console.log(`Validated packaged-validation summary freshness: ${path.relative(repoRoot, outputPath)}`) return } await fs.mkdir(path.dirname(outputPath), { recursive: true }) await fs.writeFile(outputPath, serialized, 'utf8') console.log(`Wrote ${path.relative(repoRoot, outputPath)}`) } await main()