From 142adfd39695a1cafb27b3e2340b40d6e87c3dff Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Tue, 24 Mar 2026 16:56:34 +0000 Subject: [PATCH] fix(mod_format): render format templates through smartscaf before comparing generated files --- changelog.md | 7 ++ package.json | 2 +- pnpm-lock.yaml | 10 +- ts/00_commitinfo_data.ts | 2 +- .../formatters/templates.formatter.ts | 91 ++++++++++++------- ts/mod_format/mod.plugins.ts | 2 + 6 files changed, 72 insertions(+), 42 deletions(-) diff --git a/changelog.md b/changelog.md index d2486a9..49cee0d 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # Changelog +## 2026-03-24 - 2.13.12 - fix(mod_format) +render format templates through smartscaf before comparing generated files + +- adds smartscaf-based in-memory template rendering so supplied variables are applied before detecting changes +- supports release.accessLevel as a fallback when selecting public vs private CI templates +- matches rendered output by template or destination path to handle renamed files from template frontmatter + ## 2026-03-24 - 2.13.10 - fix(config) migrate configuration handling from npmextra to smartconfig diff --git a/package.json b/package.json index 4eabfaa..5fe571b 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "@push.rocks/smartopen": "^2.0.0", "@push.rocks/smartpath": "^6.0.0", "@push.rocks/smartpromise": "^4.2.3", - "@push.rocks/smartscaf": "^4.0.19", + "@push.rocks/smartscaf": "^4.0.21", "@push.rocks/smartshell": "^3.3.7", "@push.rocks/smartunique": "^3.0.9", "@push.rocks/smartupdate": "^2.0.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index af0f58f..104e60d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -78,8 +78,8 @@ importers: specifier: ^4.2.3 version: 4.2.3 '@push.rocks/smartscaf': - specifier: ^4.0.19 - version: 4.0.19 + specifier: ^4.0.21 + version: 4.0.21 '@push.rocks/smartshell': specifier: ^3.3.7 version: 3.3.7 @@ -1216,8 +1216,8 @@ packages: '@push.rocks/smarts3@5.3.0': resolution: {integrity: sha512-6bo55ovCDEylbTxwPFZYDrZrz2babQEUmxHIexmVcP2j+6LYRHDbGYnWoyKdtqniqDFZ04pFkOoZ85hUzU5xCw==} - '@push.rocks/smartscaf@4.0.19': - resolution: {integrity: sha512-J9z2rWtFhT55kDZfWGpghnwy4aybmJoatzq5icfbZMXohS2KALuj1N17iXZ9L+43F1AwpUeZ/KnokNsh7yHZ5w==} + '@push.rocks/smartscaf@4.0.21': + resolution: {integrity: sha512-vt+O/dp/uSTdfK2CtkgMSJenYwfZLMTi9IM9uHfkKd8DaI4UvqiFCO6/smkv08zWQlLBVlUD2UWVd7RM9h1BJg==} '@push.rocks/smartserve@2.0.1': resolution: {integrity: sha512-YQb2qexfCzCqOlLWBBXKMg6xG4zahCPAxomz/KEKAwHtW6wMTtuHKSTSkRTQ0vl9jssLMAmRz2OyafiL9XGJXQ==} @@ -6224,7 +6224,7 @@ snapshots: '@push.rocks/smartrust': 1.3.1 '@tsclass/tsclass': 9.3.0 - '@push.rocks/smartscaf@4.0.19': + '@push.rocks/smartscaf@4.0.21': dependencies: '@push.rocks/lik': 6.3.1 '@push.rocks/smartfile': 11.2.7 diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 81f4de3..6b8a110 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@git.zone/cli', - version: '2.13.10', + version: '2.13.12', description: 'A comprehensive CLI tool for enhancing and managing local development workflows with gitzone utilities, focusing on project setup, version control, code formatting, and template management.' } diff --git a/ts/mod_format/formatters/templates.formatter.ts b/ts/mod_format/formatters/templates.formatter.ts index 8772472..82b828b 100644 --- a/ts/mod_format/formatters/templates.formatter.ts +++ b/ts/mod_format/formatters/templates.formatter.ts @@ -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> { + 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(); + for (const file of renderedFiles) { + fileMap.set(file.path, file.contents.toString()); + } + return fileMap; + } + async analyze(): Promise { 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; + 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, + }); } } diff --git a/ts/mod_format/mod.plugins.ts b/ts/mod_format/mod.plugins.ts index 8f77ee9..b64ff50 100644 --- a/ts/mod_format/mod.plugins.ts +++ b/ts/mod_format/mod.plugins.ts @@ -8,6 +8,7 @@ import * as smartobject from '@push.rocks/smartobject'; import * as smartnpm from '@push.rocks/smartnpm'; import * as smartconfig from '@push.rocks/smartconfig'; import * as smartdiff from '@push.rocks/smartdiff'; +import * as smartscaf from '@push.rocks/smartscaf'; export { path, @@ -18,4 +19,5 @@ export { smartnpm, smartconfig, smartdiff, + smartscaf, };