From e3095fa1fd7b3db3c6f1b4afc9ec3aa1ef1fcee6 Mon Sep 17 00:00:00 2001 From: "kubestellar-hive[bot]" Date: Sat, 19 Sep 2026 20:41:59 -0400 Subject: [PATCH] fix: sync architecture assets with disk after raster-SVG to PNG conversion importArchitecture() built record.assets from the copy-time file list and never revisited it after sanitizeArchitectureAssets() converted raster-embedded SVGs to PNG and deleted the originals. The catalog record kept the stale .svg path, validate-architectures.mjs failed on the missing asset, and the daily Import reference architectures workflow exited red before opening its update PR (failing since 2026-09-15). Rebuild record.assets from the on-disk directory after sanitization and rewrite .svg image references in the imported markdown to the converted .png path. Closes #331 Signed-off-by: kubestellar-hive[bot] --- scripts/import-architectures.mjs | 34 ++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/scripts/import-architectures.mjs b/scripts/import-architectures.mjs index 12c02a63..63b976ee 100644 --- a/scripts/import-architectures.mjs +++ b/scripts/import-architectures.mjs @@ -10,7 +10,7 @@ import { writeFileSync, } from 'node:fs'; import { execFileSync } from 'node:child_process'; -import { join, relative } from 'node:path'; +import { basename, join, relative } from 'node:path'; import { tmpdir } from 'node:os'; import { parse as yamlParse } from 'yaml'; @@ -97,14 +97,36 @@ async function importArchitecture(id, commit) { const destination = join(assetsDir, id, relative(imageDir, file)); mkdirSync(join(destination, '..'), { recursive: true }); cpSync(file, destination); - record.assets.push( - `/img/architectures/${id}/${relative(imageDir, file).replaceAll('\\', '/')}`, - ); } } - sanitizeArchitectureAssets(join(assetsDir, id)); + // Sanitization may convert raster-embedded SVGs to PNG and delete the + // originals, so capture SVG names beforehand and rebuild the asset list + // from disk afterward rather than trusting the copy-time list. + const archAssetsDir = join(assetsDir, id); + const svgsBefore = existsSync(archAssetsDir) + ? walkFiles(archAssetsDir).filter((file) => file.endsWith('.svg')) + : []; + sanitizeArchitectureAssets(archAssetsDir); + record.assets = existsSync(archAssetsDir) + ? walkFiles(archAssetsDir).map( + (file) => + `/img/architectures/${id}/${relative(archAssetsDir, file).replaceAll('\\', '/')}`, + ) + : []; + const convertedToPng = svgsBefore + .filter( + (file) => + !existsSync(file) && existsSync(file.replace(/\.svg$/i, '.png')), + ) + .map((file) => basename(file)); await mirrorProjectAssets(body); - const cleanBody = cleanMarkdown(renderProjectCards(body, id), id); + let cleanBody = cleanMarkdown(renderProjectCards(body, id), id); + for (const svgName of convertedToPng) { + cleanBody = cleanBody.replaceAll( + `/img/architectures/${id}/${svgName}`, + `/img/architectures/${id}/${svgName.replace(/\.svg$/i, '.png')}`, + ); + } record.summary = firstParagraph(cleanBody); writeFileSync( join(recordsDir, `${id}.json`),