fix(mod_format): render format templates through smartscaf before comparing generated files

This commit is contained in:
2026-03-24 16:56:34 +00:00
parent b55e75d169
commit 142adfd396
6 changed files with 72 additions and 42 deletions

View File

@@ -9,6 +9,32 @@ export class TemplatesFormatter extends BaseFormatter {
return 'templates';
}
/**
* Render a template directory through smartscaf and return a map of path → content.
*/
private async renderTemplate(templateName: string): Promise<Map<string, string>> {
const templateDir = plugins.path.join(paths.templatesDir, templateName);
const scafTemplate = new plugins.smartscaf.ScafTemplate(templateDir);
await scafTemplate.readTemplateFromDir();
const gitzoneData = this.project.gitzoneConfig?.data;
if (gitzoneData) {
await scafTemplate.supplyVariables({
module: gitzoneData.module,
projectType: gitzoneData.projectType,
});
}
const renderedFiles = await scafTemplate.renderToMemory();
const fileMap = new Map<string, string>();
for (const file of renderedFiles) {
fileMap.set(file.path, file.contents.toString());
}
return fileMap;
}
async analyze(): Promise<IPlannedChange[]> {
const changes: IPlannedChange[] = [];
const project = this.project;
@@ -25,7 +51,8 @@ export class TemplatesFormatter extends BaseFormatter {
switch (projectType) {
case 'npm':
case 'wcc':
const accessLevel = project.gitzoneConfig?.data?.npmciOptions?.npmAccessLevel;
const accessLevel = (project.gitzoneConfig?.data as any)?.release?.accessLevel
|| project.gitzoneConfig?.data?.npmciOptions?.npmAccessLevel;
const ciTemplate = accessLevel === 'public' ? 'ci_default' : 'ci_default_private';
const ciChanges = await this.analyzeTemplate(ciTemplate, [
{ templatePath: '.gitea/workflows/default_nottags.yaml', destPath: '.gitea/workflows/default_nottags.yaml' },
@@ -80,53 +107,47 @@ export class TemplatesFormatter extends BaseFormatter {
const changes: IPlannedChange[] = [];
const templateDir = plugins.path.join(paths.templatesDir, templateName);
// Check if template exists
const templateExists = await plugins.smartfs.directory(templateDir).exists();
if (!templateExists) {
logVerbose(`Template ${templateName} not found`);
return changes;
}
for (const file of files) {
const templateFilePath = plugins.path.join(templateDir, file.templatePath);
const destFilePath = file.destPath;
let renderedFiles: Map<string, string>;
try {
renderedFiles = await this.renderTemplate(templateName);
} catch (error) {
logVerbose(`Failed to render template ${templateName}: ${error.message}`);
return changes;
}
// Check if template file exists
const fileExists = await plugins.smartfs.file(templateFilePath).exists();
if (!fileExists) {
logVerbose(`Template file ${templateFilePath} not found`);
for (const file of files) {
// Look up by templatePath first, then destPath (frontmatter may rename files)
const processedContent = renderedFiles.get(file.templatePath)
|| renderedFiles.get(file.destPath);
if (!processedContent) {
logVerbose(`Template file ${file.templatePath} not found in rendered output`);
continue;
}
try {
// Read template content
const templateContent = (await plugins.smartfs
.file(templateFilePath)
const destExists = await plugins.smartfs.file(file.destPath).exists();
let currentContent = '';
if (destExists) {
currentContent = (await plugins.smartfs
.file(file.destPath)
.encoding('utf8')
.read()) as string;
}
// Check if destination file exists
const destExists = await plugins.smartfs.file(destFilePath).exists();
let currentContent = '';
if (destExists) {
currentContent = (await plugins.smartfs
.file(destFilePath)
.encoding('utf8')
.read()) as string;
}
// Only add change if content differs
if (templateContent !== currentContent) {
changes.push({
type: destExists ? 'modify' : 'create',
path: destFilePath,
module: this.name,
description: `Apply template ${templateName}/${file.templatePath}`,
content: templateContent,
});
}
} catch (error) {
logVerbose(`Failed to read template ${templateFilePath}: ${error.message}`);
if (processedContent !== currentContent) {
changes.push({
type: destExists ? 'modify' : 'create',
path: file.destPath,
module: this.name,
description: `Apply template ${templateName}/${file.templatePath}`,
content: processedContent,
});
}
}