From d39c56c9af689d5a419e3c9f3c8541ae269f386e Mon Sep 17 00:00:00 2001 From: i325261 Date: Tue, 19 May 2026 13:22:36 +0200 Subject: [PATCH 1/7] [Enhancement] Improve template handling in CapOperatorBuildPlugin and add test for user-defined custom templates --- README.md | 4 +++ lib/build.js | 68 ++++++++++++++++++++++++++++++++-------------- test/build.test.js | 19 ++++++++++++- 3 files changed, 69 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index fe3a3b5..fa0ed96 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,10 @@ The generated `chart/values.yaml` contains two types of information: > If you've already added the `templates` folder during the initial plugin call using `--with-templates` or `--with-configurable-templates` option, you can skip this step as the Helm chart is already complete. + > **Custom templates**: If you place files in the `chart/templates` folder, the build handles them as follows: + > - A file with the **same name** as a plugin-generated template (e.g. `_helpers.tpl`, `domain.yaml`, `cap-operator-cros.yaml`, `service-binding.yaml`, `service-instance.yaml`) will be used as-is instead of the plugin's default, and a message is printed to indicate this. + > - Any **additional files** you add to `chart/templates` are copied alongside the standard templates without modification. + 2. Up to this point, you've only filled in the design time information in the chart. But to deploy the application, you need to create a `runtime-values.yaml` file with all the runtime values, as mentioned in the section on configuration. You can generate the file using the plugin itself. The plugin requires the following information to generate the `runtime-values.yaml`: diff --git a/lib/build.js b/lib/build.js index 4643af3..1ab9338 100644 --- a/lib/build.js +++ b/lib/build.js @@ -5,6 +5,7 @@ SPDX-License-Identifier: Apache-2.0 const cds = require('@sap/cds-dk') const yaml = require('@sap/cds-foss').yaml +const fs = require('fs') const { exists, path } = cds.utils const { isServiceOnlyChart, @@ -33,32 +34,57 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { } async copyTemplates() { - if (exists(path.join(this.task.src, 'chart/templates'))) { - return await this.copy(path.join(this.task.src, 'chart/templates')).to(path.join(this.task.dest, 'templates')) + const userTemplatesDir = path.join(this.task.src, 'chart/templates') + const destTemplatesDir = path.join(this.task.dest, 'templates') + const hasUserTemplates = exists(userTemplatesDir) + const customTemplateMsg = (name) => `[cap-operator-plugin] Using template '${name}' from chart/templates/` + + for (const name of ['service-binding.yaml', 'service-instance.yaml']) { + const userFile = path.join(userTemplatesDir, name) + if (hasUserTemplates && exists(userFile)) { + console.log(customTemplateMsg(name)) + await this.copy(userFile).to(path.join(destTemplatesDir, name)) + } else { + await this.copy(path.join(__dirname, `../files/commonTemplates/${name}`)).to(path.join(destTemplatesDir, name)) + } } - await this.copy(path.join(__dirname, '../files/commonTemplates/')).to(path.join(this.task.dest, 'templates/')) - const valuesYaml = yaml.parse(await cds.utils.read(path.join(this.task.src, 'chart/values.yaml'))) - - // Create _helpers.tpl - await cds.utils.write(getHelperTpl({ - hasXsuaa: getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') != null - })).to(path.join(this.task.dest, 'templates/_helpers.tpl')) - const hasIas = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'identity') != null - // Create domain.yaml - await cds.utils.write(getDomainCroYaml({ - hasIas: hasIas - })).to(path.join(this.task.dest, 'templates/domain.yaml')) - - // Create cap-operator-cros.yaml - // Only filling those fields in the project input struct that are required to create CAPApplication - await cds.utils.write(getCAPOpCroYaml({ - hasIas: hasIas, - isService: isServiceOnlyChart('chart') - })).to(path.join(this.task.dest, 'templates/cap-operator-cros.yaml')) + const generatedFiles = [ + { + name: '_helpers.tpl', + generate: () => getHelperTpl({ hasXsuaa: getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') != null }) + }, + { + name: 'domain.yaml', + generate: () => getDomainCroYaml({ hasIas }) + }, + { + name: 'cap-operator-cros.yaml', + generate: () => getCAPOpCroYaml({ hasIas, isService: isServiceOnlyChart('chart') }) + } + ] + + for (const { name, generate } of generatedFiles) { + const userFile = path.join(userTemplatesDir, name) + if (hasUserTemplates && exists(userFile)) { + console.log(customTemplateMsg(name)) + await this.copy(userFile).to(path.join(destTemplatesDir, name)) + } else { + await cds.utils.write(generate()).to(path.join(destTemplatesDir, name)) + } + } + + if (hasUserTemplates) { + const knownFiles = new Set(['service-binding.yaml', 'service-instance.yaml', '_helpers.tpl', 'domain.yaml', 'cap-operator-cros.yaml']) + for (const entry of await fs.promises.readdir(userTemplatesDir)) { + if (!knownFiles.has(entry)) { + await this.copy(path.join(userTemplatesDir, entry)).to(path.join(destTemplatesDir, entry)) + } + } + } } async copyChartYaml() { diff --git a/test/build.test.js b/test/build.test.js index 920fca4..a43a4fd 100644 --- a/test/build.test.js +++ b/test/build.test.js @@ -47,6 +47,23 @@ describe('cds build', () => { }) + it('Build cap-operator chart with user-defined custom template', async () => { + execSync(`cds add cap-operator`, { cwd: bookshop }) + + fs.mkdirSync(join(bookshop, 'chart/templates'), { recursive: true }) + fs.writeFileSync(join(bookshop, 'chart/templates/my-custom-template.yaml'), '# custom user template\n') + + execSync(`cds build`, { cwd: bookshop }) + + expect(fs.readFileSync(join(bookshop, 'gen/chart/templates/my-custom-template.yaml'), 'utf8')).to.equal('# custom user template\n') + + expect(fs.existsSync(join(bookshop, 'gen/chart/templates/_helpers.tpl'))).to.equal(true) + expect(fs.existsSync(join(bookshop, 'gen/chart/templates/domain.yaml'))).to.equal(true) + expect(fs.existsSync(join(bookshop, 'gen/chart/templates/cap-operator-cros.yaml'))).to.equal(true) + expect(fs.existsSync(join(bookshop, 'gen/chart/templates/service-binding.yaml'))).to.equal(true) + expect(fs.existsSync(join(bookshop, 'gen/chart/templates/service-instance.yaml'))).to.equal(true) + }) + it('Build cap-operator chart with modified templates', async () => { execSync(`cds add cap-operator --with-templates`, { cwd: bookshop }) @@ -64,6 +81,6 @@ describe('cds build', () => { expect(getFileHash(join(__dirname,'../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/service-instance.yaml'))) expect(getFileHash(join(__dirname,'files/domain.yaml'))).to.equal(getFileHash(join(bookshop, 'gen/chart/templates/domain.yaml'))) - expect(fs.existsSync(join(bookshop, 'gen/chart/templates/_helpers.tpl'))).to.equal(false) + expect(fs.existsSync(join(bookshop, 'gen/chart/templates/_helpers.tpl'))).to.equal(true) }) }) From 8fa9aebd85f0253f2879958a807410b1834660b1 Mon Sep 17 00:00:00 2001 From: i325261 Date: Tue, 19 May 2026 13:44:20 +0200 Subject: [PATCH 2/7] [Enhancement] Add logging for template usage and Helm chart generation in CapOperatorBuildPlugin --- lib/build.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/build.js b/lib/build.js index 1ab9338..051370f 100644 --- a/lib/build.js +++ b/lib/build.js @@ -38,6 +38,7 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { const destTemplatesDir = path.join(this.task.dest, 'templates') const hasUserTemplates = exists(userTemplatesDir) const customTemplateMsg = (name) => `[cap-operator-plugin] Using template '${name}' from chart/templates/` + const defaultTemplateMsg = (name) => `[cap-operator-plugin] Using default template for '${name}'` for (const name of ['service-binding.yaml', 'service-instance.yaml']) { const userFile = path.join(userTemplatesDir, name) @@ -45,6 +46,7 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { console.log(customTemplateMsg(name)) await this.copy(userFile).to(path.join(destTemplatesDir, name)) } else { + console.log(defaultTemplateMsg(name)) await this.copy(path.join(__dirname, `../files/commonTemplates/${name}`)).to(path.join(destTemplatesDir, name)) } } @@ -73,6 +75,7 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { console.log(customTemplateMsg(name)) await this.copy(userFile).to(path.join(destTemplatesDir, name)) } else { + console.log(defaultTemplateMsg(name)) await cds.utils.write(generate()).to(path.join(destTemplatesDir, name)) } } @@ -81,6 +84,7 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { const knownFiles = new Set(['service-binding.yaml', 'service-instance.yaml', '_helpers.tpl', 'domain.yaml', 'cap-operator-cros.yaml']) for (const entry of await fs.promises.readdir(userTemplatesDir)) { if (!knownFiles.has(entry)) { + console.log(`[cap-operator-plugin] Copying user defined template '${entry}' from chart/templates/`) await this.copy(path.join(userTemplatesDir, entry)).to(path.join(destTemplatesDir, entry)) } } @@ -101,6 +105,8 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { } async build() { + console.log(`[cap-operator-plugin] Generating Helm chart in ${this.task.dest}...`) + // Copy templates await this.copyTemplates() From 68fe2e188c04a44905c89bcf2993cb69f7fcadab Mon Sep 17 00:00:00 2001 From: i325261 Date: Thu, 21 May 2026 13:26:37 +0200 Subject: [PATCH 3/7] [Enhancement] Refactor template handling in CapOperatorBuildPlugin to improve user-defined template support and logging --- lib/build.js | 53 ++++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/lib/build.js b/lib/build.js index 051370f..2463e32 100644 --- a/lib/build.js +++ b/lib/build.js @@ -40,43 +40,38 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { const customTemplateMsg = (name) => `[cap-operator-plugin] Using template '${name}' from chart/templates/` const defaultTemplateMsg = (name) => `[cap-operator-plugin] Using default template for '${name}'` - for (const name of ['service-binding.yaml', 'service-instance.yaml']) { - const userFile = path.join(userTemplatesDir, name) - if (hasUserTemplates && exists(userFile)) { - console.log(customTemplateMsg(name)) - await this.copy(userFile).to(path.join(destTemplatesDir, name)) - } else { - console.log(defaultTemplateMsg(name)) - await this.copy(path.join(__dirname, `../files/commonTemplates/${name}`)).to(path.join(destTemplatesDir, name)) - } + const staticEntry = (name) => { + const defaultFile = path.join(__dirname, `../files/commonTemplates/${name}`) + return { name, getDefault: () => cds.utils.read(defaultFile), writeDefault: (dest) => this.copy(defaultFile).to(dest) } } + const generatedEntry = (name, generate) => ({ + name, getDefault: () => generate(), writeDefault: (dest) => cds.utils.write(generate()).to(dest) + }) const valuesYaml = yaml.parse(await cds.utils.read(path.join(this.task.src, 'chart/values.yaml'))) const hasIas = getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'identity') != null - const generatedFiles = [ - { - name: '_helpers.tpl', - generate: () => getHelperTpl({ hasXsuaa: getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') != null }) - }, - { - name: 'domain.yaml', - generate: () => getDomainCroYaml({ hasIas }) - }, - { - name: 'cap-operator-cros.yaml', - generate: () => getCAPOpCroYaml({ hasIas, isService: isServiceOnlyChart('chart') }) - } + const templates = [ + staticEntry('service-binding.yaml'), + staticEntry('service-instance.yaml'), + generatedEntry('_helpers.tpl', () => getHelperTpl({ hasXsuaa: getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') != null })), + generatedEntry('domain.yaml', () => getDomainCroYaml({ hasIas })), + generatedEntry('cap-operator-cros.yaml', () => getCAPOpCroYaml({ hasIas, isService: isServiceOnlyChart('chart') })) ] - for (const { name, generate } of generatedFiles) { + for (const { name, getDefault, writeDefault } of templates) { const userFile = path.join(userTemplatesDir, name) + const destFile = path.join(destTemplatesDir, name) if (hasUserTemplates && exists(userFile)) { - console.log(customTemplateMsg(name)) - await this.copy(userFile).to(path.join(destTemplatesDir, name)) + const [userContent, defaultContent] = await Promise.all([cds.utils.read(userFile), Promise.resolve(getDefault())]) + this.pushMessage( + userContent !== defaultContent ? customTemplateMsg(name) : defaultTemplateMsg(name), + userContent !== defaultContent ? CapOperatorBuildPlugin.WARNING : CapOperatorBuildPlugin.INFO + ) + await this.copy(userFile).to(destFile) } else { - console.log(defaultTemplateMsg(name)) - await cds.utils.write(generate()).to(path.join(destTemplatesDir, name)) + this.pushMessage(defaultTemplateMsg(name), CapOperatorBuildPlugin.INFO) + await writeDefault(destFile) } } @@ -84,7 +79,7 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { const knownFiles = new Set(['service-binding.yaml', 'service-instance.yaml', '_helpers.tpl', 'domain.yaml', 'cap-operator-cros.yaml']) for (const entry of await fs.promises.readdir(userTemplatesDir)) { if (!knownFiles.has(entry)) { - console.log(`[cap-operator-plugin] Copying user defined template '${entry}' from chart/templates/`) + this.pushMessage(`[cap-operator-plugin] Copying user defined template '${entry}' from chart/templates/`, CapOperatorBuildPlugin.INFO) await this.copy(path.join(userTemplatesDir, entry)).to(path.join(destTemplatesDir, entry)) } } @@ -105,7 +100,7 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { } async build() { - console.log(`[cap-operator-plugin] Generating Helm chart in ${this.task.dest}...`) + this.pushMessage(`[cap-operator-plugin] Generating Helm chart in ${this.task.dest}...`, CapOperatorBuildPlugin.INFO) // Copy templates await this.copyTemplates() From 626d95226a35f8fc7ce6a7638e44d0def72c0ced Mon Sep 17 00:00:00 2001 From: i325261 Date: Thu, 21 May 2026 13:38:06 +0200 Subject: [PATCH 4/7] [Enhancement] Update logging message for user-defined templates in CapOperatorBuildPlugin --- lib/build.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/build.js b/lib/build.js index 2463e32..698e452 100644 --- a/lib/build.js +++ b/lib/build.js @@ -37,7 +37,7 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { const userTemplatesDir = path.join(this.task.src, 'chart/templates') const destTemplatesDir = path.join(this.task.dest, 'templates') const hasUserTemplates = exists(userTemplatesDir) - const customTemplateMsg = (name) => `[cap-operator-plugin] Using template '${name}' from chart/templates/` + const customTemplateMsg = (name) => `[cap-operator-plugin] Using updated template '${name}' from chart/templates/` const defaultTemplateMsg = (name) => `[cap-operator-plugin] Using default template for '${name}'` const staticEntry = (name) => { From e67c10dda6dda16361c4ee5d7bd261dc6bdf6ac6 Mon Sep 17 00:00:00 2001 From: i325261 Date: Thu, 21 May 2026 14:50:03 +0200 Subject: [PATCH 5/7] [Enhancement] Integrate configurable template support in CapOperatorBuildPlugin and update template handling logic --- lib/build.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/build.js b/lib/build.js index 698e452..dba468b 100644 --- a/lib/build.js +++ b/lib/build.js @@ -10,9 +10,11 @@ const { exists, path } = cds.utils const { isServiceOnlyChart, getCAPOpCroYaml, + getConfigurableCapOpCroYaml, getServiceInstanceKeyName, getDomainCroYaml, - getHelperTpl + getHelperTpl, + isConfigurableTemplateChart } = require('./util') module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { @@ -37,6 +39,7 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { const userTemplatesDir = path.join(this.task.src, 'chart/templates') const destTemplatesDir = path.join(this.task.dest, 'templates') const hasUserTemplates = exists(userTemplatesDir) + const isConfigurableTempChart = isConfigurableTemplateChart(path.join(this.task.src, 'chart')) const customTemplateMsg = (name) => `[cap-operator-plugin] Using updated template '${name}' from chart/templates/` const defaultTemplateMsg = (name) => `[cap-operator-plugin] Using default template for '${name}'` @@ -56,14 +59,14 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { staticEntry('service-instance.yaml'), generatedEntry('_helpers.tpl', () => getHelperTpl({ hasXsuaa: getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') != null })), generatedEntry('domain.yaml', () => getDomainCroYaml({ hasIas })), - generatedEntry('cap-operator-cros.yaml', () => getCAPOpCroYaml({ hasIas, isService: isServiceOnlyChart('chart') })) + generatedEntry('cap-operator-cros.yaml', () => isConfigurableTempChart ? getConfigurableCapOpCroYaml({ hasIas, isService: isServiceOnlyChart('chart') }) : getCAPOpCroYaml({ hasIas, isService: isServiceOnlyChart('chart') })) ] for (const { name, getDefault, writeDefault } of templates) { const userFile = path.join(userTemplatesDir, name) const destFile = path.join(destTemplatesDir, name) if (hasUserTemplates && exists(userFile)) { - const [userContent, defaultContent] = await Promise.all([cds.utils.read(userFile), Promise.resolve(getDefault())]) + const [userContent, defaultContent] = await Promise.all([cds.utils.read(userFile), getDefault()]) this.pushMessage( userContent !== defaultContent ? customTemplateMsg(name) : defaultTemplateMsg(name), userContent !== defaultContent ? CapOperatorBuildPlugin.WARNING : CapOperatorBuildPlugin.INFO From e738a292bd1af75f55311483ded08071ed191bd0 Mon Sep 17 00:00:00 2001 From: Anirudh Prasad Date: Thu, 21 May 2026 14:57:38 +0200 Subject: [PATCH 6/7] Update lib/build.js Co-authored-by: hyperspace-insights[bot] <209611008+hyperspace-insights[bot]@users.noreply.github.com> --- lib/build.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/build.js b/lib/build.js index dba468b..608335b 100644 --- a/lib/build.js +++ b/lib/build.js @@ -57,7 +57,7 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { const templates = [ staticEntry('service-binding.yaml'), staticEntry('service-instance.yaml'), - generatedEntry('_helpers.tpl', () => getHelperTpl({ hasXsuaa: getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') != null })), + generatedEntry('_helpers.tpl', () => getHelperTpl({ hasXsuaa: getServiceInstanceKeyName(valuesYaml['serviceInstances'], 'xsuaa') != null }, isConfigurableTempChart)), generatedEntry('domain.yaml', () => getDomainCroYaml({ hasIas })), generatedEntry('cap-operator-cros.yaml', () => isConfigurableTempChart ? getConfigurableCapOpCroYaml({ hasIas, isService: isServiceOnlyChart('chart') }) : getCAPOpCroYaml({ hasIas, isService: isServiceOnlyChart('chart') })) ] From b704c1d37454f877c21346f374a00c29c05b42a1 Mon Sep 17 00:00:00 2001 From: i325261 Date: Thu, 21 May 2026 16:02:19 +0200 Subject: [PATCH 7/7] [Enhancement] Improve handling of user-defined templates in CapOperatorBuildPlugin and update tests for nested templates --- README.md | 4 ++-- lib/build.js | 14 ++++++++------ test/build.test.js | 5 ++++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 03a21eb..ce0d17d 100644 --- a/README.md +++ b/README.md @@ -162,8 +162,8 @@ Depending on whether you used `--with-configurable-templates`, the design-time s > If you've already added the `templates` folder during the initial plugin call using `--with-templates` or `--with-configurable-templates` option, you can skip this step as the Helm chart is already complete. > **Custom templates**: If you place files in the `chart/templates` folder, the build handles them as follows: - > - A file with the **same name** as a plugin-generated template (e.g. `_helpers.tpl`, `domain.yaml`, `cap-operator-cros.yaml`, `service-binding.yaml`, `service-instance.yaml`) will be used as-is instead of the plugin's default, and a message is printed to indicate this. - > - Any **additional files** you add to `chart/templates` are copied alongside the standard templates without modification. + > - A file with the **same name** as one of the plugin-generated templates (`_helpers.tpl`, `domain.yaml`, `cap-operator-cros.yaml`, `service-binding.yaml`, `service-instance.yaml`) will be used as-is instead of the plugin's default, and a message is printed to indicate this. + > - Any **additional files** you add to `chart/templates` (i.e. files with names not in the list above) are copied alongside the standard templates without modification. 2. Up to this point, you've only filled in the design time information in the chart. But to deploy the application, you need to create a `runtime-values.yaml` file with all the runtime values, as mentioned in the section on configuration. You can generate the file using the plugin itself. diff --git a/lib/build.js b/lib/build.js index 608335b..0ad1f43 100644 --- a/lib/build.js +++ b/lib/build.js @@ -67,9 +67,11 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { const destFile = path.join(destTemplatesDir, name) if (hasUserTemplates && exists(userFile)) { const [userContent, defaultContent] = await Promise.all([cds.utils.read(userFile), getDefault()]) + const userStr = userContent?.toString() + const defaultStr = defaultContent?.toString() this.pushMessage( - userContent !== defaultContent ? customTemplateMsg(name) : defaultTemplateMsg(name), - userContent !== defaultContent ? CapOperatorBuildPlugin.WARNING : CapOperatorBuildPlugin.INFO + userStr !== defaultStr ? customTemplateMsg(name) : defaultTemplateMsg(name), + userStr !== defaultStr ? CapOperatorBuildPlugin.WARNING : CapOperatorBuildPlugin.INFO ) await this.copy(userFile).to(destFile) } else { @@ -80,10 +82,10 @@ module.exports = class CapOperatorBuildPlugin extends cds.build.Plugin { if (hasUserTemplates) { const knownFiles = new Set(['service-binding.yaml', 'service-instance.yaml', '_helpers.tpl', 'domain.yaml', 'cap-operator-cros.yaml']) - for (const entry of await fs.promises.readdir(userTemplatesDir)) { - if (!knownFiles.has(entry)) { - this.pushMessage(`[cap-operator-plugin] Copying user defined template '${entry}' from chart/templates/`, CapOperatorBuildPlugin.INFO) - await this.copy(path.join(userTemplatesDir, entry)).to(path.join(destTemplatesDir, entry)) + for (const entry of await fs.promises.readdir(userTemplatesDir, { withFileTypes: true })) { + if (entry.isDirectory() || !knownFiles.has(entry.name)) { + this.pushMessage(`[cap-operator-plugin] Copying user defined template '${entry.name}' from chart/templates/`, CapOperatorBuildPlugin.INFO) + await this.copy(path.join(userTemplatesDir, entry.name)).to(path.join(destTemplatesDir, entry.name)) } } } diff --git a/test/build.test.js b/test/build.test.js index a43a4fd..8bef76d 100644 --- a/test/build.test.js +++ b/test/build.test.js @@ -48,14 +48,17 @@ describe('cds build', () => { }) it('Build cap-operator chart with user-defined custom template', async () => { + execSync(`rm -rf gen`, { cwd: bookshop }) execSync(`cds add cap-operator`, { cwd: bookshop }) - fs.mkdirSync(join(bookshop, 'chart/templates'), { recursive: true }) + fs.mkdirSync(join(bookshop, 'chart/templates/my-subdir'), { recursive: true }) fs.writeFileSync(join(bookshop, 'chart/templates/my-custom-template.yaml'), '# custom user template\n') + fs.writeFileSync(join(bookshop, 'chart/templates/my-subdir/my-nested-template.yaml'), '# custom nested template\n') execSync(`cds build`, { cwd: bookshop }) expect(fs.readFileSync(join(bookshop, 'gen/chart/templates/my-custom-template.yaml'), 'utf8')).to.equal('# custom user template\n') + expect(fs.readFileSync(join(bookshop, 'gen/chart/templates/my-subdir/my-nested-template.yaml'), 'utf8')).to.equal('# custom nested template\n') expect(fs.existsSync(join(bookshop, 'gen/chart/templates/_helpers.tpl'))).to.equal(true) expect(fs.existsSync(join(bookshop, 'gen/chart/templates/domain.yaml'))).to.equal(true)